27 Commits

Author SHA1 Message Date
6e0a848c45 Fix QA findings: rename ambient component, add clock tab-resume sync
W-02: Renamed layout/AmbientBackground → AppAmbientBackground to avoid
naming collision with auth/AmbientBackground (IDE auto-import confusion).

S-01: Added visibilitychange listener to re-sync clock after tab
sleep/resume. Previously the interval would drift after laptop sleep
or long tab backgrounding.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 18:28:14 +08:00
b663455c26 Sync clock to minute boundary and stabilize "Updated" text
Clock: Instead of starting a 60s interval from mount time (which drifts
from the system clock), calculate ms until the next :00 second mark,
setTimeout to that point, then setInterval every 60s from there.

Updated text: Replaced formatDistanceToNow (which flickered between
"less than a minute ago" / "a minute ago" / "2 minutes ago" on each
render) with a stable minute-based calculation derived from clockNow:
"just now" / "1 min ago" / "N min ago".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 18:18:00 +08:00
3afa894e1b Add live clock to dashboard header in 12hr format
Displays current time before the date separated by a vertical bar:
"6:30 PM | Thursday, March 12, 2026". Updates every 60 seconds.
Uses tabular-nums for stable digit widths.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 18:08:05 +08:00
01c276fc8d Make ambient background global and lighten card colors
- Moved ambient from DashboardPage to AppLayout so all pages get the
  drifting gradient effect, not just the dashboard
- Lightened card colors: --card 5% → 8%, --card-elevated 7% → 11%,
  popover and FullCalendar backgrounds updated to match
- Renamed DashboardAmbient → AmbientBackground in layout/
- Glassmorphism class renamed dashboard-glass → ambient-glass,
  applied at AppLayout content wrapper level

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 12:59:12 +08:00
a4b3a8f7fe Switch ambient background to radial gradients + glassmorphism cards
Blurred circle approach was invisible on near-black backgrounds.
Use radial-gradient orbs at 25%/15% opacity instead, with semi-transparent
cards (backdrop-filter: blur) so the ambient effect shows through.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 09:44:38 +08:00
11fe3df513 Fix ambient background: use positive z-index layering instead of negative
Negative z-index (-z-10) placed orbs behind the body's opaque background,
making them invisible. Moved all ambient layers (orbs, noise texture,
vignette) into the DashboardAmbient component as absolute-positioned
children at z-0, with content at z-10. Boosted orb opacities to 12%/7%
for perceptible effect. Removed CSS pseudo-element approach in favor of
inline React elements for better stacking control.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 09:26:02 +08:00
6b02cfa1f8 Add ambient dashboard background: drifting orbs, noise texture, vignette, card breathe
Three layered effects to make the dashboard feel alive:
1. DashboardAmbient: two accent-colored drifting orbs at very low opacity
   (0.04/0.025) with 120px blur — subtle depth and movement
2. Noise texture + radial vignette via CSS pseudo-elements — breaks the
   flat digital surface and draws focus to center content
3. Card breathe animation: data-driven 4s pulsing glow on CalendarWidget
   (when event in progress) and TodoWidget (when overdue todos exist)

All effects respect prefers-reduced-motion, use accent CSS vars (works
with any user-chosen accent color), and are GPU-composited (transform +
opacity only) for negligible performance cost.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 00:54:00 +08:00
ac3f746ba3 Fix QA findings: combine todo queries, remove dead prop, add aria-labels
- Merge total_todos and total_incomplete_todos into single DB query (W-04)
- Remove unused `days` prop from UpcomingWidget interface (W-03)
- Add aria-label to focus/show-past toggle buttons (S-08)
- Add zero-duration event guard in CalendarWidget progress calc (S-07)
- Combine duplicate date-utils imports (S-01)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 00:16:00 +08:00
b41b0b6635 Add dashboard polish: micro-animations, visual upgrades, and interactivity
Batch 1+2 implementation (17 items): plus button rotation, card hover
glow consistency, DayBriefing container with Sparkles icon, WeekTimeline
hover scale + pulsing today dot + dot tooltips, countdown urgency scaling,
CalendarWidget time progress bar + current event highlight + empty state,
TodoWidget inline complete + empty state, dashboard auto-refresh (2min),
optimistic todo completion, "Updated Xm ago" with refresh button, keyboard
quick-add (Ctrl+N → e/t/r), progress rings on stat cards, staggered row
entrance in Upcoming, content crossfade, prefers-reduced-motion support,
ARIA attributes on dropdown menu, and hover:bg-card-elevated consistency.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 00:02:04 +08:00
66e230f740 Make right column cards fill height to align with Upcoming card
Wrap TodoWidget in flex-1 container and add h-full to its Card so
the Upcoming Todos card stretches to fill remaining space in the
right column, keeping both columns visually aligned.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 23:21:04 +08:00
9635401fe8 Redesign Upcoming Widget with day groups, status pills, and inline actions
Backend: Include overdue todos and snoozed reminders in /upcoming response,
add end_datetime/snoozed_until/is_overdue fields, widen snooze schema to
accept 1-1440 minutes for 1h/3h/tomorrow options.

Frontend: Full UpcomingWidget rewrite with sticky day separators (Today
highlighted in accent), collapsible groups, past-event toggle, focus mode
(Today + Tomorrow), color-coded left borders, compact type pills, relative
time for today's items, item count badge, and inline quick actions (complete
todo, snooze/dismiss reminder on hover). Card fills available height with
no dead space. DashboardPage always renders widget (no duplicate empty state).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 21:07:14 +08:00
023fa86b65 Mobile UI polish: global font scaling, tighter dashboard, cleaner calendar
Scale down all content text on mobile via .mobile-scale CSS class (excludes
navbar/UMBRA title). Hide calendar event times in month view (Google Calendar
style). Restructure CategoryFilterBar so categories display on a separate row
when toggled instead of being hidden behind the search bar. Reduce dashboard
widget density with hidden badges and tighter spacing on small screens.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 01:56:53 +08:00
1c16df4db0 Phase 1: mobile responsive foundation
- useMediaQuery hook extracted from CalendarPage inline pattern
- h-screen → h-dvh for mobile address bar viewport fix
- px-6 → px-4 md:px-6 on all page containers/toolbars (14 files)
- Input/Select text-base on mobile to prevent iOS auto-zoom
- Sheet full-width on mobile, max-w-[540px] on sm+
- Button icon size touch-friendly (44px mobile, 40px desktop)
- Tailwind hoverOnlyWhenSupported: true (fixes 157 hover interactions)
- PWA meta tags (apple-mobile-web-app-capable, theme-color)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 16:51:53 +08:00
8945295e2a Replace Sheet overlays with inline detail panels across all pages
- Calendar: move view selector left, inline EventDetailPanel with view/edit/create
  modes, fix resize on panel close, remove all Sheet/Dialog usage
- Todos: add TodoDetailPanel with inline view/edit/create, replace CategoryFilterBar
  with shared component (drag-and-drop categories), 55/45 split layout
- Reminders: add ReminderDetailPanel with inline view/edit/create, 55/45 split layout
- Dashboard: all widget items now deep-link to destination page AND open the
  relevant item's detail panel (events, todos, reminders)
- Fix TS errors: unused imports, undefined→null coalescing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 22:43:06 +08:00
898ecc407a Stage 7: final polish — transitions, navigation, calendar panel
- Add animate-fade-in page transitions to all pages
- Persist sidebar collapsed state in localStorage
- Add two-click logout confirmation using useConfirmAction
- Restructure Todos header: replace <select> with pill filters, move search right
- Move Reminders search right-aligned with spacer
- Add event search dropdown + Create Event button to Calendar toolbar
- Add search input to Projects header with name/description filtering
- Fix CategoryFilterBar search focus ring clipping with ring-inset
- Create EventDetailPanel: read-only event view with copyable fields,
  recurrence display, edit/delete actions, location name resolution
- Refactor CalendarPage to 55/45 split-panel layout matching People/Locations
- Add mobile overlay panel for calendar event details
- Add navigation state handler for CalendarPage (date/view from dashboard)
- Add navigation state handler for ProjectsPage (status filter from dashboard)
- Make all dashboard widgets navigable: stat cards → pages, week timeline
  days → calendar day view, upcoming items → source pages, countdown items
  → calendar, today's events/todos/reminders → respective pages

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 22:08:08 +08:00
5b1b9cc5b7 Fix QA issues: single AlertsProvider, null safety, snooze cleanup
- C1: Replaced duplicate useAlerts() calls with AlertsProvider context
  wrapping AppLayout — single hook instance, no double polling/toasts
- C2: Added null guard on remind_at in Active Reminders card format()
- W2: Clear snoozed_until when dismissing a reminder
- W5: Extracted getRelativeTime to shared lib/date-utils.ts
- S3: Replaced inline SVG with Lucide Bell component in toasts
- S4: Clear snoozed_until when remind_at is updated via PUT

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 00:56:56 +08:00
5080e23256 Add real-time reminder alerts with snooze/dismiss
- Backend: GET /api/reminders/due endpoint, PATCH snooze endpoint,
  snoozed_until column + migration
- Frontend: useAlerts hook polls every 30s, fires Sonner toasts on
  non-dashboard pages (max 3 + summary), renders AlertBanner on
  dashboard below stats row
- Dashboard Active Reminders card filters out items shown in banner

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 23:15:56 +08:00
819a4689b8 Add track project feature with sidebar nav and dashboard widget
Adds is_tracked boolean to projects, expandable tracked projects
in sidebar navigation, pin toggle on project cards/detail, and a
dashboard widget showing upcoming tasks from tracked projects.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 01:20:36 +08:00
4b5649758a Address code review findings for weather coordinates feature
- CRIT-1: Add lat/lon validation ([-90,90] and [-180,180]) in Pydantic schema
- WARN-1: Replace deprecated get_event_loop() with get_running_loop()
- SUG-1: Add GeoSearchResult response model to /search endpoint
- SUG-2: Dashboard weather query enables on coordinates too, not just city
- SUG-3: Clean up debounce timer on component unmount
- SUG-4: Fix geocoding URL from HTTP to HTTPS
- SUG-5: Add fallback display when weather_city is null but coords exist

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 12:17:41 +08:00
c2c4446ea6 Fix upcoming widget showing past items (yesterday's events, overdue todos)
- Add lower-bound date filter (>= today) for todos and reminders in /upcoming endpoint
- Accept client_date param for timezone-correct filtering
- Pass client_date from frontend to /upcoming API call

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 11:54:52 +08:00
bdae07fb7d Compact dashboard: single-line rows, multi-star, weather city
- UpcomingWidget: single-line rows with icon/title/date/type/priority
- CalendarWidget: whitespace-nowrap time ranges, no wrapping
- TodoWidget: compact dot + title + date + badge on one line
- Active Reminders: single-line with dot indicator
- CountdownWidget: supports array of starred events
- StatsWidget: shows city name in weather card
- Dashboard API: returns starred_events array (up to 5) instead of single

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 14:28:39 +08:00
374e07708f Fix QA review issues: route path, blocking I/O, API key leak, cache
- CRIT-1: Change weather route from /weather to / (was doubling prefix)
- CRIT-2: Use run_in_executor for urllib calls + parallel fetch
- WARN-1: Invalidate weather cache when city changes
- WARN-2: Sanitize error messages to prevent API key leakage
- SUG-2: Only enable weather query when city is configured
- SUG-4: Remove duplicate Bell import

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 13:36:06 +08:00
ca8b654471 Dashboard Phase 2: weather widget, starred events, quick add, thinner events
- Add weather router with OpenWeatherMap integration and 1-hour cache
- Add is_starred column to calendar events with countdown widget
- Add weather_city setting with Settings page input
- Replace people/locations stats with open todos count + weather card
- Add quick-add dropdown (event/todo/reminder) to dashboard header
- Make CalendarWidget events single-line thin rows
- Add rain warnings to smart briefing when chance > 40%
- Invalidate dashboard/upcoming queries on form mutations
- Migration 004: is_starred + weather_city columns

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 13:15:43 +08:00
1d21caaa62 Dashboard personalization: preferred name, colored dots, smart briefing
- Add preferred_name column to settings model/schema with migration
- Settings page gets Profile card with name input (saves on blur/enter)
- Dashboard greeting now shows "Good evening, Kyle." when name is set
- WeekTimeline dots use event's actual color when available
- New DayBriefing component shows time-of-day-aware contextual summary

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 07:37:43 +08:00
d99506c9e4 UI overhaul Stage 1: Dashboard redesign with refined dark luxury aesthetic
- Add Sora + DM Sans Google Fonts with heading/body font system
- New CSS variables for elevated surfaces, transitions, custom scrollbars
- Tailwind config: fade-in/slide-up animations, card-elevated color, font families
- Card component: hover glow, accent border on hover, smooth transitions
- New WeekTimeline component: 7-day horizontal strip with event dot indicators
- Dashboard: contextual time-of-day greeting, week timeline, redesigned 5-col layout
- Stats widget: accent-tinted gradients, icon glow backgrounds, uppercase labels
- Upcoming widget: colored left-border type indicators, unified timeline feed
- Calendar/Todo widgets: refined spacing, hover states, colored accent bars
- Sidebar: accent bar active state (border-l-2), backdrop-blur mobile overlay

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 01:35:01 +08:00
27c65ce40d Fix Round 2 code review findings: type safety, security, and correctness
Backend:
- Add Literal types for status/priority fields (project_task, todo, project schemas)
- Add AccentColor Literal validation to prevent CSS injection (settings schema)
- Add PIN max-length (72 char bcrypt limit) validation
- Fix event date filtering to use correct range overlap logic
- Add revocation check to auth_status endpoint for consistency
- Config: env-aware SECRET_KEY fail-fast, configurable COOKIE_SECURE

Frontend:
- Add withCredentials to axios for cross-origin cookie support
- Replace .toISOString() with local date formatter in DashboardPage
- Replace `as any` casts with proper indexed type access in forms
- Nginx: add CSP, Referrer-Policy headers; remove deprecated X-XSS-Protection
- Nginx: duplicate security headers in static asset location block

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 15:18:49 +08:00
1f6519635f Initial commit 2026-02-15 16:13:41 +08:00