diff --git a/src/components/common/ConfirmModal.tsx b/src/components/common/ConfirmModal.tsx index dc6e97ea..8f6c9e9c 100644 --- a/src/components/common/ConfirmModal.tsx +++ b/src/components/common/ConfirmModal.tsx @@ -6,12 +6,14 @@ function ConfirmModal({ opened, onClose, onConfirm, + confirmLabel, }: { title: string; description: string; opened: boolean; onClose: () => void; onConfirm: () => void; + confirmLabel?: string; }) { return ( @@ -29,7 +31,7 @@ function ConfirmModal({ Cancel diff --git a/src/components/panels/database/DatabasePanel.tsx b/src/components/panels/database/DatabasePanel.tsx index 2ba9417d..b187c401 100644 --- a/src/components/panels/database/DatabasePanel.tsx +++ b/src/components/panels/database/DatabasePanel.tsx @@ -98,7 +98,6 @@ function DatabasePanel({ height, fen }: { height: number; fen: string }) { isLoading, error, } = useSWR([dbType, query], async ([dbType, query]) => { - console.log("fetching opening", query); return fetchOpening(query, dbType); }); diff --git a/src/components/panels/info/PracticePanel.tsx b/src/components/panels/info/PracticePanel.tsx index 2463942f..fd470952 100644 --- a/src/components/panels/info/PracticePanel.tsx +++ b/src/components/panels/info/PracticePanel.tsx @@ -4,11 +4,16 @@ import { currentTabAtom, deckAtomFamily, } from "@/atoms/atoms"; +import ConfirmModal from "@/components/common/ConfirmModal"; import { TreeDispatchContext, TreeStateContext, } from "@/components/common/TreeStateContext"; -import { getCardForReview, getStats } from "@/components/files/opening"; +import { + buildFromTree, + getCardForReview, + getStats, +} from "@/components/files/opening"; import { Text, ActionIcon, @@ -17,8 +22,9 @@ import { Button, RingProgress, } from "@mantine/core"; +import { useToggle } from "@mantine/hooks"; import { IconX } from "@tabler/icons-react"; -import { useAtomValue, useSetAtom } from "jotai"; +import { useAtom, useAtomValue, useSetAtom } from "jotai"; import { useContext } from "react"; import { match } from "ts-pattern"; @@ -26,9 +32,15 @@ function PracticePanel() { const dispatch = useContext(TreeDispatchContext); const { root, headers } = useContext(TreeStateContext); const currentTab = useAtomValue(currentTabAtom); + const [resetModal, toggleResetModal] = useToggle(); - const deck = useAtomValue( - deckAtomFamily({ id: currentTab?.file?.name || "", root, headers, game: currentTab?.gameNumber || 0 }), + const [deck, setDeck] = useAtom( + deckAtomFamily({ + id: currentTab?.file?.name || "", + root, + headers, + game: currentTab?.gameNumber || 0, + }) ); const stats = getStats(deck); @@ -51,65 +63,94 @@ function PracticePanel() { } return ( - - - Practicing - { setPracticing(false); setInvisible(false) }}> - - - - - - {Math.round((stats.mastered / stats.total) * 100)}% mastered - - } - sections={[ - { - value: (stats.mastered / stats.total) * 100, - color: "blue", - tooltip: `${stats.mastered} mastered`, - }, - { - value: (stats.reviewing / stats.total) * 100, - color: "red", - tooltip: `${stats.reviewing} reviewing`, - }, - { - value: (stats.learning / stats.total) * 100, - color: "cyan", - tooltip: `${stats.learning} learning`, - }, - { - value: (stats.unseen / stats.total) * 100, - color: "gray", - tooltip: `${stats.unseen} unseen`, - }, - ]} - /> - {stats.due === 0 &&

You have practiced all positions. Well done!

} -
+ <> + + + Practicing + { + setPracticing(false); + setInvisible(false); + }} + > + + + + + + {Math.round((stats.mastered / stats.total) * 100)}% mastered + + } + sections={[ + { + value: (stats.mastered / stats.total) * 100, + color: "blue", + tooltip: `${stats.mastered} mastered`, + }, + { + value: (stats.reviewing / stats.total) * 100, + color: "red", + tooltip: `${stats.reviewing} reviewing`, + }, + { + value: (stats.learning / stats.total) * 100, + color: "cyan", + tooltip: `${stats.learning} learning`, + }, + { + value: (stats.unseen / stats.total) * 100, + color: "gray", + tooltip: `${stats.unseen} unseen`, + }, + ]} + /> + {stats.due === 0 && ( +

You have practiced all positions. Well done!

+ )} +
- - - - - -
+ + + + + + +
+ { + const cards = buildFromTree( + root, + headers.orientation || "white", + headers.start || [] + ); + setDeck(cards); + toggleResetModal(); + }} + confirmLabel="Reset" + /> + ); } diff --git a/src/components/panels/info/RepertoireInfo.tsx b/src/components/panels/info/RepertoireInfo.tsx index bddd1e3b..f3c85c72 100644 --- a/src/components/panels/info/RepertoireInfo.tsx +++ b/src/components/panels/info/RepertoireInfo.tsx @@ -87,6 +87,7 @@ function RepertoireInfo() { {!loading && !missingMoves && ( - )} @@ -176,7 +177,12 @@ function MissingMoves({ noRecordsText="No games found" /> - diff --git a/src/utils/treeReducer.ts b/src/utils/treeReducer.ts index 0f354ff0..1e571012 100644 --- a/src/utils/treeReducer.ts +++ b/src/utils/treeReducer.ts @@ -218,7 +218,6 @@ const treeReducer = (state: TreeState, action: TreeAction) => { state.headers.start = payload; }) .with({ type: "MAKE_MOVE" }, ({ payload }) => { - state.dirty = true; makeMove(state, payload); }) .with({ type: "MAKE_MOVES" }, ({ payload }) => { @@ -322,6 +321,7 @@ function makeMove( if (i !== -1) { state.position.push(i); } else { + state.dirty = true; const newMoveNode = createNode({ fen: chess.fen(), move: m,