11 KiB
11 KiB
Guia de Desenvolvimento - DRE Gerencial
Configuração do Ambiente
1. Pré-requisitos
- Node.js 18+
- PostgreSQL 13+
- npm ou yarn
- Git
2. Instalação
# 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
# 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
# Criar banco de dados
createdb dre_gerencial
# Executar migrações (se houver)
npx drizzle-kit migrate
Scripts Disponíveis
1. Desenvolvimento
# 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
# 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
// ✅ Bom
interface AnaliticoItem {
id: number;
valor: number;
data_competencia: string;
}
// ❌ Evitar
const data: any = await response.json();
2. React Hooks
- Usar
useCallbackpara funções passadas como props - Usar
useMemopara cálculos pesados - Evitar dependências desnecessárias em
useEffect
// ✅ 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
// ✅ 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
// 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
// src/types/nova-funcionalidade.ts
export interface NovaFuncionalidadeItem {
id: number;
nome: string;
valor: number;
}
2. Adicionando Novo Componente
Estrutura do componente
// 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
// 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
// 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
# 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
// __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
// __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
// 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
// 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
// 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
# Build otimizado
npm run build
# Verificar build
npm run start
2. Variáveis de Ambiente de Produção
# 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
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
# Verificar se PostgreSQL está rodando
pg_ctl status
# Verificar conexão
psql -h localhost -U postgres -d dre_gerencial
Erro de Build
# Limpar cache
rm -rf .next node_modules
npm install
npm run build
Erro de TypeScript
# Verificar tipos
npx tsc --noEmit
# Atualizar tipos
npm update @types/react @types/react-dom
2. Logs de Erro
// 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
# 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
- Implementar CI/CD com GitHub Actions
- Adicionar testes E2E com Playwright
- Implementar monitoramento com Sentry
- Adicionar Storybook para componentes
- Implementar PWA para mobile
- Adicionar internacionalização (i18n)
- Implementar cache com Redis
- Adicionar métricas com Analytics