Aller au contenu principal

✅ Checklist: Implementar Nova Secção/Feature

Feature: _________________________
Data início: //2026
Desenvolvedor: _________________________
Estimativa: 4-6 horas


📋 Pré-Implementação

Planeamento

  • Definir nome da feature (ex: services, bookings, staff)
  • Definir campos necessários (nome, descrição, etc)
  • Definir operações CRUD necessárias (list, create, edit, delete, search)
  • Definir abas do rightMenu (mínimo 2, máximo 6)
  • Ler PADRAO-ARQUITETURAL.md completo
  • Consultar exemplos: LocationsPage.tsx + TestingCenterPage.tsx

Preparação do Ambiente

  • Backend rodando: uvicorn src.main:app --reload
  • Frontend rodando: npm run dev
  • Database conectada (PostgreSQL)
  • Git branch criada: git checkout -b feature/{feature-name}

🗄️ Fase 1: Database (30 min)

Migration Alembic

  • Criar migration: alembic revision -m "create {feature} table"
  • Implementar upgrade():
    • op.create_table('{feature}_items', ...)
    • Colunas obrigatórias: id, created_at
    • Colunas específicas da feature
    • Índices para campos pesquisáveis
  • Implementar downgrade(): op.drop_table('{feature}_items')
  • Rodar migration: alembic upgrade head
  • Validar tabela criada: psql -c "\d {feature}_items"

Rollback Test

  • Testar downgrade: alembic downgrade -1
  • Voltar ao topo: alembic upgrade head

🐍 Fase 2: Backend (90 min)

Estrutura de Pastas

  • Criar: mkdir -p backend/src/modules/{feature}
  • Criar: touch backend/src/modules/{feature}/__init__.py
  • Criar ficheiros: routes.py, models.py, schemas.py, service.py

models.py (SQLAlchemy)

  • Importar: from sqlalchemy import Column, Integer, String, DateTime
  • Criar classe {Feature}Item(Base):
    • __tablename__ = "{feature}_items"
    • Campo id (primary key)
    • Campos específicos da feature
    • Campos created_at, updated_at
  • Testar import: python -c "from src.modules.{feature}.models import {Feature}Item"

schemas.py (Pydantic)

  • Criar Create{Feature}Dto:
    • Campos obrigatórios com Field(...)
    • Campos opcionais com Optional[]
    • Validações (min_length, max_length, pattern)
  • Criar Update{Feature}Dto:
    • Todos campos Optional[]
  • Criar {Feature}Response:
    • Todos campos do modelo
    • class Config: from_attributes = True
  • Testar validação:
    dto = Create{Feature}Dto(name="Test")
    assert dto.name == "Test"

service.py (Business Logic)

  • Criar classe {Feature}Service:
    • __init__(self, db: Session)
    • Método list() → retorna todos
    • Método get(item_id) → retorna 1 por ID
    • Método create(data: CreateDto) → insere no DB
    • Método update(item_id, data: UpdateDto) → atualiza
    • Método delete(item_id) → apaga
  • Testar service isoladamente (pytest)

routes.py (FastAPI Endpoints)

  • Criar router = APIRouter(prefix="/{feature}", tags=["{feature}"])
  • Endpoint GET / (list):
    • response_model=List[{Feature}Response]
    • db: Session = Depends(get_db)
    • Chamar service.list()
  • Endpoint POST / (create):
    • response_model={Feature}Response, status_code=201
    • Validar data: Create{Feature}Dto
    • Chamar service.create(data)
  • Endpoint GET /{item_id} (get):
    • Retornar 404 se não encontrar
  • Endpoint PATCH /{item_id} (update):
    • Validar data: Update{Feature}Dto
  • Endpoint DELETE /{item_id} (delete):
    • status_code=204
    • Retornar None

Registrar Router

  • Editar backend/src/main.py:
    from src.modules.{feature}.routes import router as {feature}_router
    app.include_router({feature}_router, prefix="/api")
  • Recarregar backend (hot reload automático)
  • Testar endpoints:
    • curl http://localhost:8000/api/{feature}
    • curl -X POST http://localhost:8000/api/{feature} -H "Content-Type: application/json" -d '{"name":"Test"}'
    • Verificar docs: http://localhost:8000/docs

⚛️ Fase 3: Frontend - Estrutura (60 min)

Types TypeScript

  • Criar frontend/src/types/{feature}.ts:
    export interface {Feature}Item {
    id: number
    name: string
    // ... outros campos
    created_at: string
    }

    export interface Create{Feature}Dto {
    name: string
    // ... campos obrigatórios
    }
  • Validar: npx tsc --noEmit

API Client

  • Criar frontend/src/services/{feature}Api.ts:
    import axios from 'axios'

    export const {feature}Api = {
    list: () => axios.get('/api/{feature}'),
    get: (id: number) => axios.get(`/api/{feature}/${id}`),
    create: (data: Create{Feature}Dto) => axios.post('/api/{feature}', data),
    update: (id: number, data: Update{Feature}Dto) => axios.patch(`/api/{feature}/${id}`, data),
    delete: (id: number) => axios.delete(`/api/{feature}/${id}`),
    }
  • Testar no console do browser:
    await {feature}Api.list()

Componentes Tab (Pure)

  • Criar pasta: mkdir -p frontend/src/components/{feature}
  • Criar {Feature}ListTab.tsx:
    • Props: items: {Feature}Item[], onDelete: (id) => void
    • Renderizar lista de cards
    • Empty state: "Nenhum item cadastrado"
    • Botão apagar em cada card
  • Criar {Feature}FormTab.tsx:
    • Props: onSubmit: (data) => void, onCancel: () => void
    • Form com campos necessários
    • Validação inline
    • Botões "Salvar" + "Cancelar"
  • (Opcional) Criar {Feature}StatsTab.tsx, {Feature}SettingsTab.tsx
  • Criar index.ts:
    export { {Feature}ListTab } from './{Feature}ListTab'
    export { {Feature}FormTab } from './{Feature}FormTab'

Page Component (Orquestrador)

  • Criar: frontend/src/pages/admin/{feature}/{Feature}Page.tsx
  • Estado:
    const [items, setItems] = useState<{Feature}Item[]>([])
    const [selectedItem, setSelectedItem] = useState<{Feature}Item | null>(null)
    const [activeRightId, setActiveRightId] = useState('list')
  • Handler callback:
    function handleRightMenuSelect(id: string) {
    setActiveRightId(id)
    }
  • Handlers CRUD:
    • handleCreate(data) → API call + setItems()
    • handleEdit(id, data) → API call + update array
    • handleDelete(id) → API call + filter array
  • useEffect para carregar items:
    useEffect(() => {
    {feature}Api.list().then(res => setItems(res.data))
    }, [])
  • Definir rightMenu:
    const rightMenu = [
    { id: 'list', icon: '📋', label: 'Listar', color: 'blue' },
    { id: 'new', icon: '➕', label: 'Novo', color: 'green' },
    ]
  • Renderizar com AdminSectionLayout:
    <AdminSectionLayout
    title="Minha Feature"
    rightMenu={rightMenu}
    activeRightId={activeRightId}
    onRightSelect={handleRightMenuSelect}
    >
    {activeRightId === 'list' && <{Feature}ListTab ... />}
    {activeRightId === 'new' && <{Feature}FormTab ... />}
    </AdminSectionLayout>

Adicionar Rota

  • Editar frontend/src/App.tsx (ou router):
    <Route path="/admin/{feature}" element={<{Feature}Page />} />
  • Adicionar link na sidebar admin (se aplicável)

Validação Frontend

  • Abrir http://localhost:3000/admin/{feature}
  • Verificar que página renderiza sem erros console
  • Verificar que botões sidebar aparecem e respondem ao hover
  • Clicar "Listar" → deve mostrar listagem (ou empty state)
  • Clicar "Novo" → deve mostrar formulário

🧪 Fase 4: Testes E2E (60 min)

Estrutura de Testes

  • Determinar número sequencial: próximo disponível (ex: 06, 07, 08, 09)
  • Criar: mkdir -p frontend/tests/e2e/{number}-{feature}-list
  • Criar: mkdir -p frontend/tests/e2e/{number+1}-{feature}-create
  • Criar: mkdir -p frontend/tests/e2e/{number+2}-{feature}-edit
  • Criar: mkdir -p frontend/tests/e2e/{number+3}-{feature}-delete

Test: List

  • Criar {number}-{feature}-list/list.spec.ts:
    • test.beforeEach: login + goto /admin/{feature}
    • Test: "should display items in table"
      • Verificar título h1
      • Verificar botão "Listar" ativo (classe bg-blue-500)
      • Verificar items aparecem (.item-card)
      • Screenshot: 01_items_visible.png
    • Test: "should show empty state when no items"
      • Verificar mensagem "Nenhum item cadastrado"
      • Screenshot: 02_empty_state.png
    • Test: "should navigate to create form"
      • Clicar botão "Novo"
      • Verificar formulário aparece
      • Screenshot: 03_form_opened.png

Test: Create

  • Criar {number+1}-{feature}-create/create.spec.ts:
    • Test: "should create item successfully"
      • Clicar "Novo"
      • Preencher campos obrigatórios
      • Clicar "Salvar"
      • Verificar toast success
      • Verificar item aparece na listing
      • Screenshots: 01_form_filled.png, 02_item_created.png
    • Test: "should validate required fields"
      • Clicar "Novo"
      • Clicar "Salvar" (sem preencher)
      • Verificar mensagens de erro
      • Screenshot: 03_validation_errors.png

Test: Edit

  • Criar {number+2}-{feature}-edit/edit.spec.ts:
    • Test: "should edit item successfully"
      • Clicar botão "Editar"
      • Alterar campo (ex: nome)
      • Salvar
      • Verificar mudança refletiu na listing

Test: Delete

  • Criar {number+3}-{feature}-delete/delete.spec.ts:
    • Test: "should delete item with confirmation"
      • Clicar botão "Apagar"
      • Verificar modal confirmação
      • Confirmar
      • Verificar item removido da listing
    • Test: "should cancel delete"
      • Clicar "Apagar"
      • Cancelar no modal
      • Verificar item permanece

Rodar Testes

  • Rodar todos: npm run test:e2e
  • Verificar que todos passam (verde)
  • Verificar screenshots gerados em test-results/
  • Abrir relatório: npx playwright show-report

📖 Fase 5: Documentação (30 min)

Guia de Usuário

  • Criar docs/ADMIN/{FEATURE}.md:
    # {Feature Name}

    ## Introdução
    [Descrição da feature]

    ## Listar {Features}
    [Como ver listagem]
    ![](../../test-results/{feature}-list/01_items_visible.png)

    ## Criar Novo {Feature}
    [Passo a passo]
    ![](../../test-results/{feature}-create/01_form_filled.png)

    ## Editar {Feature}
    [Como editar]

    ## Apagar {Feature}
    [Como apagar com confirmação]
  • Adicionar screenshots dos testes
  • Incluir perguntas comuns (FAQ)

Atualizar Índices

  • Adicionar em docs/ADMIN/INDEX.md
  • Adicionar em README.md do projeto (se aplicável)

✅ Fase 6: Validação Final (30 min)

Checklist Completo

Frontend ✅

  • Página renderiza sem erros console
  • Sidebar buttons funcionam (trocam abas)
  • Listagem mostra items
  • Criar item funciona (aparece na listing)
  • Editar item funciona (reflete mudanças)
  • Apagar item funciona (remove da listing + modal confirmação)
  • Empty state aparece quando sem items
  • Loading states durante API calls
  • Toast feedback (success verde, error vermelho)
  • Responsivo (mobile, tablet, desktop)
  • TypeScript compila: npx tsc --noEmit (0 errors)
  • ESLint sem warnings críticos
  • Build production: npm run build (success)

Backend ✅

  • Endpoints retornam status corretos:
    • GET / → 200 + array
    • POST / → 201 + objeto criado
    • GET /{id} → 200 ou 404
    • PATCH /{id} → 200 + objeto atualizado
    • DELETE /{id} → 204
  • Validação Pydantic rejeita dados inválidos (422)
  • Database persiste dados corretamente
  • Queries otimizadas (sem N+1)
  • CORS configurado (frontend consegue chamar API)
  • Logs informativos (não apenas errors)
  • Docs interativa: http://localhost:8000/docs

Database ✅

  • Migration roda sem errors: alembic upgrade head
  • Rollback funciona: alembic downgrade -1
  • Tabela existe: \d {feature}_items no psql
  • Índices criados para campos pesquisáveis
  • Constraints respeitadas (NOT NULL, UNIQUE, etc)

Tests E2E ✅

  • Todos testes passam: npm run test:e2e (100% verde)
  • Screenshots capturados (mínimo 5-10)
  • Testes cobrem:
    • Happy path (criar, editar, apagar)
    • Validation errors (campos obrigatórios)
    • Empty states
    • Confirmação de delete
  • Testes rodam em < 2 minutos
  • Relatório: npx playwright show-report

Documentação ✅

  • Guia criado em docs/ADMIN/{FEATURE}.md
  • Screenshots embedded
  • Passo-a-passo claro
  • FAQ com perguntas comuns
  • Índices atualizados

🚀 Fase 7: Deploy & Commit (15 min)

Commit

  • Verificar ficheiros alterados: git status
  • Adicionar ao staging: git add .
  • Commit com mensagem descritiva:
    git commit -m "feat: implement {Feature} CRUD with admin UI

    - Frontend: {Feature}Page + 2-4 tab components
    - Backend: {feature} module (routes, models, schemas, service)
    - Database: {feature}_items table migration
    - Tests: E2E coverage for list, create, edit, delete
    - UI: Follows AdminSectionLayout pattern (sidebar + conditional tabs)
    - Docs: User guide with screenshots

    Refs: #{issue-number}
    "
  • Push: git push origin feature/{feature-name}

Pull Request (se aplicável)

  • Criar PR no GitLab/GitHub
  • Adicionar descrição com screenshots
  • Linkar issues relacionadas
  • Solicitar review

Merge (após aprovação)

  • Merge para main/develop
  • Verificar CI/CD passa (testes automáticos)
  • Deploy para staging/production

📊 Métricas de Sucesso

Tempo total gasto: ______ horas
Testes passando: ______ / ______ (100% esperado)
Cobertura E2E: ✅ list, create, edit, delete
Erros TypeScript: 0
Erros Console: 0
Screenshots capturados: ______

Feature completa? ✅ Sim / ❌ Não


🐛 Troubleshooting

Se encontrar problemas, consultar:

Problemas comuns:

  1. Sidebar não troca abas → Verificar renderização condicional DENTRO de children
  2. State não atualiza → Verificar setItems() após create/edit/delete
  3. Backend 422 → Verificar schemas Pydantic vs dados enviados
  4. TypeScript errors → Verificar interfaces em types/{feature}.ts
  5. Testes falham → Verificar seletores, timeout, login helper

✅ Checklist completo! Se todos checkboxes estão marcados, feature está pronta para produção.

Próximo passo: Implementar próxima feature seguindo este mesmo checklist.