Feature: „Meine Woche" — persönliche 7-Tage-Übersicht

Alle Bausteine waren da (Ampel/Trend, ToDo-Status, Anwesenheit), aber niemand
sah je seinen eigenen Verlauf. Neue Query dayEntry.myWeek + Route /meine-woche
(pro Tag Ampel, Antritt→Feierabend, ToDo-Zähler). Nav-Tab „Woche" + Shortcut g w.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Raffael SheikhandClaude Opus 4.8 committed 2026-06-07 12:39:09 +02:00
1 parent 4311eadf50
commit 7a7cc75dd6
5 files changed
+137 -1

No files matched your search

+39 -1
View File
@@ -1,5 +1,5 @@
import { TRPCError } from '@trpc/server';
import { and, eq, isNull, lt, asc, desc, inArray } from 'drizzle-orm';
import { and, eq, gte, isNull, lt, lte, asc, desc, inArray } from 'drizzle-orm';
import { dayEntry, todo, blocker, user, type Db, type DayEntry, type Todo } from '@cockpit/db';
import { DayEntrySchemas } from '@cockpit/shared';
import { router, protectedProcedure } from '../trpc.js';
@@ -693,6 +693,44 @@ export const dayEntryRouter = router({
.where(eq(dayEntry.date, date));
return rows;
}),
/**
* Persönliche Wochenübersicht: die letzten 7 Kalendertage des eigenen Users —
* pro Tag Status/Ampel/Trend, grobe Anwesenheit (Antritt→Feierabend) und ein
* ToDo-Zähler (erledigt/offen/verworfen). Speist die Route „Meine Woche".
*/
myWeek: protectedProcedure.query(async ({ ctx }) => {
const today = todayIso();
const from = addCalendarDays(today, -6);
const entries = await ctx.db
.select()
.from(dayEntry)
.where(
and(eq(dayEntry.userId, ctx.user.id), gte(dayEntry.date, from), lte(dayEntry.date, today)),
)
.orderBy(asc(dayEntry.date));
const ids = entries.map((e) => e.id);
const todos = ids.length
? await ctx.db.select().from(todo).where(inArray(todo.dayEntryId, ids))
: [];
const counts = new Map<string, { done: number; open: number; dropped: number }>();
for (const t of todos) {
const c = counts.get(t.dayEntryId) ?? { done: 0, open: 0, dropped: 0 };
c[t.status] += 1;
counts.set(t.dayEntryId, c);
}
return entries.map((e) => ({
date: e.date,
status: e.status,
ampel: e.ampel,
trend: e.trend,
checkedInAt: e.checkedInAt,
checkedOutAt: e.checkedOutAt,
todos: counts.get(e.id) ?? { done: 0, open: 0, dropped: 0 },
}));
}),
});
// Helper für Cron-Endpoint