diff options
| author | nsfisis <54318333+nsfisis@users.noreply.github.com> | 2026-02-08 21:24:08 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-02-08 21:24:08 +0900 |
| commit | c0d092b3bfef491d9aa02a4e7e8f503ea35e6420 (patch) | |
| tree | ac2e447cc7a2e568187a414c241258adf009c1d5 /src/client | |
| parent | 5e7c3ad7ed8c287b538de97d4de3a4df87e9a100 (diff) | |
| parent | 6d53e63d9f3fd81125d0f61e9701ecd262318875 (diff) | |
| download | kioku-c0d092b3bfef491d9aa02a4e7e8f503ea35e6420.tar.gz kioku-c0d092b3bfef491d9aa02a4e7e8f503ea35e6420.tar.zst kioku-c0d092b3bfef491d9aa02a4e7e8f503ea35e6420.zip | |
Merge pull request #13 from nsfisis/claude/clarify-deck-numbers-mg3d4
Simplify deck stats to show due card count from server
Diffstat (limited to 'src/client')
| -rw-r--r-- | src/client/pages/DeckDetailPage.test.tsx | 29 | ||||
| -rw-r--r-- | src/client/pages/DeckDetailPage.tsx | 52 |
2 files changed, 12 insertions, 69 deletions
diff --git a/src/client/pages/DeckDetailPage.test.tsx b/src/client/pages/DeckDetailPage.test.tsx index 815dff1..3c741ad 100644 --- a/src/client/pages/DeckDetailPage.test.tsx +++ b/src/client/pages/DeckDetailPage.test.tsx @@ -258,33 +258,16 @@ describe("DeckDetailPage", () => { ); }); - it("displays card counts by state", () => { + it("displays due card count from deck data", () => { renderWithProviders({ - initialDeck: mockDeck, + initialDeck: { ...mockDeck, dueCardCount: 5 }, initialCards: mockCards, }); - // New cards (state=0, but card-1 is not due yet, so 0) - const newLabel = screen.getByText("New"); - expect(newLabel).toBeDefined(); - const newContainer = newLabel.parentElement; - expect(newContainer?.querySelector(".text-info")?.textContent).toBe("0"); - - // Learning cards (state=1 or 3, none in mockCards) - const learningLabel = screen.getByText("Learning"); - expect(learningLabel).toBeDefined(); - const learningContainer = learningLabel.parentElement; - expect(learningContainer?.querySelector(".text-warning")?.textContent).toBe( - "0", - ); - - // Review cards (state=2, card-2 is due now) - const reviewLabel = screen.getByText("Review"); - expect(reviewLabel).toBeDefined(); - const reviewContainer = reviewLabel.parentElement; - expect(reviewContainer?.querySelector(".text-success")?.textContent).toBe( - "1", - ); + const dueLabel = screen.getByText("Due"); + expect(dueLabel).toBeDefined(); + const dueContainer = dueLabel.parentElement; + expect(dueContainer?.querySelector(".text-primary")?.textContent).toBe("5"); }); it("does not display card list (cards are hidden)", () => { diff --git a/src/client/pages/DeckDetailPage.tsx b/src/client/pages/DeckDetailPage.tsx index 6bc89ba..d717d60 100644 --- a/src/client/pages/DeckDetailPage.tsx +++ b/src/client/pages/DeckDetailPage.tsx @@ -7,7 +7,6 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { useAtomValue } from "jotai"; import { Suspense } from "react"; import { Link, useParams } from "wouter"; -import { getEndOfStudyDayBoundary } from "../../shared/date"; import { cardsByDeckAtomFamily, deckByIdAtomFamily } from "../atoms"; import { ErrorBoundary } from "../components/ErrorBoundary"; import { LoadingSpinner } from "../components/LoadingSpinner"; @@ -25,52 +24,21 @@ function DeckHeader({ deckId }: { deckId: string }) { ); } -// CardState values from FSRS -const CardState = { - New: 0, - Learning: 1, - Review: 2, - Relearning: 3, -} as const; - function DeckStats({ deckId }: { deckId: string }) { + const { data: deck } = useAtomValue(deckByIdAtomFamily(deckId)); const { data: cards } = useAtomValue(cardsByDeckAtomFamily(deckId)); - // Count cards due today (study day boundary is 3:00 AM) - const boundary = getEndOfStudyDayBoundary(); - const dueCards = cards.filter((card) => new Date(card.due) < boundary); - - // Count by card state - const newCards = dueCards.filter((card) => card.state === CardState.New); - const learningCards = dueCards.filter( - (card) => - card.state === CardState.Learning || card.state === CardState.Relearning, - ); - const reviewCards = dueCards.filter( - (card) => card.state === CardState.Review, - ); - return ( <div className="bg-white rounded-xl border border-border/50 p-6 mb-6"> - <div className="grid grid-cols-4 gap-4"> + <div className="grid grid-cols-2 gap-4"> <div> <p className="text-sm text-muted mb-1">Total</p> <p className="text-2xl font-semibold text-ink">{cards.length}</p> </div> <div> - <p className="text-sm text-muted mb-1">New</p> - <p className="text-2xl font-semibold text-info">{newCards.length}</p> - </div> - <div> - <p className="text-sm text-muted mb-1">Learning</p> - <p className="text-2xl font-semibold text-warning"> - {learningCards.length} - </p> - </div> - <div> - <p className="text-sm text-muted mb-1">Review</p> - <p className="text-2xl font-semibold text-success"> - {reviewCards.length} + <p className="text-sm text-muted mb-1">Due</p> + <p className="text-2xl font-semibold text-primary"> + {deck.dueCardCount} </p> </div> </div> @@ -100,7 +68,7 @@ function DeckContent({ deckId }: { deckId: string }) { <Suspense fallback={ <div className="bg-white rounded-xl border border-border/50 p-6 mb-6"> - <div className="grid grid-cols-4 gap-4"> + <div className="grid grid-cols-2 gap-4"> <div> <div className="h-4 w-12 bg-muted/20 rounded animate-pulse mb-1" /> <div className="h-8 w-10 bg-muted/20 rounded animate-pulse" /> @@ -109,14 +77,6 @@ function DeckContent({ deckId }: { deckId: string }) { <div className="h-4 w-12 bg-muted/20 rounded animate-pulse mb-1" /> <div className="h-8 w-10 bg-muted/20 rounded animate-pulse" /> </div> - <div> - <div className="h-4 w-16 bg-muted/20 rounded animate-pulse mb-1" /> - <div className="h-8 w-10 bg-muted/20 rounded animate-pulse" /> - </div> - <div> - <div className="h-4 w-14 bg-muted/20 rounded animate-pulse mb-1" /> - <div className="h-8 w-10 bg-muted/20 rounded animate-pulse" /> - </div> </div> </div> } |
