diff --git a/.vscode/settings.json b/.vscode/settings.json index 58ff454..239dab8 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,4 @@ { "typescript.tsdk": "node_modules\\.pnpm\\typescript@4.9.5\\node_modules\\typescript\\lib", "typescript.enablePromptUseWorkspaceTsdk": true -} \ No newline at end of file +} diff --git a/lib/hooks/use-local-storage.ts b/lib/hooks/use-local-storage.ts new file mode 100644 index 0000000..69ddb52 --- /dev/null +++ b/lib/hooks/use-local-storage.ts @@ -0,0 +1,35 @@ +import { useEffect, useState } from 'react'; + +export default function useLocalStorage({ + key, + initialValue, + serialize = JSON.stringify, + deserialize = JSON.parse +}: { + key: string; + initialValue: T; + serialize?: (value: T) => string; + deserialize?: (value: string) => T; +}) { + const [stored, setStored] = useState(() => { + try { + const localStorageValue = window.localStorage.getItem(key); + if (localStorageValue !== null) { + return deserialize(localStorageValue); + } else { + return initialValue; + } + } catch { + return initialValue; + } + }); + useEffect(() => { + try { + const serializedState = serialize(stored); + window.localStorage.setItem(key, serializedState); + } catch { + // Ignore + } + }, [key, serialize, stored]); + return [stored, setStored]; +} diff --git a/lib/puzzles.ts b/lib/puzzles.ts index c96eb73..570162d 100644 --- a/lib/puzzles.ts +++ b/lib/puzzles.ts @@ -2,8 +2,7 @@ export const getChapters = async ({ token }: { token: string }): Promise = (key, { next }) => { const socket = new WebSocket(key); diff --git a/ui/Puzzle.tsx b/ui/Puzzle.tsx index 63f559e..2cfae6e 100644 --- a/ui/Puzzle.tsx +++ b/ui/Puzzle.tsx @@ -1,17 +1,17 @@ 'use client'; import cookies from 'js-cookie'; -import { notFound } from 'next/navigation'; +import { notFound, useRouter } from 'next/navigation'; import { useState } from 'react'; import { useForm } from 'react-hook-form'; import { useSWRConfig } from 'swr'; import { usePuzzle } from '@/lib/hooks/use-puzzles'; -import AppLink from './AppLink'; import Button from './Button'; import Input from './Input'; import ToHTML from './ToHTML'; +import { getURL } from '@/lib/utils'; type PuzzleData = { answer: string; @@ -29,6 +29,7 @@ export default function Puzzle({ token, id }: { token: string; id: number }) { const { data: puzzle, isLoading } = usePuzzle({ token, id }); const { mutate } = useSWRConfig(); + const router = useRouter(); const { register, handleSubmit } = useForm({ defaultValues: { @@ -118,19 +119,21 @@ export default function Puzzle({ token, id }: { token: string; id: number }) { ) : (
-
+

- Tentatives : {puzzle.tries} + Tentative(s) : {puzzle.tries}

Score : {puzzle.score}

- - - +
)}
diff --git a/ui/Puzzles.tsx b/ui/Puzzles.tsx index ff6e033..0b0ee43 100644 --- a/ui/Puzzles.tsx +++ b/ui/Puzzles.tsx @@ -1,7 +1,7 @@ 'use client'; import { useRouter } from 'next/navigation'; -import { useContext, useMemo, useState } from 'react'; +import { type ChangeEvent, useContext, useEffect, useMemo, useState } from 'react'; import { useForm } from 'react-hook-form'; import { useSWRConfig } from 'swr'; @@ -17,6 +17,7 @@ import { useGroups } from '@/lib/hooks/use-groups'; import { usePuzzles } from '@/lib/hooks/use-puzzles'; import type { Chapter, Puzzle } from '@/lib/puzzles'; import { cn } from '@/lib/utils'; +import useLocalStorage from '@/lib/hooks/use-local-storage'; export default function Puzzles({ token }: { token: string }) { const { data: me } = useContext(UserContext); @@ -62,6 +63,16 @@ export default function Puzzles({ token }: { token: string }) { return data?.find((chapter) => chapter.id === filterChapter)?.puzzles; }, [data, filter, filterChapter]); + useEffect(() => { + const { hash } = window.location; + if (hash) { + const element = document.querySelector(hash); + if (element) { + element.scrollIntoView({ behavior: 'smooth' }); + } + } + }, []); + return ( <> {(!isLoading && @@ -283,6 +294,13 @@ function FilterChapter({ setFilter: (filter: string) => void; setFilterChapter: (chapter: number) => void; }) { + const [stored, setStored] = useLocalStorage({ + key: 'puzzles-filter', + initialValue: '' + }); + + console.log(stored); + let options = [] as { title: string; value: string }[]; options = chapters @@ -294,21 +312,28 @@ function FilterChapter({ return { title: t!.name, value: t!.name }; }) as { title: string; value: string }[]; - - options?.unshift({ title: 'Pas encore terminé', value: 'no-completed' }); + options?.unshift({ title: 'Pas encore terminé', value: 'no-completed' }); options?.unshift({ title: 'Terminés', value: 'completed' }); options?.unshift({ title: 'Tout les puzzles', value: '' }); setFilterChapter(chapter.id); - return ( - ; } type GroupData = { diff --git a/ui/Select.tsx b/ui/Select.tsx index c2af9eb..d27a0fa 100644 --- a/ui/Select.tsx +++ b/ui/Select.tsx @@ -22,7 +22,7 @@ const Select = forwardRef< ref={ref} > {options.map((option) => ( - ))} diff --git a/ui/Tips.tsx b/ui/Tips.tsx index 5642f1a..9171eef 100644 --- a/ui/Tips.tsx +++ b/ui/Tips.tsx @@ -17,7 +17,7 @@ export default function Tips({ className, kind = 'info', text }: TipsProps) { className })} > -

{text}

+

{text}

); }