aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/client/db/study-builder.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/db/study-builder.ts')
-rw-r--r--src/client/db/study-builder.ts82
1 files changed, 82 insertions, 0 deletions
diff --git a/src/client/db/study-builder.ts b/src/client/db/study-builder.ts
new file mode 100644
index 0000000..25d1652
--- /dev/null
+++ b/src/client/db/study-builder.ts
@@ -0,0 +1,82 @@
+import type { CardStateType } from "./index";
+import {
+ localCardRepository,
+ localNoteFieldTypeRepository,
+ localNoteFieldValueRepository,
+ localNoteRepository,
+ localNoteTypeRepository,
+} from "./repositories";
+
+export interface StudyCardView {
+ id: string;
+ deckId: string;
+ noteId: string;
+ isReversed: boolean;
+ state: CardStateType;
+ noteType: {
+ frontTemplate: string;
+ backTemplate: string;
+ };
+ fieldValuesMap: Record<string, string>;
+}
+
+/**
+ * Build study card views for all due cards in a deck from IndexedDB.
+ *
+ * Cards whose note or note type has been soft-deleted are skipped, mirroring
+ * the server-side enrichment in `enrichCardsForStudy`.
+ */
+export async function buildStudyCards(
+ deckId: string,
+): Promise<StudyCardView[]> {
+ const dueCards = await localCardRepository.findDueCards(deckId);
+ if (dueCards.length === 0) {
+ return [];
+ }
+
+ const noteTypeFieldsCache = new Map<string, Map<string, string>>();
+ const result: StudyCardView[] = [];
+
+ for (const card of dueCards) {
+ const note = await localNoteRepository.findById(card.noteId);
+ if (!note || note.deletedAt !== null) continue;
+
+ const noteType = await localNoteTypeRepository.findById(note.noteTypeId);
+ if (!noteType || noteType.deletedAt !== null) continue;
+
+ let fieldTypeIdToName = noteTypeFieldsCache.get(noteType.id);
+ if (!fieldTypeIdToName) {
+ const fieldTypes = await localNoteFieldTypeRepository.findByNoteTypeId(
+ noteType.id,
+ );
+ fieldTypeIdToName = new Map(fieldTypes.map((ft) => [ft.id, ft.name]));
+ noteTypeFieldsCache.set(noteType.id, fieldTypeIdToName);
+ }
+
+ const fieldValues = await localNoteFieldValueRepository.findByNoteId(
+ note.id,
+ );
+ const fieldValuesMap: Record<string, string> = {};
+ for (const fv of fieldValues) {
+ const name = fieldTypeIdToName.get(fv.noteFieldTypeId);
+ if (name) {
+ fieldValuesMap[name] = fv.value;
+ }
+ }
+
+ result.push({
+ id: card.id,
+ deckId: card.deckId,
+ noteId: card.noteId,
+ isReversed: card.isReversed,
+ state: card.state,
+ noteType: {
+ frontTemplate: noteType.frontTemplate,
+ backTemplate: noteType.backTemplate,
+ },
+ fieldValuesMap,
+ });
+ }
+
+ return result;
+}