vendaweb-api/docs/development.md

530 lines
11 KiB
Markdown

# Guia de Desenvolvimento - DRE Gerencial
## Configuração do Ambiente
### 1. **Pré-requisitos**
- Node.js 18+
- PostgreSQL 13+
- npm ou yarn
- Git
### 2. **Instalação**
```bash
# Clone o repositório
git clone <repository-url>
cd dre-modelo
# Instale as dependências
npm install
# Configure as variáveis de ambiente
cp .env.example .env.local
```
### 3. **Variáveis de Ambiente**
```env
# Database
POSTGRES_DB=dre_gerencial
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
POSTGRES_USER=postgres
POSTGRES_PASSWORD=sua_senha
# Next.js
NEXT_PUBLIC_APP_URL=http://localhost:3000
```
### 4. **Configuração do Banco**
```bash
# Criar banco de dados
createdb dre_gerencial
# Executar migrações (se houver)
npx drizzle-kit migrate
```
## Scripts Disponíveis
### 1. **Desenvolvimento**
```bash
# Iniciar servidor de desenvolvimento
npm run dev
# Build para produção
npm run build
# Iniciar servidor de produção
npm run start
# Linting
npm run lint
```
### 2. **Banco de Dados**
```bash
# Gerar migração
npx drizzle-kit generate
# Aplicar migração
npx drizzle-kit migrate
# Visualizar schema
npx drizzle-kit studio
```
## Estrutura do Projeto
```
src/
├── app/ # Next.js App Router
│ ├── api/ # API Routes
│ │ ├── analitico/ # API analítica
│ │ └── dre/ # API DRE
│ ├── DRE/ # Páginas DRE
│ │ ├── analitico.tsx # Componente analítico
│ │ ├── page.tsx # Página principal
│ │ └── teste.tsx # Componente principal
│ ├── globals.css # Estilos globais
│ └── layout.tsx # Layout raiz
├── components/ # Componentes reutilizáveis
│ └── ui/ # Componentes UI base
├── db/ # Configuração do banco
│ ├── index.ts # Conexão Drizzle
│ └── schema.ts # Schema do banco
└── lib/ # Utilitários
└── utils.ts # Funções utilitárias
```
## Padrões de Código
### 1. **TypeScript**
- Sempre usar tipos explícitos
- Interfaces para props de componentes
- Tipos específicos para dados de API
```typescript
// ✅ Bom
interface AnaliticoItem {
id: number;
valor: number;
data_competencia: string;
}
// ❌ Evitar
const data: any = await response.json();
```
### 2. **React Hooks**
- Usar `useCallback` para funções passadas como props
- Usar `useMemo` para cálculos pesados
- Evitar dependências desnecessárias em `useEffect`
```typescript
// ✅ Bom
const fetchData = useCallback(async () => {
// lógica de fetch
}, [filtros]);
// ❌ Evitar
const fetchData = async () => {
// lógica de fetch
};
```
### 3. **Styling**
- Usar Tailwind CSS para styling
- Classes utilitárias para responsividade
- Variantes com class-variance-authority
```typescript
// ✅ Bom
const buttonVariants = cva(
'inline-flex items-center justify-center',
{
variants: {
variant: {
default: 'bg-primary text-primary-foreground',
outline: 'border border-input bg-background',
},
},
}
);
// ❌ Evitar
const styles = {
button: 'bg-blue-500 text-white px-4 py-2',
};
```
## Desenvolvimento de Novas Funcionalidades
### 1. **Adicionando Nova API**
#### Criar arquivo de rota
```typescript
// src/app/api/nova-funcionalidade/route.ts
import { NextRequest, NextResponse } from 'next/server';
import db from '@/db';
export async function GET(request: NextRequest) {
try {
// Lógica da API
const data = await db.execute(sql`SELECT * FROM tabela`);
return NextResponse.json(data.rows);
} catch (error) {
console.error('Erro:', error);
return NextResponse.json(
{ error: 'Erro interno' },
{ status: 500 }
);
}
}
```
#### Adicionar tipos
```typescript
// src/types/nova-funcionalidade.ts
export interface NovaFuncionalidadeItem {
id: number;
nome: string;
valor: number;
}
```
### 2. **Adicionando Novo Componente**
#### Estrutura do componente
```typescript
// src/components/NovaFuncionalidade.tsx
'use client';
import { useState, useEffect } from 'react';
import { Button } from '@/components/ui/button';
interface NovaFuncionalidadeProps {
filtros: {
dataInicio: string;
dataFim: string;
};
}
export default function NovaFuncionalidade({ filtros }: NovaFuncionalidadeProps) {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(false);
const fetchData = async () => {
setLoading(true);
try {
const response = await fetch(`/api/nova-funcionalidade?${new URLSearchParams(filtros)}`);
const result = await response.json();
setData(result);
} catch (error) {
console.error('Erro:', error);
} finally {
setLoading(false);
}
};
useEffect(() => {
fetchData();
}, [filtros]);
return (
<div className="w-full">
<h2 className="text-lg font-bold mb-4">Nova Funcionalidade</h2>
{loading ? (
<div>Carregando...</div>
) : (
<div>
{/* Renderizar dados */}
</div>
)}
</div>
);
}
```
### 3. **Adicionando Nova Página**
#### Criar página
```typescript
// src/app/nova-pagina/page.tsx
import NovaFuncionalidade from '@/components/NovaFuncionalidade';
export default function NovaPagina() {
return (
<div className="w-full min-h-screen p-4">
<NovaFuncionalidade filtros={{ dataInicio: '', dataFim: '' }} />
</div>
);
}
```
## Debugging
### 1. **Logs de Desenvolvimento**
```typescript
// Usar console.log para debugging
console.log('Dados recebidos:', data);
// Logs estruturados
console.log({
timestamp: new Date().toISOString(),
component: 'AnaliticoComponent',
action: 'fetchData',
data: data.length
});
```
### 2. **React Developer Tools**
- Instalar extensão do Chrome/Firefox
- Inspecionar estado dos componentes
- Profiler para performance
### 3. **Network Tab**
- Verificar requisições de API
- Analisar tempo de resposta
- Verificar payloads
## Testes
### 1. **Configuração de Testes**
```bash
# Instalar dependências de teste
npm install --save-dev @testing-library/react @testing-library/jest-dom jest jest-environment-jsdom
# Configurar Jest
# jest.config.js
const nextJest = require('next/jest');
const createJestConfig = nextJest({
dir: './',
});
const customJestConfig = {
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
moduleNameMapping: {
'^@/(.*)$': '<rootDir>/src/$1',
},
testEnvironment: 'jest-environment-jsdom',
};
module.exports = createJestConfig(customJestConfig);
```
### 2. **Testes Unitários**
```typescript
// __tests__/components/Analitico.test.tsx
import { render, screen } from '@testing-library/react';
import AnaliticoComponent from '@/app/DRE/analitico';
describe('AnaliticoComponent', () => {
it('renders without crashing', () => {
const filtros = {
dataInicio: '2024-01',
dataFim: '2024-12',
};
render(<AnaliticoComponent filtros={filtros} />);
expect(screen.getByText('Análise Analítica')).toBeInTheDocument();
});
});
```
### 3. **Testes de API**
```typescript
// __tests__/api/analitico.test.ts
import { GET } from '@/app/api/analitico/route';
describe('/api/analitico', () => {
it('returns data for valid parameters', async () => {
const request = new Request('http://localhost:3000/api/analitico?dataInicio=2024-01&dataFim=2024-12');
const response = await GET(request);
const data = await response.json();
expect(response.status).toBe(200);
expect(Array.isArray(data)).toBe(true);
});
});
```
## Performance
### 1. **Otimizações de Bundle**
```typescript
// Lazy loading de componentes
const AnaliticoComponent = lazy(() => import('./analitico'));
// Dynamic imports
const HeavyComponent = dynamic(() => import('./HeavyComponent'), {
loading: () => <div>Carregando...</div>,
});
```
### 2. **Otimizações de Renderização**
```typescript
// Memoização de componentes
const MemoizedComponent = memo(({ data }) => {
return <div>{data.map(item => <Item key={item.id} data={item} />)}</div>;
});
// Memoização de cálculos
const expensiveValue = useMemo(() => {
return data.reduce((sum, item) => sum + item.valor, 0);
}, [data]);
```
### 3. **Otimizações de API**
```typescript
// Cache de dados
const { data, isLoading } = useQuery({
queryKey: ['analitico', filtros],
queryFn: () => fetchAnaliticoData(filtros),
staleTime: 5 * 60 * 1000, // 5 minutos
});
```
## Deploy
### 1. **Build de Produção**
```bash
# Build otimizado
npm run build
# Verificar build
npm run start
```
### 2. **Variáveis de Ambiente de Produção**
```env
# Produção
POSTGRES_DB=dre_gerencial_prod
POSTGRES_HOST=prod-db-host
POSTGRES_PORT=5432
POSTGRES_USER=prod_user
POSTGRES_PASSWORD=prod_password
NEXT_PUBLIC_APP_URL=https://dre-gerencial.com
```
### 3. **Docker (Opcional)**
```dockerfile
# Dockerfile
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
EXPOSE 3000
CMD ["npm", "start"]
```
## Troubleshooting
### 1. **Problemas Comuns**
#### Erro de Conexão com Banco
```bash
# Verificar se PostgreSQL está rodando
pg_ctl status
# Verificar conexão
psql -h localhost -U postgres -d dre_gerencial
```
#### Erro de Build
```bash
# Limpar cache
rm -rf .next node_modules
npm install
npm run build
```
#### Erro de TypeScript
```bash
# Verificar tipos
npx tsc --noEmit
# Atualizar tipos
npm update @types/react @types/react-dom
```
### 2. **Logs de Erro**
```typescript
// Error boundary
class ErrorBoundary extends Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
console.error('Error caught by boundary:', error, errorInfo);
}
render() {
if (this.state.hasError) {
return <div>Algo deu errado.</div>;
}
return this.props.children;
}
}
```
## Contribuição
### 1. **Fluxo de Trabalho**
```bash
# Criar branch
git checkout -b feature/nova-funcionalidade
# Fazer commits
git add .
git commit -m "feat: adiciona nova funcionalidade"
# Push
git push origin feature/nova-funcionalidade
# Criar Pull Request
```
### 2. **Padrões de Commit**
```
feat: nova funcionalidade
fix: correção de bug
docs: atualização de documentação
style: formatação de código
refactor: refatoração de código
test: adição de testes
chore: tarefas de manutenção
```
### 3. **Code Review**
- Verificar tipos TypeScript
- Testar funcionalidades
- Validar performance
- Verificar acessibilidade
- Revisar documentação
## Próximos Passos
1. **Implementar CI/CD** com GitHub Actions
2. **Adicionar testes E2E** com Playwright
3. **Implementar monitoramento** com Sentry
4. **Adicionar Storybook** para componentes
5. **Implementar PWA** para mobile
6. **Adicionar internacionalização** (i18n)
7. **Implementar cache** com Redis
8. **Adicionar métricas** com Analytics