feat: T4 wave 6 - reminders and morning digest, next steps UI, warnings and notifications UI

- In-app reminders: task due (skips rescheduled tasks, catch-up wording)
  and a per-user morning digest step in the daily job
- Frontend: "Als Nächstes" on the colony page, "Heute" on the dashboard,
  inspection-due card, season chip, apiary overview fields, cleanup
  sheet for ended colonies
- Frontend: plausibility warnings that stay until dismissed, withdrawal
  spans in the calendar, notification bell with categories and links,
  notification settings in the profile
- ARCHITECTURE.md: T4a sections 11.1-11.10, assumptions 31-41, handler
  table and daily job step order

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
Nick SzaunigandClaude Opus 5.5 committed 2026-10-14 17:05:32 +02:00
1 parent ef33e5549b
commit 32c61c8e14
77 files changed
+5309 -142

No files matched your search

+16 -6
View File
@@ -68,13 +68,23 @@ const CAPTURE_PATHS: Partial<Record<SuggestionIntent, string>> = {
WINTER_CHECK: "/winter",
};
/** Winter checks are entered from the winter page, which has no colony parameter. */
const PATHS_WITHOUT_COLONY = new Set(["/winter"]);
const DEFAULT_CAPTURE_PATH = "/inspections/new";
export function captureHref(intent: SuggestionIntent, colonyId: string | null): string {
/** From July on the winter check is the autumn one (as the autopilot's own link says). */
const FIRST_AUTUMN_MONTH = 7;
export function captureHref(
intent: SuggestionIntent,
colonyId: string | null,
now: Date = new Date(),
): string {
const path = CAPTURE_PATHS[intent] ?? DEFAULT_CAPTURE_PATH;
if (!colonyId || PATHS_WITHOUT_COLONY.has(path)) return path;
return `${path}?colonyId=${encodeURIComponent(colonyId)}`;
if (!colonyId) return path;
const query = `colonyId=${encodeURIComponent(colonyId)}`;
if (path === "/winter") {
// The winter page opens the dialog of that colony for the season.
const season = now.getMonth() + 1 >= FIRST_AUTUMN_MONTH ? "AUTUMN" : "SPRING";
return `${path}?${query}&season=${season}`;
}
return `${path}?${query}`;
}