Baustein 3: Wochenplan als Startseite, Fortschritt, Wochen verschieben

- Wochenplan ist die Startseite des Azubis: Thema, Leitfrage, fuenf Tage
  mit Theorie und Praxis, Fortschrittsbalken, was noch offen ist
- Ausbilder sieht je Azubi die laufende Woche mit Stand und offenen Punkten
- /woche/<nr> fuer jede Woche, Ausbilder waehlt ueber ?azubi= den Stand;
  Zugriff wird serverseitig bei jedem Aufruf geprueft
- Tabelle wochenplanung mit geplantem und tatsaechlichem Datum, Zustand
  und Notiz fuer den Azubi
- Verschieben per Datumsfeld, wahlweise mit allen folgenden Wochen
- Reihenfolge per Ziehen und Ablegen sowie per Tastatur (Alt + Pfeil)
- Warnung bei sich ueberlappenden Terminen
- Plan entsteht automatisch beim Anlegen eines Azubikontos
- Planungs- und Fortschrittslogik als reine Funktionen, 36 Tests dafuer
- Insgesamt 104 Tests

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Florian Wilde
2026-09-10 09:04:39 +02:00
co-authored by Claude Opus 5
parent 1af5613e9b
commit 103a603eb4
29 changed files with 2158 additions and 47 deletions
+28 -1
View File
@@ -63,10 +63,37 @@ export const handoutGelesen = sqliteTable(
(t) => [primaryKey({ columns: [t.benutzerId, t.handoutId] }), index('handout_gelesen_benutzer_idx').on(t.benutzerId)],
);
/** Zustände einer eingeplanten Woche – als Aufzählung, nicht als freier Text. */
export const wochenStatus = ['geplant', 'laufend', 'abgeschlossen'] as const;
export type WochenStatus = (typeof wochenStatus)[number];
export const wochenplanung = sqliteTable(
'wochenplanung',
{
id: text('id').primaryKey(),
ausbildungId: text('ausbildung_id')
.notNull()
.references(() => ausbildung.id, { onDelete: 'cascade' }),
wochenNummer: integer('wochen_nummer').notNull(),
geplantVon: text('geplant_von').notNull(),
geplantBis: text('geplant_bis').notNull(),
tatsaechlichVon: text('tatsaechlich_von'),
status: text('status', { enum: wochenStatus }).notNull().default('geplant'),
notiz: text('notiz'),
geaendertAm: text('geaendert_am').notNull(),
},
(t) => [
uniqueIndex('wochenplanung_woche_idx').on(t.ausbildungId, t.wochenNummer),
index('wochenplanung_termin_idx').on(t.ausbildungId, t.geplantVon),
index('wochenplanung_status_idx').on(t.ausbildungId, t.status),
],
);
export type Benutzer = typeof benutzer.$inferSelect;
export type Sitzung = typeof sitzung.$inferSelect;
export type Ausbildung = typeof ausbildung.$inferSelect;
export type HandoutGelesen = typeof handoutGelesen.$inferSelect;
export type Wochenplanung = typeof wochenplanung.$inferSelect;
/** Wird von der Schema-Abgleichprüfung im Test verwendet. */
export const alleTabellen = { benutzer, sitzung, ausbildung, handoutGelesen };
export const alleTabellen = { benutzer, sitzung, ausbildung, handoutGelesen, wochenplanung };