Commit graph

16 commits

Author SHA1 Message Date
le king fu
78471543c3 fix: separate subtask expand chevron from detail view icon (#63)
Split TaskItem into two independent states:
- `expanded` (chevron): toggles subtask visibility, only shown when
  subtasks exist
- `detailOpen` (search icon + title click): opens detail panel with
  notes, priority, edit/delete actions

The two actions are fully independent — expanding subtasks does not
open the detail view and vice versa.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 21:15:59 -04:00
le king fu
21020406b2 fix: prevent sub-subtask creation, limit nesting to 2 levels (#62)
Web: hide "Add subtask" button when depth >= 1 in TaskItem.
API: reject task creation if parentId points to a task that already
has a parentId (max depth validation).
Mobile: hide subtask section in task detail when viewing a subtask.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 21:13:43 -04:00
le king fu
894ac03072 feat: add refresh button on web + swipe-to-refresh on mobile (#61)
Web: add a RefreshCw button next to the list title in TaskList that
calls router.refresh() with a spin animation.

Mobile: add RefreshControl to DraggableFlatList on both inbox and
list detail screens, using the app's blue accent color.

Also deduplicate list insert values in sync/route.ts (review feedback).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 21:04:55 -04:00
le king fu
6c36ebcce5 fix: wrap inbox merge in transaction, revert seed to random UUID (#60)
Address review feedback:
1. Wrap inbox deduplication (select, reassign tasks, soft-delete) in a
   db.transaction() for atomicity.
2. Revert seed.ts to use random UUID — a fixed ID shared across users
   would cause PK conflicts. The sync endpoint handles deduplication.
3. Subtasks share the same listId as their parent, so the reassign
   query already covers them (clarified in comment).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 20:54:55 -04:00
le king fu
d9daf9eda4 fix: resolve duplicate inbox on web after mobile sync (#60)
When mobile syncs its inbox (fixed ID) to the web, check if an inbox
already exists for the user. If so, reassign tasks and soft-delete the
old inbox to prevent duplicates. Also harmonize seed.ts to use the same
fixed inbox ID as mobile.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 20:50:12 -04:00
le king fu
8f7204e4b1 fix: resolve sync data inconsistency between mobile and web (#55)
Three root causes fixed:

1. API GET /api/sync returned raw entities but mobile client expected
   {changes: [...], sync_token} format — pullChanges() iterated
   data.changes which was undefined, silently skipping all server data.
   Now transforms entities into the SyncPullChange format.

2. Mobile outbox writes used snake_case keys (due_date, list_id, etc.)
   but server processOperation spreads data directly into Drizzle which
   expects camelCase (dueDate, listId). Fixed all outbox writes to use
   camelCase. Also fixed task_tag → taskTag entity type.

3. Missing completedAt in task outbox payloads — completion state was
   lost during sync. Added completedAt to both create and update outbox
   entries, and added Date conversion in server update handler.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 15:28:36 -04:00
le king fu
a5e9aa6f09 fix: rename .env.example to .env.template to avoid false positive (#53)
The defenseur flagged web/.env.example as a tracked secret file.
Renaming to .env.template avoids the .env* pattern match while
keeping the same purpose as a configuration template.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 15:20:55 -04:00
le king fu
89b3dada4a fix: replace Link with anchor tags for Logto auth routes
Next.js <Link> components prefetch routes on render/hover. When used
for /api/logto/sign-out, this triggered the sign-out handler during
normal navigation, clearing the session cookie and causing auth loops.

Also: wrap getAuthenticatedUser with React cache() for deduplication,
clean up diagnostic logging.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 14:31:04 -04:00
le king fu
9933c3678e fix: pass full URL to handleSignIn for callback URI matching
The Logto SDK needs the full callback URL (not just searchParams) to
verify it matches the redirect URI registered during sign-in.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 13:28:08 -04:00
le king fu
f786947941 fix: resolve Logto auth crash on web — remove illegal cookie set in layout
The (app)/layout.tsx was calling cookieStore.set() which is forbidden in
Server Components under Next.js 16 (only allowed in Server Actions and
Route Handlers). This caused a 500 error immediately after Logto login.

Also includes: mobile sync client improvements, i18n updates, web API
rate limiting, Bearer token support for mobile clients, and Dockerfile
optimizations.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 13:12:59 -04:00
le king fu
6328a8d0d3 fix: correct Logto session cookie prefix in middleware
Cookie is named `logto_<appId>` not `logto:<appId>`.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 08:56:21 -04:00
le king fu
cb04adcc2e feat: implement web frontend with full task management UI (#39)
- Protected (app) layout with sidebar, header, theme toggle
- List detail page with tasks, filters, sorting
- Inline task editing (title, notes, priority, due date, recurrence)
- Subtask creation and nested display
- Dark mode (class-based, persisted to localStorage)
- WebSocket sync hook (connects via ticket auth, auto-refresh)
- Responsive sidebar (hamburger on mobile)
- French UI strings throughout
- Components: Sidebar, TaskList, TaskItem, TaskForm, FilterBar,
  ThemeToggle, Header, AppShell

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 12:40:11 -04:00
le king fu
6d2e7449f3 feat: add WebSocket server with ticket auth and heartbeat (#38)
- Custom server (server.ts) wrapping Next.js + ws on same port
- Ticket-based auth: validates ephemeral nonce from /api/ws-ticket
- Origin validation against allowlist
- Session revalidation every 15 min (sends auth_expired, closes)
- Heartbeat every 30s (ping/pong, terminates dead connections)
- broadcastToUser() for API routes to notify connected clients
- Shared ticket store between API route and WS server via globalThis
- Health endpoint now reports active WS connections
- Dockerfile updated to use custom server

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 11:55:28 -04:00
le king fu
be9ba65337 feat: implement REST API backend with full CRUD and sync (#37)
- Lists, Tasks, Tags CRUD endpoints with soft-delete
- Sync endpoints (GET since + POST batch with idempotency keys)
- WS ticket endpoint (ephemeral nonce, 30s TTL, single use)
- Auth middleware on all endpoints via getAuthenticatedUser()
- BOLA prevention: userId check on every entity operation
- Zod strict schemas for input validation
- Filters and sorting on task listing

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 11:47:53 -04:00
le king fu
42c39907cd feat: integrate Logto auth with middleware and login page (#36)
- Logto config matching la-compagnie-maximus pattern
- API routes: sign-in, callback, sign-out
- Next.js middleware protecting all routes except /auth and /api
- Auth helper to extract userId (sub) from Logto context
- Login page with Compte Maximus branding

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 11:37:20 -04:00
le king fu
022fe53b92 feat: setup Next.js web project with Drizzle + PostgreSQL schema (#35)
- Init Next.js App Router with TypeScript, Tailwind, standalone output
- Drizzle ORM pg-core schema (sl_lists, sl_tasks, sl_tags, sl_task_tags)
- Database client, seed script, drizzle.config
- Health endpoint (/api/health) with DB latency check
- Dockerfile for Coolify deployment
- .env.example with DATABASE_URL and Logto config placeholders

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 11:03:34 -04:00