feat(t-paliad-110): refactor Dashboard rails — drop Erledigt card, add Später + Termine rail
PR-4 of the Fristen+Termine unification, closing out t-paliad-110. Fristen rail (was 5 cards): - Erledigt card removed (status=completed stays reachable via the EventsPage filter dropdown — no card on the rail per the new model) - Später card added (pending deadlines past Mon-week-after, click filters to /deadlines?status=later) - 4+1 final shape: Überfällig (conditional alarm) · Heute · Diese Woche · Nächste Woche · Später Termine rail (new): 3 cards — Heute · Diese Woche · Später. No Überfällig (past appointments aren't urgent), no Nächste Woche (low-value distinction for appointments per the design rationale). Cards click through to /appointments?status=… so users land in the matching EventsPage view. Backend (DashboardService.loadSummary): - DeadlineSummary.CompletedThisWeek dropped, .Later added - AppointmentSummary added (Today / ThisWeek / Later) - One CTE-based query computes both rails alongside MatterSummary; bucket cutoffs share computeDeadlineBucketBounds with /api/events/summary + /api/deadlines/summary so all three surfaces stay in lockstep Frontend: - dashboard.tsx: Erledigt card removed, Später card + Termine section added - client/dashboard.ts: types updated, renderAppointmentSummary added - 4 new i18n keys (DE+EN): dashboard.summary.later + dashboard.appointment_summary.heading - CSS: .dashboard-card-later (muted blue) + 3 .dashboard-card-appt-* rules reusing the existing --bucket-* tokens go build/vet/test ./... clean. bun run build clean (1396 keys).
This commit is contained in:
@@ -14,7 +14,13 @@ interface DeadlineSummary {
|
||||
today: number;
|
||||
this_week: number;
|
||||
next_week: number;
|
||||
completed_this_week: number;
|
||||
later: number;
|
||||
}
|
||||
|
||||
interface AppointmentSummary {
|
||||
today: number;
|
||||
this_week: number;
|
||||
later: number;
|
||||
}
|
||||
|
||||
interface MatterSummary {
|
||||
@@ -60,6 +66,7 @@ interface ActivityEntry {
|
||||
interface DashboardData {
|
||||
user: DashboardUser | null;
|
||||
deadline_summary: DeadlineSummary;
|
||||
appointment_summary: AppointmentSummary;
|
||||
matter_summary: MatterSummary;
|
||||
upcoming_deadlines: UpcomingDeadline[];
|
||||
upcoming_appointments: UpcomingAppointment[];
|
||||
@@ -98,6 +105,7 @@ function render(): void {
|
||||
if (!data) return;
|
||||
renderGreeting(data.user);
|
||||
renderSummary(data.deadline_summary);
|
||||
renderAppointmentSummary(data.appointment_summary);
|
||||
renderMatters(data.matter_summary);
|
||||
renderDeadlines(data.upcoming_deadlines);
|
||||
renderAppointments(data.upcoming_appointments);
|
||||
@@ -133,17 +141,23 @@ function renderSummary(s: DeadlineSummary): void {
|
||||
setCount("dashboard-count-today", s.today);
|
||||
setCount("dashboard-count-this-week", s.this_week);
|
||||
setCount("dashboard-count-next-week", s.next_week);
|
||||
setCount("dashboard-count-completed", s.completed_this_week);
|
||||
setCount("dashboard-count-later", s.later);
|
||||
|
||||
// Überfällig is an emergency category — hide the card entirely on a clean
|
||||
// slate (the .dashboard-summary-grid uses auto-fit so the row re-flows to
|
||||
// 4 cards) and trip the alarm styling when there's anything overdue. See
|
||||
// t-paliad-105 / t-paliad-106.
|
||||
// t-paliad-105 / t-paliad-106 / t-paliad-110.
|
||||
const overdueCard = document.getElementById("dashboard-card-overdue")!;
|
||||
overdueCard.classList.toggle("dashboard-card-overdue-hidden", s.overdue === 0);
|
||||
overdueCard.classList.toggle("dashboard-card-alarm", s.overdue > 0);
|
||||
}
|
||||
|
||||
function renderAppointmentSummary(s: AppointmentSummary): void {
|
||||
setCount("dashboard-count-appt-today", s.today);
|
||||
setCount("dashboard-count-appt-this-week", s.this_week);
|
||||
setCount("dashboard-count-appt-later", s.later);
|
||||
}
|
||||
|
||||
function renderMatters(s: MatterSummary): void {
|
||||
setCount("dashboard-matter-active", s.active);
|
||||
setCount("dashboard-matter-archived", s.archived);
|
||||
|
||||
@@ -667,6 +667,8 @@ const translations: Record<Lang, Record<string, string>> = {
|
||||
"dashboard.summary.this_week": "Diese Woche",
|
||||
"dashboard.summary.next_week": "N\u00e4chste Woche",
|
||||
"dashboard.summary.completed": "Erledigt",
|
||||
"dashboard.summary.later": "Später",
|
||||
"dashboard.appointment_summary.heading": "Termine auf einen Blick",
|
||||
"dashboard.matters.heading": "Meine Akten",
|
||||
"dashboard.matters.active": "Aktiv",
|
||||
"dashboard.matters.archived": "Archiviert",
|
||||
@@ -2165,6 +2167,8 @@ const translations: Record<Lang, Record<string, string>> = {
|
||||
"dashboard.summary.this_week": "This week",
|
||||
"dashboard.summary.next_week": "Next week",
|
||||
"dashboard.summary.completed": "Done",
|
||||
"dashboard.summary.later": "Later",
|
||||
"dashboard.appointment_summary.heading": "Appointments at a glance",
|
||||
"dashboard.matters.heading": "My matters",
|
||||
"dashboard.matters.active": "Active",
|
||||
"dashboard.matters.archived": "Archived",
|
||||
|
||||
@@ -57,7 +57,7 @@ export function renderDashboard(): string {
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Traffic-light deadline summary */}
|
||||
{/* Traffic-light deadline summary (4+1: Überfällig conditional + 4 universal — t-paliad-110) */}
|
||||
<section className="dashboard-summary" aria-labelledby="dashboard-summary-heading">
|
||||
<h2 id="dashboard-summary-heading" className="dashboard-section-heading" data-i18n="dashboard.summary.heading">
|
||||
Fristen auf einen Blick
|
||||
@@ -79,9 +79,30 @@ export function renderDashboard(): string {
|
||||
<div className="dashboard-card-count" id="dashboard-count-next-week">0</div>
|
||||
<div className="dashboard-card-label" data-i18n="dashboard.summary.next_week">Nächste Woche</div>
|
||||
</a>
|
||||
<a href="/deadlines?status=completed" className="dashboard-card dashboard-card-done" id="dashboard-card-completed">
|
||||
<div className="dashboard-card-count" id="dashboard-count-completed">0</div>
|
||||
<div className="dashboard-card-label" data-i18n="dashboard.summary.completed">Erledigt</div>
|
||||
<a href="/deadlines?status=later" className="dashboard-card dashboard-card-later" id="dashboard-card-later">
|
||||
<div className="dashboard-card-count" id="dashboard-count-later">0</div>
|
||||
<div className="dashboard-card-label" data-i18n="dashboard.summary.later">Später</div>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Termine summary rail — 3 cards: Heute · Diese Woche · Später (t-paliad-110) */}
|
||||
<section className="dashboard-summary" aria-labelledby="dashboard-appointment-summary-heading">
|
||||
<h2 id="dashboard-appointment-summary-heading" className="dashboard-section-heading" data-i18n="dashboard.appointment_summary.heading">
|
||||
Termine auf einen Blick
|
||||
</h2>
|
||||
<div className="dashboard-summary-grid">
|
||||
<a href="/appointments?status=today" className="dashboard-card dashboard-card-appt-today" id="dashboard-card-appt-today">
|
||||
<div className="dashboard-card-count" id="dashboard-count-appt-today">0</div>
|
||||
<div className="dashboard-card-label" data-i18n="dashboard.summary.today">Heute</div>
|
||||
</a>
|
||||
<a href="/appointments?status=this_week" className="dashboard-card dashboard-card-appt-week" id="dashboard-card-appt-thisweek">
|
||||
<div className="dashboard-card-count" id="dashboard-count-appt-this-week">0</div>
|
||||
<div className="dashboard-card-label" data-i18n="dashboard.summary.this_week">Diese Woche</div>
|
||||
</a>
|
||||
<a href="/appointments?status=later" className="dashboard-card dashboard-card-appt-later" id="dashboard-card-appt-later">
|
||||
<div className="dashboard-card-count" id="dashboard-count-appt-later">0</div>
|
||||
<div className="dashboard-card-label" data-i18n="dashboard.summary.later">Später</div>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -505,6 +505,7 @@ export type I18nKey =
|
||||
| "dashboard.activity.event"
|
||||
| "dashboard.activity.heading"
|
||||
| "dashboard.activity.system"
|
||||
| "dashboard.appointment_summary.heading"
|
||||
| "dashboard.appointments.empty"
|
||||
| "dashboard.appointments.heading"
|
||||
| "dashboard.deadlines.empty"
|
||||
@@ -517,6 +518,7 @@ export type I18nKey =
|
||||
| "dashboard.onboarding"
|
||||
| "dashboard.summary.completed"
|
||||
| "dashboard.summary.heading"
|
||||
| "dashboard.summary.later"
|
||||
| "dashboard.summary.next_week"
|
||||
| "dashboard.summary.overdue"
|
||||
| "dashboard.summary.this_week"
|
||||
|
||||
@@ -5702,6 +5702,17 @@ input[type="range"]::-moz-range-thumb {
|
||||
.dashboard-card-green { border-left: 3px solid var(--bucket-next-week); }
|
||||
.dashboard-card-done .dashboard-card-count { color: var(--bucket-done); }
|
||||
.dashboard-card-done { border-left: 3px solid var(--bucket-done); }
|
||||
/* Später bucket on the Fristen rail — muted blue (t-paliad-110). */
|
||||
.dashboard-card-later .dashboard-card-count { color: var(--bucket-later); }
|
||||
.dashboard-card-later { border-left: 3px solid var(--bucket-later); }
|
||||
/* Termine rail uses the same urgency token family — keep the palette
|
||||
consistent across rails so users read both at the same glance. */
|
||||
.dashboard-card-appt-today .dashboard-card-count { color: var(--bucket-today); }
|
||||
.dashboard-card-appt-today { border-left: 3px solid var(--bucket-today); }
|
||||
.dashboard-card-appt-week .dashboard-card-count { color: var(--bucket-week); }
|
||||
.dashboard-card-appt-week { border-left: 3px solid var(--bucket-week); }
|
||||
.dashboard-card-appt-later .dashboard-card-count { color: var(--bucket-later); }
|
||||
.dashboard-card-appt-later { border-left: 3px solid var(--bucket-later); }
|
||||
|
||||
/* Überfällig alarm — see t-paliad-105 / t-paliad-106.
|
||||
When overdue > 0 the card flips from a calm border-left accent to a
|
||||
|
||||
Reference in New Issue
Block a user