aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/client/atoms/cards.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/atoms/cards.ts')
-rw-r--r--src/client/atoms/cards.ts51
1 files changed, 42 insertions, 9 deletions
diff --git a/src/client/atoms/cards.ts b/src/client/atoms/cards.ts
index 4a6e72e..7771cdb 100644
--- a/src/client/atoms/cards.ts
+++ b/src/client/atoms/cards.ts
@@ -1,7 +1,8 @@
import { atomFamily } from "jotai-family";
import { atomWithSuspenseQuery } from "jotai-tanstack-query";
-import { apiClient } from "../api/client";
-import type { CardStateType } from "../db";
+import type { CardStateType, LocalCard } from "../db";
+import { localCardRepository } from "../db/repositories";
+import { ensureBootstrap } from "./sync";
export interface Card {
id: string;
@@ -25,19 +26,51 @@ export interface Card {
syncVersion: number;
}
+function localCardToView(card: LocalCard): Card {
+ return {
+ id: card.id,
+ deckId: card.deckId,
+ noteId: card.noteId,
+ isReversed: card.isReversed,
+ front: card.front,
+ back: card.back,
+ state: card.state,
+ due: card.due.toISOString(),
+ stability: card.stability,
+ difficulty: card.difficulty,
+ elapsedDays: card.elapsedDays,
+ scheduledDays: card.scheduledDays,
+ reps: card.reps,
+ lapses: card.lapses,
+ lastReview: card.lastReview ? card.lastReview.toISOString() : null,
+ createdAt: card.createdAt.toISOString(),
+ updatedAt: card.updatedAt.toISOString(),
+ deletedAt: card.deletedAt ? card.deletedAt.toISOString() : null,
+ syncVersion: card.syncVersion,
+ };
+}
+
+async function loadCardsByDeck(deckId: string): Promise<Card[]> {
+ const cards = await localCardRepository.findByDeckId(deckId);
+ cards.sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime());
+ return cards.map(localCardToView);
+}
+
// =====================
-// Cards by Deck - Suspense-compatible
+// Cards by Deck - Suspense-compatible, IndexedDB-first
// =====================
export const cardsByDeckAtomFamily = atomFamily((deckId: string) =>
atomWithSuspenseQuery(() => ({
queryKey: ["decks", deckId, "cards"],
- queryFn: async () => {
- const res = await apiClient.rpc.api.decks[":deckId"].cards.$get({
- param: { deckId },
- });
- const data = await apiClient.handleResponse<{ cards: Card[] }>(res);
- return data.cards;
+ queryFn: async (): Promise<Card[]> => {
+ const cards = await loadCardsByDeck(deckId);
+ if (cards.length > 0) {
+ ensureBootstrap();
+ return cards;
+ }
+ await ensureBootstrap();
+ return loadCardsByDeck(deckId);
},
})),
);