- 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>
284 lines
12 KiB
Markdown
284 lines
12 KiB
Markdown
# UMBRA - Project Progress
|
|
|
|
## Overview
|
|
Personal life administration web app with dark theme, accent color customization, and Docker deployment.
|
|
|
|
**Stack:** React + TypeScript | FastAPI + SQLAlchemy | PostgreSQL | Docker Compose
|
|
|
|
---
|
|
|
|
## Milestone Tracker
|
|
|
|
### Phase 1: Scaffolding & Infrastructure
|
|
- [x] `docker-compose.yaml` - 3-service architecture (db, backend, frontend)
|
|
- [x] `.env` / `.env.example` - Environment configuration
|
|
- [x] `.gitignore` - Root gitignore
|
|
- [x] Backend: FastAPI app skeleton (`app/main.py`, `config.py`, `database.py`)
|
|
- [x] Backend: `requirements.txt` with all Python dependencies
|
|
- [x] Backend: Alembic migration setup (`alembic.ini`, `env.py`, initial migration)
|
|
- [x] Backend: `start.sh` startup script
|
|
- [x] Backend: `Dockerfile` - Python 3.12-slim
|
|
- [x] Frontend: Vite + React scaffold (`package.json`, `vite.config.ts`, `tsconfig.json`)
|
|
- [x] Frontend: Tailwind CSS + PostCSS configuration
|
|
- [x] Frontend: `index.html` entry point
|
|
- [x] Frontend: `nginx.conf` - SPA serving + API proxy
|
|
- [x] Frontend: `Dockerfile` - Multi-stage node build + nginx serve
|
|
- [x] Verify `docker-compose up --build` boots all services
|
|
|
|
### Phase 2: Auth & Layout
|
|
- [x] Backend: Settings model + schema
|
|
- [x] Backend: Auth router (PIN setup, login, logout, status with bcrypt + itsdangerous)
|
|
- [x] Frontend: `LockScreen.tsx` - PIN setup/login UI
|
|
- [x] Frontend: `useAuth.ts` hook (TanStack Query)
|
|
- [x] Frontend: `AppLayout.tsx` + `Sidebar.tsx` - Main layout with navigation
|
|
- [x] Frontend: Accent color theming system (`useTheme.ts`, CSS custom properties)
|
|
- [x] Frontend: 12 shadcn/ui components (button, card, input, dialog, select, badge, etc.)
|
|
|
|
### Phase 3: Core Features
|
|
- [x] Backend: Todo model, schema, router (CRUD + toggle + filters)
|
|
- [x] Frontend: `TodosPage`, `TodoList`, `TodoItem`, `TodoForm`
|
|
- [x] Backend: Calendar Event model, schema, router (CRUD + date range filter)
|
|
- [x] Frontend: `CalendarPage` (FullCalendar integration), `EventForm`
|
|
- [x] Frontend: FullCalendar dark theme CSS overrides in `index.css`
|
|
- [x] Backend: Reminder model, schema, router (CRUD + dismiss)
|
|
- [x] Frontend: `RemindersPage`, `ReminderList`, `ReminderForm`
|
|
|
|
### Phase 4: Project Management
|
|
- [x] Backend: Project model with tasks relationship + cascade delete
|
|
- [x] Backend: ProjectTask model, schema, router (nested CRUD under projects)
|
|
- [x] Frontend: `ProjectsPage`, `ProjectCard`, `ProjectDetail`, `ProjectForm`, `TaskForm`
|
|
|
|
### Phase 5: People & Locations
|
|
- [x] Backend: Person model, schema, router (CRUD + search)
|
|
- [x] Frontend: `PeoplePage`, `PersonCard`, `PersonForm`
|
|
- [x] Backend: Location model, schema, router (CRUD + category filter)
|
|
- [x] Frontend: `LocationsPage`, `LocationCard`, `LocationForm`
|
|
|
|
### Phase 6: Dashboard & Upcoming
|
|
- [x] Backend: Dashboard aggregation endpoint (stats, events, todos, reminders)
|
|
- [x] Backend: Upcoming endpoint (unified items sorted by date)
|
|
- [x] Frontend: `DashboardPage` with all widgets + upcoming integration
|
|
- [x] Frontend: `StatsWidget` (projects, people, locations counts)
|
|
- [x] Frontend: `UpcomingWidget` (unified timeline with type icons)
|
|
- [x] Frontend: `TodoWidget` (upcoming todos with priority badges)
|
|
- [x] Frontend: `CalendarWidget` (today's events with color indicators)
|
|
- [x] Frontend: Active reminders section in dashboard
|
|
|
|
### Phase 7: Settings & Polish
|
|
- [x] Backend: Settings router (get/update settings, change PIN)
|
|
- [x] Frontend: `SettingsPage` (accent color picker, upcoming range, PIN change)
|
|
- [x] Integration fixes: All frontend API paths match backend routes
|
|
- [x] Integration fixes: HTTP methods (PUT for updates, PATCH for toggle/dismiss)
|
|
- [x] Integration fixes: Type definitions match backend response schemas
|
|
- [ ] Integration testing (end-to-end CRUD verification) <-- POST-BUILD
|
|
- [x] Final styling pass (responsive sidebar, empty states, loading skeletons)
|
|
|
|
---
|
|
|
|
## Integration Fixes Applied
|
|
These were caught during review and fixed:
|
|
|
|
| Issue | Fix |
|
|
|-------|-----|
|
|
| Settings field `upcoming_days_range` | Renamed to `upcoming_days` |
|
|
| CalendarEvent fields `start`/`end` | Renamed to `start_datetime`/`end_datetime` |
|
|
| Reminder field `dismissed` | Renamed to `is_dismissed`, added `is_active` |
|
|
| Project status values | Changed from `active/on_hold` to `not_started/in_progress/completed` |
|
|
| Calendar API path `/calendar/events` | Fixed to `/events` |
|
|
| All update forms using `api.patch` | Fixed to `api.put` (backend uses PUT) |
|
|
| Todo toggle using generic PATCH | Fixed to `api.patch('/todos/{id}/toggle')` |
|
|
| Reminder dismiss using generic PATCH | Fixed to `api.patch('/reminders/{id}/dismiss')` |
|
|
| Settings update using PATCH | Fixed to `api.put` |
|
|
| PIN change path `/auth/change-pin` | Fixed to `/settings/pin` |
|
|
| Dashboard data shape mismatch | Aligned TodoWidget, CalendarWidget with actual API response |
|
|
| Missing UpcomingWidget in dashboard | Added with `/api/upcoming` fetch |
|
|
|
|
## Post-Build Fixes Applied
|
|
These were found during first Docker build and integration testing:
|
|
|
|
| Issue | Fix |
|
|
|-------|-----|
|
|
| `Person.relationship` column shadowed SQLAlchemy's `relationship()` function | Aliased import to `sa_relationship` in `person.py` |
|
|
| Missing `backend/app/__init__.py` | Created empty `__init__.py` for Python package recognition |
|
|
| Backend port 8000 not exposed in `docker-compose.yaml` | Added `ports`, `healthcheck`, and `condition: service_healthy` |
|
|
| `get_db()` redundant `session.close()` inside `async with` | Removed `finally: await session.close()` |
|
|
| `datetime.utcnow()` deprecated in Python 3.12 | Replaced with `datetime.now(timezone.utc)` in `todos.py` |
|
|
| Calendar date selection wiped start/end fields | Added `formatInitialDate()` to convert date-only to `datetime-local` format |
|
|
| Dashboard "today's events" used server UTC time | Added `client_date` query param so frontend sends its local date |
|
|
| Calendar drag-and-drop didn't persist | Added `eventDrop` handler with backend PUT call |
|
|
| Timed event drag-and-drop sent timezone-aware datetimes to naive DB column | Used `toLocalDatetime()` helper instead of `.toISOString()` |
|
|
| All-day event dates empty when editing (datetime vs date format mismatch) | Added `formatForInput()` to normalize values for `date` vs `datetime-local` inputs |
|
|
| Project create/update `MissingGreenlet` error (lazy load in async context) | Re-fetch with `selectinload(Project.tasks)` after commit in `projects.py` |
|
|
| Generic error toasts gave no useful information | Added `getErrorMessage()` helper to `api.ts`, updated all 8 form components |
|
|
| Sidebar not responsive on mobile | Split into desktop sidebar + mobile overlay with hamburger menu in `AppLayout` |
|
|
| Plain "Loading..." text on all pages | Created `Skeleton`, `ListSkeleton`, `GridSkeleton`, `DashboardSkeleton` components |
|
|
| Basic empty states with no visual cue | Created `EmptyState` component with icon, message, and action button across all pages |
|
|
| No logout button | Added logout button to sidebar footer with `LogOut` icon and destructive hover style |
|
|
| Todo category filter was case sensitive | Changed to case-insensitive comparison with `.toLowerCase()` |
|
|
| Dialog/popup forms too narrow and cramped | Widened `DialogContent` from `max-w-lg` to `max-w-xl` with mobile margin |
|
|
|
|
---
|
|
|
|
## Outstanding Items (Resume Here If Halted)
|
|
|
|
### Critical (blocks deployment):
|
|
1. ~~**Docker build verification**~~ - DONE: All 3 services boot successfully
|
|
2. ~~**npm install verification**~~ - DONE: Frontend packages install correctly
|
|
|
|
### Important (blocks functionality):
|
|
3. ~~**Alembic migration test**~~ - DONE: Tables create correctly on first boot
|
|
4. ~~**Auth flow test**~~ - DONE: PIN setup works, PIN change works, session persistence works, logout added
|
|
5. ~~**End-to-end CRUD test**~~ - DONE: All features verified — Calendar, Projects, Todos (create/edit/filter/search), People (CRUD + search), Locations (CRUD + filter), Reminders (CRUD + dismiss), Settings (accent color + PIN)
|
|
|
|
### Nice to have (polish):
|
|
6. ~~**Responsive sidebar**~~ - DONE: Mobile hamburger menu with overlay, desktop collapse/expand
|
|
7. ~~**Toast notifications**~~ - DONE: All forms now show meaningful error messages via `getErrorMessage()`
|
|
8. ~~**Empty states**~~ - DONE: All pages show icon + message + action button when empty
|
|
9. ~~**Loading skeletons**~~ - DONE: Animated skeleton placeholders replace plain "Loading..." text
|
|
|
|
---
|
|
|
|
## File Inventory (100+ files total)
|
|
|
|
### Backend (40 files)
|
|
```
|
|
backend/
|
|
├── Dockerfile
|
|
├── requirements.txt
|
|
├── start.sh
|
|
├── .gitignore
|
|
├── alembic.ini
|
|
├── alembic/
|
|
│ ├── env.py
|
|
│ ├── script.py.mako
|
|
│ └── versions/
|
|
│ └── 001_initial_migration.py
|
|
└── app/
|
|
├── main.py
|
|
├── config.py
|
|
├── database.py
|
|
├── models/
|
|
│ ├── __init__.py
|
|
│ ├── settings.py
|
|
│ ├── todo.py
|
|
│ ├── calendar_event.py
|
|
│ ├── reminder.py
|
|
│ ├── project.py
|
|
│ ├── project_task.py
|
|
│ ├── person.py
|
|
│ └── location.py
|
|
├── schemas/
|
|
│ ├── __init__.py
|
|
│ ├── settings.py
|
|
│ ├── todo.py
|
|
│ ├── calendar_event.py
|
|
│ ├── reminder.py
|
|
│ ├── project.py
|
|
│ ├── project_task.py
|
|
│ ├── person.py
|
|
│ └── location.py
|
|
└── routers/
|
|
├── __init__.py
|
|
├── auth.py
|
|
├── dashboard.py
|
|
├── todos.py
|
|
├── events.py
|
|
├── reminders.py
|
|
├── projects.py
|
|
├── people.py
|
|
├── locations.py
|
|
└── settings.py
|
|
```
|
|
|
|
### Frontend (60+ files)
|
|
```
|
|
frontend/
|
|
├── Dockerfile
|
|
├── nginx.conf
|
|
├── package.json
|
|
├── vite.config.ts
|
|
├── tsconfig.json
|
|
├── tsconfig.node.json
|
|
├── postcss.config.js
|
|
├── tailwind.config.ts
|
|
├── components.json
|
|
├── index.html
|
|
├── .gitignore
|
|
└── src/
|
|
├── main.tsx
|
|
├── App.tsx
|
|
├── index.css (includes FullCalendar dark overrides)
|
|
├── lib/
|
|
│ ├── utils.ts
|
|
│ └── api.ts
|
|
├── hooks/
|
|
│ ├── useAuth.ts
|
|
│ ├── useSettings.ts
|
|
│ └── useTheme.ts
|
|
├── types/
|
|
│ └── index.ts
|
|
└── components/
|
|
├── ui/ (12 components)
|
|
├── layout/ (AppLayout, Sidebar)
|
|
├── auth/ (LockScreen)
|
|
├── dashboard/ (DashboardPage, StatsWidget, UpcomingWidget, TodoWidget, CalendarWidget, ProjectsWidget)
|
|
├── todos/ (TodosPage, TodoList, TodoItem, TodoForm)
|
|
├── calendar/ (CalendarPage, EventForm)
|
|
├── reminders/ (RemindersPage, ReminderList, ReminderForm)
|
|
├── projects/ (ProjectsPage, ProjectCard, ProjectDetail, ProjectForm, TaskForm)
|
|
├── people/ (PeoplePage, PersonCard, PersonForm)
|
|
├── locations/ (LocationsPage, LocationCard, LocationForm)
|
|
└── settings/ (SettingsPage)
|
|
```
|
|
|
|
### Root
|
|
```
|
|
docker-compose.yaml
|
|
.env / .env.example
|
|
.gitignore
|
|
progress.md
|
|
```
|
|
|
|
---
|
|
|
|
## How to Resume Development
|
|
|
|
If development is halted, pick up from the **Outstanding Items** section above:
|
|
|
|
1. Check which items are still marked incomplete in the Milestone Tracker
|
|
2. Address **Critical** items first (Docker build verification)
|
|
3. Then **Important** items (auth flow, CRUD testing)
|
|
4. Finally **Polish** items (responsive, loading states)
|
|
|
|
### Quick Start Commands
|
|
```bash
|
|
# Build and run everything
|
|
docker-compose up --build
|
|
|
|
# Rebuild just backend after changes
|
|
docker-compose up --build backend
|
|
|
|
# Rebuild just frontend after changes
|
|
docker-compose up --build frontend
|
|
|
|
# View logs
|
|
docker-compose logs -f
|
|
|
|
# View specific service logs
|
|
docker-compose logs -f backend
|
|
docker-compose logs -f frontend
|
|
|
|
# Reset database (destructive)
|
|
docker-compose down -v && docker-compose up --build
|
|
|
|
# Stop everything
|
|
docker-compose down
|
|
```
|
|
|
|
### First-Time Setup
|
|
1. Run `docker-compose up --build`
|
|
2. Navigate to `http://localhost`
|
|
3. You'll see the PIN setup screen (first run)
|
|
4. Create a PIN and you'll be redirected to the dashboard
|
|
5. Use the sidebar to navigate between features
|