Arbeitstag-Grenze auf 6 Uhr + Feierabend reversibel

Nachtarbeit über Mitternacht brach bisher den Check-Out ("Du bist heute
noch nicht locked in") und sperrte nach versehentlichem Feierabend den Tag.

- Tag = Kalendertag des Check-ins; eine über Mitternacht laufende Session
  zaehlt zum Starttag, bis 06:00 des Folgetags (isWorkdaySealed)
- checkOut/today finden den offenen Eintrag statt stur "heute"
- reopen ("Arbeit fortsetzen") hebt einen Feierabend wieder auf
- applyWorkdayBoundary: nahtloser 6-Uhr-Schnitt (Auto-Checkout + Folge-Tag,
  offene ToDos wandern mit)
- Reflexion/ToDo-Edit folgen der 6-Uhr-Grenze statt Mitternacht
- Cron apply-workday-boundaries fuer Team-Dashboard-Konsistenz

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 10:48:23 +02:00
1 parent b39c67d1aa
commit 39e259f3ac
5 files changed
+308 -49

No files matched your search

+23 -4
View File
@@ -332,6 +332,14 @@ function CheckInOutBar({
await utils.dashboard.overview.invalidate();
},
});
const reopen = trpc.dayEntry.reopen.useMutation({
onSuccess: async () => {
toast('Willkommen zurück — Arbeit fortgesetzt.');
await utils.dayEntry.today.invalidate();
await utils.dashboard.overview.invalidate();
},
onError: (err) => toast(err.message),
});
const hhmm = (d: string | Date | null) =>
d
? new Intl.DateTimeFormat('de-DE', {
@@ -353,10 +361,21 @@ function CheckInOutBar({
Arbeitsantritt <span className="font-mono">{hhmm(checkedInAt)}</span>
</span>
{checkedOutAt ? (
<span className="text-[var(--color-ink-muted)]">
· Feierabend <span className="font-mono">{hhmm(checkedOutAt)}</span>
{duration && ` · ${duration}`}
</span>
<>
<span className="text-[var(--color-ink-muted)]">
· Feierabend <span className="font-mono">{hhmm(checkedOutAt)}</span>
{duration && ` · ${duration}`}
</span>
<Button
size="sm"
variant="ghost"
className="ml-auto"
disabled={reopen.isPending}
onClick={() => reopen.mutate()}
>
<Play size={14} /> Arbeit fortsetzen
</Button>
</>
) : (
<Button
size="sm"