vendaweb-api/docs/development.md

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 useCallback para funções passadas como props
  • Usar useMemo para 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

  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