diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 0c3ddd5..c46d5e5 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -46,7 +46,9 @@ "Bash(where jq *)", "Bash(powershell -NonInteractive -Command ' *)", "Bash(powershell -NonInteractive -Command \"Get-Content '.claude/settings.json' | ConvertFrom-Json | ConvertTo-Json -Depth 10\")", - "Bash(node -e \"const rw = require\\('react-window'\\); console.log\\(Object.keys\\(rw\\)\\)\")" + "Bash(node -e \"const rw = require\\('react-window'\\); console.log\\(Object.keys\\(rw\\)\\)\")", + "Bash(git log *)", + "Bash(Get-Content .env.example)" ] }, "hooks": { diff --git a/CLAUDE.md b/CLAUDE.md index 42eeee9..7b2bff8 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -14,14 +14,16 @@ npm run lint # ESLint ## Modelo de Dados -**Task:** `id, title, clickupLink?, assignee, status ('backlog'|'em andamento'|'bloqueado'|'concluído'), phases {design,approval,dev,qa} cada com {start,end} YYYY-MM-DD, createdAt` +**Task:** `id, title, clickupLink?, status {blocked, blockedAt?}, subtasks: Subtask[], createdAt, concludedAt?, concludedBy?, clientId?` + +**Subtask:** `id, title (livre, obrigatório), status (SubtaskStatus), start (YYYY-MM-DD), end (YYYY-MM-DD), assignees (member ids), active, order` — substitui o antigo `Step`. Tabela: `task_subtasks` + `subtask_assignees`. + +**SubtaskStatus (enum):** `analise-ux` | `analise-dev` | `design` | `aprovacao-design` | `desenvolvimento` | `homologacao` | `qa` | `publicacao` — controla a cor/ícone da subtask nas views; o título é livre. **Member:** `id, name, role ('Designer'|'Developer'), avatar (iniciais), avatar_url?, email?, auth_user_id?, access_role ('admin'|'user'), is_active?, created_at?, deactivated_at?` **UserPreferences:** `id, user_id (fk → members.id), theme ('light'|'dark'|'system'), language ('pt-BR'|'en'), notifications_enabled, default_view ('home'|'calendar'|'timeline'|'list'), client_order (text[]), notification_step_overdue (bool, def true), notification_task_stalled (bool, def true), notification_member_overloaded (bool, def true), stalled_days_threshold (int 1–30, def 5), overload_threshold (int 1–20, def 3), created_at, updated_at` -**Fases:** Design (5d, violeta) → Approval (3d, laranja) → Dev (7d, azul) → QA (3d, esmeralda). Cascata automática. - ## Branding - **Nome:** Run/Way diff --git a/docs/components/task-modal.md b/docs/components/task-modal.md index d14a02a..869186b 100644 --- a/docs/components/task-modal.md +++ b/docs/components/task-modal.md @@ -2,18 +2,44 @@ **Ficheiro:** `src/components/TaskModal.tsx` -## Cascata de Fases -Ao alterar o **início** de uma fase, a duração é preservada e fases seguintes avançam. Ao alterar o **fim**, fases seguintes arrastam (cascata bidirecional). +## Responsabilidade -### Restrições (garantidas após cada alteração) -- `approval.start` >= `nextBusinessDay(design.end)` -- `dev.start` >= `nextBusinessDay(approval.end)` -- `qa.start` >= `nextBusinessDay(dev.end)` +Modal de criação e edição de demandas. Gere o formulário de subtasks de forma dinâmica (N subtasks livres, sem lista fixa de 8 tipos). + +## Subtasks + +Cada subtask tem: +- **title** (obrigatório) — nome livre dado pelo usuário +- **status** (`SubtaskStatus`) — controla cor/ícone; dropdown com os 8 valores de `STEP_TYPES_ORDER` +- **progressStatus** (`SubtaskProgressStatus`) — andamento operacional: A fazer, Pronta, Em andamento, Em revisão, Aguardando, Bloqueada, Precisa de ajustes, Pausada, Concluída ou Cancelada +- **start / end** — datas obrigatórias quando subtask existe +- **assignees** — opcional; toggle por membro +- Botão de remover por subtask +- Botão "+ Adicionar subtask" no rodapé da lista + +Nova demanda começa **sem subtasks**. O usuário adiciona livremente. ## Validação + - `title`: mín. 3 caracteres -- `clickupLink`: opcional, deve começar com `http` +- `clickupLink`: opcional, deve ser URL válida (`https://...`) +- Pelo menos 1 subtask com `title` preenchido e datas `start`/`end` válidas (`end >= start`) + +## Confirmação de fim de semana / feriado + +Se alguma subtask tiver datas em fim de semana ou feriado, exibe `ConfirmModal` com 3 opções: +- Salvar mesmo assim +- Prolongar para próximo dia útil (via `nextNonHolidayBusinessDay`) +- Cancelar + +## Lógica de estado + +O estado interno usa `SubtaskDraft` (Subtask + `_tempId` para identificação local antes de persistir). Subtasks novas têm `id: ''`; subtasks existentes mantêm o `id` do banco — o `updateTask` do CRUD diferencia novas (INSERT) de existentes (UPDATE/DELETE) por este campo. + +## Dirty detection / submit + +`useFormState` rastreia `isDirty` comparando snapshot inicial vs estado atual. Botão "Salvar" desabilitado enquanto `!isDirty || submitting`. ## Apagar Demanda -- Botão "Apagar" no footer (só visível ao editar) -- Confirmação via `confirm()` antes de eliminar + +Botão "Apagar" no footer (só visível ao editar). Delega para prop `onDelete`. diff --git a/docs/components/ui.md b/docs/components/ui.md index a0b7088..f7267a7 100644 --- a/docs/components/ui.md +++ b/docs/components/ui.md @@ -14,4 +14,30 @@ Wrapper sobre `