261 lines
9.9 KiB
Markdown
261 lines
9.9 KiB
Markdown
# Gantt Board
|
|
|
|
Task and sprint board built with Next.js + Zustand and Supabase-backed API persistence.
|
|
|
|
## Current Product Behavior
|
|
|
|
### Feb 20, 2026 updates
|
|
|
|
- Added task attachments with Supabase persistence.
|
|
- Added URL-based task detail pages (`/tasks/{taskId}`) so tasks can be opened/shared by link.
|
|
- Replaced flat notes/comments with threaded comments.
|
|
- Added unlimited nested replies (reply to comment, reply to reply, no depth limit).
|
|
- Updated UI wording from "notes" to "comments".
|
|
- Improved attachment opening/rendering by coercing MIME types (including `.md` as text) and using blob URLs for reliable in-browser viewing.
|
|
- Added lightweight collaborator identity tracking for task/comment authorship.
|
|
|
|
### Feb 21, 2026 updates
|
|
|
|
- Stabilized auth and settings flows with Supabase Auth credentials.
|
|
- Login/password validation now uses Supabase Auth credentials.
|
|
- Reset password flow no longer depends on `public.users.password_hash`.
|
|
- Settings API response handling was hardened to avoid client script errors.
|
|
- Avatar preset key collision warning in settings was fixed.
|
|
|
|
### Feb 22, 2026 updates
|
|
|
|
- Fixed sprint date timezone drift (for example `2026-02-22` rendering as `2/21` in US time zones).
|
|
- Standardized sprint date parsing across Kanban, Backlog, Sprint Board, Archive, and task detail sprint pickers.
|
|
- `POST /api/sprints` and `PATCH /api/sprints` now normalize `startDate`/`endDate` to `YYYY-MM-DD` before writing to Supabase.
|
|
|
|
### Feb 23, 2026 updates
|
|
|
|
- Removed non-live fallback data paths from the task store; board data now comes from Supabase-backed APIs only.
|
|
- Removed legacy schema expectations from API code and docs (`legacy_id`, `meta` dependency, non-existent task columns).
|
|
- Task detail now includes explicit Project + Sprint selection; selecting a sprint auto-aligns `projectId`.
|
|
- API validation now accepts UUID-shaped IDs used by existing data and returns clearer error payloads for failed writes.
|
|
|
|
### Sprint date semantics (important)
|
|
|
|
- Sprint dates are treated as local calendar-day boundaries:
|
|
- `startDate` means local `12:00:00 AM` of that date.
|
|
- `endDate` means local `11:59:59.999 PM` of that date.
|
|
- Supabase stores sprint dates as SQL `DATE` (`YYYY-MM-DD`) in `sprints.start_date` and `sprints.end_date`.
|
|
- API contract for `/api/sprints`:
|
|
- Accepts date strings with a `YYYY-MM-DD` prefix (`YYYY-MM-DD` or ISO timestamp).
|
|
- Normalizes and persists only the date part (`YYYY-MM-DD`).
|
|
- `PATCH` returns `400` for invalid `startDate`/`endDate` format.
|
|
- Example request payloads:
|
|
- `POST /api/sprints`
|
|
- `{ "name": "Sprint 1", "startDate": "2026-02-16", "endDate": "2026-02-22", "status": "active", "projectId": "<uuid>" }`
|
|
- `PATCH /api/sprints`
|
|
- `{ "id": "<sprint-id>", "startDate": "2026-02-16T00:00:00.000Z", "endDate": "2026-02-22T23:59:59.999Z" }`
|
|
- persisted as `start_date = '2026-02-16'`, `end_date = '2026-02-22'`
|
|
- Do not use `new Date("YYYY-MM-DD")` for sprint display logic. Use shared helpers:
|
|
- `parseSprintStart(...)`
|
|
- `parseSprintEnd(...)`
|
|
- `toLocalDateInputValue(...)`
|
|
|
|
### Data model and status rules
|
|
|
|
- Tasks use labels (`tags: string[]`) and can have multiple labels.
|
|
- Tasks support attachments (`attachments: TaskAttachment[]`).
|
|
- Tasks persist identity references via `createdById`, `updatedById`, and `assigneeId`.
|
|
- Display fields (`createdByName`, `updatedByName`, `assigneeName`, avatar/email) are resolved from `users` data in API/UI, not stored as separate task table columns.
|
|
- There is no active `backlog` status in workflow logic.
|
|
- A task is considered in Backlog when `sprintId` is empty.
|
|
- Current status values:
|
|
- `open`
|
|
- `todo`
|
|
- `blocked`
|
|
- `in-progress`
|
|
- `review`
|
|
- `validate`
|
|
- `archived`
|
|
- `canceled`
|
|
- `done`
|
|
- New tasks default to `status: open`.
|
|
|
|
### Authentication and sessions
|
|
|
|
- Added account-based authentication with:
|
|
- `POST /api/auth/register`
|
|
- `POST /api/auth/login`
|
|
- `POST /api/auth/logout`
|
|
- `GET /api/auth/session`
|
|
- Added a dedicated login/register screen at `/login`.
|
|
- Added account settings at `/settings` for authenticated users.
|
|
- Main board (`/`) and task detail pages (`/tasks/{taskId}`) require an authenticated session.
|
|
- Main board and task detail headers include quick access to Settings and Logout.
|
|
- API routes now enforce auth on task read/write/delete (`/api/tasks` returns `401` when unauthenticated).
|
|
- Added `PATCH /api/auth/account` to update profile and password for the current user.
|
|
- Session cookie: `gantt_session` (HTTP-only, same-site lax, secure in production).
|
|
- Added `Remember me` in auth forms:
|
|
- Checked: persistent 30-day cookie/session.
|
|
- Unchecked: browser-session cookie (clears on browser close), with server-side short-session expiry.
|
|
- Forgot-password currently uses a dev reset-link flow unless an external email provider is integrated.
|
|
- Task/comment authorship now uses authenticated user identity.
|
|
- Added `GET /api/auth/users` so task forms can load assignable users.
|
|
- User records now include optional `avatarUrl` profile photos.
|
|
|
|
### Task assignment
|
|
|
|
- You can assign or unassign tasks in:
|
|
- New Task modal
|
|
- Task detail popup on board
|
|
- URL task detail page (`/tasks/{taskId}`)
|
|
- New tasks default to the current signed-in user as assignee.
|
|
- Kanban and Backlog cards show a visible assignee avatar/initial pill.
|
|
- When someone else updates status (for example closes a task), updater fields still track who made that change.
|
|
|
|
### Profile photos and account settings
|
|
|
|
- Account Settings (`/settings`) has separate save actions:
|
|
- `Save Profile` for name/email/photo
|
|
- `Update Password` for password-only changes
|
|
- Profile photos can be uploaded/removed in settings.
|
|
- Users without uploaded photos get a generated default avatar (unique by user seed).
|
|
- Settings also provides multiple preset avatar choices.
|
|
- Profile photos appear in:
|
|
- Board/task header identity chips
|
|
- Assignee pills on Kanban and Backlog
|
|
- Threaded comment author avatars
|
|
- Creator/updater identity rows on task detail views
|
|
- Avatar updates persist in Supabase profile tables and propagate through session/user APIs.
|
|
|
|
### Labels
|
|
|
|
- Labels are independent of project/sprint selection.
|
|
- You can add/remove labels inline in:
|
|
- New Task modal
|
|
- Task Detail page
|
|
- Label entry supports:
|
|
- Enter/comma to add
|
|
- Existing-label suggestions
|
|
- Quick-add chips
|
|
- Case-insensitive de-duplication
|
|
|
|
### Task detail pages
|
|
|
|
- Clicking a task from Kanban or Backlog opens a dedicated route:
|
|
- `/tasks/{taskId}`
|
|
- Task detail is no longer popup-only behavior.
|
|
- Each task now has a shareable deep link.
|
|
- Task detail includes explicit Project and Sprint dropdowns.
|
|
|
|
### Attachments
|
|
|
|
- Task detail page supports adding multiple attachments per task.
|
|
- Attachments are stored with each task in Supabase and survive refresh/restart.
|
|
- Attachment UI supports:
|
|
- Upload multiple files
|
|
- Open/view file
|
|
- Markdown (`.md`) preview rendering in browser tab
|
|
- Text/code preview for common file types including iOS project/code files (`.swift`, `.plist`, `.pbxproj`, `.storyboard`, `.xib`, `.xcconfig`, `.entitlements`)
|
|
- Syntax-highlighted source rendering (highlight.js) with copy-source action
|
|
- CSV table preview and sandboxed HTML preview with source view
|
|
- Download file
|
|
- Remove attachment
|
|
|
|
### Threaded comments
|
|
|
|
- Comments are now threaded, not flat.
|
|
- You can:
|
|
- Add top-level comments
|
|
- Reply to any comment
|
|
- Reply to replies recursively (unlimited depth)
|
|
- Delete any comment or reply from the thread
|
|
- Thread data is persisted in Supabase through the existing `/api/tasks` sync flow.
|
|
|
|
### Backlog drag and drop
|
|
|
|
Backlog view supports moving tasks between:
|
|
- Current sprint
|
|
- Other sprint sections
|
|
- Backlog
|
|
|
|
Status behavior on drop:
|
|
- Drop into any sprint section: `status -> open`
|
|
- Drop into backlog section: `status -> open`
|
|
- `sprintId` is set/cleared based on destination
|
|
|
|
Changes persist through store sync to Supabase.
|
|
|
|
### Kanban drag and drop
|
|
|
|
Kanban supports drag by visible left handle on each task card.
|
|
|
|
Columns:
|
|
- `To Do` contains statuses: `open`, `todo`
|
|
- `In Progress` contains statuses: `blocked`, `in-progress`, `review`, `validate`
|
|
- `Done` contains statuses: `archived`, `canceled`, `done`
|
|
|
|
Drop behavior:
|
|
- Drop on column body: applies that column's default status
|
|
- `To Do` -> `open`
|
|
- `In Progress` -> `in-progress`
|
|
- `Done` -> `done`
|
|
- Drop on status chip target: applies exact status
|
|
- Drop on a task: adopts that task's exact status
|
|
|
|
During drag, the active target column shows expanded status drop zones for clarity.
|
|
|
|
### Layout
|
|
|
|
- Left sidebar cards (Current Sprint and Labels quick view) were removed.
|
|
- Main board now uses full width for Kanban/Backlog views.
|
|
|
|
## Persistence
|
|
|
|
- Client state is managed with Zustand.
|
|
- Persistence is handled through Supabase-backed API routes:
|
|
- `/api/tasks`
|
|
- `/api/projects`
|
|
- `/api/sprints`
|
|
- No local task/project/sprint fallback dataset is used.
|
|
- API reads/writes Supabase tables only.
|
|
|
|
## Run locally
|
|
|
|
```bash
|
|
npm install
|
|
npm run dev
|
|
```
|
|
|
|
Open `http://localhost:3000`.
|
|
Task URLs follow `http://localhost:3000/tasks/{taskId}`.
|
|
|
|
## Scripts
|
|
|
|
```bash
|
|
npm run dev
|
|
npm run build
|
|
npm run start
|
|
npm run lint
|
|
```
|
|
|
|
## CLI Tools for AI Access
|
|
|
|
Located in `scripts/` directory. These allow programmatic access without browser automation.
|
|
|
|
```bash
|
|
# Task CRUD
|
|
./scripts/gantt-task-crud.sh list [status] # List all tasks
|
|
./scripts/gantt-task-crud.sh get <task-id> # Get specific task
|
|
./scripts/gantt-task-crud.sh create "Title" [status] [priority] [project-id] [assignee-id]
|
|
./scripts/gantt-task-crud.sh update <task-id> <field> <value>
|
|
./scripts/gantt-task-crud.sh delete <task-id>
|
|
|
|
# File Attachments
|
|
./scripts/attach-file.sh <task-id> <file-path> # Attach file to task
|
|
./scripts/view-attachment.sh <task-id> [index] # View attachment content
|
|
```
|
|
|
|
**Requires:** `scripts/.env` with `SUPABASE_URL` and `SUPABASE_SERVICE_ROLE_KEY`
|
|
|
|
See: `STANDARD_CLI_INTEGRATION.md` in workspace for full pattern.
|
|
|
|
## Notes
|
|
|
|
- You may see a Next.js warning about multiple lockfiles and inferred workspace root. This is non-blocking for local dev.
|