Commit Graph
54 Commits
Author SHA1 Message Date
Raffael SheikhandClaude Opus 4.8 2eef94afce chore(format): Prettier auf time.ts anwenden
Alt-Bestand nie formatiert — isolierter Format-Lauf vor der byProject-Query.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 12:14:31 +02:00
Raffael SheikhandClaude Opus 4.8 c98d27e70c api: Audit-Log verdrahtet (auditedProcedure an kritische Mutationen)
withAudit war als tRPC-Wrapper definiert, aber an keine Procedure gehaengt
(audit_event blieb leer). Jetzt eine echte tRPC-v11-Middleware-Procedure
(auditedProcedure), die nach erfolgreicher Mutation best-effort einen
audit_event schreibt (Fehler beim Audit kippen die Mutation nicht).

Verdrahtet an die folgenreichen Zustandsuebergaenge:
- blocker.resolve
- project.archive, project.setPhase, project.addPhaseGate

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 12:06:13 +02:00
Raffael SheikhandClaude Opus 4.8 6e7f639013 chore(format): Prettier auf project.ts anwenden
Alt-Bestand nie formatiert — isolierter Format-Lauf vor der Audit-Verdrahtung.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 12:05:26 +02:00
Raffael SheikhandClaude Opus 4.8 9bae1702aa db: Foreign Keys für blocker- und Tageseintrag-Verweise (Migration 0017)
Bisher reine uuid-Spalten ohne referenzielle Integritaet -> Orphan-Risiko, wenn
das Ziel geloescht wird. Jetzt echte FKs mit ON DELETE SET NULL:

- day_entry.blocker_id -> blocker
- blocker.area_id -> area
- blocker.project_id -> project

Migration bereinigt vorab verwaiste IDs (UPDATE ... SET NULL), damit ADD
CONSTRAINT auf Altdaten nicht bricht. Verifiziert: alle 18 Migrationen laufen
gegen frische Postgres 16 durch, FKs angelegt.

(todo.bezug_id / time_entry.bezug_id bleiben FK-frei: echt polymorph ueber
bezug_kind project/deal/campaign — kein einzelner FK moeglich.)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 12:01:24 +02:00
Raffael SheikhandClaude Opus 4.8 ff0a15b94e UI: Touch-Sichtbarkeit der Hover-Aktionen
Edit/Delete/Start/Zeit-Buttons waren nur per group-hover sichtbar (opacity-0)
und damit auf Touch-Geraeten unerreichbar. Jetzt mobil dauerhaft sichtbar, ab
sm (Desktop) weiterhin Hover-Reveal.

- TimelineSection (Bearbeiten/Loeschen einer Zeit-Zeile)
- heute (Task starten/fortsetzen, Zeit nachtragen)
- reflexion (ToDo-Titel bearbeiten)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 11:50:54 +02:00
Raffael SheikhandClaude Opus 4.8 f600c9f187 UI: alle 8 Dialoge auf barrierearme Modal-Basis umgestellt
Bisher waren alle Overlay-Dialoge plain divs ohne role/Fokus-Trap/Escape.
Jetzt setzen sie auf <Modal> auf (role=dialog, aria-modal, Fokus-Trap +
-Rueckgabe, Escape, Body-Scroll-Lock, konsistenter X-Button, Scroll bei langem
Inhalt).

- Modal: X-Schliessen-Button + max-h-[90vh]/overflow-y-auto ergaenzt
- BlockerDialog, ManualDialog (Timeline)
- leads: CSV-Import + Neuer Lead
- bereich: Neues Projekt
- projekt: Gate-Review + Projekt abschliessen
- lead: Zu Deal machen

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 11:49:05 +02:00
Raffael SheikhandClaude Opus 4.8 30006e3b32 chore(format): Prettier auf B4-Zieldateien anwenden
Vorbereitung der Modal-Umstellung: TimelineSection/leads/bereich (Alt-Bestand
nie formatiert) + kleiner B3-Nachzug in projekt/lead. Reine Formatierung, damit
die folgenden Modal-Commits nur echte Aenderungen zeigen.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 11:38:40 +02:00
Raffael SheikhandClaude Opus 4.8 8b0df9cc4e UI: Fehler-States statt weißer Leerseiten bei Query-Fehlern
Dashboard/Projekt/Lead/Team/Historie rendern bei fehlgeschlagener Query nicht
mehr ein stilles `return null` (leere weisse Seite), sondern einen Hinweis mit
"Neu laden"-Button.

- Neue Komponente ErrorState (Meldung + optionaler Retry)
- 5 Routen: if (q.isError || !q.data) -> ErrorState mit q.refetch()

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 11:35:52 +02:00
Raffael SheikhandClaude Opus 4.8 90caa282ee UI: Bestätigungsdialog vor allen Löschungen (Projekt + Lead)
Bisher loeschten 8 Muelltonnen-Icons sofort und unwiderruflich, ganz ohne
Rueckfrage. Jetzt fragt jeder Loeschpfad ueber useConfirm() nach.

- projekt.tsx: Aenderung, Stakeholder, Risiko, Meilenstein
- lead.tsx: Kontakt, Touchpoint, offene Frage, Anhang

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 11:28:48 +02:00
Raffael SheikhandClaude Opus 4.8 33a740ca7e chore(format): Prettier auf heute/projekt/lead.tsx anwenden
Diese drei Dateien waren nicht prettier-konform (nie formatiert). Isolierter
Format-Lauf, damit der folgende Logik-Commit nur die echten Aenderungen zeigt.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 11:28:19 +02:00
Raffael SheikhandClaude Opus 4.8 00b611fa3b UI: Modal-Basis + Confirm-Infrastruktur + Feierabend-Tagesabschluss
Fundament für Paket B (UI/UX-Härtung):
- Modal: barrierearmer Basis-Dialog (role/aria-modal, Fokus-Trap, Escape,
  Fokus-Rückgabe, Body-Scroll-Lock, Portal). Basis für alle App-Dialoge.
- ConfirmProvider/useConfirm: imperative Bestaetigung (await confirm({...}))
  statt window.confirm(); wird als Naechstes an die Loeschpfade gehaengt.
- Feierabend-Dialog: Tagesabschluss mit Zusammenfassung (erledigt/offen/
  verworfen) + Hinweis auf offene/unreflektierte ToDos und fehlende Reflexion.
  Check-Out feuert erst nach Bestaetigung; bleibt reversibel.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 11:19:40 +02:00
Raffael SheikhandClaude Opus 4.8 7285ed9cae Backup-Sidecar: täglicher pg_dump scharf geschaltet
Das dokumentierte Backup lief real nie (stock postgres-Image ohne Cron,
backup.sh nirgends eingebunden) -> bei Volume-/Disk-Verlust drohte Totalverlust.

- Neuer service "backup" (docker-compose.yml): postgres:16-alpine als Sidecar,
  taeglicher pg_dump um BACKUP_HOUR (Default 03:00 Europe/Berlin)
- backup-loop.sh: abhaengigkeitsfreier Tages-Scheduler (umgeht busybox-cron-
  Environment-Eigenheiten)
- backup.sh korrigiert: laeuft remote gegen PGHOST mit PGPASSWORD; -Fc statt
  "-Fc | gzip" (war doppelt komprimiert und als .sql.gz nicht restore-bar) -> .dump
- BACKUP_HOUR/BACKUP_RETENTION_DAYS konfigurierbar (.env.example)
- operations.md: Backup-/Restore-Anleitung an Ist-Zustand angepasst

Verifiziert: pg_dump erstellt + pg_restore in frische DB, Daten intakt.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 11:09:38 +02:00
Raffael SheikhandClaude Opus 4.8 39e259f3ac 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>
2026-06-07 10:48:23 +02:00
dejanandClaude Opus 4.8 b39c67d1aa Zeit-heute-Liste aufsteigend sortieren (Vormittag → Abend)
ci / quality (push) Failing after 34s
ci / build (push) Has been skipped
deploy / deploy (push) Successful in 46s
Blöcke werden jetzt nach Startzeit aufsteigend angezeigt statt neueste
zuerst.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 21:08:35 +02:00
dejanandClaude Opus 4.8 3e61cd563d Status-Anzeige robust gegen leere/lahmende Verlauf-Query
ci / quality (push) Failing after 43s
ci / build (push) Has been skipped
deploy / deploy (push) Successful in 46s
Der aktuelle Projektstatus hing allein an der statusHistory-Query. Kam
die beim Laden mal leer oder fehlerhaft zurück, stand fälschlich "Noch
kein Status gesetzt", obwohl der statusCache (aus demselben byId-Load)
den Status hatte. Jetzt: Verlauf vorhanden -> volle Anzeige; sonst
Fallback auf statusCache-Badge; "Noch kein Status" nur wenn die Query
erfolgreich leer ist. Zusätzlich Lade-/Fehlerzustand.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 21:00:53 +02:00
dejanandClaude Opus 4.8 8b49641c3f Reflexionsfeld "Sonst noch was?" in "Fazit" umbenennen
ci / quality (push) Failing after 39s
ci / build (push) Has been skipped
deploy / deploy (push) Successful in 45s
Label + Platzhalter angepasst: jeder fasst im Fazit zusammen, was er
gemacht hat. Damit ergibt auch der Text in "Gestern im Team" Sinn.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 20:54:13 +02:00
dejanandClaude Opus 4.8 ba8e524261 Deadline nachträglich editierbar, Arbeitsmodus aus UI entfernen
ci / quality (push) Failing after 28s
ci / build (push) Has been skipped
deploy / deploy (push) Successful in 53s
Deadline lässt sich jetzt direkt im Projekt-Header bearbeiten (Inline-
Datepicker mit Freitag/Wochenende-Warnung), via project.update. Der
Arbeitsmodus (Kanban/Cycle) ist in ebw bedeutungslos und fliegt aus der
Projekterstellung und der Header-Zeile raus. DB-Spalte bleibt ungenutzt
bestehen (keine destruktive Migration nötig).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 20:52:16 +02:00
dejanandClaude Opus 4.8 684841ffb4 Projektlogo auch in Dashboard-Listen anzeigen
ci / quality (push) Failing after 43s
ci / build (push) Has been skipped
deploy / deploy (push) Successful in 53s
Logo erscheint jetzt zusätzlich bei "Anstehende Meilensteine" (neben dem
Projekt-Link) und bei "Pflicht-Minimum offen" (vor dem Namen). Dashboard-
Queries liefern dafür project.logoUrl mit.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 20:47:58 +02:00
dejanandClaude Opus 4.8 1206dc5e0f Projektlogo: quadratisches Logo hochladen & anzeigen
ci / quality (push) Failing after 42s
ci / build (push) Has been skipped
deploy / deploy (push) Successful in 53s
Logo kann bei der Projekterstellung und nachträglich im Projekt-Header
hochgeladen werden. Client-seitiger Center-Crop auf 256px WebP, gespeichert
als Data-URL in neuer Spalte project.logo_url (Migration 0016). Anzeige in
der Bereichs-Projektliste (Card) und im Detail-Header, mit Initialen-
Platzhalter wenn kein Logo gesetzt ist.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 20:44:58 +02:00
dejanandClaude Opus 4.8 45a87711fb Gestern im Team: pro User nur die neueste Reflexion
ci / quality (push) Failing after 42s
ci / build (push) Has been skipped
deploy / deploy (push) Successful in 52s
Im Dashboard-Feed wird je User nur noch die aktuellste Reflexion als
eine Card gezeigt (Dedup über userId, feedRows ist bereits nach Datum
absteigend sortiert). Ältere Einträge sieht man weiterhin unter
"Ganze Historie". Angezeigter Text ist der Freitext "Sonst noch was?"
(reflectionText).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 20:38:09 +02:00
dejanandClaude Opus 4.8 77cb36cd72 Bereichs-Karten aus dem Dashboard entfernen
ci / quality (push) Failing after 34s
ci / build (push) Has been skipped
deploy / deploy (push) Successful in 45s
Die Bereiche (Entwicklung/Vertrieb/Marketing/Allgemein) raus aus dem
Dashboard. AmpelDot + Ampel-Typ wurden dadurch ungenutzt, ebenfalls
entfernt.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 20:32:31 +02:00
dejanandClaude Opus 4.8 1b186d8be6 Anstehende Meilensteine im Dashboard anzeigen
ci / quality (push) Failing after 38s
ci / build (push) Has been skipped
deploy / deploy (push) Successful in 52s
Projektübergreifende Liste offener/überfälliger Meilensteine mit Datum,
sortiert nach Fälligkeit. Überfällige rot markiert, relative Tagesangabe
("in 3 Tagen" / "überfällig"), direkt verlinkt aufs Projekt. Sitzt oben
zwischen Showstoppern und kritischen Modi.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 20:29:16 +02:00
dejanandClaude Opus 4.8 e46d107b2d Verlinkungen im Projekt-Detail editierbar machen
ci / quality (push) Failing after 43s
ci / build (push) Has been skipped
deploy / deploy (push) Successful in 51s
Risikoliste und Lessons Learned konnten bisher nur beim Anlegen bzw.
Abschluss gesetzt werden. Jetzt ist die ganze Verlinkungen-Karte über
"Bearbeiten" editierbar (Outline, Plane, Risikoliste, Lessons Learned).
Leeres Feld entfernt den Link, URLs werden serverseitig validiert.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 20:11:44 +02:00
dejanandClaude Opus 4.8 390a99bf5e chore: "Buch"-Erwähnungen aus UI & Kommentaren entfernen
ci / quality (push) Failing after 36s
ci / build (push) Has been skipped
deploy / deploy (push) Successful in 1m11s
User-sichtbare Hinweise (Meilenstein-Mindestanzahl, Stakeholder-Empty,
Freitags-Warnung) ohne Quellenangabe umformuliert; Dev-Kommentare von
"Buch Kap. X" auf "Leitfaden" geändert.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 19:49:39 +02:00
dejanandClaude Opus 4.8 d8a224d5af chore(db): ehemalige Pausen löschen (Migration 0015)
ci / quality (push) Failing after 35s
ci / build (push) Has been skipped
deploy / deploy (push) Successful in 53s
Daten-Migration entfernt alle alten 'break'-Zeiteinträge (das Pause-Feature
wurde abgeschafft). Sie erschienen sonst als graue Blöcke in der Team-Timeline.
Läuft beim Deploy automatisch über runMigrations.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 19:03:37 +02:00
dejanandClaude Opus 4.8 7f9a4506c5 refactor(zeit): Pausen nicht mehr buchen — Lücken zwischen Tasks = Pause
ci / quality (push) Failing after 45s
ci / build (push) Has been skipped
deploy / deploy (push) Successful in 53s
Pause-Feature entfernt: kein Pause-Button, kein break-Buchen mehr. Man bucht
nur Tasks; stoppt man eine Task und es läuft keine andere, ist die Lücke
automatisch eine Pause — im Kalender/Tagesansicht schlicht leer. Tasks bleiben
pausierbar (Stop = Pause, erneut Start = Fortsetzen → mehrere Segmente auf
dieselbe Task, Lücke dazwischen leer). Wall-Clock zählt Lücken ohnehin nicht.

- time.pause-Endpoint entfernt; 'break' aus der angebotenen Kategorienliste
  raus (bleibt im Enum für Altdaten).
- TimerPill: Pause-Button + Pause-Panel-Grund entfernt; Stop/Start je Task bleibt
  (= pausieren/fortsetzen). Heute-ToDo-Zeile entsprechend beschriftet.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 18:56:54 +02:00
dejanandClaude Opus 4.8 5bbb4abffa feat(zeit): Check-In/Check-Out + Kimai-Sync-Naht (ENTWICKLUN-9)
ci / quality (push) Failing after 42s
ci / build (push) Has been skipped
deploy / deploy (push) Successful in 1m20s
Arbeitsantritt = bestehender Lock-in (setzt checkedInAt); neu dazu:
- Check-Out / Feierabend: dayEntry.checkedOutAt + Endpoint dayEntry.checkOut;
  Heute-Seite zeigt „Arbeitsantritt HH:MM" und einen „Feierabend / Check-Out"-
  Button, danach Antritt/Feierabend/Dauer.
- Kimai-Anbindung (config-gated, best-effort, nicht blockierend): lib/kimai.ts
  mit clockIn/clockOut. Check-In startet ein Kimai-Timesheet, Check-Out stoppt
  es; ID + Sync-Status auf dem dayEntry (kimaiTimesheetId, kimaiSynced).
  No-Op solange KIMAI_BASE_URL/API_TOKEN/PROJECT_ID/ACTIVITY_ID nicht gesetzt.

Migration 0014 (checkedOutAt, kimaiTimesheetId, kimaiSynced). Env-Vars als
optional ergänzt + in .env.example dokumentiert.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 18:46:18 +02:00
dejanandClaude Opus 4.8 9942cd8e88 feat(zeit): mehrere Timer parallel (ENTWICKLUN-6)
ci / quality (push) Failing after 44s
ci / build (push) Has been skipped
deploy / deploy (push) Successful in 53s
Mehrere Tasks gleichzeitig tracken. Unique-Index "ein aktiver Timer pro User"
entfernt (Migration 0013); time.start stoppt den laufenden nicht mehr, sondern
läuft parallel.

- time.now liefert jetzt ALLE laufenden Timer (Array) inkl. ToDo-Titel.
- time.stop({id}) stoppt einen bestimmten Timer; time.stopAll stoppt alle.
- time.pause stoppt ALLE laufenden Tasks und startet eine Pause (passt zum
  Pause-Ticket „alle laufenden Tasks pausiert").
- TimerPill: zeigt Anzahl laufender Timer; Panel listet alle mit Live-Zähler +
  einzelnem Stop, „Weiteren Task starten", Grund-Nachtrag für Pausen.
- Heute-ToDo-Zeile: Start/Stop pro ToDo unabhängig (Array-basiert).

Zusammenspiel: Team-Timeline zeigt parallele Stränge, „Gesamt"-Zeit zählt
Überlappung weiterhin nur einmal (Wall-Clock).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 18:28:48 +02:00
dejanandClaude Opus 4.8 66adc49e2c feat(heute): ungeplant Erledigtes nachtragen (ENTWICKLUN-7)
ci / quality (push) Failing after 43s
ci / build (push) Has been skipped
deploy / deploy (push) Successful in 53s
Drive-by-Aufgaben ("btw, Yevgen-Security-Fix hab ich auch noch gemacht")
strukturiert erfassen statt nur im Freitext. Neues Feld todo.unplanned +
Endpoint dayEntry.addUnplanned: legt sofort ein erledigtes, als „ungeplant"
markiertes ToDo an.

- Schnell-Eingabe „Ungeplant erledigt" auf Heute (Mid-Day) und in der
  Reflexion (End-of-Day-Recall).
- "ungeplant"-Badge in Heute, Reflexion und Historie.
- historyForDate liefert das unplanned-Flag mit.
- Reflexions-Freitext bleibt für die Tages-Story.

Migration 0012 (todo.unplanned).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 18:09:38 +02:00
dejanandClaude Opus 4.8 516b35bf15 feat(team-view): horizontale Team-Timeline (ENTWICKLUN-8)
ci / quality (push) Failing after 33s
ci / build (push) Has been skipped
deploy / deploy (push) Successful in 1m17s
Neue Seite /team (Tab „Team", g t): horizontale Tages-Timeline mit einer Spur
pro Person. Zeit-Blöcke werden nach Start/Ende auf einer Stundenachse
positioniert, eingefärbt nach Kategorie; überlappende Blöcke landen auf
parallelen Sub-Spuren ("parallele Zeitstränge"). Laufende Blöcke (heute) ticken
live und sind rot umrandet. Datums-Navigation (Tag vor/zurück, Picker, „Heute"),
Hover-Tooltip mit Label/Zeitraum/Dauer, Kategorie-Legende.

Endpoint time.teamTimeline({date?}) liefert pro Person die Roh-Einträge
(Start/Ende/Kategorie/Label); Achse & Sub-Spuren rechnet das Frontend.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 17:58:47 +02:00
dejanandClaude Opus 4.8 9bf20fbabd feat(historie): team-weite Tages-Historie (ENTWICKLUN-10)
ci / quality (push) Failing after 46s
ci / build (push) Has been skipped
deploy / deploy (push) Successful in 55s
Neue Seite /historie: pro vergangenem Tag sieht man, was jede/r gemacht hat —
Reflexion (Ampel/Trend/Text) + ToDos (erledigt/offen/verworfen), plus Liste
„ohne Eintrag". Datums-Navigation (vorheriger/nächster Werktag, Datum-Picker);
Default = vorheriger Werktag. Heutige Reflexionen bleiben privat (nur ToDos).

- Endpoint dayEntry.historyForDate({date?}) liefert Einträge + prev/next-Werktag.
- TopNav-Tab „Historie" (g i), Link „Ganze Historie →" im Dashboard-Feed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 17:46:49 +02:00
dejanandClaude Opus 4.8 c3d3c4500e fix(dashboard): "Gestern im Team" war immer leer (ENTWICKLUN-13)
ci / quality (push) Failing after 35s
ci / build (push) Has been skipped
deploy / deploy (push) Successful in 53s
Der Vortags-Feed verlangte published_at IS NOT NULL, gesetzt nur vom Cron
publish-day-entries. Auf Prod ist dieser Cron nicht eingeplant (keine crontab/
kein Scheduler) → published_at blieb bei allen echten Reflexionen null → Feed
immer leer (auf Dev sah's gut aus, weil der Seed published_at setzt).

Feed jetzt vom Cron entkoppelt: zeigt volle Reflexionen mit Datum < heute
(heutige bleiben privat bis morgen), sortiert nach Datum/Reflexionszeit.
Gilt für dashboard.overview.feed und dayEntry.feed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 17:39:17 +02:00
dejanandClaude Opus 4.8 8fd72bcb69 fix(zeit): über Mitternacht laufende Timer bleiben sichtbar (ENTWICKLUN-14)
ci / quality (push) Failing after 40s
ci / build (push) Has been skipped
deploy / deploy (push) Successful in 53s
Ein um 23:00 gestarteter, noch laufender Timer hatte Start-Datum = gestern und
fiel nach Mitternacht aus listToday/teamToday (Filter nach Start-Datum=heute) —
nur die TimerPill zeigte ihn noch.

- listToday/teamToday: Filter „overlapsToday" = heute gestartet ODER heute
  beendet (Mitternacht überschritten) ODER laufend → Eintrag bleibt sichtbar.
- Tages-Summen clampen den Anteil auf den heutigen Tag (berlinDayStartMs,
  DST-korrekt) → über Mitternacht gelaufene Blöcke werden nicht falsch zugezählt.
- ToDo-Titel werden tagesübergreifend serverseitig aufgelöst (time.now +
  listToday) → Task bleibt benannt, auch wenn das ToDo von gestern ist.
- Timeline zeigt das Start-Datum, wenn ein Eintrag nicht heute begonnen hat.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 17:29:47 +02:00
dejanandClaude Opus 4.8 040dd62735 fix(web): Stale-Chunk-Fehler nach Deploy automatisch abfangen
ci / quality (push) Failing after 39s
ci / build (push) Has been skipped
deploy / deploy (push) Successful in 57s
"Failed to fetch dynamically imported module" trat auf, wenn ein offener Tab
nach einem Deploy auf alte (gehashte, inzwischen gelöschte) Route-Chunks zeigt.
Jetzt:
- lazyWithReload() lädt bei fehlgeschlagenem Lazy-Import einmal automatisch neu
  (holt frische index.html); sessionStorage-Guard verhindert Reload-Schleifen.
- vite:preloadError-Event wird ebenfalls abgefangen (modulepreload-Fehler).
- errorElement (RouteError) ersetzt die Dev-Default-Fehlerseite durch eine
  saubere "Neu laden"-Ansicht als Fallback.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 17:15:01 +02:00
dejanandClaude Opus 4.8 02bd682fa5 feat(zeit): Pause-Button (ENTWICKLUN-15)
ci / quality (push) Failing after 35s
ci / build (push) Has been skipped
deploy / deploy (push) Successful in 46s
Pause-Button in der Timer-Pill (sichtbar im Leerlauf und während ein Task
läuft): ein Klick stoppt den laufenden Task und startet sofort eine Pause
(break-Eintrag) — bis man wieder eine Aufgabe aktiviert. Läuft eine Pause,
zeigt die Pill sie mit Live-Zähler; ein Panel erlaubt optional einen Grund
nachzutragen (z. B. Bürofahrt, Essen), „Weiter mit Aufgabe" oder „Pause
beenden". Grund ist optional — Pause kann einfach Pause sein.

Reine Frontend-Änderung (nutzt time.start mit category 'break'), keine Migration.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 17:11:23 +02:00
dejanandClaude Opus 4.8 22f79460b2 fix: Bug-Review-Fixes + README aktualisiert
ci / quality (push) Failing after 38s
ci / build (push) Has been skipped
deploy / deploy (push) Successful in 53s
Backend:
- Vortags-Feed (dashboard.overview + dayEntry.feed) sortierte aufsteigend
  mit limit(50) → zeigte die ÄLTESTEN statt neuesten Einträge. Jetzt desc.
- deal.updateStage: wonValueEur wurde beim Gewinnen mit der Wahrscheinlichkeit
  gewichtet → zu niedriger Won-Umsatz. Jetzt voller Auftragswert.
- Pflicht-Minimum „Status aktuell" wurde global (letzte Reflexion irgendwo)
  statt pro Projekt berechnet. Jetzt je Projekt aus dem jüngsten Statusbericht.
- time.listToday/teamToday nutzten fixen +02:00-Offset → im Winter (CET) um
  1h verschobene Tagesgrenze. Jetzt DST-sicher via AT TIME ZONE 'Europe/Berlin'.

Frontend:
- lead.tsx + projekt.tsx: Datumsanzeigen nutzten UTC (toISOString) → abends
  Off-by-one. Jetzt Berlin-lokal formatiert.
- reflexion.tsx: Submit mappte nur den initialen ToDo-Snapshot → mitten am Tag
  ergänzte ToDos verloren ihren Status. Jetzt über die aktuelle Liste.
- leads.tsx: CSV-Zeilenzähler konnte „-1" zeigen (Math.max).
- TimerPill: Label ohne Control (a11y-Lint-Error, war repo-weit rot) + unused
  clsx-Import behoben → pnpm lint jetzt 0 Errors.

DB: seed.ts unbedingten updatedAt-Bump aller User entfernt (Debug-Rest).

README: vollständig auf aktuellen Stand gebracht (Leads/CRM, CSV-Import,
PM-Tiefe, Phasen/Status/Risiken/Stakeholder/Änderungen, Tabellen bis 0011,
tRPC-Router, staleTime 0, Auto-Deploy-Runner + Startup-Migrationen).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 17:00:03 +02:00
dejanandClaude Opus 4.8 19db774c4c feat(leads): Leads universell mit Projekten verknüpfen
ci / quality (push) Failing after 44s
ci / build (push) Has been skipped
deploy / deploy (push) Successful in 54s
Ein Projekt lebt in genau einem Heimat-Bereich und wird einmal angelegt;
Leads bekommen eine optionale Verknüpfung dorthin (lead.projectId), egal in
welchem Bereich das Projekt wohnt — kein redundantes Anlegen mehr.

- Migration 0011: lead.project_id (FK → project, ON DELETE SET NULL).
- Lead anlegen / CSV-Import / Lead-Detail: Projekt zuordnen; CSV ordnet alle
  importierten Leads einem Projekt zu.
- Projektseite: neue "Leads"-Sektion (Vertriebs-Sicht des Projekts).
- Vertrieb: "Projekte mit Vertriebsaktivität" — bereichsübergreifend alle
  Projekte mit verknüpften Leads (so erscheint ein Entwicklungsprojekt hier,
  WEIL es Leads hat). Rein interne Projekte ohne Leads tauchen nicht auf.
- Lead-Liste/Detail zeigen das verknüpfte Projekt.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 16:08:59 +02:00
dejanandClaude Opus 4.8 68480c1eb1 feat(heute): ToDos mitten am Tag hinzufügen
ci / quality (push) Failing after 33s
ci / build (push) Has been skipped
deploy / deploy (push) Successful in 52s
Nach dem Lock-in konnte man ToDos nur bearbeiten/abhaken, aber keine neuen
anlegen. Neuer Endpoint dayEntry.addTodo hängt ein einzelnes ToDo an den
heutigen Tageseintrag an (erlaubt solange der Eintrag vom heutigen
Berlin-Tag ist, auch nach der Reflexion). Inline-Feld „Neues ToDo
hinzufügen" in der EinstempeltView; aktualisiert Heute + Dashboard-Sichten.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 15:47:54 +02:00
dejanandClaude Opus 4.8 bcae44eeb3 fix(streak): Feiertage, Wochenend-Edge & Lookback-Deckel
ci / build (push) Has been skipped
ci / quality (push) Failing after 38s
deploy / deploy (push) Successful in 55s
- Feiertage: isWerktag berücksichtigt jetzt die 9 bundesweiten gesetzlichen
  Feiertage (Oster-Computus + feste Tage) → ein Feiertag bricht die Streak
  nicht mehr (zählt wie ein Wochenende neutral). Landesspezifische Feiertage
  bewusst (noch) nicht enthalten.
- Wochenend-Edge: Reflexion an Sa/So setzte die angezeigte Streak auf 0
  (Schleife brach am Nicht-Werktag ab). Jetzt wird übersprungen statt gebrochen.
- Lookback von 120 auf 400 Tage erhöht, damit lange Streaks nicht
  abgeschnitten werden.
- Streak-Zähllogik in reine, getestete countStreakDays() ausgelagert
  (8 Streak- + 5 Feiertags-Tests).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 15:42:25 +02:00
dejanandClaude Opus 4.8 1f0c9efd59 fix(web): Daten nach Aktionen ohne Refresh aktuell
ci / build (push) Has been skipped
deploy / deploy (push) Successful in 47s
ci / quality (push) Failing after 42s
staleTime war 30 s → nach „Lock in" zeigte das Dashboard bis zu 30 s alte
Cache-Stände, erst ein Browser-Refresh half. Jetzt staleTime 0: Seiten
holen beim Aufrufen/Tab-Fokus frische Daten (kein Polling). Zusätzlich
invalidiert checkIn jetzt dashboard.overview, dayEntry.todayTeam und
todayPresence, damit ein offenes Dashboard sofort mitzieht.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 15:27:29 +02:00
dejanandClaude Opus 4.8 b7b54fcec5 fix(zeit): Gesamt-Zeit als Wall-Clock statt Summe paralleler Tasks
ci / quality (push) Failing after 1m8s
ci / build (push) Has been skipped
deploy / deploy (push) Successful in 1m55s
"Zeit im Team heute" (und "Zeit heute") summierten alle Task-Dauern —
wer 5 Tasks parallel trackt, hatte 10h statt 2h Anwesenheit. Gesamt wird
jetzt als Vereinigung überlappender Intervalle berechnet (unionSeconds).
Pro-Aufgabe/Kategorie bleibt separat als Summe erhalten und wird als
"getrackt X" angezeigt; der Verteilungsbalken nutzt diese Summe als Nenner.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 15:06:27 +02:00
dejanandClaude Opus 4.8 43eeabaea2 fix(bereich): Bereich-Dropdown im "Neues Projekt"-Dialog war leer
ci / quality (push) Failing after 45s
ci / build (push) Has been skipped
deploy / deploy (push) Successful in 53s
Zwei Ursachen behoben:
- Frontend: areaId/Default wurden nur beim Mount aus dem (noch ladenden)
  areas-Prop berechnet → kein Default, keine Platzhalter-Option. Jetzt via
  useEffect Default setzen sobald Areas geladen sind + Platzhalter-Option.
- Prod: Deploy seedet nicht → frische DB hatte keine Areas. Neue
  ensureBaseAreas() legt die Basis-Bereiche idempotent beim API-Start an
  (nach den Migrationen), analog zu runMigrations.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 19:28:59 +02:00
dejanandClaude Opus 4.8 9c5207527a chore(ci): Deploy auslösen (Features 0008–0010 + CSV-Import live bringen)
ci / quality (push) Failing after 33s
ci / build (push) Has been skipped
deploy / deploy (push) Successful in 34s
Runner kam nach dem letzten Push online; löst die deploy.yml-Pipeline für
den aktuellen origin/main aus (Lead-CRM, PM-Tiefe, CSV-Import). API wendet
Migrationen 0008–0010 beim Start an.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 19:17:15 +02:00
Raffael SheikhandClaude Opus 4.8 67e8916634 fix(web): Caddyfile ins Image backen — SPA statt Caddy-Default-Seite
ci / quality (push) Failing after 37s
ci / build (push) Has been skipped
deploy / deploy (push) Successful in 52s
Das web-Runtime-Image (caddy:2-alpine) hatte keine eigene Config, daher
lieferte Caddy seine Default-Welcome-Seite aus /usr/share/caddy statt der
gebauten SPA aus /srv ("Caddy works!"). Eigene Caddyfile (root /srv,
try_files SPA-Fallback) wird jetzt nach /etc/caddy/Caddyfile kopiert.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 19:02:27 +02:00
Raffael SheikhandClaude Opus 4.8 3b928d0ad0 ci(deploy): Auto-Deploy-Runner für Push auf main + reproduzierbarer API-Build
ci / quality (push) Failing after 35s
ci / build (push) Has been skipped
deploy / deploy (push) Successful in 53s
- .gitea/workflows/deploy.yml: deployt bei Push auf main via Host-Runner
  (git reset --hard origin/main in /opt/build/cockpit, docker compose up
  -d --build in /opt/stacks/cockpit, Healthcheck auf cockpit-api).
- Auto-Migrate: runMigrations() (drizzle-orm Migrator) wird beim API-Start
  aufgerufen; Schema wird vor dem Listen idempotent aktualisiert.
- API-Dockerfile: Workspace-Libs (@cockpit/db, @cockpit/shared) werden jetzt
  mit Emit kompiliert und main/exports im Image auf dist gebogen. Vorher war
  das Prod-Image nicht reproduzierbar baubar (Node konnte die TS-Quelle der
  Libs nicht laden → ERR_MODULE_NOT_FOUND). Dev-Modus und Web-/Vite-Build
  bleiben unberührt.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 18:51:17 +02:00
dejanandClaude Opus 4.8 9f3ee13094 feat(leads): CSV-Import für Leads
ci / quality (push) Failing after 1m11s
ci / build (push) Has been skipped
"CSV importieren"-Dialog auf /leads. Serverseitiger lead.importCsv:
eigener CSV-Parser (Quotes/Kommata/Zeilenumbrüche, mit Tests),
header-basiertes Mapping (umlaut-tolerant). Pro Zeile entsteht ein Lead
(Adresse → standorte) + primärer Kontakt; Notizen werden als erster
Austausch-Log-Eintrag gespeichert. Dedup über Firmenname.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 18:17:50 +02:00
dejanandClaude Opus 4.8 864a1cef6a feat(projekt): Projektmanagement-Tiefe nach Buch & Leitfaden v3.0
ci / quality (push) Failing after 1m0s
ci / build (push) Has been skipped
Operationalisiert den ToolCTRL-Projektmanagement-Leitfaden auf der
Projekt-Detailseite (hybrid: Cockpit-Primitive nativ, Schwergewichtiges
per Outline-Link):

- Projekt-Modus (Relax/Standard/Eskalation/Taskforce) + Dashboard-Surfacing
- Risiko- & Chancen-Register (Wahrscheinlichkeit×Auswirkung, Showstopper,
  Owner, Strategie) — offene Showstopper landen auf dem Dashboard
- Stakeholder-Analyse mit Macht/Interesse-Matrix
- Ziel & Definition: SMART-Ziel, Nicht-Ziele, Liefergegenstaende, Maxime,
  Zieldreieck (welche Ecke gibt nach)
- Meilensteine editierbar inkl. Ergebnis/Kundennutzen, Freitags-/
  Feiertags-Warnung, Mindest-2-Hinweis
- Phasen-Lebenszyklus (Definition→Planung→Umsetzung→Abschluss) mit Gate-Reviews
- Projekt-Statusbericht (Ampel/Trend/Text, extern-Flag, Verlauf) — speist
  statusCache & Pflicht-Minimum
- Änderungs-Log (Scope-Creep-Schutz), strukturierter Abschluss mit
  Checkliste + Abschlussvermerk

Migrationen 0009_pm_insights + 0010_leitfaden_phases. Enthält auch die
gemeinsame schema.ts (inkl. Lead-Tabellen aus dem Vor-Commit) und Seed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 17:31:30 +02:00
dejanandClaude Opus 4.8 d72aa9fbf3 feat(vertrieb): Lead-CRM mit Dossiers, Kontakten & Austausch-Log
Neues Lead-Modul im Vertriebsbereich: qualitative Dossiers (Stammdaten,
Pain & Bedarf, Soft Factors, Strategie), Kontaktpersonen, Austausch-Log
mit Follow-up-Daten und Lead→Deal-Promotion. Routen /leads (Liste, nach
Status gruppiert) und /lead/:id (Dossier), Teaser im Bereich Vertrieb.

Migration 0008_lead_crm (lead, lead_contact, lead_touchpoint).
Datenmodell-Tabellen liegen in der gemeinsamen schema.ts (Folge-Commit).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 17:31:14 +02:00
dejanandClaude Opus 4.8 8933169ba9 feat(reflexion): ToDo-Titel inline editierbar
ToDos in der Reflexion lassen sich per Klick auf den Titel korrigieren
(z. B. Tippfehler), Enter speichert / Escape bricht ab. Neuer Endpoint
dayEntry.editTodoTitle — nur eigene ToDos vom heutigen Berlin-Tag,
ändert den Titel in-place (Status/Reihenfolge/IDs bleiben).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 17:31:03 +02:00
dejanandClaude Opus 4.8 804b7637e7 Dashboard: dynamische Locked-in-Überschrift im Team-Bereich
ci / quality (push) Has been cancelled
ci / build (push) Has been cancelled
Statt fester "Heute im Team"-Überschrift jetzt zählerabhängiger Satz:
0 / 1 Person / mehrere Personen.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 17:03:30 +02:00