91 Commits

Author SHA1 Message Date
80f3f3ed10 Calendar enhancements: scroll navigation, birthday color editing, event templates
- Add wheel scroll navigation in month view (debounced, prevents rapid scrolling)
- Allow editing color on system calendars (Birthdays) - name field disabled
- Event templates: full CRUD backend (model, schema, router, migration 011)
- Event templates: sidebar section with create/edit/delete, click to pre-fill EventForm
- Register event_templates router at /api/event-templates

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 17:34:16 +08:00
a11fcbcbcc Projects enhancements: inline editing, extended statuses, subtask interactions, kanban subtask view
- Inline task editing in TaskDetailPanel (replaces sheet-based edit flow)
- Extended task statuses: blocked, review, on_hold with color maps everywhere
- Click subtasks to navigate, delete subtasks from detail pane
- Kanban shows subtasks when a task with subtasks is selected
- Subtask sorting follows parent sort mode (priority/due_date)
- Progress bar on task rows showing subtask completion
- Default due date inheritance from parent task or project
- New status options in TaskForm select dropdown

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 12:04:10 +08:00
4169c245c2 Global enhancements: none priority, optional remind_at, required labels, textarea flex, remove color picker
- Add "none" priority (grey) to task/todo schemas, types, and all priority color maps
- Make remind_at optional on reminders (schema, model, migration 010)
- Add required prop to Label component with red asterisk indicator
- Add invalid:ring-red-500 to Input, Select, Textarea base classes
- Mark mandatory fields with required labels across all forms
- Replace fixed textarea rows with min-h + flex-1 for auto-expand
- Remove color picker from ProjectForm
- Align TaskRow metadata into fixed-width columns

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 11:58:19 +08:00
bfe97fd749 Fix 5 testing bugs: priority badge width, recurring event errors, nested subtask UI, comment timestamps, close button
- Widen priority badge from w-10 to w-14 to fit "medium" text, add "none" case
- Guard against null end_datetime in event update validation
- Exclude current event from this_and_future DELETE to prevent 404
- Use Python-side datetime.now for comment timestamps (avoids UTC offset)
- Hide "Add subtask" button when viewing a subtask (prevents nested nesting)
- Add X close button to TaskDetailPanel header on desktop

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 11:53:09 +08:00
6e50089201 ProjectDetail overhaul: master-detail layout, comments, sorting, kanban
- Backend: TaskComment model + migration, comment CRUD endpoints,
  task reorder endpoint, updated selectinload for comments
- Frontend: Two-panel master-detail layout with TaskRow (compact)
  and TaskDetailPanel (full details + comments section)
- Sort toolbar: manual (drag-and-drop via @dnd-kit), priority, due date
- Kanban board view with drag-and-drop between status columns
- Responsive: mobile falls back to overlay panel on task select

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 03:22:44 +08:00
3a7eb33809 Fix unused imports in ProjectDetail
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 02:57:53 +08:00
d4ba98c6eb UI refresh: Projects pages (Phase 4)
- ProjectsPage: h-16 header, segmented pill filter, summary stat cards
- ProjectCard: sentence case, stylesheet status colors, hover glow, overdue dates
- ProjectDetail: summary progress card, compact task rows, overdue highlighting
- ProjectForm: Dialog → Sheet migration, 2-column layout, delete in footer
- TaskForm: Dialog → Sheet migration, 2-column grid layout, delete in footer

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 02:56:07 +08:00
084daf5c7f Fix QA findings: null guard on end_datetime, reminders in night briefing, extract filter
- W1: Guard end_datetime null checks in DayBriefing (lines 48, 95, 112)
- W2: Include active reminders in pre-5AM night briefing fallback
- S1: Extract _not_parent_template filter constant in dashboard.py

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 02:36:11 +08:00
56876841c7 Fix scope dialog button alignment and night briefing showing wrong day
- Replace DialogFooter with plain div for vertical button layout in scope dialog
- Add today's remaining items to night briefing (before 5 AM) before tomorrow preview

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 02:13:16 +08:00
e22cad1d86 Fix QA findings: firstDay reactivity, state revert, helper extraction
- W1: Add key prop to FullCalendar so firstDay change triggers remount
- W2: Revert firstDayOfWeek toggle state on API failure
- S1: Extract _rule_int helper in recurrence service to reduce duplication

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 02:02:15 +08:00
f66ffba0ef Fix calendar not resizing when sidebar collapses
Use ResizeObserver on the calendar container to call
FullCalendar.updateSize() when the sidebar transition
changes the available width.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 01:39:23 +08:00
c62f8bc2a2 Add first day of week setting and fix calendar header alignment
- Add first_day_of_week column to settings (0=Sunday, 1=Monday)
- Add Calendar section in Settings with toggle button
- Pass firstDay to FullCalendar from settings
- Align calendar toolbar and sidebar header to h-16 (matches UMBRA header)
- Remove border/padding wrapper from calendar grid for full-width layout

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 01:33:45 +08:00
5701e067dd Fix issues from QA review: critical bugs, warnings, and accessibility
- C1: Nominatim search already uses run_in_executor (non-blocking)
- C2: Ensure target event is deleted in "this_and_future" scope
- W3: Add Field constraints (ge/le) on RecurrenceRule fields
- W4: Add safety cleanup for body overflow on Sheet unmount
- W5: Block drag-drop/resize on recurring events (must use scope dialog)
- W6: Discard stale LocationPicker responses via request ID
- S8: Add role="dialog" and aria-modal to Sheet component

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 01:22:57 +08:00
f826d05c60 Fix recurrence edit/delete scope and simplify weekly UI
- Weekly recurrence no longer requires manual weekday selection;
  auto-derives from event start date
- EventForm now receives and forwards editScope prop to API
  (edit_scope in PUT body, scope query param in DELETE)
- CalendarPage passes scope through proper prop instead of _editScope hack
- Backend this_and_future: inherits parent's recurrence_rule when child
  has none, properly regenerates children after edit
- Backend: parent-level edits now delete+regenerate all children

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 01:08:00 +08:00
232bdd3ef2 Fix recurrence_rule validation + smoother Sheet animation
- Add field_validator to coerce recurrence_rule from legacy strings,
  empty strings, and JSON strings into RecurrenceRule or None
- Increase Sheet slide-in duration to 350ms with cubic-bezier(0.16, 1, 0.3, 1)
  for a more premium feel

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 01:00:16 +08:00
d811890509 Add Sheet forms, recurrence UI, all-day fix, LocationPicker
- Sheet component: slide-in panel replacing Dialog for all forms
- EventForm: structured recurrence picker, all-day end-date offset fix,
  LocationPicker with OSM search integration
- CalendarPage: scope dialog for editing/deleting recurring events
- TodoForm/ReminderForm/LocationForm: migrated to Sheet with 2-col layouts
- LocationPicker: debounced search combining local DB + Nominatim results
- Backend: /locations/search endpoint with OSM proxy
- CSS: slimmer all-day event bars in calendar grid
- Types: RecurrenceRule interface, extended CalendarEvent fields

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 00:42:12 +08:00
5b056cf674 Add calendar redesign frontend with multi-calendar UI
- Custom toolbar replacing FullCalendar defaults (nav, today, view switcher)
- Calendar sidebar with visibility toggles, color dots, add/edit support
- CalendarForm dialog for creating/editing calendars with color swatches
- EventForm updated to use calendar dropdown instead of color picker
- CSS overrides: accent-tinted today highlight, now indicator, rounded event pills
- Types updated for Calendar interface and mixed id types

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 19:14:06 +08:00
7d4089762e Fix upcoming widget row alignment with consistent priority column
The priority badge was conditionally rendered, causing rows without
priority to have fewer flex children and shifting the date/type columns.
Now always renders a fixed-width priority slot (invisible when empty).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 12:36:35 +08:00
e74d4cf7c6 Align date/time column in upcoming widget
Give the date column a fixed width (7rem) and right-align it so
entries with different date formats (date-only vs datetime) line up.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 12:26:47 +08:00
7c02b4f824 Remove unused label variable in weather location dropdown
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 12:20:37 +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
1545da48e5 Add coordinate-based weather lookup with location search
Replace plain-text city input with geocoding search that resolves
lat/lon coordinates for accurate OpenWeatherMap queries. Users can
now search, see multiple results with state/country detail, and
select the exact location.

- Add GET /api/weather/search endpoint (OWM Geocoding API)
- Add weather_lat/weather_lon columns to settings model + migration
- Use lat/lon for weather API calls when available, fall back to city name
- Replace settings text input with debounced search + dropdown selector
- Show selected location as chip with clear button

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 12:11:02 +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
fa7b50233e Compact stat cards: ~50% shorter, recede as informational strip
- Padding: p-4 → px-3 py-2
- Number: text-3xl → text-xl
- Icons: p-2 h-5 w-5 → p-1.5 h-4 w-4
- Label/number gap: space-y-2 → space-y-0.5
- Weather: description + city inline with temp on one line
- Grid gap tightened from gap-3 to gap-2.5

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 14:48:54 +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
10546de751 Fix TS error: preferred_name can be null from API
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 07:59:23 +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
e9b3c90b0d Remove unused formatISO import from WeekTimeline
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 01:40:38 +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
c5adc316ef resolved event create bug 2026-02-19 20:44:14 +08:00
d5080f59af fixed day view visual bug 2026-02-19 20:38:11 +08:00
a352a50b63 resolved click & drag bug 2026-02-19 20:24:41 +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
1aaa2b3a74 Fix code review findings: security hardening and frontend fixes
Backend:
- Add rate limiting to login (5 attempts / 5 min window)
- Add secure flag to session cookies with helper function
- Add PIN min-length validation via Pydantic field_validator
- Fix naive datetime usage in todos.py (datetime.now() not UTC)
- Disable SQLAlchemy echo in production
- Remove auto-commit from get_db to prevent double commits
- Add lower bound filter to upcoming events query
- Add SECRET_KEY default warning on startup
- Remove create_all from lifespan (Alembic handles migrations)

Frontend:
- Fix ReminderForm remind_at slice for datetime-local input
- Add window.confirm() dialogs on all destructive actions
- Redirect authenticated users away from login screen
- Replace error: any with getErrorMessage helper in LockScreen

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 07:49:21 +08:00
ccfbf6df96 Add subtasks feature to project tasks
Backend:
- Add self-referencing parent_task_id FK on project_tasks with CASCADE delete
- Add Alembic migration 002 for parent_task_id column + index
- Update schemas with parent_task_id in create, nested subtasks in response
- Chain selectinload for subtasks on all project queries
- Validate parent must be top-level task (single nesting level only)

Frontend:
- Add parent_task_id and subtasks[] to ProjectTask type
- ProjectDetail: expand/collapse chevrons, subtask progress bars, inline
  subtask rendering with accent left border, add/edit/delete subtask buttons
- TaskForm: accept parentTaskId prop, include in create payload, context-aware
  dialog title (New Task vs New Subtask)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 01:31:46 +08:00
a1b2067faa Fix Sonner toaster blocking button clicks on login screen
Sonner's toaster container has z-index: 999999999 with no pointer-events: none,
creating an invisible overlay that intercepts clicks. Set pointer-events: none on
the container and pointer-events: auto on individual toasts so buttons underneath
remain clickable while toasts stay interactive.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 20:58:30 +08:00
cea1c36d92 Fix logout, category filter, dialog width, and mark all tests complete
- Add logout button to sidebar with destructive hover styling
- Fix case-sensitive todo category filter with .toLowerCase()
- Widen dialog popups from max-w-lg to max-w-xl with mobile margin
- Update CLAUDE.md with commit-and-push instruction
- Update progress.md: all CRUD tests verified, all outstanding items resolved

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 20:46:18 +08:00
e6387065ad updated name from lifemanager to umbra, 2026-02-15 20:21:55 +08:00
1f6519635f Initial commit 2026-02-15 16:13:41 +08:00