✅ 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)
- Campos obrigatórios com
- Criar
Update{Feature}Dto:- Todos campos
Optional[]
- Todos campos
- 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
- Validar
- 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}_routerapp.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: numbername: string// ... outros camposcreated_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
- Props:
- Criar
{Feature}FormTab.tsx:- Props:
onSubmit: (data) => void,onCancel: () => void - Form com campos necessários
- Validação inline
- Botões "Salvar" + "Cancelar"
- Props:
- (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:<AdminSectionLayouttitle="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
- Verificar título
- 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: "should create item successfully"
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: "should edit item successfully"
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
- Test: "should delete item with confirmation"
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]## Criar Novo {Feature}[Passo a passo]## 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.mddo 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}_itemsno 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 screenshotsRefs: #{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:
- PADRAO-ARQUITETURAL.md - Secção "Erros Comuns"
- PLANO-ONBOARDING-E2E-DOCUMENTACAO.md - Secção 2.8.12
Problemas comuns:
- Sidebar não troca abas → Verificar renderização condicional DENTRO de
children - State não atualiza → Verificar
setItems()após create/edit/delete - Backend 422 → Verificar schemas Pydantic vs dados enviados
- TypeScript errors → Verificar interfaces em
types/{feature}.ts - 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.