Die fachlichen Inhalte liegen als Dateien unter content/ und werden beim Start eingelesen, geprueft und in den Speicher geladen. - Inhaltslader mit Zod-Schemata und Querverweispruefung - Fehlermeldungen nennen Datei und Zeile, gesammelt statt beim ersten Fehler geworfen; die Anwendung startet bei Fehlern nicht - npm run inhalte:pruefen prueft ohne Start - Handout-Ansicht mit festem Aufbau, Uebersicht nach Themenbloecken - Volltextsuche mit Gewichtung und Trefferausschnitt - Gelesen-Markierung je Handout - Glossar mit Suche und automatischer Verlinkung in den Handouts - Beispielinhalte: 4 Wochen, 12 Handouts, 24 Merkkarten, 4 Aufgaben, 4 Checklisten, 2 Lernzielkontrollen, 24 Glossareintraege - rahmenplan.yaml aus FIAusbV 2020 und KMK-Rahmenlehrplan, mit Fundstellen - gray-matter entfernt, YAML-Kopf wird selbst herausgeloest - npm run screenshots nimmt die Bilder fuer die Anleitung auf - 39 neue Tests, insgesamt 68 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
44 lines
1.5 KiB
TypeScript
44 lines
1.5 KiB
TypeScript
import { and, eq } from 'drizzle-orm';
|
||
import { datenbank, schema } from '../db';
|
||
import { jetzt } from '../zeit';
|
||
|
||
/** Fortschritt beim Lesen der Handouts. */
|
||
|
||
export function gelesenSet(benutzerId: string): Set<string> {
|
||
const zeilen = datenbank()
|
||
.select({ handoutId: schema.handoutGelesen.handoutId })
|
||
.from(schema.handoutGelesen)
|
||
.where(eq(schema.handoutGelesen.benutzerId, benutzerId))
|
||
.all();
|
||
return new Set(zeilen.map((z) => z.handoutId));
|
||
}
|
||
|
||
export function gelesenAm(benutzerId: string, handoutId: string): string | null {
|
||
const zeile = datenbank()
|
||
.select({ gelesenAm: schema.handoutGelesen.gelesenAm })
|
||
.from(schema.handoutGelesen)
|
||
.where(and(eq(schema.handoutGelesen.benutzerId, benutzerId), eq(schema.handoutGelesen.handoutId, handoutId)))
|
||
.get();
|
||
return zeile?.gelesenAm ?? null;
|
||
}
|
||
|
||
export function alsGelesenMerken(benutzerId: string, handoutId: string): void {
|
||
datenbank()
|
||
.insert(schema.handoutGelesen)
|
||
.values({ benutzerId, handoutId, gelesenAm: jetzt() })
|
||
.onConflictDoNothing()
|
||
.run();
|
||
}
|
||
|
||
export function alsUngelesenMerken(benutzerId: string, handoutId: string): void {
|
||
datenbank()
|
||
.delete(schema.handoutGelesen)
|
||
.where(and(eq(schema.handoutGelesen.benutzerId, benutzerId), eq(schema.handoutGelesen.handoutId, handoutId)))
|
||
.run();
|
||
}
|
||
|
||
/** Anzahl gelesener Handouts – für die Fortschrittsanzeige. */
|
||
export function anzahlGelesen(benutzerId: string): number {
|
||
return gelesenSet(benutzerId).size;
|
||
}
|