Skip to content

Commit

Permalink
Ak event form (#23)
Browse files Browse the repository at this point in the history
fix: authOptions callback
init event form

---------

Co-authored-by: alexandre-kakal-akarah <[email protected]>
Co-authored-by: GuillaumeD <[email protected]>
  • Loading branch information
3 people authored Jun 26, 2024
1 parent 806b542 commit b1641ad
Show file tree
Hide file tree
Showing 16 changed files with 439 additions and 28 deletions.
33 changes: 33 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"@radix-ui/react-popover": "^1.1.1",
"@radix-ui/react-radio-group": "^1.2.0",
"@radix-ui/react-select": "^2.1.1",
"@radix-ui/react-slider": "^1.2.0",
"@radix-ui/react-slot": "^1.1.0",
"bcrypt": "^5.1.1",
"class-variance-authority": "^0.7.0",
Expand Down
2 changes: 2 additions & 0 deletions src/app/(app)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from "react";
import Nav from "@/components/Nav";
import { ReactParallaxProvider } from "@/providers/Providers";
import EventForm from "@/components/form/event/EventForm";

export default function AppLayout({
children,
Expand All @@ -10,6 +11,7 @@ export default function AppLayout({
return (
<ReactParallaxProvider>
{children}
<EventForm />
<Nav />
</ReactParallaxProvider>
);
Expand Down
16 changes: 14 additions & 2 deletions src/app/(app)/parcours/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,27 @@ import React from "react";
import ParallaxImage from "@/components/clients/ParallaxImage";
import Rating from "@/components/Rating";
import { Icons } from "@/components/Icons";
import { Button } from "@/components/ui/button";
import { buttonAction } from "@/types/enums/button";

type Params = { id: string };

const JourneyDetail = ({ params }: { params: Params }) => {
// get journey by id
return (
<main className="flex min-h-screen flex-col bg-gray">
<ParallaxImage />
<div className="relative flex-1 -translate-y-4 rounded-t-2xl px-5 pb-40 pt-14">
<div className="relative">
<ParallaxImage />
<Button
action={buttonAction.SET_JOURNEY_ID}
ressourceId={parseInt(params.id)}
className="absolute right-5 top-5 border-orange bg-gray"
>
<span>Créer un évènement</span>
<Icons.arrowLink fill="#d8552b" className="ml-2" />
</Button>
</div>
<div className="relative flex-1 rounded-t-2xl px-5 pb-40 pt-14">
<div className="absolute left-4 top-0 flex gap-[6px]">
<div className="flex items-center rounded-b-md bg-white px-2 py-[6px]">
<Icons.dumbbel />
Expand Down
3 changes: 2 additions & 1 deletion src/app/(app)/profil/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import TopBar from "@/components/TopBar";
import Link from "next/link";
import { Icons } from "@/components/Icons";
import { Button } from "@/components/ui/button";
import { buttonAction } from "@/types/enums/button";

const Profil = () => {
return (
Expand Down Expand Up @@ -55,7 +56,7 @@ const Profil = () => {
<span className="font-semibold">Mentions légales</span>
</Link>
</section>
<Button isSignOut variant="danger">
<Button action={buttonAction.SIGN_OUT} variant="danger">
Déconnexion
</Button>
<Button variant="dangerFilled">Supprimer mon compte</Button>
Expand Down
2 changes: 1 addition & 1 deletion src/app/api/journeys/route.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { handleException } from "@/app/utils/errorHandlerUtils";
import { handleException } from "@/utils/errorHandlerUtils";
import {
getAllJourneys,
registerOrModifyJourney,
Expand Down
13 changes: 8 additions & 5 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from "react";
import type { Metadata, Viewport } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
import { NextAuthProvider } from "@/providers/Providers";

const inter = Inter({ subsets: ["latin"] });

Expand Down Expand Up @@ -55,10 +56,12 @@ export default function RootLayout({
children: React.ReactNode;
}>) {
return (
<html lang="fr">
<body className={`${inter.className} min-h-screen bg-background`}>
{children}
</body>
</html>
<NextAuthProvider>
<html lang="fr">
<body className={`${inter.className} min-h-screen bg-background`}>
{children}
</body>
</html>
</NextAuthProvider>
);
}
208 changes: 208 additions & 0 deletions src/components/form/event/EventForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
"use client";
import React, { useState } from "react";
import { eventFormSchema } from "@/validators/EventFormSchema";
import { z } from "zod";
import { useEventFormStore } from "@/store/eventFormStore";
import { useForm, SubmitHandler } from "react-hook-form";
import {
Form,
FormControl,
FormField,
FormItem,
FormMessage,
} from "@/components/ui/form";
import { Button } from "@/components/ui/button";
import { zodResolver } from "@hookform/resolvers/zod";
import { Icons } from "@/components/Icons";
import { Input } from "@/components/ui/input";
import { Label } from "@radix-ui/react-label";
import { Event } from "@prisma/client";
import { Textarea } from "@/components/ui/textarea";

type EventRequestBody = Omit<Event, "id" | "createdAt" | "updatedAt">;
export type EventFormValues = z.infer<typeof eventFormSchema>;

const EventForm = () => {
const { isVisible, hideModal, journeyIdValue, setJourneyIdValue } =
useEventFormStore();
const [formStatus, setFormStatus] = useState<"idle" | "errored">("idle");

const form = useForm<EventFormValues>({
resolver: zodResolver(eventFormSchema),
defaultValues: {
title: "",
description: "",
numberPlayerMin: 1,
numberPlayerMax: 40,
isPrivate: false,
accessCode: undefined,
},
});

if (!isVisible) return null;

const processForm: SubmitHandler<EventFormValues> = async (data) => {
const parsedData = eventFormSchema.safeParse(data);
if (!parsedData.success || !journeyIdValue) {
setFormStatus("errored");
return;
}
try {
const body: EventRequestBody = {
journeyId: journeyIdValue,
authorId: 1,
title: data.title,
description: data.description,
numberPlayerMin: data.numberPlayerMin,
numberPlayerMax: data.numberPlayerMax,
isPrivate: data.isPrivate,
accessCode: data.accessCode || null,
endAt: data.endAt,
startAt: data.startAt,
image: "",
};
const response = await fetch("/api/events", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(body),
});

console.log(response, "create event response");
} catch (error) {
console.log(error);
}
console.log(data);
};

const dismissModal = () => {
hideModal();
form.reset();
setFormStatus("idle");
setJourneyIdValue(null);
};

return (
<div className="fixed left-0 top-0 z-10 flex size-full flex-col overflow-scroll bg-background px-5 pb-12 pt-5">
<div className="flex justify-end">
<Button onClick={dismissModal}>
<span>Quitter</span>
<Icons.close width={14} height={14} className="ml-2" />
</Button>
</div>
<Form {...form}>
{!form.formState.isSubmitSuccessful && formStatus === "idle" && (
<form onSubmit={form.handleSubmit(processForm)}>
<FormField
control={form.control}
name="title"
render={({ field }) => (
<FormItem>
<FormControl>
<>
<Label htmlFor="title">Titre*</Label>
<Input {...field} id="title" />
</>
</FormControl>
<FormMessage className="text-red-500" />
</FormItem>
)}
/>

<FormField
control={form.control}
name="description"
render={({ field }) => (
<FormItem>
<FormControl>
<>
<Label htmlFor="description">Description*</Label>
<Textarea {...field} id="description" />
</>
</FormControl>
<FormMessage className="text-red-500" />
</FormItem>
)}
/>
<div className="flex gap-5">
<FormField
control={form.control}
name="numberPlayerMin"
render={({ field }) => (
<FormItem>
<FormControl>
<>
<Label htmlFor="numberPlayerMin">
Nombre mininum de participants*
</Label>
<Input {...field} type="number" id="numberPlayerMin" />
</>
</FormControl>
<FormMessage className="text-red-500" />
</FormItem>
)}
/>
<FormField
control={form.control}
name="numberPlayerMax"
render={({ field }) => (
<FormItem>
<FormControl>
<>
<Label htmlFor="numberPlayerMax">
Nombre maximum de participants*
</Label>
<Input {...field} type="number" id="numberPlayerMax" />
</>
</FormControl>
<FormMessage className="text-red-500" />
</FormItem>
)}
/>
</div>
</form>
)}

{form.formState.isSubmitSuccessful && formStatus !== "errored" && (
<div className="mt-[10vh]">
<h2 className="mb-8 text-4xl font-bold">
Votre évènement a bien été enregistré !
</h2>
<p className="mb-6">
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Quasi
nam illo iste veniam ea! Doloremque distinctio mollitia omnis.
</p>
<Button type="button" onClick={dismissModal}>
<span>Terminer</span>
<Icons.check
width={14}
height={14}
className="ml-2"
fill="#d8552b"
/>
</Button>
</div>
)}

{formStatus === "errored" && (
<div className="mt-[10vh]">
<h2 className="mb-8 text-4xl font-bold">
Oups, une erreur est survenue...
</h2>
<p className="mb-6">
Votre évènement n'a pas pu être créé, veuillez réessayer plus
tard.
</p>
<Button type="button" onClick={dismissModal}>
<span>Fermer</span>
<Icons.close width={14} height={14} className="ml-2" />
</Button>
</div>
)}
</Form>
</div>
);
};

export default EventForm;
Loading

0 comments on commit b1641ad

Please sign in to comment.