# Plano de Desenvolvimento - Sistema de Chamados ## Meta imediata Construir o nucleo de tickets compartilhado entre web e desktop (Tauri), garantindo base solida para canais, SLAs e automacoes futuras. ## Fase A - Fundamentos da plataforma 1. **Scaffold e DX** - Criar projeto Next.js (App Router) com Typescript, ESLint, Tailwind, shadcn/ui. - Configurar alias de paths, lint/prettier opinativo. - Ajustar `globals.css` para tokens de cor/tipografia conforme layout base. 2. **Design system inicial** - Importar componentes `dashboard-01` e `sidebar-01` via shadcn. - Ajustar paleta (tons de cinza + destaque primario) e tipografia (Inter/Manrope). - Implementar layout shell (sidebar + header) reutilizavel. 3. **Autenticacao placeholder** - Configurar stub de sessao (cookie + middleware) para navegacao protegida. ### Status da fase - OK Scaffold Next.js + Tailwind + shadcn/ui criado em `web/`. - OK Layout base atualizado (sidebar, header, cards, grafico) com identidade da aplicacao. - OK Auth placeholder via cookie + middleware e bootstrap de usuario no Convex. ## Fase B - Nucleo de tickets 1. **Modelagem compartilhada** - Definir esquema Prisma para Ticket, TicketEvent, User (minimo), Queue/View. - Publicar Zod schemas/Types para uso no frontend. 2. **Fluxo principal** - Pagina `tickets` com tabela (TanStack) suportando filtros basicos. - Pagina de ticket com timeline de eventos/comentarios (dados mockados). - Implementar modo play preliminar (simula proxima tarefa da fila). 3. **Mutations** - Formulario de criacao/edicao com validacao. - Comentarios publico/privado (UX + componentes). ### Status parcial - OK `prisma/schema.prisma` criado com entidades centrais (User, Team, Ticket, Comment, Event, SLA). - OK Schemas Zod e mocks compartilhados em `src/lib/schemas` e `src/lib/mocks`. - OK Paginas `/tickets`, `/tickets/[id]` e `/play` prontas com componentes dedicados (filtros, tabela, timeline, modo play). - OK Integração com backend Convex (consultas/mutações + file storage). Prisma mantido apenas como referência. ## Fase C - Servicos complementares (posterior) - SLAs (BullMQ + Redis), notificacoes, ingest de e-mail, portal cliente, etc. ## Backlog imediato - [x] Expor portal do cliente com listagem de tickets filtrada por `viewerId` (Convex + UI) - [x] Completar painel administrativo (times, filas, campos e SLAs) com RBAC server/client - [ ] Consolidar sincronização Better Auth ↔ Convex para fluxo de convites e resets de senha - [ ] Expandir suite de testes (UI + Convex) cobrindo guardas, relatórios e mapeadores críticos - [ ] Implementar fluxo completo de convites (criação, envio, revogação e aceite) para administradores - [ ] Habilitar ações avançadas para agentes (edição de categorias, reassigação rápida) com as devidas permissões ### Iniciativa atual — Autenticação real e personas - [x] Migrar placeholder para Better Auth + Prisma (handlers Next, cliente React e sync Convex). - [x] Expor roles (`admin`, `agent`, `customer`) e aplicar guardas (`requireUser/Staff/Admin/Customer`) no Convex. - [x] Ajustar middleware e componentes para usar `viewerId`/`actorId`, evitando vazamento de dados entre tenants. - [x] Criar portal do cliente para abertura/consulta de chamados e comentários públicos. - [x] Consolidar painel administrativo (times, filas, campos e SLAs) com UI protegida por RBAC completo. - [ ] Entregar fluxo de convites Better Auth (criação, envio, revogação) e gerenciamento de agentes. ## Proximas entregas sugeridas 1. Finalizar onboarding/offboarding de agentes com convites Better Auth, sincronização Convex e trilhas de auditoria. 2. Evoluir painel administrativo com gestão de categorias avançadas e permissões granulares para agentes. 3. Expandir relatórios operacionais (workSummary, tendências de SLA/CSAT) com alertas e comparativos configuráveis. 4. Automatizar pipeline CI (lint + vitest) integrando checagens obrigatórias. 5. Revisar UX dos fluxos de atendimento (play next, comentários) com feedback otimista e trilha de auditoria. ## Acompanhamento Atualizar este arquivo a cada marco relevante (setup concluido, nucleo funcional, etc.). --- # Guia do Projeto (para agentes e contribuidores) Este repositório foi atualizado para usar Convex como backend em tempo real para o núcleo de tickets. Abaixo, um guia prático conforme o padrão de AGENTS.md para orientar contribuições futuras. ## Decisões técnicas atuais - Backend: Convex (funções + banco + storage) em `web/convex/`. - Esquema: `web/convex/schema.ts`. - Tickets API: `web/convex/tickets.ts` (list/getById/create/addComment/updateStatus/playNext). - Upload de arquivos: `web/convex/files.ts` (Convex Storage). - Filas: `web/convex/queues.ts` (resumo por fila). - Seed/bootstrap: `web/convex/seed.ts`, `web/convex/bootstrap.ts`. - Autenticação: Better Auth + Prisma (SQLite) com roles (`admin`, `agent`, `customer`) sincronizadas com Convex - Login: `web/src/app/login/page.tsx` + `web/src/components/login/login-form.tsx` - Middleware e guards: `web/middleware.ts`, helpers em `web/src/lib/auth{,z, -server}.ts` - Cliente React: `web/src/lib/auth-client.tsx` (sincroniza sessão Better Auth ↔ Convex, expõe helpers de role) - Frontend (Next.js + shadcn/ui) - Páginas principais: `/tickets`, `/tickets/[id]`, `/tickets/new`, `/play`. - UI ligada ao Convex com `convex/react`. - Toasts: `sonner` via `Toaster` em `web/src/app/layout.tsx`. - Mapeamento/validação de dados - Convex retorna datas como `number` (epoch). A UI usa `Date`. - Sempre converter/validar via Zod em `web/src/lib/mappers/ticket.ts`. - Não retornar `Date` a partir de funções do Convex. - Prisma: mantido apenas como referência de domínio (não é fonte de dados ativa). ## Como rodar - Pré‑requisitos: Node LTS + pnpm. - Passos: - `cd web && pnpm i` - `pnpm convex:dev` (mantém gerando tipos e rodando backend dev) - Criar `.env.local` com `NEXT_PUBLIC_CONVEX_URL=` - Em outro terminal: `pnpm dev` - Login em `/login`; seed opcional em `/dev/seed`. ## Convenções de código - Não use `Date` em payloads do Convex; use `number` (epoch ms). - Normalize dados no front via mappers Zod antes de renderizar. - UI com shadcn/ui; priorize componentes existentes e consistência visual. - Labels e mensagens em PT‑BR (status, timeline, toasts, etc.). - Atualizações otimistas com rollback em erro + toasts de feedback. - Comentários de supressão: prefira `@ts-expect-error` com justificativa curta para módulos gerados do Convex; evite `@ts-ignore`. ## Estrutura útil - `web/convex/*` — API backend Convex. - `web/src/lib/mappers/*` — Conversores server→UI com Zod. - `web/src/components/tickets/*` — Tabela, filtros, detalhe, timeline, comentários, play. ## Scripts (pnpm) - `pnpm convex:dev` — Convex (dev + geração de tipos) - `pnpm dev` — Next.js (App Router) - `pnpm build` / `pnpm start` — build/produção ## Backlog imediato (próximos passos) - Form “Novo ticket” em Dialog shadcn + React Hook Form + Zod + toasts. - Atribuição/transferência de fila no detalhe (selects com update otimista). - Melhorias de layout adicionais no painel “Detalhes” (quebras, largura responsiva) e unificação de textos PT‑BR. - Testes unitários dos mapeadores com Vitest. ## Checklist de PRs - [ ] Funções Convex retornam apenas tipos suportados (sem `Date`). - [ ] Dados validados/convertidos via Zod mappers antes da UI. - [ ] Textos/labels em PT‑BR. - [ ] Eventos de UI com feedback (toast) e rollback em erro. - [ ] Documentação atualizada se houver mudanças em fluxo/env. --- ## Próximas Entregas (Roadmap detalhado) 1) UX/Visual (shadcn/ui) - Padronizar cartões em todas as telas (Play, Visualizações) com o mesmo padrão aplicado em Conversa/Detalhes/Timeline (bordas, sombra, paddings). - Aplicar microtipografia consistente: headings H1/H2, tracking, tamanhos, cores em PT‑BR. - Skeletons de carregamento nos principais painéis (lista de tickets, recentes, play next). - Melhorar tabela: estados hover/focus, ícones de canal, largura de colunas previsível e truncamento. 2) Comentários e anexos - Dropzone também no “Novo ticket” (já implementado) com registro de comentário inicial e anexos. - Grid de anexos com miniaturas e legenda; manter atributo `download` com o nome original. - Preview em modal para imagens (feito) e suporte a múltiplas linhas no grid. - Botão para copiar link de arquivo (futuro, usar URL do storage). 3) Timeline e eventos - Mensagens amigáveis em PT‑BR (feito para CREATED/STATUS/ASSIGNEE/QUEUE). - Incluir sempre `actorName`/`actorAvatar` no payload; evitar JSON cru na UI. - Exibir avatar e nome do ator nas entradas (parcialmente feito). 4) Dados e camada Convex - Sempre retornar datas como `number` (epoch) e converter no front via mappers Zod. - Padronizar import do Convex com `@/convex/_generated/api` (alias criado). - Evitar `useQuery` com args vazios — proteger chamadas (gates) e, quando necessário, fallback de mock para IDs `ticket-*`. 5) Autenticação / Sessão (placeholder) - Cookie `demoUser` e bootstrap de usuário no Convex (feito). Trocar por Auth.js/Clerk quando for o momento. 6) Testes - Vitest configurado; adicionar casos para mapeadores (já iniciado) e smoke tests básicos de páginas. - Não usar Date em assertions de payload — sempre comparar epoch ou `instanceof Date` após mapeamento. 7) Acessibilidade e internacionalização - Labels e mensagens 100% em PT‑BR; evitar termos como `QUEUE_CHANGED` na UI. - Navegação por teclado em Dialogs/Selects; aria-labels em botões de ação. 8) Observabilidade (posterior) - Logs de evento estruturados no Convex; traces simples no client para ações críticas. --- ## Endpoints Convex (resumo) - `tickets.list({ tenantId, status?, priority?, channel?, queueId?, search?, limit? })` - `tickets.getById({ tenantId, id })` - `tickets.create({ tenantId, subject, summary?, priority, channel, queueId?, requesterId })` - `tickets.addComment({ ticketId, authorId, visibility, body, attachments?[] })` - `tickets.updateStatus({ ticketId, status, actorId })` — gera evento com `toLabel` e `actorName`. - `tickets.changeAssignee({ ticketId, assigneeId, actorId })` — gera evento com `assigneeName`. - `tickets.changeQueue({ ticketId, queueId, actorId })` — gera evento com `queueName`. - `tickets.playNext({ tenantId, queueId?, agentId })` — atribui ticket e registra evento. - `tickets.updatePriority({ ticketId, priority, actorId })` — altera prioridade e registra `PRIORITY_CHANGED`. - `tickets.remove({ ticketId, actorId })` — remove ticket, eventos e comentários (tenta excluir anexos do storage). - `queues.summary({ tenantId })` - `files.generateUploadUrl()` — usar via `useAction`. - `users.ensureUser({ tenantId, email, name, avatarUrl?, role?, teams? })` Observações: - Não retornar `Date` nas funções Convex; usar `number` e converter na UI com os mappers em `src/lib/mappers`. - Evitar passar `{}` para `useQuery` — args devem estar definidos ou a query não deve ser invocada. --- ## Padrões de Código - UI: shadcn/ui (Field, Dialog, Select, Badge, Table, Spinner) + Tailwind. - Dados: Zod para validação; mappers para converter server→UI (epoch→Date, null→undefined). - Texto: PT‑BR em labels, toasts e timeline. - UX: updates otimistas + toasts (status, assignee, fila, comentários). - Imports do Convex: sempre `@/convex/_generated/api`. --- ## Como abrir PR - Crie uma branch descritiva (ex.: `feat/tickets-attachments-grid`). - Preencha a descrição com: contexto, mudanças, como testar (pnpm scripts), screenshots quando útil. - Checklist: - [ ] Sem `Date` no retorno Convex. - [ ] Labels PT‑BR. - [ ] Skeleton/Loading onde couber. - [ ] Mappers atualizados se tocar em payloads. - [ ] AGENTS.md atualizado se houver mudança de padrões. --- ## Atualizações recentes (dez/2025) - RBAC do Convex reforçado: `tickets.list`, `tickets.getById`, `workSummary` e mutações sensíveis (`changeQueue`, `updateCategories`, `startWork/pauseWork`, `updatePriority`) agora exigem `viewerId/actorId` e validam `requireStaff` com `tenantId`. - Componentes de tickets (tabela, painel de recentes, play next, cabeçalho/detalhe) passam a usar o contexto Better Auth para prover `viewerId`, com `useQuery` protegido por `"skip"` enquanto não há sessão. - Testes (`pnpm vitest run`) executados após as alterações para garantir regressão zero. ## Progresso recente (mar/2025) Resumo do que foi implementado desde o último marco: - Rich text (Tiptap) com SSR seguro para comentários e descrição inicial do ticket - Componente: `web/src/components/ui/rich-text-editor.tsx` - Comentários: `web/src/components/tickets/ticket-comments.rich.tsx` (visibilidade Público/Interno, anexos tipados) - Novo ticket (Dialog + Página): campos de descrição usam rich text; primeiro comentário é registrado quando houver conteúdo. - Tipagem estrita (remoção de `any`) no front e no Convex - Uso consistente de `Id<>` e `Doc<>` (Convex) e schemas Zod (record tipado em v4). - Queries `useQuery` com "skip" quando necessário; mapeadores atualizados. - Filtros server-side - `tickets.list` agora escolhe o melhor índice (por `status`, `queueId` ou `tenant`) e só então aplica filtros complementares. - UI do detalhe do ticket (Header) - Prioridade como dropdown-badge translúcida: `web/src/components/tickets/priority-select.tsx` (nova Convex `tickets.updatePriority`). - Seleção de responsável com avatar no menu. - Ação de exclusão com modal (ícones, confirmação): `web/src/components/tickets/delete-ticket-dialog.tsx` (Convex `tickets.remove`). - Correções e DX - Tiptap: `immediatelyRender: false` + `setContent({ emitUpdate: false })` para evitar mismatch de hidratação. - Validação de assunto no Dialog “Novo ticket” (trim + `setError`) para prevenir `ZodError` em runtime. Arquivos principais tocados: - Convex: `web/convex/schema.ts`, `web/convex/tickets.ts` (novas mutations + tipagem `Doc/Id`). - UI: `ticket-summary-header.tsx`, `ticket-detail-view.tsx`, `ticket-comments.rich.tsx`, `new-ticket-dialog.tsx`, `play-next-ticket-card.tsx`. - Tipos e mapeadores: `web/src/lib/schemas/ticket.ts`, `web/src/lib/mappers/ticket.ts`. ## Guia de layout/UX aplicado - Header do ticket - Ordem: `#ref` • PrioritySelect (badge) • Status (badge/select) • Ações (Excluir) - Tipografia: título forte, resumo como texto auxiliar, metadados em texto pequeno. - Combos de Categoria/ Subcategoria exibidos como selects dependentes com salvamento automático (sem botões dedicados). - Comentários - Composer com rich text + Dropzone; seletor de visibilidade. - Lista com avatar, nome, carimbo relativo e conteúdo rich text. - Prioridades (labels) - LOW (cinza), MEDIUM (azul), HIGH (âmbar), URGENT (vermelho) — badge translúcida no trigger do select. ## Próximos passos sugeridos (UI/Funcionais) Curto prazo (incremental): - [ ] Transformar Status em dropdown-badge (mesmo padrão de Prioridade). - [ ] Estados vazios com `Empty` (ícone, título, descrição, CTA) na lista de comentários e tabela. - [ ] Edição inline no header (Assunto/Resumo) com botões Reset/Salvar (mutations dedicadas). - [ ] Polir cards (bordas/padding/sombra) nas telas Play/Tickets para padronizar com Header/Conversa. Médio prazo: - [ ] Combobox (command) para responsável com busca. - [ ] Paginação/ordenção server-side em `tickets.list`. - [ ] Unificar mensagens de timeline e payloads (sempre `actorName`/`actorAvatar`). - [ ] Testes Vitest para mapeadores e smoke tests básicos das páginas. ## Como validar manualmente - Rich text: comentar em `/tickets/[id]` com formatação, anexos e alternando visibilidade. - Prioridade: alterar no cabeçalho; observar evento de timeline e toasts. - Exclusão: acionar modal no cabeçalho e confirmar; conferir redirecionamento para `/tickets`. - Novo ticket: usar Dialog; assunto com menos de 3 chars deve bloquear submit com erro no campo. --- ## Atualizações recentes (abr/2025) Resumo do que foi integrado nesta rodada para o núcleo de tickets e UX: - Header do ticket - Status como dropdown‑badge (padrão visual alinhado às badges existentes). - Edição inline de Assunto/Resumo com Cancelar/Salvar e toasts. - Ação de Play/Pause (toggle de atendimento) com eventos WORK_STARTED/WORK_PAUSED na timeline. - Layout dos campos reorganizado: labels acima e controles abaixo (evita redundância do valor + dropdown lado a lado). - Tabela e comentários - Empty states padronizados com Empty + CTA de novo ticket. - Notificações - Toaster centralizado no rodapé (bottom‑center) com estilo consistente. - Título do app - Atualizado para “Sistema de chamados”. Backend Convex - ickets.updateSubject e ickets.updateSummary adicionadas para edição do cabeçalho. - ickets.toggleWork adicionada; campo opcional working no schema de ickets. Próximos passos sugeridos - Status dropdown‑badge também na tabela (edição rápida opcional com confirmação). - Combobox (command) para busca de responsável no select. - Tokens de cor: manter badges padrão do design atual; quando migração completa para paleta Rever estiver definida, aplicar via globals.css para herdar em todos os componentes. - Testes (Vitest): adicionar casos de mappers e smoke tests de páginas. Observações de codificação - Evitar `any`; usar TicketStatus/TicketPriority e Id<>/Doc<> do Convex. - Não retornar Date do Convex; sempre epoch (number) e converter via mappers Zod. ## Atualizações recentes (out/2025) - Cabeçalho de ticket agora persiste automaticamente mudanças de categoria/subcategoria, mostrando toasts e bloqueando os selects enquanto a mutação é processada. - Normalização de nomes de fila/time aplicada também ao retorno de `tickets.playNext`, garantindo rótulos "Chamados"/"Laboratório" em todos os fluxos. - ESLint ignora `convex/_generated/**` e supressões migradas para `@ts-expect-error` com justificativa explícita. - Mutação `tickets.remove` não requer mais `actorId`; o diálogo de exclusão apenas envia `ticketId`. ## Atualizações recentes (nov/2025) - Dialog de novo ticket redesenhado: duas colunas com botão “Criar” no cabeçalho, dropzone mais compacta, categorias primária/secundária empilhadas e rótulos explícitos. - Validação do assunto relaxada para evitar `ZodError` prematuro; verificação manual permanece na submissão. - Placeholder cinza claro "Escreva um comentário..." aplicado ao editor Tiptap e seção renomeada para “Comentários”. - Linhas da tabela de tickets agora são totalmente clicáveis (mouse e teclado), reforçando acessibilidade e atalho de navegação. - Toasts e layouts refinados para manter consistência entre criação, listagem e detalhe dos tickets. ## Atualizações recentes (out/2025) - Tabela de tickets refinada com ícones de canal, prioridade ajustável inline e indicadores suavizados (fila/status/categoria) para reduzir ruído visual. - Definido plano de migração para Better Auth com RBAC (admin/agent/customer), portal do cliente e painel administrativo para filas/categorias/agentes. - Próximo passo: iniciar fase de implementação da autenticação real, substituindo middleware placeholder e alinhando Convex aos novos papéis. - Better Auth agora usa banco SQLite local (`db.sqlite`) e o schema Prisma foi migrado com sucesso via `pnpm exec prisma migrate dev --name init`. - Configuração do `postcss.config.mjs` corrigida para usar `@tailwindcss/postcss` como plugin executável, liberando a suíte do Vitest (`pnpm exec vitest run`). - Script `pnpm auth:seed` cria/atualiza o usuário inicial (`admin@sistema.dev` / `admin123`) usando `better-auth/crypto` para hash de senha. - Página de login refeita com layout em duas colunas (header + imagem lateral) e formulário integrado ao Better Auth (`LoginForm`). - Middleware atualizado aplica RBAC inicial (clientes direcionados ao portal, rotas `/admin` reservadas a administradores) e helpers de role expostos em `src/lib/authz.ts`; página `/portal` criada como placeholder do futuro autosserviço. ## Próximos passos estratégicos ### Produto / Experiência - [ ] Unificar revisão visual do modal de novo ticket com microinterações (estado de salvamento, validações inline). - [ ] Implementar filtros salváveis e quick actions na listagem (ex.: alterar status diretamente). - [ ] Exibir indicadores de anexos na tabela e nos cartões de “tickets recentes”. ### Técnica - [ ] Corrigir configuração do `postcss.config.mjs` (plugin inválido impede execução do Vitest) e restaurar cobertura de testes automatizados. - [ ] Formalizar camada de autenticação (Auth.js ou Clerk) com refresh de sessão e proteção de rotas no Convex (`auth.getUserIdentity`). - [ ] Mapear RBAC inicial (admin/agente/visualização) e refletir nas mutations do Convex. - [ ] Configurar ambientes `staging`/`production` do Convex com variáveis (.env) versionadas via doppler/1Password. - [ ] Automatizar lint/test/build no CI (GitHub Actions) e bloquear merge sem execução. ### Administrativa / Operacional - [ ] Inventariar acessos: quem possui permissão no Convex, GitHub e futuros serviços (Redis, email, armazenamento S3?). - [ ] Criar checklists de onboarding/offboarding de agentes (criação de usuário, associação a filas, provisionamento de avatar). - [ ] Definir plano de capacidade para armazenamento de anexos (quotas por tenant, política de retenção) e alertas. - [ ] Preparar mock de integrações externas (e-mail entrante, WhatsApp) para futuras etapas. - [ ] Documentar fluxo de suporte interno (quem revisa PRs, janelas de deploy, rollback). Manter este arquivo atualizado ao concluir cada item estratégico ou quando surgirem novas dependências administrativas. ## Atualizações recentes (mai/2026) - Login corporativo refinado com instruções revisadas para primeiro acesso e mensagens de erro totalmente em PT-BR. - Script `pnpm auth:seed` executado para garantir o usuário administrador padrão (`admin@sistema.dev` / `admin123`). - Toast de autenticação inválida agora informa "E-mail ou senha inválidos", alinhando o feedback com o restante da interface. ### Próximos passos imediatos - [ ] Implementar fluxo completo de convites (criação, expiração, revogação) integrado ao Better Auth e Convex. - [ ] Adicionar testes Vitest/E2E cobrindo dashboards, relatórios e guardas de RBAC no front. - [ ] Mapear permissões de edição avançada para agentes (categorias, campos rápidos) antes de liberar novas mutações. ## Atualizações recentes (jun/2026) - RBAC do Convex reforçado em times, filas, campos, SLAs e relatórios; todas as chamadas exigem `viewerId`/`actorId` conforme o papel (admin ou staff). - Painel administrativo atualizado para consumir as novas assinaturas protegidas, com validações de sessão Better Auth e feedback de toasts. - Dashboard principal passou a exibir métricas reais via `reports.dashboardOverview` e séries históricas por canal com `reports.ticketsByChannel`. - Portal do cliente publicado com isolamento por `viewerId`, garantindo que clientes visualizem apenas seus chamados.