From fee3251946b4aacc1cd2a31767ccb513f588fedf Mon Sep 17 00:00:00 2001 From: mAi Date: Tue, 26 May 2026 12:35:10 +0200 Subject: [PATCH] =?UTF-8?q?feat(dashboard):=20polish=20Events=20tab=20?= =?UTF-8?q?=E2=80=94=20summary=20header,=20fuller=20day=20labels?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 5h slice 5 — the Events tab's routing landed in slice 2; this slice adds the dedicated-surface polish that distinguishes it from the Events card on the Tasks tab. Changes: - Top header summary: 'N events · next 7 days' so m sees the window shape at a glance without scanning rows. - Day headings now carry three columns: the relative label ('Today' / 'Tomorrow' / weekday), the ISO date (mono font), and a right-aligned event count. Bigger visual hierarchy than the cards-tab flavour to justify the dedicated tab's existence. - Empty-state copy invites linking a CalDAV calendar from a project's detail page so a never-seen-events tab doesn't feel broken. - StartLabel fallback to '—' when an event has no parseable start time so the row doesn't collapse weirdly. CSS adds .dash-events-summary, .event-day-heading flex layout, .event-day-label / .event-day-date / .event-day-count spans, and a constrained .dash-events-empty for the empty-state width. Test: TestDashboardEventsViewRenders now also asserts the empty-state copy ships, so a future refactor that drops the invite-to-link prose gets caught. --- web/dashboard_view_test.go | 5 +++++ web/static/style.css | 15 ++++++++++++--- web/templates/dashboard_section.tmpl | 13 ++++++++++--- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/web/dashboard_view_test.go b/web/dashboard_view_test.go index 881b31a..7382f0b 100644 --- a/web/dashboard_view_test.go +++ b/web/dashboard_view_test.go @@ -93,6 +93,8 @@ func TestDashboardTasksViewFallback(t *testing.T) { // TestDashboardEventsViewRenders confirms that ?view=events renders the // promoted Events surface (dash-events-view) and not the cards or tiles. +// Also asserts the slice-5 polish: the empty state copy invites the user +// to link a CalDAV calendar so the dedicated tab doesn't feel broken. func TestDashboardEventsViewRenders(t *testing.T) { srv, pool := mustServer(t) defer pool.Close() @@ -107,6 +109,9 @@ func TestDashboardEventsViewRenders(t *testing.T) { if strings.Contains(body, `class="card card-tasks"`) { t.Errorf("view=events should NOT render the Tasks 5-card layout") } + if !strings.Contains(body, "Link a CalDAV calendar") { + t.Errorf("empty-state copy should invite linking a calendar") + } } // TestDashboardUnknownViewFallsBackToTiles confirms graceful default diff --git a/web/static/style.css b/web/static/style.css index 9a1f11e..605b9eb 100644 --- a/web/static/style.css +++ b/web/static/style.css @@ -421,11 +421,20 @@ table.bulk .chip-add-btn:hover { background: var(--accent); color: var(--accent- .dashboard .dash-tiles-quiet .tile { opacity: 0.85; } .dashboard .dash-events-view { margin-top: 8px; } -.dashboard .dash-events-view .event-day-large { margin: 16px 0; } -.dashboard .dash-events-view .event-day-large h2 { - font-size: 1em; font-weight: 600; margin: 0 0 8px 0; +.dashboard .dash-events-summary { margin: 4px 0 16px; } +.dashboard .dash-events-summary h2 { margin: 0; font-size: 1.05em; font-weight: 600; } +.dashboard .dash-events-view .event-day-large { margin: 18px 0; } +.dashboard .dash-events-view .event-day-heading { + font-size: 0.95em; font-weight: 600; margin: 0 0 8px 0; border-bottom: 1px dotted var(--border); padding-bottom: 4px; + display: flex; gap: 10px; align-items: baseline; } +.dashboard .dash-events-view .event-day-label { color: var(--fg); } +.dashboard .dash-events-view .event-day-date { + font-family: ui-monospace, SFMono-Regular, monospace; font-size: 0.85em; +} +.dashboard .dash-events-view .event-day-count { margin-left: auto; font-size: 0.85em; } +.dashboard .dash-events-empty { margin: 24px 0; max-width: 540px; } .dashboard .dash-events-view .event-list { list-style: none; padding: 0; margin: 0; } .dashboard .dash-events-view .event-row { display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap; diff --git a/web/templates/dashboard_section.tmpl b/web/templates/dashboard_section.tmpl index 60d0dcc..13aa4c3 100644 --- a/web/templates/dashboard_section.tmpl +++ b/web/templates/dashboard_section.tmpl @@ -236,13 +236,20 @@ {{define "dashboard-events-view"}}
{{if .P.Events}} +
+

{{.P.EventsTotal}} event{{if ne .P.EventsTotal 1}}s{{end}} · next 7 days

+
{{range .P.Events}}
-

{{.DayLabel}} ({{len .Events}})

+

+ {{.DayLabel}} + {{.DayKey}} + {{len .Events}} event{{if ne (len .Events) 1}}s{{end}} +

    {{range .Events}}
  • - {{.StartLabel}} + {{if .StartLabel}}{{.StartLabel}}{{else}}—{{end}} {{.Item.PrimaryPath}} {{.Event.Summary}} {{if .Event.Location}}· {{.Event.Location}}{{end}} @@ -253,7 +260,7 @@
{{end}} {{else}} -

No events in the next 7 days.

+

No events in the next 7 days. Link a CalDAV calendar from a project's detail page to start surfacing events here.

{{end}}
{{end}}