'use client'; import { zodResolver } from '@hookform/resolvers/zod'; import cookies from 'js-cookie'; import { notFound, useRouter } from 'next/navigation'; import { useContext, useState } from 'react'; import { useForm } from 'react-hook-form'; import { useSWRConfig } from 'swr'; import * as z from 'zod'; import { usePuzzle } from '@/lib/hooks/use-puzzles'; import { getURL } from '@/lib/utils'; import { Button } from '@/components/ui/Button'; import { Form, FormControl, FormField, FormItem, FormLabel } from '@/components/ui/Form'; import { Input } from '@/components/ui/Input'; import ToHTML from '@/components/ui/ToHTML'; import { UserContext } from '@/context/user'; import { type Puzzle } from '@/lib/puzzles'; import { Loader2 } from 'lucide-react'; import { Separator } from '@/components/ui/Separator'; type Granted = { tries: number | null; score?: number | null; message?: string | null; success?: boolean | null; }; export default function Puzzle({ token, id }: { token: string; id: number }) { const { data: me } = useContext(UserContext); const { data: puzzle, isLoading } = usePuzzle({ token, id }); const router = useRouter(); if (!puzzle && isLoading) { return <>; } if (!puzzle) { notFound(); } // TODO : add a check to see if the user is in the group of the puzzle if (me?.groups.length === 0) { router.push('/dashboard/puzzles'); } return (

{puzzle.name}{' '} ({puzzle.scoreMax} points)

{!puzzle.score ? ( ) : (

Tentative{puzzle.tries && puzzle.tries > 1 ? 's' : ''} :{' '} {puzzle.tries}

Score : {puzzle.score}

)}
); } const InputFormSchema = z.object({ answer: z.string().nonempty().trim(), code_file: z.any().optional() }); function InputForm({ puzzle }: { puzzle?: Puzzle }) { const form = useForm>({ resolver: zodResolver(InputFormSchema), defaultValues: { answer: '', code_file: undefined } }); const { mutate } = useSWRConfig(); const [isLoading, setIsLoading] = useState(false); const [granted, setGranted] = useState(null); async function onSubmit(data: z.infer) { setIsLoading(true); const formData = new FormData(); if (data.code_file) { formData.append('code_file', data.code_file[0]); } formData.append('answer', data.answer); const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/puzzleResponse/${puzzle!.id}`, { method: 'POST', body: formData, headers: { Authorization: `Bearer ${cookies.get('token')}}` } }); if (res.ok || res.status === 403 || res.status === 406 || res.status === 423) { const data = res.ok || res.status === 406 ? ((await res.json()) as Granted) : null; if (data && data.score) { mutate(`puzzles/${puzzle?.id}`); } else if (data && data.tries) setGranted(data); else if (res.ok && data?.success) setGranted({ tries: null, score: null, message: 'Réponse correcte' }); else if (res.status === 423) setGranted({ tries: null, score: null, message: 'Réponse incorrecte' }); else if (res.status === 403) mutate(`puzzles/${puzzle?.id}`); } setIsLoading(false); form.reset(); } return (
( Réponse )} /> ( Fichier )} />
{granted && (

{granted.message}

{granted.tries && (

Il vous reste {granted.tries} tentative{granted.tries > 1 ? 's' : ''}

)}
)}
); }