39 Commits

Author SHA1 Message Date
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
d89758fedf Add materialized recurring events backend
- Migration 007: parent_event_id (self-ref FK CASCADE), is_recurring, original_start columns on calendar_events
- CalendarEvent model: three new Mapped[] columns for recurrence tracking
- RecurrenceRule Pydantic model: typed schema for every_n_days, weekly, monthly_nth_weekday, monthly_date
- CalendarEventCreate/Update: accept structured RecurrenceRule (router serializes to JSON string for DB)
- CalendarEventUpdate: edit_scope field (this | this_and_future)
- CalendarEventResponse: exposes parent_event_id, is_recurring, original_start
- recurrence.py service: generates unsaved child ORM objects from parent rule up to 365-day horizon
- GET /: excludes parent template rows (children are displayed instead)
- POST /: creates parent + bulk children when recurrence_rule provided
- PUT /: scope=this detaches occurrence; scope=this_and_future deletes future siblings and regenerates
- DELETE /: scope=this deletes one; scope=this_and_future deletes future siblings; no scope deletes all (CASCADE)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 00:37:21 +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
093bceed06 Add multi-calendar backend support with virtual birthday events
- New Calendar model and calendars table with system/default flags
- Alembic migration 006: creates calendars, seeds Personal+Birthdays, migrates existing events
- CalendarEvent model gains calendar_id FK and calendar_name/calendar_color properties
- Updated CalendarEventCreate/Response schemas to include calendar fields
- New /api/calendars CRUD router (blocks system calendar deletion/rename)
- Events router: selectinload on all queries, default-calendar assignment on POST, virtual birthday event generation from People with birthdays when Birthdays calendar is visible

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 19:07:35 +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
97242ee928 Fix dashboard endpoint returning past todos and reminders
- Add lower-bound filter (>= today) for upcoming_todos in /dashboard
- Add lower-bound filter (>= today_start) for active_reminders
- Prevents DayBriefing summary from referencing stale items

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 11:58:36 +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
a638b39d4d updated .env.example to include openweathermap api key input 2026-02-20 14:03:32 +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
b60ea1ace2 Merge branch 'ui/dashboard-overhaul' of https://git.sentinelforest.xyz/rohskiddo/UMBRA into ui/dashboard-overhaul 2026-02-20 01:36:10 +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
7ecc81f27e 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:31:52 +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
901c766ced restructure of directory 2026-02-18 21:48:06 +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
81edf81d13 Fix MissingGreenlet on subtask serialization
Chain second-level selectinload(ProjectTask.subtasks) on task create, update,
and list endpoints. Pydantic's recursive ProjectTaskResponse schema accesses
.subtasks on each subtask, which triggers lazy loading without eager load.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 01:39:41 +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
47baf2529c updated claud.md 2026-02-16 00:26:30 +08:00
01aa7d0694 updated claud.md with more specific subagent use 2026-02-15 23:58:08 +08:00
f128b07e12 updated claude and gitignore 2026-02-15 21:04:42 +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
96c225f4f7 updated README.md 2026-02-15 16:19:55 +08:00
c0a9d6ab95 Update README.md 2026-02-15 08:17:15 +00:00
1f6519635f Initial commit 2026-02-15 16:13:41 +08:00