docs: add expo tasks & etapes feature design spec

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Arthur Belleville 2026-04-15 09:06:42 +02:00
parent 4f31275c82
commit 32fd9c1b2e
No known key found for this signature in database

View file

@ -0,0 +1,158 @@
# Expo App: Tasks & Etapes Feature Design
**Date:** 2026-04-15
**Scope:** Add task and etape (stage) management to the Expo mobile app, reusing the existing Supabase backend.
## Context
The web app (`apps/main`) has a full kanban-based task system with etapes (parent tasks/stages). The Expo app (`xtablo-expo/`) currently has no task management. This spec brings task and etape CRUD to mobile with a mobile-native UX.
### Key Backend Facts
- **No REST API for tasks** — the web app queries Supabase directly via PostgREST. The mobile app will do the same.
- **Etapes are tasks with `is_parent: true`** — not a separate table. Child tasks link via `parent_task_id`.
- **View:** `tasks_with_assignee` joins assignee profile info (name, avatar).
- **RLS** handles authorization — no manual user filtering needed.
- **Task statuses:** `todo`, `in_progress`, `in_review`, `done`.
## Navigation & Entry Point
### Tablo Detail Screen
New screen: `app/(app)/tablo/[id].tsx`
Accessed by tapping a tablo in the existing tablos list. Contains:
- Header: tablo name, color indicator, status badge
- Task list as primary content (described below)
This screen becomes the natural place to add more sections later (files, members, settings).
**Route update:** The tablos list screen (`app/(app)/(tabs)/tablos.tsx`) navigates to this new screen on tablo tap, instead of the current behavior.
## Task List UI
The task list is organized as **collapsible sections by etape**:
### Section Structure
- Each **etape** renders as a section header: etape title, task count badge, collapse/expand chevron
- A **"Sans Étape"** section at the bottom for tasks with no `parent_task_id`
- Sections are ordered by etape `position` (ascending)
### Within Each Section
- Tasks grouped by status with small color-coded status sub-headers (Todo, In Progress, In Review, Done)
- Tasks ordered by `position` within each status group
### Task Row
Each task row displays:
- Status color dot (blue=todo, yellow=in_progress, purple=in_review, green=done)
- Title (single line, truncated)
- Assignee avatar (small circle, or empty circle placeholder if unassigned)
- Due date badge (gray normally, red if overdue)
### Interactions
- **Tap section header** → collapse/expand the section
- **Tap task row** → navigate to task detail screen
- **Swipe left on task** → reveal delete action with confirmation
- **Pull-to-refresh** → refetch tasks and etapes
- **Floating "+" button** (bottom-right) → navigate to task creation screen
## Task Detail Screen
New screen: `app/(app)/task/[id].tsx`
Used for both creating and editing tasks. Routes:
- **Edit:** `/task/{taskId}?tabloId={tabloId}``id` param is the task UUID
- **Create:** `/task/new?tabloId={tabloId}``id` param is the literal string `"new"`
### Form Fields
| Field | Input Type | Required | Notes |
|-------|-----------|----------|-------|
| Title | Text input | Yes | Single line |
| Description | Multiline text input | No | Expandable |
| Status | Horizontal segmented control | Yes | 4 options, color-coded. Defaults to "todo" on create. |
| Assignee | Bottom sheet picker | No | Lists tablo members with avatars. "Unassigned" option at top. |
| Etape | Bottom sheet picker | No | Lists etapes for the tablo. "Sans Étape" option at top. |
| Due date | Native date picker | No | iOS DateTimePicker / Android date dialog. Format: YYYY-MM-DD. |
### Behavior
- **Create mode:** Status defaults to "todo". Etape and assignee default to null. "Save" button creates the task via `useCreateTask()`.
- **Edit mode:** All fields pre-populated from existing task data. "Save" button updates via `useUpdateTask()`.
- **Delete:** Red "Delete" button at the bottom of the edit screen. Confirmation dialog before deletion via `useDeleteTask()`.
- **No auto-save** — explicit save button to avoid accidental edits on mobile.
## Etape Management
Managed directly from the tablo detail screen — no separate screen.
### Interactions
- **Long-press etape section header** → action menu with "Edit" and "Delete"
- **"+" button** next to the etape headers area → create new etape
- **Edit** → bottom sheet with: title input, description input, due date picker
- **Delete** → confirmation dialog. Child tasks become orphaned (move to "Sans Étape" section).
### No Reorder on Mobile
Etapes display in `position` order from the database. Manual drag-to-reorder is not implemented on mobile — users can reorder from the web app.
## Tablo Members (Read-Only)
A read-only members fetch to support the task assignee picker:
- Hook: `useTabloMembers(tabloId)`
- Query: Supabase query for tablo members with name, avatar, role
- Used only within the assignee picker bottom sheet
- No invite/manage/remove functionality
## New Files
### Screens
| File | Purpose |
|------|---------|
| `app/(app)/tablo/[id].tsx` | Tablo detail screen with task list |
| `app/(app)/tablo/_layout.tsx` | Layout for tablo routes |
| `app/(app)/task/[id].tsx` | Task detail/create/edit screen |
| `app/(app)/task/_layout.tsx` | Layout for task routes |
### Components
| File | Purpose |
|------|---------|
| `components/TaskList.tsx` | Full task list with etape sections |
| `components/TaskRow.tsx` | Single task row in the list |
| `components/EtapeSection.tsx` | Collapsible etape section header |
| `components/EtapeSheet.tsx` | Bottom sheet for etape create/edit |
| `components/AssigneePicker.tsx` | Bottom sheet for assignee selection |
| `components/EtapePicker.tsx` | Bottom sheet for etape selection |
| `components/StatusControl.tsx` | Horizontal segmented status selector |
### Hooks
| Hook | Query Key | Purpose |
|------|-----------|---------|
| `useTasksByTablo(tabloId)` | `["tasks", "tablo", tabloId]` | Fetch tasks for a tablo (from `tasks_with_assignee` view, `is_parent: false`) |
| `useCreateTask()` | mutation | Insert into `tasks` table |
| `useUpdateTask()` | mutation | Update task fields |
| `useDeleteTask()` | mutation | Hard delete task |
| `useTabloEtapes(tabloId)` | `["tablo-etapes", tabloId]` | Fetch etapes (`is_parent: true`) for a tablo |
| `useCreateEtape()` | mutation | Insert parent task |
| `useUpdateEtape()` | mutation | Update etape fields |
| `useDeleteEtape()` | mutation | Hard delete etape |
| `useTabloMembers(tabloId)` | `["tablo-members", tabloId]` | Fetch members for assignee picker |
### Cache Invalidation
Mutations invalidate:
- Task mutations → `["tasks", "tablo", tabloId]`
- Etape mutations → `["tablo-etapes", tabloId]` and `["tasks", "tablo", tabloId]`
## Out of Scope
- Drag-and-drop reordering (tasks or etapes)
- Kanban board view
- Batch position updates
- File management on tablo detail
- Member management (invite/remove)
- Tablo settings editing
- Subscription/upgrade gating (freemium checks)
- Push notifications for task assignments