1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
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;
}
|