Compare commits

...

No commits in common. "main" and "Cliente/OestPan" have entirely different histories.

699 changed files with 107793 additions and 358 deletions

View File

@ -0,0 +1,54 @@
# Plano de Ajuste - Ambiente Financeiro V2
## Resumo
Este documento detalha as alterações necessárias para alimentar os gráficos do painel financeiro utilizando os endpoints de backend especificados.
## 1. Ajuste nos Serviços de Integração (`extratoService.js`)
Precisamos adicionar/atualizar os métodos para consumir as novas rotas:
### Endpoints
* **Fluxo Diário**: Utilizar a rota existente `/extrato/fluxo` e processar o array `diario`.
* **Receitas (Planejado vs Executado)**: Nova rota `/extrato/planejado/grafico`.
* **Despesas (Planejado vs Executado)**: Nova rota `/extrato/despesas/grafico`.
### Implementação
Criar os seguintes métodos no `extratoService`:
```javascript
// Buscar dados comparativos de Receitas
fetchReceitasPlanejadasGrafico: (params) => api.get('/extrato/planejado/grafico', { params })
// Buscar dados comparativos de Despesas
fetchDespesasPlanejadasGrafico: (params) => api.get('/extrato/despesas/grafico', { params })
```
## 2. Processamento de Dados (`useDashboard.js`)
O hook `useDashboard` será responsável por formatar os dados para o `recharts`.
### Fluxo de Recebimentos (Entradas)
* **Fonte**: `fluxo.diario`
* **Filtro**: `tipoOperacao === 'C'`
* **Formato para Gráfico**:
```javascript
{
name: 'DD/MM',
valor: 1234.56
}
```
### Fluxo de Despesas (Saídas)
* **Fonte**: `fluxo.diario`
* **Filtro**: `tipoOperacao === 'D'`
## 3. Componentes Visuais (`DashboardView.jsx`)
Novos gráficos ou atualização dos existentes:
1. **Gráfico de Recebimentos (Diário)**: Barra ou Linha (Verde/Emerald).
2. **Gráfico de Despesas (Diário)**: Barra ou Linha (Vermelho/Rose).
3. **Comparativo Planejado vs Executado**: Gráfico de barras agrupadas ou composto.
## Próximos Passos
1. Implementar métodos no service.
2. Atualizar hook para buscar e processar dados.
3. Inserir gráficos na View.

49
.agent/SENIOR_AGENT.md Normal file
View File

@ -0,0 +1,49 @@
# 🧠 SENIOR AGENT - WAR ROOM ENGINE (v1.0)
Você é a consciência coletiva de um conselho executivo de elite e engenheiros de classe mundial (iT Guys Standards). Sua missão é aniquilar a mediocridade e impor excelência técnica.
## 🏛️ O CONSELHO (Mental Profiles)
A cada tarefa, você ativa a perspectiva dos seguintes especialistas conforme a necessidade:
- **Logan Roy (CEO)**: Foco em Poder, Respeito e Visão Macro. Se o produto não "impõe respeito", é refutado.
- **Steve Jobs (CPO)**: Foco em Design, Tipografia e Intuição. "Whitespace" é sagrado.
- **Tony Stark (CTO)**: Foco em Engenharia Pura. Latência, Docker, Nginx, Regra dos 14KB.
- **Gordon Ramsay (Code Quality)**: "Grita" com código sujo. Exige HTML semântico e CSS Fluido.
---
## 📜 AS LEIS IMUTÁVEIS (Tech Bible)
### 1. Performance (Rule of 14KB)
- HTML crítico + CSS inicial **DEVE** caber em **~14KB** (10 pacotes TCP) para renderização no primeiro RTT.
- Use `agent_cli.py audit` para validar.
### 2. Frontend Fluido
- **PROIBIDO** usar `px` fixos ou `vw` puro para fontes/layouts.
- **OBRIGATÓRIO**: `clamp(min, val, max)`, `min()`, e `max()`.
- Ex: `font-size: clamp(1rem, 2.5vw, 2rem);`
### 3. Native First
- Não use bibliotecas para o que o browser faz sozinho.
- **Modais**: `<dialog>` + `.showModal()`.
- **Accordions**: `<details>` + `<summary>`.
### 4. Reuso e Modularidade
- **Composição > Novo Arquivo**: SEMPRE busque componentes em `src/components/` antes de criar novos.
- **Hooks Reutilizáveis**: Extraia lógica de views para hooks em `src/hooks/` ou `features/*/hooks/`.
- **Services Finos**: Um service por domínio (ex: `workspaceConciliacaoService`).
- **Playground Primeiro**: Teste componentes novos no `dev-tools` (Playground) antes da integração.
---
## ⚙️ PROTOCOLO OPERACIONAL
1. **Contexto via CLI**: Use `python .agent/agent_cli.py context [api|context|history]` para buscar dados.
2. **Auditoria**: SEMPRE rode `python .agent/agent_cli.py audit` ao finalizar uma feature.
3. **Registro**: Documente mudanças importantes com `python .agent/agent_cli.py register "Mensagem"`.
4. **Minimalismo**: Mantenha as respostas curtas, viscerais e tecnicamente densas.
---
**Filosofia iT Guys**: "Eficiência não é um recurso, é um fundamento."

109
.agent/agent_cli.py Normal file
View File

@ -0,0 +1,109 @@
import typer
import os
import json
from rich.console import Console
from rich.panel import Panel
from rich.table import Table
from rich.progress import Progress, SpinnerColumn, TextColumn
app = typer.Typer(help="PlatformSistemas Senior Agent CLI - War Room Engine")
console = Console()
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
DATA_DIR = BASE_DIR
def load_json(filename):
path = os.path.join(DATA_DIR, filename)
if not os.path.exists(path):
return None
with open(path, 'r', encoding='utf-8') as f:
return json.load(f)
@app.command()
def context(topic: str = typer.Argument("general", help="Topic to get context for (api, database, context)")):
"""Retrieve structured project context from JSON data stores."""
data = load_json(f"{topic}.json")
if not data:
console.print(f"[red]Context for '{topic}' not found.[/red]")
return
console.print(Panel(f"Project Context: [bold cyan]{topic.upper()}[/bold cyan]", border_style="blue"))
console.print_json(data=data)
from rules.technical_rules import audit_file
@app.command()
def audit(path: str = typer.Argument(".", help="Path or file to audit")):
"""Perform technical audit following 'War Room' rules (CSS Fluidity, 14KB, etc)."""
console.print(f"[yellow]Auditing:[/yellow] {path}")
files_to_audit = []
if os.path.isfile(path):
files_to_audit.append(path)
else:
for root, _, files in os.walk(path):
if any(x in root for x in ['node_modules', '.git', 'dist', 'build']):
continue
for f in files:
if f.endswith(('.html', '.css', '.js', '.jsx')):
files_to_audit.append(os.path.join(root, f))
table = Table(title="Audit Results")
table.add_column("File", style="white")
table.add_column("Rule", style="cyan")
table.add_column("Status")
table.add_column("Details")
for file_path in files_to_audit:
results = audit_file(file_path)
rel_path = os.path.relpath(file_path, os.getcwd())
for r in results:
status = "[green]✅ PASS[/green]" if r['passed'] else "[red]❌ FAIL[/red]"
table.add_row(rel_path, r['rule'], status, r['details'])
console.print(table)
@app.command()
def create(type: str, name: str, ambient: str = "workspace"):
"""Create a new component, service, or hook."""
console.print(f"[cyan]Creating {type}:[/cyan] [bold]{name}[/bold] in [bold]{ambient}[/bold]")
# Path mappings based on project structure
paths = {
"component": f"src/features/{ambient}/components/{name}.jsx",
"service": f"src/features/{ambient}/{name}Service.js",
"hook": f"src/features/{ambient}/hooks/use{name}.js"
}
if type not in paths:
console.print(f"[red]Invalid type. Use: component, service, hook.[/red]")
return
target_path = os.path.join(os.getcwd(), paths[type])
os.makedirs(os.path.dirname(target_path), exist_ok=True)
# Template generation (simplified)
template = f"// New {type} created by Senior Agent\nexport const {name} = () => {{}};"
with open(target_path, 'w', encoding='utf-8') as f:
f.write(template)
console.print(f"[green]Successfully created at:[/green] {target_path}")
@app.command()
def register(feature: str, status: str = "active"):
"""Register a new feature or change in the project history."""
history = load_json("history.json") or []
history.append({
"feature": feature,
"status": status,
"timestamp": "2026-02-08" # Should be dynamic
})
with open(os.path.join(DATA_DIR, "history.json"), 'w', encoding='utf-8') as f:
json.dump(history, f, indent=2)
console.print(f"[green]Registered feature:[/green] {feature}")
if __name__ == "__main__":
app()

52
.agent/api.json Normal file
View File

@ -0,0 +1,52 @@
{
"status_summary": {
"Dashboard": "Em Construção",
"Receitas": "Demonstração Visual",
"Despesas": "Demonstração Visual",
"Conciliação": "Ativo",
"Configurações": "Em Construção"
},
"endpoints": [
{
"path": "/categorias/transacoes/pendentes",
"method": "GET",
"description": "Retorna todas as transações que ainda não foram conciliadas",
"status": "Implementado",
"service": "workspaceConciliacaoService"
},
{
"path": "/categorias/cruzamentos",
"method": "GET",
"params": ["caixinha", "mes", "ano"],
"description": "Retorna cruzamentos de transações com filtros opcionais",
"status": "Implementado",
"service": "workspaceConciliacaoService"
},
{
"path": "/boletos/status",
"method": "GET",
"description": "Lista todos os boletos com seus status",
"status": "Disponível (Não integrado)",
"module": "IncomesView"
},
{
"path": "/extrato/apresentar",
"method": "GET",
"description": "Lista todas as transações do extrato bancário",
"status": "Integrado",
"service": "extratoService"
},
{
"path": "/auth",
"method": "POST",
"params": ["username", "password", "Passo", "data_envio"],
"description": "Login - Passo 1 e 2 (2FA)",
"status": "Implementado",
"hook": "useWorkspaceAuth"
}
],
"technical_notes": {
"service_pattern": "Uses handleRequest with mockFn and apiFn wrappers.",
"hook_pattern": "Standard useEffect for data fetching with loading states."
}
}

27
.agent/context.json Normal file
View File

@ -0,0 +1,27 @@
{
"project_name": "Integra Finance (PRALOG)",
"objective": "React application with modular architecture, high performance, and premium design.",
"environment": {
"url_base": "https://dev.workspace.itguys.com.br",
"url_platform": "https://dev.workspace.itguys.com.br/plataforma/",
"credentials": {
"user": "financeiro@pralog.com.br",
"pass": "123Mudar"
}
},
"dev_commands": {
"run": "npm run dev",
"build": "npm run build",
"lint": "ESLint + Prettier"
},
"modules": [
{ "name": "auth", "purpose": "Authentication" },
{ "name": "financeiro-v2", "purpose": "Reconciliation, Accounts Payable/Receivable", "views": ["BoletosView", "ClientsView", "Conciliacao"] },
{ "name": "workspace", "purpose": "Expenses, Incomes, Reconciliation", "views": ["ExpensesView", "IncomesView", "LoginView", "ReconciliationView"] },
{ "name": "rh", "purpose": "HR Dashboard, Employees, Experience Contracts" }
],
"architecture_notes": {
"playground": "All new components must pass through dev-tools (Playground) first.",
"standards": "High performance (14KB rule), fluid typography (clamp), Docker-ready."
}
}

39
.agent/database.json Normal file
View File

@ -0,0 +1,39 @@
{
"tables": [
{
"name": "entradas_planejadas",
"description": "Receitas planejadas (quotes/estimates)",
"pk": "id (EST-000001)",
"fields": ["data_criacao", "cliente_id", "total", "status (ENUM)"],
"relations": ["cliente_id -> clientes.id"]
},
{
"name": "clientes",
"description": "Cadastro de clientes",
"pk": "id",
"fields": ["nome", "cpf_cnpj", "tipo_pessoa", "status_serv", "valor_servico"],
"unique": ["cpf_cnpj", "tipo_pessoa"]
},
{
"name": "despesas",
"description": "Registro de despesas e lançamentos contábeis",
"pk": "id",
"fields": ["data", "conta_despesa", "fornecedor_id", "montante", "status"],
"relations": ["fornecedor_id -> fornecedores.id", "cliente_id -> clientes.id"]
},
{
"name": "fornecedores",
"description": "Cadastro de fornecedores",
"pk": "id",
"fields": ["nome", "cpf_cnpj", "tipo_pessoa", "status", "contas_pagar"]
}
],
"relationships": {
"diagram": "clientes (1) -> (N) entradas_planejadas; fornecedores (1) -> (N) despesas; despesas (1) -> (N) despesas_diario"
},
"conventions": {
"monetary": "DECIMAL(15,2)",
"dates": "DATE (YYYY-MM-DD)",
"timestamps": "Automatic handled by DB"
}
}

44
.agent/history.json Normal file
View File

@ -0,0 +1,44 @@
[
{
"feature": "Refatora\u00e7\u00e3o do diret\u00f3rio .agent",
"status": "in_progress",
"description": "Migra\u00e7\u00e3o para modelo CLI-centric inspirado em .gemini para economia de tokens.",
"timestamp": "2026-02-08"
},
{
"feature": "Consolida\u00e7\u00e3o de Agentes",
"status": "completed",
"description": "M\u00faltiplos agentes removidos em favor do Senior Agent (War Room Engine).",
"timestamp": "2026-02-08"
},
{
"feature": "Permitido par\u00eanteses no Nome Completo e liberada edi\u00e7\u00e3o de Nome e Despachante nos formul\u00e1rios GR",
"status": "active",
"timestamp": "2026-02-08"
},
{
"feature": "Ajustadas rotas de API para Bases e Respons\u00e1veis nas configura\u00e7\u00f5es do GR",
"status": "active",
"timestamp": "2026-02-08"
},
{
"feature": "Corre\u00e7\u00e3o nas rotas de edi\u00e7\u00e3o de Bases e Respons\u00e1veis do GR",
"status": "active",
"timestamp": "2026-02-08"
},
{
"feature": "Corrigido erro nos cards de Pend\u00eancias/Revis\u00e3o do GR para Despachantes",
"status": "active",
"timestamp": "2026-02-08"
},
{
"feature": "Ajuste do painel Status de Cobran\u00e7a: centro com total de boletos e legenda vertical com quantitativo e tipografia fluida.",
"status": "active",
"timestamp": "2026-02-08"
},
{
"feature": "Implementado seletor de per\u00edodo (Anual/Mensal) no dashboard do GR com filtros de m\u00eas e ano.",
"status": "active",
"timestamp": "2026-02-08"
}
]

View File

@ -0,0 +1,87 @@
import os
import re
def check_css_fluidity(content):
"""Checks for hardcoded px in CSS unless it's 0 or 1px."""
# Find patterns like "300px", "margin: 20px"
px_pattern = re.compile(r'(\d+px)')
matches = px_pattern.findall(content)
# Ignore 0px, 1px, 2px (usually borders)
critical_matches = [m for m in matches if int(m.replace('px', '')) > 2]
return critical_matches
def check_14kb_rule(file_path):
"""Checks if file size is below 14KB."""
size = os.path.getsize(file_path)
return size < 14336 # 14KB in bytes
def audit_file(file_path):
results = []
# 14KB Check
if file_path.endswith(('.html', '.css', '.js', '.jsx')):
is_ok = check_14kb_rule(file_path)
results.append({
"rule": "14KB Limit",
"passed": is_ok,
"details": f"Size: {os.path.getsize(file_path)} bytes"
})
# Content Checks for JS/JSX
if file_path.endswith(('.js', '.jsx')):
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
# 1. Loading States
if any(x in content for x in ['form', 'onSubmit', 'handleSubmit']):
has_loading = 'loading' in content.lower() or 'disabled' in content.lower()
results.append({
"rule": "Loading/Disabled States",
"passed": has_loading,
"details": "Checking if form handles loading/disabled states."
})
# 2. Required Fields
has_validation = any(x in content.lower() for x in ['required', 'schema', 'validation', 'validate'])
results.append({
"rule": "Field Validation",
"passed": has_validation,
"details": "Checking for required fields or schema validation."
})
# 3. Error Handling
has_error = any(x in content.lower() for x in ['error', 'catch', 'try'])
results.append({
"rule": "Error Handling",
"passed": has_error,
"details": "Checking for API error handling or try/catch blocks."
})
# 4. Visual Feedback
has_feedback = any(x in content.lower() for x in ['toast', 'alert', 'sonner', 'message'])
results.append({
"rule": "Visual Feedback (Toasts)",
"passed": has_feedback,
"details": "Checking for user feedback mechanisms (Toasts/Alerts)."
})
# 5. Service Usage (instead of direct axios/fetch)
if 'axios' in content and 'Service' not in content and 'useApiContract' not in content:
results.append({
"rule": "Service Abstraction",
"passed": False,
"details": "Direct axios call found. API calls should be in Services or use useApiContract."
})
# CSS Fluidity Check
if file_path.endswith('.css'):
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
bad_px = check_css_fluidity(content)
results.append({
"rule": "CSS Fluidity (clamp/min/max)",
"passed": len(bad_px) == 0,
"details": f"Found these hardcoded px: {bad_px}" if bad_px else "All good!"
})
return results

152
.agent/scripts/README.md Normal file
View File

@ -0,0 +1,152 @@
# Scripts de Automação Dev Sênior Front-end
Scripts para acelerar tarefas repetitivas no desenvolvimento.
---
## Scripts Disponíveis
### 1. `check-reuse.js` - Análise de Reutilização
**Antes de criar qualquer código**, use este script para verificar o que já existe.
```bash
# Buscar componentes/hooks/services relacionados
node .agent/scripts/check-reuse.js user
node .agent/scripts/check-reuse.js card
node .agent/scripts/check-reuse.js auth
```
**Saída**: Lista todos os arquivos relacionados ao termo buscado.
---
### 2. `create-component.js` - Criar Componente
Cria estrutura completa de componente (Produção + Dev + index).
```bash
# Componente compartilhado
node .agent/scripts/create-component.js UserCard
# Componente de feature específica
node .agent/scripts/create-component.js EmployeeCard rh
node .agent/scripts/create-component.js BoletoList financeiro-v2
```
**Gera**:
- `[Nome].jsx` - Versão produção
- `[Nome].dev.jsx` - Versão Playground
- `index.js` - Entry point
---
### 3. `create-hook.js` - Criar Hook
Cria hook customizado com template padrão.
```bash
# Hook global
node .agent/scripts/create-hook.js useAuth
# Hook de feature
node .agent/scripts/create-hook.js useEmployeeData rh
node .agent/scripts/create-hook.js useBoletos financeiro-v2
```
**Template inclui**: useState, useEffect, loading, error handling.
---
### 4. `create-service.js` - Criar Service
Cria service com CRUD completo.
```bash
# Service global
node .agent/scripts/create-service.js userService
# Service de feature
node .agent/scripts/create-service.js employeeService rh
node .agent/scripts/create-service.js boletoService financeiro-v2
```
**Métodos inclusos**: getList, getById, create, update, delete.
---
## Workflow Recomendado
### Criar Novo Componente
```bash
# 1. Verificar se já existe
node .agent/scripts/check-reuse.js UserCard
# 2. Se não existir, criar
node .agent/scripts/create-component.js UserCard rh
# 3. Implementar lógica
# Editar: src/features/rh/components/UserCard/UserCard.jsx
# 4. Adicionar ao Playground
# Cadastrar em: src/features/dev-tools/views/PlaygroundView.jsx
# 5. Testar no Playground antes de usar em views
```
### Criar Nova Feature Completa
```bash
# 1. Verificar reutilização
node .agent/scripts/check-reuse.js employee
# 2. Criar service
node .agent/scripts/create-service.js employeeService rh
# 3. Criar hook
node .agent/scripts/create-hook.js useEmployee rh
# 4. Criar componentes necessários
node .agent/scripts/create-component.js EmployeeCard rh
node .agent/scripts/create-component.js EmployeeForm rh
# 5. Testar componentes no Playground
# 6. Criar view usando os componentes
```
---
## Outros Scripts Úteis
### Scripts Existentes
- `check-orchestrator.js` - Validar orquestrador de agentes
- `docs-update.js` - Atualizar documentação
- `git-commit-by-day.js` - Commits organizados por dia
---
## Regras de Ouro
1. **SEMPRE** rodar `check-reuse.js` antes de criar código novo
2. **SEMPRE** testar no Playground antes de usar em produção
3. **SEMPRE** validar build: `npm run dev`
4. **Componentes < 150 linhas** - extrair se maior
---
## Atalhos Package.json (Adicionar)
```json
{
"scripts": {
"new:component": "node .agent/scripts/create-component.js",
"new:hook": "node .agent/scripts/create-hook.js",
"new:service": "node .agent/scripts/create-service.js",
"check:reuse": "node .agent/scripts/check-reuse.js"
}
}
```
**Uso após adicionar**:
```bash
npm run check:reuse user
npm run new:component UserCard rh
npm run new:hook useUserData
npm run new:service userService
```

View File

@ -0,0 +1,8 @@
/**
* Verifica se o orquestrador e todos os agentes carregam corretamente.
*/
import { AgentOrchestrator } from '../orchestrator/AgentOrchestrator.js';
const o = new AgentOrchestrator();
console.log('Agents:', o.agents.map((a) => a.name).join(', '));

View File

@ -0,0 +1,91 @@
#!/usr/bin/env node
/**
* Script: Analisar reutilização de código
* Busca componentes, hooks e services existentes antes de criar novos
* Uso: node check-reuse.js [termo-de-busca]
* Exemplo: node check-reuse.js user
*/
const fs = require('fs');
const path = require('path');
const [, , searchTerm] = process.argv;
if (!searchTerm) {
console.error('❌ Termo de busca é obrigatório!');
console.log('Uso: node check-reuse.js [termo-de-busca]');
process.exit(1);
}
const srcPath = path.join(__dirname, '../../src');
// Buscar arquivos recursivamente
function findFiles(dir, pattern, results = []) {
const files = fs.readdirSync(dir);
files.forEach(file => {
const filePath = path.join(dir, file);
const stat = fs.statSync(filePath);
if (stat.isDirectory() && !file.includes('node_modules')) {
findFiles(filePath, pattern, results);
} else if (file.toLowerCase().includes(pattern.toLowerCase())) {
results.push(filePath.replace(srcPath, 'src'));
}
});
return results;
}
console.log(`\n🔍 Buscando por: "${searchTerm}"\n`);
// Buscar componentes
const components = findFiles(path.join(srcPath, 'components'), searchTerm);
const featureComponents = findFiles(path.join(srcPath, 'features'), searchTerm)
.filter(f => f.includes('/components/'));
// Buscar hooks
const hooks = findFiles(path.join(srcPath, 'hooks'), searchTerm);
const featureHooks = findFiles(path.join(srcPath, 'features'), searchTerm)
.filter(f => f.includes('/hooks/'));
// Buscar services
const services = findFiles(path.join(srcPath, 'services'), searchTerm);
const featureServices = findFiles(path.join(srcPath, 'features'), searchTerm)
.filter(f => f.includes('Service'));
// Exibir resultados
if (components.length > 0) {
console.log('📦 Componentes Compartilhados:');
components.forEach(c => console.log(` - ${c}`));
console.log('');
}
if (featureComponents.length > 0) {
console.log('📦 Componentes de Features:');
featureComponents.forEach(c => console.log(` - ${c}`));
console.log('');
}
if (hooks.length > 0 || featureHooks.length > 0) {
console.log('🎣 Hooks:');
[...hooks, ...featureHooks].forEach(h => console.log(` - ${h}`));
console.log('');
}
if (services.length > 0 || featureServices.length > 0) {
console.log('🔌 Services:');
[...services, ...featureServices].forEach(s => console.log(` - ${s}`));
console.log('');
}
const total = components.length + featureComponents.length + hooks.length +
featureHooks.length + services.length + featureServices.length;
if (total === 0) {
console.log('❌ Nenhum arquivo encontrado.');
console.log('✅ Pode criar novo componente/hook/service com esse nome.\n');
} else {
console.log(`✅ Total encontrado: ${total} arquivos`);
console.log(`⚠️ Verifique se pode reutilizar antes de criar novo!\n`);
}

View File

@ -0,0 +1,87 @@
#!/usr/bin/env node
/**
* Script: Criar novo componente com estrutura padrão
* Uso: node create-component.js NomeDoComponente [feature]
* Exemplo: node create-component.js UserCard rh
*/
const fs = require('fs');
const path = require('path');
const [, , componentName, feature] = process.argv;
if (!componentName) {
console.error('❌ Nome do componente é obrigatório!');
console.log('Uso: node create-component.js NomeDoComponente [feature]');
process.exit(1);
}
// Definir caminho baseado em feature ou shared
const basePath = feature
? path.join(__dirname, '../../src/features', feature, 'components', componentName)
: path.join(__dirname, '../../src/components/shared', componentName);
// Criar pasta
if (!fs.existsSync(basePath)) {
fs.mkdirSync(basePath, { recursive: true });
}
// Template Produção
const prodTemplate = `import { Card } from '@/components/ui/card';
/**
* ${componentName} - Componente de produção
*/
export const ${componentName} = ({ data, className = '' }) => {
return (
<Card className={\`\${className}\`}>
<div className="p-4">
<h3 className="text-lg font-semibold">${componentName}</h3>
{/* Implementar conteúdo */}
</div>
</Card>
);
};
`;
// Template Dev (Playground)
const devTemplate = `import { ${componentName} } from './${componentName}';
/**
* ${componentName}.dev - Versão para Playground com controles
*/
export const ${componentName}Dev = () => {
const mockData = {
// Mock data para testes
};
return (
<div className="space-y-4">
<div className="p-4 bg-muted rounded">
<h4 className="text-sm font-medium mb-2">Controles (Dev)</h4>
{/* Adicionar controles de teste */}
</div>
<${componentName} data={mockData} />
</div>
);
};
`;
// Template index.js
const indexTemplate = `export { ${componentName} } from './${componentName}';
export { ${componentName}Dev } from './${componentName}.dev';
`;
// Escrever arquivos
fs.writeFileSync(path.join(basePath, `${componentName}.jsx`), prodTemplate);
fs.writeFileSync(path.join(basePath, `${componentName}.dev.jsx`), devTemplate);
fs.writeFileSync(path.join(basePath, 'index.js'), indexTemplate);
console.log(`✅ Componente ${componentName} criado com sucesso!`);
console.log(`📁 Caminho: ${basePath}`);
console.log(`\n📝 Próximos passos:`);
console.log(`1. Implementar lógica em ${componentName}.jsx`);
console.log(`2. Adicionar controles em ${componentName}.dev.jsx`);
console.log(`3. Cadastrar no Playground (PlaygroundView.jsx)`);
console.log(`4. Testar no Playground antes de usar em views`);

View File

@ -0,0 +1,76 @@
#!/usr/bin/env node
/**
* Script: Criar novo hook customizado
* Uso: node create-hook.js useNomeDoHook [feature]
* Exemplo: node create-hook.js useUserData rh
*/
const fs = require('fs');
const path = require('path');
const [, , hookName, feature] = process.argv;
if (!hookName || !hookName.startsWith('use')) {
console.error('❌ Nome do hook é obrigatório e deve começar com "use"!');
console.log('Uso: node create-hook.js useNomeDoHook [feature]');
process.exit(1);
}
// Definir caminho
const basePath = feature
? path.join(__dirname, '../../src/features', feature, 'hooks')
: path.join(__dirname, '../../src/hooks');
const fileName = `${hookName}.js`;
const filePath = path.join(basePath, fileName);
// Criar pasta se não existir
if (!fs.existsSync(basePath)) {
fs.mkdirSync(basePath, { recursive: true });
}
// Template do hook
const hookTemplate = `import { useState, useEffect } from 'react';
/**
* ${hookName} - Hook customizado
* @returns {Object} - Estado e funções do hook
*/
export const ${hookName} = () => {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
useEffect(() => {
// Implementar lógica
}, []);
const handleAction = async () => {
try {
setLoading(true);
// Implementar ação
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};
return {
data,
loading,
error,
handleAction,
};
};
`;
// Escrever arquivo
fs.writeFileSync(filePath, hookTemplate);
console.log(`✅ Hook ${hookName} criado com sucesso!`);
console.log(`📁 Caminho: ${filePath}`);
console.log(`\n📝 Próximos passos:`);
console.log(`1. Implementar lógica do hook`);
console.log(`2. Adicionar testes se necessário`);
console.log(`3. Importar nas views que precisam`);

View File

@ -0,0 +1,131 @@
#!/usr/bin/env node
/**
* Script: Criar novo service para feature
* Uso: node create-service.js NomeService [feature]
* Exemplo: node create-service.js userService rh
*/
const fs = require('fs');
const path = require('path');
const [, , serviceName, feature] = process.argv;
if (!serviceName) {
console.error('❌ Nome do service é obrigatório!');
console.log('Uso: node create-service.js NomeService [feature]');
process.exit(1);
}
// Normalizar nome (adicionar Service se não tiver)
const normalizedName = serviceName.endsWith('Service')
? serviceName
: `${serviceName}Service`;
// Definir caminho
const basePath = feature
? path.join(__dirname, '../../src/features', feature)
: path.join(__dirname, '../../src/services');
const fileName = `${normalizedName}.js`;
const filePath = path.join(basePath, fileName);
// Criar pasta se não existir
if (!fs.existsSync(basePath)) {
fs.mkdirSync(basePath, { recursive: true });
}
// Template do service
const serviceTemplate = `import api from '@/services/api';
/**
* ${normalizedName} - Service para gerenciar dados
*/
const ${normalizedName} = {
/**
* Buscar lista
* @param {Object} filters - Filtros opcionais
* @returns {Promise<Array>}
*/
async getList(filters = {}) {
try {
const response = await api.get('/endpoint', { params: filters });
return response.data;
} catch (error) {
console.error('Erro ao buscar lista:', error);
throw error;
}
},
/**
* Buscar por ID
* @param {string|number} id - ID do registro
* @returns {Promise<Object>}
*/
async getById(id) {
try {
const response = await api.get(\`/endpoint/\${id}\`);
return response.data;
} catch (error) {
console.error('Erro ao buscar item:', error);
throw error;
}
},
/**
* Criar novo
* @param {Object} data - Dados para criar
* @returns {Promise<Object>}
*/
async create(data) {
try {
const response = await api.post('/endpoint', data);
return response.data;
} catch (error) {
console.error('Erro ao criar:', error);
throw error;
}
},
/**
* Atualizar
* @param {string|number} id - ID do registro
* @param {Object} data - Dados para atualizar
* @returns {Promise<Object>}
*/
async update(id, data) {
try {
const response = await api.put(\`/endpoint/\${id}\`, data);
return response.data;
} catch (error) {
console.error('Erro ao atualizar:', error);
throw error;
}
},
/**
* Deletar
* @param {string|number} id - ID do registro
* @returns {Promise<void>}
*/
async delete(id) {
try {
await api.delete(\`/endpoint/\${id}\`);
} catch (error) {
console.error('Erro ao deletar:', error);
throw error;
}
},
};
export default ${normalizedName};
`;
// Escrever arquivo
fs.writeFileSync(filePath, serviceTemplate);
console.log(`✅ Service ${normalizedName} criado com sucesso!`);
console.log(`📁 Caminho: ${filePath}`);
console.log(`\n📝 Próximos passos:`);
console.log(`1. Ajustar endpoints da API`);
console.log(`2. Adicionar métodos específicos se necessário`);
console.log(`3. Importar em hooks ou views`);

View File

@ -0,0 +1,16 @@
/**
* Runner para DocumentationAgent.updateDocs().
* Uso: npm run agent:docs:update
*/
import { DocumentationAgent } from '../agents/DocumentationAgent.js';
const agent = new DocumentationAgent();
const result = await agent.updateDocs({ projectRoot: process.cwd() });
if (result.error) {
console.error('❌ Erro:', result.error);
process.exit(1);
}
if (result.warnings?.length) result.warnings.forEach((w) => console.warn('⚠️', w));
console.log('✅ Documentação atualizada. Ambientes:', result.environments?.length ?? 0);

View File

@ -0,0 +1,21 @@
/**
* Runner para GitSyncAgent.commitByDay().
* Uso: npm run agent:git:commit [-- --dry-run]
*/
import { GitSyncAgent } from '../agents/GitSyncAgent.js';
const dryRun = process.argv.includes('--dry-run');
const agent = new GitSyncAgent();
const result = await agent.commitByDay({ dryRun });
if (result.userMessage) console.log('\n⚠ ' + result.userMessage);
if (result.retryPrompt) console.log('➡️ ' + result.retryPrompt);
if (result.commits?.length) {
console.log('\n📦 Commits:', result.commits.length);
result.commits.forEach((c) => console.log(` ${c.date}: ${c.message}`));
}
if (result.errors?.length) console.error('\n❌ Erros:', result.errors);
process.exit(result.passed ? 0 : 1);

View File

@ -0,0 +1,31 @@
# SKILL: Architecture Rules (.agent/skills/architecture-rules)
## 📌 Objetivo
Garantir que a evolução do `PlatformSistemas` mantenha o isolamento total entre os módulos e siga o padrão "Zero-Boilerplate" para conexões com o backend.
## 🏗️ Regras de Escopo de Componentes
### 1. Libs/Shared (`src/components/shared`)
* **Definição:** Apenas componentes **Puros** e **Burros** (Stateless ou State-local).
* **Proibido:** Lógica de negócio, chamadas ao `api.js` ou dependência de contextos específicos de feature (ex: `useVehicles`).
* **Exemplos:** `Button.jsx`, `ModalBase.jsx`, `Input.jsx`, `LoadingOverlay.jsx`.
### 2. Feature-Specific (`src/features/[feature]/components`)
* **Definição:** Componentes que possuem lógica de negócio ou dependem de hooks da própria feature.
* **Obrigatório:** Devem viver dentro da pasta da feature correspondente.
* **Exemplos:** `VehicleCard.jsx` (Prafrot), `AttendanceFormModal.jsx` (Prafrot), `TripDetailsModal.jsx` (Prafrot).
## 🔌 Regra "Zero-Boilerplate" (API Contract)
* **JAMAIS** crie arquivos `*Service.js` para novas funcionalidades.
* **Sempre Use** o hook `useApiContract.js` em conjunto com o arquivo de configuração JSON correspondente (ex: `prafrotRoutes.json`).
* **TanStack Query:** Use os poderes de cache e invalidação automática providos pelo re-query através do hook central.
## 🛡️ Muralha de Isolamento
1. **Tokens Modulares:** Sempre injete o token correspondente ao módulo via `getTokenForModule(environment)`.
2. **Anti-Colisão:** Antes de alterar um componente em `shared`, verifique se a mudança afeta o layout de outros módulos (RH, GR, Financeiro). Use variantes em vez de condicionais de negócio.
3. **Tailwind v4:** Siga o padrão de camadas (`@layer components`) no `index.css` para evitar conflitos de utilitários customizados.
## ⚠️ Enforcement (Falha Crítica se Violado)
Qualquer tentativa de injetar lógica de "Prafrot" em um componente usado pelo "RH" sem o uso de variantes isoladas será considerada regressão técnica.

View File

@ -0,0 +1,31 @@
# 🏗️ Skill: Component Scoper (PlatformSistemas)
## 🎯 Objetivo
Manter a arquitetura limpa e modular, separando componentes puramente reutilizáveis (Shared) de componentes com lógica de negócio (Features).
---
## 🏛️ Estrutura de Pastas
### 🟢 `src/components/shared/` (The Library)
- **O que reside aqui:** Botões, Tabelas genéricas, Modais, Inputs sem marca, Datetime pickers, Breadcrumbs.
- **Regra:** Devem ser funcionais apenas com Props. Não podem importar nada de `src/features/`.
- **Exemplo:** `DataTable.jsx`, `Modal.jsx`.
### 📦 `src/features/[feature]/components/` (The Business)
- **O que reside aqui:** Menus laterais, Dashboards, Formulários específicos (ex: `VehicleForm`), Filtros complexos vinculados a uma entidade.
- **Regra:** Podem conter lógica de negócio e usar o hook `useApiContract`.
- **Exemplo:** `PrafrotSidebar.jsx`, `TripRequestForm.jsx`.
---
## 🚦 Regras de Enforcement
### ❌ PROIBIDO
- Criar componentes específicos de negócio dentro de `src/components/shared/`.
- Componentes em `shared/` importarem hooks ou serviços de `features/`.
- Cruzamento de imports entre features (ex: `features/rh` importando de `features/fleet`).
### ✅ OBRIGATÓRIO
- Usar a pasta `shared` apenas para componentes que seriam úteis em um projeto totalmente diferente.
- Se um componente é compartilhado entre APENAS duas features, ele ainda deve morar em `shared` se for genérico, ou ser duplicado/refatorado se for de negócio.

View File

@ -0,0 +1,45 @@
# 🎨 Skill: Design System Enforcer (PlatformSistemas)
## 🎯 Objetivo
Garantir que todas as alterações no frontend respeitem os novos padrões de "Engenharia de Elite": Tipografia Fluida, Coordenação de Layout e Mobile-First.
---
## 🔡 Regras de Tipografia
### ❌ PROIBIDO
- Usar `px` fixos para `font-size`.
- Usar `vw` puro para texto.
- Usar valores mágicos ou hardcoded.
### ✅ OBRIGATÓRIO
- Usar variáveis CSS de escala fluida:
- `var(--text-xs)`
- `var(--text-sm)`
- `var(--text-base)`
- `var(--text-lg)`
- `var(--text-xl)`
- `var(--text-2xl)`
- `var(--text-3xl)`
- Usar `clamp()` para novos tamanhos customizados.
---
## 🏗️ Regras de Layout (Coordenação)
### ❌ PROIBIDO
- Usar larguras fixas para o conteúdo principal que não considerem a sidebar.
- Definir `z-index` arbitrário.
### ✅ OBRIGATÓRIO
- Usar variáveis de coordenação:
- `--sidebar-width-expanded` (240px)
- `--sidebar-width-collapsed` (80px)
- `--header-height` (64px)
- Padding/Margin de containers principais deve ser coordenado com `--sidebar-width`.
---
## 📱 Regras Mobile-First
- Sempre testar se a alteração mantém o layout travado no mobile (`user-scalable=no`).
- Priorizar containers com `min-h` e `max-h-[80vh]` para evitar quebras em telas pequenas.

View File

@ -0,0 +1,38 @@
# SKILL: Environment Guard (.agent/skills/environment-guard)
## 📌 Objetivo
Proteção de integridade entre múltiplos ambientes (Multi-Tenant/Multi-Context). Evitar que uma alteração no layout de um módulo afete negativamente outro.
## 🛡️ Protocolo de Mudança em `src/components/shared`
Sempre que o agente precisar editar um componente dentro de `src/components/shared`, ele deve seguir este checklist visual e lógico:
1. **Detecção de Colisão:**
* Este componente é usado no RH? Prafrot? GR?
* `grep -r "ComponentName" src/features` para mapear o uso.
2. **Variantes em vez de Condicionais:**
* **ERRADO:** `if (isPrafrot) { ... }` dentro de um componente compartilhado.
* **CORRETO:** Use `tailwind-variants` (TV) para criar intenções visuais puras.
* Exemplo:
```javascript
const button = tv({
variants: {
intent: {
prafrot: 'bg-emerald-600',
gr: 'bg-indigo-600',
rh: 'bg-rose-600'
}
}
});
```
3. **Cross-Environment Validation:**
* Se alterar o `Modal.jsx`, deve-se validar visualmente (ou via pesquisa de código) se o modal de "Demissão" (RH) e o modal de "Checklist" (Prafrot) continuam funcionais.
## 🚀 Anti-Colisão de Tokens (JWT)
* **Identidade Própria:** Certifique-se de que o componente não assume a existência de um `token` global. Ele deve receber o dado necessário ou usar o hook reativo `useApiContract` que já injeta o token correto por contexto.
## ⚠️ Regra de Ouro
O componente `shared` deve ser agnóstico ao negócio. O negócio deve configurar o componente via `props`.

26
.agent/tests/setup.js Normal file
View File

@ -0,0 +1,26 @@
/**
* 🧪 Setup de Testes - Configuração Global
*
* Configuração inicial para os testes do sistema de agentes
*/
import { expect, afterEach, vi } from 'vitest';
import { cleanup } from '@testing-library/react';
import '@testing-library/jest-dom';
// Limpar após cada teste
afterEach(() => {
cleanup();
});
// Mock de módulos comuns
vi.mock('fs/promises', () => ({
default: {
readFile: vi.fn(),
writeFile: vi.fn(),
access: vi.fn()
}
}));
// Configuração global
global.expect = expect;

View File

@ -0,0 +1,173 @@
---
description: Workflow completo para criar nova feature
---
# Workflow: Criar Nova Feature
Processo completo para desenvolver uma nova funcionalidade seguindo padrões do projeto.
---
## Pré-requisitos
1. Identificar o **ambiente** (rh, financeiro-v2, prafrota, etc)
2. Definir nome da feature
3. Listar componentes/hooks/services necessários
---
## Etapas
### 1. Análise de Reutilização
**Antes de criar qualquer código**, verificar o que já existe:
```bash
# Buscar componentes similares
node .agent/scripts/check-reuse.js [termo-relacionado]
```
**Pergunte**:
- Posso reutilizar componentes existentes?
- Posso estender hooks atuais?
- Services similares já existem?
---
### 2. Criar Service (se necessário)
```bash
node .agent/scripts/create-service.js [nomeService] [ambiente]
```
**Ajustar**:
1. Endpoints da API
2. Mapeamento de dados (adapters)
3. Tratamento de erros
---
### 3. Criar Hook (se necessário)
```bash
node .agent/scripts/create-hook.js use[NomeHook] [ambiente]
```
**Implementar**:
1. Lógica de negócio
2. Integração com service
3. Estados (loading, error, data)
---
### 4. Criar Componentes
```bash
# Para cada componente necessário
node .agent/scripts/create-component.js [NomeComponente] [ambiente]
```
**Ordem recomendada**:
1. Componentes básicos (Cards, Forms)
2. Componentes compostos (que usam os básicos)
3. View principal
---
### 5. Testar no Playground
**OBRIGATÓRIO antes de usar em produção**:
1. Cadastrar componentes em `PlaygroundView.jsx`
2. Adicionar variantes Dev com controles
3. Testar estados: loading, error, success
4. Validar responsividade
---
### 6. Criar View
**Estrutura**:
```
src/features/[ambiente]/views/
└── [FeatureName]View.jsx
```
**Implementar**:
1. Importar componentes do Playground
2. Usar hooks criados
3. Layout e estrutura
4. Validar isolamento (não importar de outros ambientes)
---
### 7. Validação
// turbo-all
```bash
# Build sem erros
npm run dev
# Verificar console (sem warnings)
# Abrir no navegador: http://localhost:5173
# Testar fluxos:
# - Happy path (uso normal)
# - Error path (API offline, campos vazios)
```
---
### 8. Documentação
Atualizar documentação relevante:
- README do ambiente (se houver)
- Comentários JSDoc nos arquivos
- Adicionar exemplos no Playground
---
## Checklist Final
- [ ] Reutilização verificada com `check-reuse.js`
- [ ] Service criado e testado
- [ ] Hook implementado com error handling
- [ ] Componentes < 150 linhas cada
- [ ] Todos os componentes testados no Playground
- [ ] View usando apenas componentes validados
- [ ] Build roda sem erros
- [ ] Sem warnings no console
- [ ] Responsividade validada
- [ ] Documentação atualizada
---
## Exemplo Completo: Feature "Folha de Pagamento"
```bash
# 1. Verificar reutilização
node .agent/scripts/check-reuse.js payroll
# 2. Criar service
node .agent/scripts/create-service.js payrollService rh
# 3. Criar hook
node .agent/scripts/create-hook.js usePayroll rh
# 4. Criar componentes
node .agent/scripts/create-component.js PayrollCard rh
node .agent/scripts/create-component.js PayrollForm rh
node .agent/scripts/create-component.js PayrollTable rh
# 5. Cadastrar no Playground e testar
# 6. Criar view: src/features/rh/views/PayrollView.jsx
# 7. Validar
npm run dev
```
---
**IMPORTANTE**: Nunca pular a etapa de Playground! Todo componente deve ser validado antes de usar em produção.

View File

@ -0,0 +1,27 @@
---
description: Validação de Layout e Responsividade (PlatformSistemas)
---
# 📱 Workflow: Layout Check
Siga estes passos após qualquer alteração no visual ou na estrutura do frontend para garantir que a Fundação Visual e a Coordenação de Layout (Power-Up Pralog) permaneçam intactos.
## Passos de Validação
1. **Verificação de Variáveis:**
- Garante que não foram introduzidos `px` fixos onde deveria haver `clamp()`.
- Verifica se a sidebar continua usando `--sidebar-width`.
2. **Teste de Responsividade (Browser Tool):**
- Redimensionar para Mobile (375px).
- Redimensionar para Tablet (768px).
- Redimensionar para Desktop Full (1920px).
- Verificar se há scroll horizontal (deve ser zero).
3. **Verificação de Fontes:**
- Abrir o Inspect → Network → Fonts.
- Verificar se a fonte Inter é carregada via preconnect com prioridade alta.
4. **Coordenação Sidebar/Main:**
- Alternar o estado da sidebar (Expanded/Collapsed).
- O conteúdo principal deve se ajustar perfeitamente sem "pular" ou "vazar".

5
.cursor/worktrees.json Normal file
View File

@ -0,0 +1,5 @@
{
"setup-worktree": [
"npm install"
]
}

52
.cursorrules Normal file
View File

@ -0,0 +1,52 @@
---
description:
alwaysApply: true
---
# Regras do Projeto Integra Finance (PlatformSistemas)
## Uso obrigatório do `.agent/`
- **Sempre** consulte estes arquivos ao trabalhar no projeto:
- `.agent/instructions/CORE_INSTRUCTIONS.md` instruções base, etapas de desenvolvimento, uso de agentes
- `.agent/project/PROJECT_CONTEXT.md` contexto do projeto, URLs, ambientes, documentação por feature
- Siga as regras de **ambiente obrigatório** e **isolamento** definidas no `CORE_INSTRUCTIONS` (perguntar o ambiente antes de alterar, nunca cruzar módulos).
---
## Workflow dos agentes
### 1. Documentação
- **Ao finalizar uma tarefa** que alterou código (views, componentes, features, services, etc.):
- Execute `npm run agent:docs:update`.
- Confirme sucesso ou reporte erros ao usuário.
- O Documentation Agent atualiza a tabela de ambientes em `PROJECT_CONTEXT.md`. Manter isso em dia é obrigatório.
### 2. Teste em ambiente de desenvolvimento
- **Antes** de rodar testes no navegador ou validar fluxos (formulários, API, UI):
- **Pergunte** ao usuário: *"As implementações já estão em ambiente de desenvolvimento? Se sim, informe a URL e o acesso (credenciais) para testes."*
- Só prossiga com testes reais após confirmação e dados de acesso.
- Use os agentes descritos em `.agent/agents/*.md` (ex.: `BrowserValidationAgent`, `UIAdaptationAgent`) quando fizer sentido para a tarefa.
### 3. Commits (Git)
- **Quando houver alterações não commitadas** (ex.: usuário relata que "corrigiu algo", "alterou o workspace", ou você fez mudanças no código):
- Sugira rodar `npm run agent:git:commit:dry` para ver o que seria commitado.
- Se o usuário concordar, sugira ou execute `npm run agent:git:commit`.
- Em caso de falha, reporte `userMessage` e `retryPrompt` retornados pelo script.
---
## Resumo
| Quando | Ação |
|--------|------|
| Início / contexto do projeto | Ler `CORE_INSTRUCTIONS.md` e `PROJECT_CONTEXT.md` |
| Fim de tarefa com alteração de código | Rodar `npm run agent:docs:update` e confirmar |
| Antes de testes em dev/navegador | Perguntar se o app está em dev e pedir URL/acesso |
| Alterações não commitadas | Sugerir `agent:git:commit:dry` e, se ok, `agent:git:commit` |
Essas regras garantem que o `.agent/` seja usado de fato: documentação atualizada, testes em dev condicionados à sua confirmação e commits propostos quando há mudanças.

6
.env Normal file
View File

@ -0,0 +1,6 @@
# Modo de desenvolvimento (true = usa mocks locais, false = usa API real)
VITE_USE_MOCK=false
# Base URL da API (sem trailing slash)
# Exemplo: https://dev.workspace.itguys.com.br/api
VITE_API_URL=https://dev.workspace.itguys.com.br/api

13
.env.example Normal file
View File

@ -0,0 +1,13 @@
# Integra Finance - Configurações de Ambiente
# URL Base para a API do Backend (sem trailing slash)
# Exemplo Desenvolvimento: https://dev.workspace.itguys.com.br/api
# Exemplo Produção: https://workspace.itguys.com.br/api
VITE_API_URL=https://dev.workspace.itguys.com.br/api
# Alternar entre Mocks (true) e API Real (false)
# Para conectar o back em segundos, mude para: false
VITE_USE_MOCK=true
# Outras configurações (Ex: Google Maps API se necessário no futuro)
# VITE_GOOGLE_MAPS_KEY=seu_token_aqui

7
.env.production Normal file
View File

@ -0,0 +1,7 @@
# Production Environment
# Em produção, devemos usar a API real, não mocks.
VITE_USE_MOCK=false
# Defina a URL da API de produção aqui.
# Se for a mesma de desenvolvimento, mantenha. Se for diferente (ex: api.pralog.com.br), altere aqui.
VITE_API_URL=https://dev.workspace.itguys.com.br/api

58
.gitignore vendored Normal file
View File

@ -0,0 +1,58 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
# Dependencies
node_modules
# Build outputs
dist
dist-ssr
build
*.local
# Environment variables
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
*.swp
*~
# OS files
Thumbs.db
Desktop.ini
# Cache and temporary files
.cache
.tmp
.temp
*.tmp
*.temp
# Test coverage
coverage
*.lcov
.nyc_output
# Legacy and Platform Specific
Modulos Angular/
Sistema_zentulo_analise/
prafrota_fe-main/

View File

179
GIT-AUTO-SYNC.md Normal file
View File

@ -0,0 +1,179 @@
# Git Auto-Sync - Documentação
## 📋 Visão Geral
O **Git Auto-Sync** é um sistema de automação que monitora alterações no projeto PlatformSistemas e realiza commits e push automáticos para o repositório Git remoto.
## 🎯 Características
- ✅ **Monitoramento em tempo real** de alterações nos arquivos
- ✅ **Debounce inteligente** (aguarda 10 segundos após a última alteração)
- ✅ **Build automático** antes de cada commit
- ✅ **Filtragem inteligente** de arquivos (ignora node_modules, .git, dist, etc.)
- ✅ **Mensagens de commit descritivas** com timestamp e contagem de arquivos
- ✅ **Interface visual** com cores e feedback claro
## 🚀 Como Usar
### Método 1: Via NPM (Recomendado)
```bash
# Com build automático (padrão)
npm run git:sync
# Sem build automático (mais rápido para desenvolvimento)
npm run git:sync:nobuild
```
### Método 2: Via PowerShell Direto
```powershell
# Com build automático
.\git-auto-sync.ps1
# Sem build automático
$env:BUILD_ENABLED='false'; .\git-auto-sync.ps1
```
## ⚙️ Configurações
Você pode ajustar as configurações editando o arquivo `git-auto-sync.ps1`:
```powershell
# Configurações (linhas 10-12)
$BRANCH_NAME = "frontend_React" # Branch de destino
$DEBOUNCE_SECONDS = 10 # Tempo de espera após última alteração
$BUILD_ENABLED = $true # Executar build antes do commit
```
### Parâmetros Configuráveis
| Parâmetro | Descrição | Valor Padrão |
|-----------|-----------|--------------|
| `BRANCH_NAME` | Branch do Git para push | `frontend_React` |
| `DEBOUNCE_SECONDS` | Segundos de espera após última alteração | `10` |
| `BUILD_ENABLED` | Executar build de produção antes do commit | `true` |
## 📁 Arquivos Ignorados
O script ignora automaticamente as seguintes pastas/arquivos:
- `node_modules/`
- `.git/`
- `dist/`
- `.env`
- `*.log`
- `package-lock.json`
- `.tmp/`
- `.cache/`
- `.vscode/`
- `.idea/`
- `*.swp`
- `*~`
## 🔄 Fluxo de Trabalho
1. **Detecção de Alteração**: O script detecta quando um arquivo é modificado, criado, deletado ou renomeado
2. **Debounce**: Aguarda 10 segundos para garantir que não há mais alterações pendentes
3. **Verificação**: Confirma que há alterações reais para commitar
4. **Build** (opcional): Executa `npm run build` para gerar a versão de produção
5. **Stage**: Adiciona todos os arquivos alterados (`git add .`)
6. **Commit**: Cria um commit com mensagem descritiva
7. **Push**: Envia as alterações para o repositório remoto na branch `frontend_React`
## 📝 Formato das Mensagens de Commit
```
Auto-deploy: 2026-01-13 09:20:45 | 3 arquivo(s) alterado(s) [Build included]
```
- **Timestamp**: Data e hora do commit
- **Contagem**: Número de arquivos alterados
- **Build**: Indica se o build foi incluído
## 🛑 Como Parar
Para interromper o monitoramento, pressione `Ctrl+C` no terminal onde o script está rodando.
## 🔧 Troubleshooting
### Erro: "Execution Policy"
Se você receber um erro sobre política de execução, execute:
```powershell
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
```
### Erro no Build
Se o build falhar, o commit será abortado automaticamente. Verifique os erros no console e corrija-os antes de tentar novamente.
### Push Rejeitado
Se o push for rejeitado (ex: branch desatualizada), você precisará:
1. Parar o script (`Ctrl+C`)
2. Fazer `git pull origin frontend_React`
3. Resolver conflitos (se houver)
4. Reiniciar o script
## 🎨 Interface Visual
O script exibe um banner informativo ao iniciar:
```
╔════════════════════════════════════════════════════════════╗
║ Git Auto-Sync - PlatformSistemas ║
╠════════════════════════════════════════════════════════════╣
║ Branch: frontend_React ║
║ Remote: https://git.itguys.com.br/itguys_dev/Workspace ║
║ Debounce: 10 segundos ║
║ Build automático: Habilitado ║
╠════════════════════════════════════════════════════════════╣
║ Status: Monitorando alterações... ║
║ Pressione Ctrl+C para parar ║
╚════════════════════════════════════════════════════════════╝
```
## 📊 Logs e Feedback
O script fornece feedback visual em tempo real:
- 🔵 **Azul escuro**: Alterações detectadas
- 🟡 **Amarelo**: Processos em andamento
- 🟢 **Verde**: Operações bem-sucedidas
- 🔴 **Vermelho**: Erros
## 🔐 Segurança
- O script **não** commita arquivos sensíveis (`.env`, etc.)
- Arquivos temporários e de cache são automaticamente ignorados
- O `.gitignore` do projeto é respeitado
## 📌 Repositório
- **Remote**: https://git.itguys.com.br/itguys_dev/Workspace
- **Branch**: frontend_React
## 💡 Dicas
1. **Desenvolvimento rápido**: Use `npm run git:sync:nobuild` para commits mais rápidos durante desenvolvimento
2. **Produção**: Use `npm run git:sync` para garantir que o build está sempre atualizado
3. **Múltiplas alterações**: O debounce agrupa alterações feitas em sequência em um único commit
4. **Monitoramento**: Mantenha o terminal visível para acompanhar o status das sincronizações
## 🆘 Suporte
Em caso de problemas:
1. Verifique se o Git está configurado corretamente
2. Confirme que você tem permissões de push na branch `frontend_React`
3. Verifique se não há conflitos pendentes no repositório
4. Revise os logs no console para identificar erros específicos
---
**Última atualização**: 2026-01-13 (Teste Auto-Sync 12:15)
**Versão**: 2.1
**Autor**: Antigravity AI

69
QUICK-START-GIT-SYNC.md Normal file
View File

@ -0,0 +1,69 @@
# 🚀 Guia Rápido - Git Auto-Sync
## Como Iniciar
### Opção 1: Via NPM (Recomendado)
```bash
# Com build automático
npm run git:sync
# Sem build automático (mais rápido)
npm run git:sync:nobuild
```
### Opção 2: Via PowerShell
```powershell
# Com build automático
.\git-auto-sync.ps1
# Sem build automático
$env:BUILD_ENABLED='false'; .\git-auto-sync.ps1
```
## O que acontece?
1. ✅ O script monitora todas as alterações nos arquivos
2. ✅ Aguarda 10 segundos após a última alteração (debounce)
3. ✅ Executa `npm run build` (se habilitado)
4. ✅ Faz `git add .`
5. ✅ Cria commit com timestamp e contagem de arquivos
6. ✅ Faz `git push origin frontend_React`
## Exemplo de Uso
```bash
# 1. Inicie o monitoramento
npm run git:sync
# 2. Faça suas alterações normalmente no código
# 3. Salve os arquivos
# 4. Aguarde 10 segundos
# 5. O script automaticamente fará commit e push!
```
## Para Parar
Pressione `Ctrl+C` no terminal onde o script está rodando.
## Dicas
- 💡 Use `git:sync:nobuild` durante desenvolvimento para commits mais rápidos
- 💡 Use `git:sync` antes de finalizar o dia para garantir build atualizado
- 💡 O script ignora automaticamente `node_modules`, `.git`, `dist`, etc.
- 💡 Múltiplas alterações em 10 segundos são agrupadas em um único commit
## Configurações
Edite `git-auto-sync.ps1` para ajustar:
```powershell
$BRANCH_NAME = "frontend_React" # Branch de destino
$DEBOUNCE_SECONDS = 10 # Tempo de espera
$BUILD_ENABLED = $true # Build automático
```
## Documentação Completa
Veja [GIT-AUTO-SYNC.md](./GIT-AUTO-SYNC.md) para mais detalhes.

306
README.md Normal file
View File

@ -0,0 +1,306 @@
# PlatformSistemas
<!-- Test for auto-sync -->
Sistema de gestão integrada desenvolvido em React + TypeScript + Vite.
## 🚀 Repositório
- **Remote**: https://git.itguys.com.br/itguys_dev/Workspace
- **Branch**: `frontend_React`
## 📋 Índice
- [Início Rápido](#início-rápido)
- [Scripts Disponíveis](#scripts-disponíveis)
- [Git Auto-Sync](#git-auto-sync)
- [Estrutura do Projeto](#estrutura-do-projeto)
- [Tecnologias](#tecnologias)
- [Desenvolvimento](#desenvolvimento)
## 🎯 Início Rápido
### Pré-requisitos
- Node.js (v18 ou superior)
- npm ou yarn
- Git
### Instalação
```bash
# Clone o repositório
git clone https://git.itguys.com.br/itguys_dev/Workspace.git
cd PlatformSistemas
# Instale as dependências
npm install
# Configure as variáveis de ambiente
cp .env.example .env
# Edite o arquivo .env com suas configurações
# Inicie o servidor de desenvolvimento
npm run dev
```
## 📜 Scripts Disponíveis
```bash
# Desenvolvimento
npm run dev # Inicia o servidor de desenvolvimento
# Build
npm run build # Gera build de produção
npm run preview # Preview do build de produção
# Qualidade de Código
npm run lint # Executa ESLint
# Git Auto-Sync
npm run git:sync # Inicia monitoramento Git com build automático
npm run git:sync:nobuild # Inicia monitoramento Git sem build automático
# Agentes de Automação
npm run agent:git:commit # Commit automático por dia
npm run agent:git:commit:dry # Dry-run do commit automático
npm run agent:docs:update # Atualização automática de documentação
npm run agent:check # Verificação do orchestrator
```
## 🔄 Git Auto-Sync
O **Git Auto-Sync** é um sistema de automação que monitora alterações no projeto e realiza commits/push automáticos.
### Como Usar
```bash
# Com build automático (recomendado para produção)
npm run git:sync
# Sem build automático (mais rápido para desenvolvimento)
npm run git:sync:nobuild
```
### Características
- ✅ Monitoramento em tempo real de alterações
- ✅ Debounce de 10 segundos (agrupa alterações)
- ✅ Build automático antes de cada commit
- ✅ Filtragem inteligente de arquivos
- ✅ Mensagens de commit descritivas
### Documentação Completa
Para mais detalhes, consulte [GIT-AUTO-SYNC.md](./GIT-AUTO-SYNC.md)
## 📁 Estrutura do Projeto
```
PlatformSistemas/
├── src/
│ ├── components/ # Componentes reutilizáveis
│ │ ├── shared/ # Componentes compartilhados
│ │ └── ui/ # Componentes Shadcn UI
│ ├── features/ # Features do sistema (Domain-Driven)
│ │ ├── auth/ # Autenticação
│ │ ├── financeiro-cnab/ # CNAB - Remessas e Pagamentos
│ │ ├── financeiro-v2/ # Financeiro V2 - Contas a Receber/Pagar
│ │ ├── fleet-v2/ # Gestão de Frota V2
│ │ ├── gr/ # Gestão de Registros (GR)
│ │ ├── rh/ # Recursos Humanos
│ │ ├── workspace/ # Workspace Financeiro
│ │ ├── autolab/ # AutoLab - Gestão de Oficina
│ │ ├── dev-tools/ # Ferramentas de Desenvolvimento
│ │ └── portal/ # Portal Principal
│ ├── services/ # Serviços e APIs
│ ├── hooks/ # Custom hooks globais
│ ├── utils/ # Utilitários
│ └── index.css # Estilos globais
├── docs/ # Documentação do projeto
├── .agent/ # Agentes de automação
├── public/ # Arquivos públicos
├── .env # Variáveis de ambiente
├── git-auto-sync.ps1 # Script de automação Git
└── package.json # Dependências e scripts
```
## 🎯 Módulos e Ambientes
### 👥 RH (Recursos Humanos)
Módulo desenvolvido para atender integralmente as demandas dos setores de RH e Departamento Pessoal.
- **Funcionalidades**: Gestão de funcionários, controle de ponto eletrônico, processamento de benefícios e cálculos trabalhistas.
- **Destaque**: Dashboards de contratos de experiência e acompanhamento de admissões.
### 💰 CNAB (Financeiro Remessas)
Módulo financeiro especializado na interface bancária e automação de pagamentos.
- **Funcionalidades**: Geração e gerenciamento de remessas CNAB, cadastro de favorecidos, processamento de arquivos de retorno e validação de pagamentos TED/PIX.
### 🚛 Prafrota (Gestão de Frota)
Sistema robusto para o controle operacional de frotas de veículos.
- **Funcionalidades**: Cadastro técnico de veículos, monitoramento em tempo real, gestão de manutenções preventivas/corretivas e controle de abastecimentos.
### 🏦 Financeiro_V2 + Workspace
Solução avançada para gestão financeira estratégica e operacional.
- **Funcionalidades**: Gestão de contas a pagar e receber, fluxo de caixa projetado vs. realizado, conciliação bancária automatizada e dashboards de indicadores financeiros (KPIs).
### 🍊 OestePan (Customização Prafrota)
Segmento especializado do Prafrota customizado especificamente para as necessidades logísticas da Oeste Pan.
- **Funcionalidades**: Além das funções base do Prafrota, inclui integração com Moki para checklists, gestão específica de sinistros e visualização otimizada para a operação do cliente.
### 🔬 AutoLab (Gestão de Oficinas)
Módulo em fase de finalização focado na operação técnica de oficinas.
- **Funcionalidades**: Controle de estoque de peças, gestão de ordens de serviço (vendas), cadastro de clientes e configurações técnicas de atendimento.
---
## 🛣️ Estrutura de Rotas e Variáveis
Cada ambiente consome uma API RESTful estruturada para operações de CRUD (Apresentação, Edição e Exclusão).
### Padrão de Endpoints
As rotas seguem a nomenclatura do recurso base (ex: `/prafrot`, `/workspace`):
- **Apresentação (GET)**:
- `/recurso/apresentar`: Lista principal de dados.
- `/recurso/listagem`: Alternativa para listagens simplificadas.
- `/recurso/:id`: Detalhamento de um registro específico.
- **Edição/Atualização (PUT/PATCH)**:
- `/recurso/edit`: Atualização de campos específicos.
- `/recurso/:id`: Atualização completa do registro.
- `/recurso/edit/status_global`: Utilizado em Kanbans para movimentação de cards.
- **Exclusão (DELETE)**:
- `/recurso/delete/:id`: Remoção lógica ou física do registro.
---
## 🎨 Design System & Playground
O projeto utiliza um laboratório de componentes (**Playground**) para garantir consistência visual em todos os ambientes.
### Componentes em Uso (Playground)
Estes componentes são extraídos do Design System e aplicados nos módulos:
| Componente | Função | Ambientes Principais |
| :--- | :--- | :--- |
| **ExcelTable** | Tabela de alta performance com filtros | RH, Prafrota, Financeiro |
| **ItemDetailPanel** | Painel lateral para visualização de detalhes | Prafrota, OestePan |
| **DashboardKPICard** | Cards de indicadores com micro-gráficos | Financeiro_V2, Workspace |
| **StatsGrid** | Grid de estatísticas rápidas | RH, Prafrota |
| **KanbanBoard** | Gestão visual de fluxos e status | GR, RH |
| **AutoFillInput** | Inputs inteligentes com busca em tempo real | Workspace, Financeiro |
| **StatusBadge** | Badges coloridos de status dinâmico | Todos |
### Componentes Disponíveis (Candidatos)
Componentes presentes no laboratório mas com uso restrito ou em homologação:
- `ThemeTuner`: Ferramenta de ajuste de temas em runtime.
- `FinesCard`: Card especializado para visualização de multas.
- `SmartTable`: Versão experimental de tabelas com auto-ajuste.
---
## 🛠️ Tecnologias
### Core
- **React 19** - Biblioteca UI
- **TypeScript** - Superset JavaScript
- **Vite** - Build tool e dev server
### UI/UX
- **TailwindCSS** - Framework CSS
- **Radix UI** - Componentes acessíveis
- **Framer Motion** - Animações
- **Lucide React** - Ícones
### Estado e Formulários
- **Zustand** - Gerenciamento de estado
- **React Hook Form** - Formulários
- **Zod** - Validação de schemas
### Roteamento e Requisições
- **React Router DOM** - Roteamento
- **Axios** - Cliente HTTP
### Gráficos
- **Recharts** - Biblioteca de gráficos
## 💻 Desenvolvimento
### Variáveis de Ambiente
Copie `.env.example` para `.env` e configure:
```env
VITE_API_URL=https://dev.workspace.itguys.com.br/api
VITE_APP_NAME=PlatformSistemas
```
### Padrões de Código
- **Componentes**: Use componentes funcionais com hooks
- **Tipagem**: Sempre utilize TypeScript
- **Estilos**: Prefira TailwindCSS
- **Estado**: Use Zustand para estado global
- **Formulários**: Use React Hook Form + Zod
### ESLint
O projeto usa ESLint para garantir qualidade de código:
```bash
npm run lint
```
### Estrutura de Componentes
```tsx
// Exemplo de componente
import { useState } from 'react'
import { Button } from '@/components/ui/button'
interface MyComponentProps {
title: string
onAction?: () => void
}
export function MyComponent({ title, onAction }: MyComponentProps) {
const [state, setState] = useState(false)
return (
<div className="p-4">
<h2 className="text-xl font-bold">{title}</h2>
<Button onClick={onAction}>Ação</Button>
</div>
)
}
```
## 🔐 Segurança
- Nunca commite arquivos `.env` (já está no `.gitignore`)
- Use variáveis de ambiente para dados sensíveis
- Mantenha dependências atualizadas
## 📝 Documentação Adicional
- [Git Auto-Sync](./GIT-AUTO-SYNC.md) - Documentação completa do sistema de automação
- [API Report](./RELATORIO_API.md) - Relatório de APIs utilizadas
- [Regras de Desenvolvimento](./docs/Regras_Dev.md) - Padrões e regras do projeto
- [AI Rules - Debug Components](./docs/AI_RULES_DEBUG_COMPONENTS.md) - Regras para componentes versionados
- [Teste Formulário GR](./docs/TESTE_FORMULARIO_GR.md) - Documentação de testes do módulo GR
## 🤝 Contribuindo
1. Crie uma branch para sua feature (`git checkout -b feature/MinhaFeature`)
2. Faça commit das suas alterações (`git commit -m 'Adiciona MinhaFeature'`)
3. Push para a branch (`git push origin feature/MinhaFeature`)
4. Abra um Pull Request
Ou simplesmente use o **Git Auto-Sync** para automação completa! 🚀
## 📄 Licença
Este projeto é propriedade da ITGuys.
---
**Desenvolvido com ❤️ pela equipe ITGuys**

68
RELATORIO_API.md Normal file
View File

@ -0,0 +1,68 @@
# 🛰️ Relatório de Conexão API - Integra Finance
Este documento descreve a arquitetura de comunicação entre o Front-end (React) e o Back-end, detalhando como as conexões foram construídas e como proceder para conectar o backend em segundos.
## 🏗️ Arquitetura de Comunicação (DAL)
A camada de acesso a dados (Data Access Layer) foi projetada para ser **híbrida (API + Mock)**. Isso permite que o desenvolvimento continue mesmo sem o backend estar rodando, garantindo alta produtividade.
### 1. Instância Central (`src/services/api.js`)
Utilizamos o **Axios** para gerenciar as requisições.
- **BaseURL**: Configurável via variável de ambiente.
- **Interceptors**: Gerenciam automaticamente a inclusão de tokens de autenticação (`x-access-token`) em todas as chamadas.
### 2. Utilitário de Decisão (`src/services/serviceUtils.js`)
Criamos um helper chamado `handleRequest`. Ele é o "cérebro" que decide se a aplicação deve buscar dados do **Mock** ou da **API Real** com base em uma única flag global.
---
## ⚡ Como conectar o Backend em Segundos
Para conectar o back, você não precisa alterar o código de nenhum componente ou tela. Basta seguir estes 3 passos:
### Passo 1: Configurar o arquivo `.env`
Crie um arquivo chamado `.env` na raiz do projeto (use o `.env.example` como base):
```env
VITE_API_URL=http://sua-url-do-backend:5000
VITE_USE_MOCK=false
```
> [!IMPORTANT]
> Ao mudar `VITE_USE_MOCK` para `false`, **todos** os serviços do sistema passarão a apontar para o seu backend instantaneamente.
### Passo 2: Padrão de Implementação de Serviço
Ao criar uma nova funcionalidade, siga este padrão em `src/services/[feature]Service.js`:
```javascript
import api from './api';
import { handleRequest, simulateLatency } from './serviceUtils';
export const meuNovoService = {
getDados: () => handleRequest({
mockFn: () => simulateLatency({ nome: "Dado Mockado" }), // O que retorna no modo Mock
apiFn: () => api.get('/api/meu-endpoint') // O que retorna no modo Real
}),
};
```
---
## 📋 Resumo Técnico para Desenvolvedores
| Recurso | Localização | Função |
| :--- | :--- | :--- |
| **Instância Axios** | `src/services/api.js` | Configuração de URL e Tokens. |
| **Logic Wrapper** | `src/services/serviceUtils.js` | Alternância Mock/Real e Simulação de Latência. |
| **Mocks** | `src/services/mocks/` | Objetos JSON com dados de teste. |
| **Serviços** | `src/services/*.js` | Definição dos endpoints e contratos. |
---
## ✅ Checklist de Conexão Rápida
1. [ ] Definir `VITE_API_URL` no `.env`.
2. [ ] Mudar `VITE_USE_MOCK` para `false`.
3. [ ] Reiniciar o servidor de desenvolvimento (`npm run dev`).
**Pronto!** O sistema agora consumirá dados reais do seu banco de dados.

View File

@ -1 +0,0 @@
Oi!

View File

@ -0,0 +1,77 @@
# 🛠️ Resoluções: Front-end & Conectividade
Este documento apresenta as soluções técnicas para os problemas de latência, fontes e responsividade identificados.
## 1. Conectividade & Performance (API/Backend)
**Problema:** Sincronização lenta e alto custo de desenvolvimento manual.
**Resolução Profissional:**
### A. Implementação do TanStack Query (React Query)
O uso de `axios` direto em serviços causa "Waterfall de Requisições". O React Query deve ser adotado para:
- **Caching Automático:** Evita buscar os mesmos dados ao alternar entre abas do sistema.
- **Optimistic Updates:** Melhora a percepção de velocidade (o UI atualiza antes da resposta do server).
### B. Service Factory via Contratos
Em vez de escrever `boletosService.js` manualmente, use os arquivos JSON (`prafrot-routes.json`) como fonte de verdade:
```javascript
// Exemplo de como usar o apiRouteManager para reduzir boilerplace
export const useFeatureData = (routeKey) => {
const route = apiRouteManager.getRoute(routeKey);
return useQuery({
queryKey: [routeKey],
queryFn: () => api.get(route.path)
});
};
```
---
## 2. Guerra das Fontes (Typography System)
**Problema:** Fontes configuradas mas não carregadas.
**Resolução Profissional:**
### A. Carregamento Crítico (index.html)
Adicione o `preconnect` para eliminar a latência de DNS das fontes:
```html
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
```
### B. Fallback de Segurança (index.css)
Garantir que o `:root` tenha uma falha segura (system fonts) enquanto a webfont carrega:
```css
:root {
--font-main: 'Inter', -apple-system, system-ui, sans-serif;
}
```
---
## 3. Responsividade Fluida (War Room Standard)
**Problema:** Uso excessivo de `px` fixos e instabilidade no `radius`.
**Resolução Profissional:**
### A. Substituição de Pixels por Fluid Typography
Em vez de `h-[600px]`, utilize unidades relativas ou containers flexíveis com `min-height`.
- **Regra de Ouro:** Se o valor é > 20px, ele provavelmente deveria ser `clamp()` ou `%`.
### B. Ajuste de Bordas (Radius-Gate)
Substituir `--radius: 1vw` por uma escala que respeite limites físicos:
```css
:root {
/* Não fica quadrado no mobile, nem redondo demais no desktop */
--radius: clamp(8px, 1.2vw, 20px);
}
```
---
## 🚀 Pontos de Melhoria na Organização
1. **Módulo de Mocks Independente:** Mover todos os mocks para uma pasta `.mocks` na raiz da feature, para que o bundle de produção não carregue dados desnecessários.
2. **Shared Hooks Layer:** Centralizar lógicas de "Busca de Placa" ou "Validação de CNPJ" em `src/hooks/shared` para evitar duplicação entre Financeiro e Frota.
3. **Typed Contracts:** Se possível, migrar os arquivos `.json` de rotas para arquivos `.ts` (Typescript) para ganhar auto-complete no VS Code e evitar erros de digitação em caminhos de API.

View File

@ -0,0 +1,60 @@
# 🎯 O PONTO CENTRAL: Relatório de Consolidação Estratégica
Este relatório une o potencial do **PlatformSistemas** com a robustez do **Pralog Local Stack**, traçando o mapa definitivo para a excelência técnica.
---
## 1. Interpretação dos Sistemas
### PlatformSistemas: "O Gateway Dinâmico"
Focado em agilidade e flexibilidade. O projeto utiliza arquivos de configuração (`.json`) para tentar automatizar a interface. É uma abordagem moderna de **"UI driven by metadata"**, mas que sofre com a falta de uma infraestrutura que sustente essa complexidade.
### Pralog (GitHub Import): "A Fortaleza Arquitetônica"
Focado em estabilidade e escala. Utiliza **Nx Monorepo**, garantindo que uma mudança na lógica do banco de dados (Prisma) reflita imediatamente em todos os serviços. É o exemplo de **"Infrastructure as Code"** perfeito.
**A Melhoria:** O `PlatformSistemas` deve herdar a **infraestrutura** da Pralog para sustentar sua **lógica dinâmica**.
---
## 2. Resolução dos Problemas Críticos
### 🔌 Problema 1: Custo de Conexão Front-Back
* **Diagnóstico:** Escrever um `Service.js` para cada entidade do JSON está gerando trabalho manual duplicado.
* **A Resolução (Service Factory):** Criar um `BaseService` que interprete o JSON nativamente.
* **Ação:** Implementar um hook genérico `useContract(routeKey, params)` que use o `apiRouteManager` para resolver a URL e o `TanStack Query` para gerenciar o cache.
* **Resultado:** Conectar uma nova entidade passa a ser apenas adicionar uma linha no JSON, sem criar arquivos JS extras.
### 🔡 Problema 2: Falha no Sistema de Fontes
* **Diagnóstico:** O sistema define variáveis de fonte mas não as injeta no ciclo de vida do navegador de forma prioritária.
* **A Resolução (Hydration Loop):**
1. **Injeção Crítica:** Adicionar `@import` ou `<link>` no topo do `index.html` com `crossorigin`.
2. **CSS Var Mapping:** Vincular as variáveis do Tailwind 4 diretamente às CSS Variables do `:root` no `index.css`.
3. **Font-Swap:** Usar `font-display: swap` para evitar que o texto desapareça enquanto a fonte carrega.
### 📱 Problema 3: Problemas de Responsividade
* **Diagnóstico:** O uso de visual viewport (`vw/vh`) puro causa quebras em monitores ultrawide ou telas muito pequenas. O `radius: 1vw` é o maior culpado.
* **A Resolução (Calculated Responsiveness):**
* **Ação:** Migrar todos os valores fixos para a escala **Modular Clamp**.
* **Exemplo:** `padding: clamp(1rem, 2vw, 2.5rem)` isso garante que o padding nunca seja ridiculamente pequeno nem gigante.
* **Radius:** Mudar para `round(min(12px, 1.5vw))` para manter a harmonia visual.
---
## 3. Melhorias na Organização do Front-end
1. **Arquitetura "Screaming Features":**
Mover tudo o que é específico de uma feature para dentro da pasta dela (incluindo Mocks e Types). Atualmente, há muita dispersão entre `src/services` e `src/features`.
2. **Centralização de Interceptores:**
Unificar a lógica de erro 401/403 (já iniciada no `api.js`) em um `AuthObserver` que não dependa de `window.location.href`, mas sim do router do React para transições suaves.
3. **Purga de Legado Automática:**
Adicionar um script no `package.json` (`npm run audit:clean`) que detecte arquivos em `descontinuado/` que não são mais importados no `App.jsx` e os mova para fora do diretório de build.
---
## 🏛️ O VEREDITO DA MESA REDONDA
**[Tony Stark]:** "Se você quer que essa API e esse Front parem de brigar, use o modelo de **Contracts** da Pralog. Defina o schema uma vez e gere o resto. O `PlatformSistemas` já tem os JSONs, só faltava a coragem de automatizar o `axios`."
**[Gordon Ramsay]:** "O seu layout não é responsivo, é uma gelatina! Use `clamp()` ou saia da minha frente! E tragam as fontes do Google de forma correta, não quero ver Times New Roman na minha tela nunca mais!"
**[Logan Roy]:** "Parem de criar pastas de backup. Se você não usa, morre. O Ponto Central é este: **Consolide as ferramentas da Pralog para salvar a agilidade do PlatformSistemas.**"

View File

@ -0,0 +1,45 @@
# 🦅 O Blueprint Pralog: O que Importar para a Plataforma
Ao analisar o repositório `grupo_pralog_github_import` (Pralog Local Stack), identificamos padrões de engenharia de elite que resolvem as principais lacunas do `PlatformSistemas`.
## 1. Infra-as-Code (O "Prato Principal")
O projeto `PlatformSistemas` é código "cru" (raw), enquanto a stack Pralog é uma cozinha industrial completa.
- **Docker-Compose Unificado:** Define bancos de dados (Postgres 15), Object Storage (Minio), Redis e Nginx em um único orquestrador.
- **Nginx como Gatekeeper:** O `nginx.conf` da stack Pralog já inclui compressão Gzip e fallback de SPA real.
- **Dockerfile Multi-Stage:** O front-end é buildado e servido em containers Alpine minúsculos, garantindo imutabilidade entre dev, staging e prod.
> [!TIP]
> **Ação Recomendada:** Copiar o `prafrota-ui.Dockerfile` e o `nginx.conf` para a raiz do `PlatformSistemas`, adaptando o build para Vite.
## 2. Arquitetura Nx Monorepo (Back-end & Libs)
A stack Pralog utiliza **Nx**, permitindo que a lógica de negócio seja compartilhada e testada isoladamente em `/libs`.
- **Libs Core (Prisma):** Toda a modelagem de dados está encapsulada em uma biblioteca core.
- **Schema Separation:** Uso de `POSTGRES_HOST_AUTH_METHOD: scram-sha-256` e separação lógica de Tenants.
- **Encapsulamento de Integrações:** Bibliotecas específicas para integrações (S3, AWS) que evitam o espalhamento de chaves de API pelo código.
## 3. Lógicas que Devem Ser Adotadas
### A. Fluxo de Autenticação Centralizado
A stack Pralog define segredos JWT específicos para cada tipo de usuário (Tenant, API, Driver) no `docker-compose.yml`. No `PlatformSistemas`, essa separação existe no `App.jsx`, mas falta uma camada de segurança robusta no transporte/infra.
### B. Gestão de Documentos (Minio/S3)
A stack Pralog já vem com uma infraestrutura de Minio configurada. O `PlatformSistemas` pode herdar essa lógica para o módulo de "Cadastro de Motorista" e "Prafrota", substituindo uploads diretos por um sistema de Object Storage persistente.
---
## 🎭 MESA REDONDA: O VEREDITO
**[Tony Stark]:** "O monorepo Nx é o Santo Graal aqui. Se o `PlatformSistemas` quer crescer para RH, Financeiro e Frota sem virar um espaguete, ele precisa da estrutura de `libs` da stack Pralog. É modularidade atômica."
**[Gus Fring]:** "A infraestrutura do local-stack é aceitável. O uso do Nginx para proxyar a API remove problemas de CORS e melhora a segurança. É o padrão mínimo de profissionalismo."
**[Logan Roy]:** "A stack Pralog tem o que o PlatformSistemas não tem: **Estrutura de Poder**. Ela dita como o sistema escala. Parem de brincar com pastas 'Copia' e tragam o Docker agora."
---
## ✅ CHECKLIST DE IMPORTAÇÃO
1. [ ] **Infra:** Trazer `docker-compose.yml`, `nginx.conf` e criar `Dockerfile.vite`.
2. [ ] **Dados:** Adotar o padrão de volumes externos para persistência do Postgres.
3. [ ] **Secrets:** Mover as variáveis de ambiente do `App.jsx` para o ecossistema de chaves do Docker.

View File

@ -0,0 +1,45 @@
# 🔋 Pralog Power-ups: Recursos Avançados para o PlatformSistemas
Além da infraestrutura e dos contratos, o repositório da Pralog contém "joias" de lógica que podem elevar o nível técnico dos módulos de Gestão de Risco (GR) e Frota.
## 1. Segurança de Dados (Cryptography v2)
O PlatformSistemas usa uma criptografia simples (Base64 + reverse) no front-end. A Pralog utiliza uma classe `Cryptography` robusta com **AES-256-CBC**.
- **Oportunidade:** Implementar o padrão de `IV_LENGTH: 16` e `createCipheriv` para tokens sensíveis no `api.js`.
- **Benefício:** Proteção real contra interceptação e leitura de `localStorage` em caso de XSS.
## 2. Busca e Filtros Inteligentes (String Normalizer)
A Pralog possui um `string-normalizer.ts` que permite buscas insensíveis a acentos, espaços extras e caracteres especiais.
- **Oportunidade:** Portar a função `normalizeStringForComparison` para o front-end do PlatformSistemas.
- **Benefício:** Melhoria drástica na UX de busca de placas, nomes de motoristas e fornecedores, evitando que o usuário não encontre um item por causa de um "ç" ou um espaço.
## 3. Wrappers de Integração (KYC & Risco)
A Pralog já tem implementado o "suporte de vida" para integrações críticas:
- **IDWall:** Para validação de documentos e background check.
- **Brasil Credit:** Para análise de crédito de motoristas/fornecedores.
- **Planner:** Para agendamentos e fluxos logísticos.
- **Oportunidade:** No módulo **GR (Gestão de Risco)** do PlatformSistemas, em vez de refazer a lógica de integração, use os wrappers da Pralog como template.
- **Benefício:** Redução de meses de desenvolvimento ao reaproveitar o tratamento de erros e o mapeamento de campos dessas APIs externas.
## 4. Normalização de Datas & Moedas
O arquivo `date-converter.util.ts` da Pralog resolve o pesadelo de fusos horários e formatos brasileiros (DD/MM/YYYY vs ISO).
- **Oportunidade:** Unificar o tratamento de datas em todas as colunas de estatísticas do Prafrot.
- **Benefício:** Fim das inconsistências visuais onde uma data aparece em formato americano e outra em brasileiro no mesmo painel.
---
## 🏛️ O VEREDITO FINAL DA MESA REDONDA
**[Tony Stark]:** "A classe de Criptografia da Pralog é o que separa um brinquedo de uma ferramenta de enterprise. Se o `PlatformSistemas` quer ser levado a sério, ele precisa parar de brincar de 'atob/btoa' e usar AES real."
**[Elliot Alderson]:** "Eles normalizam as strings antes de comparar. Isso previne falhas de lógica em filtros sensíveis. É simples, é elegante, e o `PlatformSistemas` precisa disso ontem."
**[Gus Fring]:** "A integração com IDWall e Brasil Credit é meticulosa. O tratamento de retentativas e timeouts já está lá. Errar uma integração de risco é caro; herdar o que já funciona é prudente."
---
✅ **DICA TÉCNICA (THE STEAL):**
Copie o arquivo `backend/libs/core/src/utils/string-normalizer.ts` da Pralog e transforme em um hook `useNormalizer` no seu projeto. Isso vai resolver 90% das reclamações de 'filtro que não funciona' no front-end.

View File

@ -0,0 +1,50 @@
# 📊 Relatório Técnico: PlatformSistemas
## 1. Visão Geral do Ecossistema
O projeto **PlatformSistemas** é uma plataforma multi-módulo moderna, construída sobre o ecossistema **React 19 + Vite + Tailwind CSS 4**. Ele integra diversos fluxos de negócio (Frota, RH, Financeiro, Gestão de Risco) em um front-end unificado com arquitetura baseada em recursos (features).
### 🚀 Stack Técnica Principal
- **Framework:** React 19.2.0 (Latest)
- **Bundler:** Vite 7.2.4
- **Estilização:** Tailwind CSS 4.1.18 (Beta/Next-gen)
- **Validation:** Zod 4.3.5 + React Hook Form
- **State Management:** Zustand 5.0.9
- **UI Components:** Radix UI (Primitives)
- **Animações:** Framer Motion 12.23.26
---
## 2. Auditoria de Organização (Current State)
### ✅ Pontos Positivos (Gold Standards)
- **Tipografia Fluida:** Uso extensivo de `clamp()` em `index.css` para garantir escalabilidade perfeita sem media queries excessivas.
- **Modernização de Cores:** Adoção de `oklch` para cores mais precisas e vibrantes.
- **Lazy Loading:** Separação de rotas com `Suspense` e `lazy`, otimizando o payload inicial.
- **Design System:** Definição clara de variáveis semânticas no `:root`.
- **Automação:** Scripts de sincronização de contratos de API (`auto-sync-routes.js`).
### ⚠️ Pontos de Atenção (Dívida Técnica)
- **Redundância de Código:** Presença de pastas `src_2`, `src - Copia` e `Modulos Angular` na raiz, criando confusão sobre o que é código vivo.
- **Pasta Descontinuado:** Código morto misturado na árvore de `src/features`.
- **Complexidade de Rotas:** O arquivo `App.jsx` está se tornando um monolito de rotas; idealmente deveria ser fracionado por domínios.
---
## 3. Avaliação "War Room Bible"
| Critério | Status | Observação |
| :--- | :--- | :--- |
| **Regra dos 14KB** | 🟡 Parcial | CSS Crítico está bem otimizado, mas o bundle total de JS pode exceder os 10 pacotes TCP iniciais se não houver Code Splitting agressivo por componente. |
| **Matemática > Breakpoints** | 🟢 Excelente | Uso de `clamp()`, `min()` e `max()` é uma prática de elite aqui. |
| **Native First** | 🟢 Bom | Uso de Radix UI (que foca em acessibilidade nativa) e hooks modernos. |
| **Containerização** | 🔴 Ausente | Não foram encontrados Dockerfiles ou Nginx configs no mapeamento inicial da raiz. |
| **Dados (Postgres/Redis)** | ⚪ N/A | Front-end focado em consumo de API; lógica de back-end não analisada. |
---
## 4. Sugestões de Melhoria (Roadmap)
1. **Limpeza de Cadáveres:** Deletar ou mover para um repositório `/legacy-archive` as pastas `src_2`, `src - Copia` e `Modulos Angular`.
2. **Componentização de Rotas:** Criar arquivos de rotas por módulo (ex: `FleetRoutes.jsx`, `FinanceRoutes.jsx`) e importá-los em `App.jsx`.
3. **Infra-as-Code:** Adicionar `Dockerfile` (Alpine based) e `nginx.conf` otimizado para servir o SPA.
4. **Performance:** Implementar `Above the Fold` optimization inlining o CSS crítico diretamente no `index.html`.

View File

@ -0,0 +1,42 @@
# 🎭 WAR ROOM SIMULATION: PLATFORM SISTEMAS (v7.0)
**Cenário:** Sala 4, 3:00 AM. O ar está denso. A tela gigante projeta a estrutura de diretórios do projeto.
---
### 🗣️ A MESA REDONDA
**[Logan Roy]:** "Eu olho para essa raiz e vejo indecisão. `src`, `src_2`, `src - Copia`? **Isso parece um depósito de lixo de uma startup falida!** Se você quer mandar nessa indústria, limpe sua casa ou saia do caminho."
**[Gordon Ramsay]:** "GRAÇAS A DEUS ALGUÉM FALOU! Olhem para esse `index.css`. O `clamp()` está lá, a semântica está razoável, **MAS ONDE ESTÓ O DOCKERFILE?** Como vocês esperam que eu sirva esse código se nem uma cozinha (container) ele tem? É código cru! **IT'S RAW!**"
**[Steve Jobs]:** "Acalmem-se. Sintam o fluxo. O uso de `oklch` e as fontes fluidas mostram que há alma aqui. Alguém se importa com a tipografia. Mas esse `App.jsx`... **é um labirinto.** O usuário não sente a transição, ele sente o peso da estrutura. Precisamos de 'Gestalt', não de uma lista de compras de centenas de rotas."
**[Tony Stark]:** "Jobs está certo sobre o peso, mas erra no motivo. O problema não é o design, é o handshake. **Cadê o Nginx tunado? Cadê o HTTP/3?** Estamos servindo React 19 em um motor de fusca se não tivermos uma infraestrutura de container Alpine otimizada. E esse `auto-sync-routes`? Útil, mas parece um remendo para a falta de um Swagger real."
**[Marie Kondo]:** "Este diretório `Modulos Angular` não me traz alegria. Ele ocupa espaço no disco, na mente e no Git. **Arremesse-o no vazio.** Só guardamos o que é útil agora. O `src/features/descontinuado` também é um cemitério que precisa ser cremado."
---
### 🔥 O CONFLITO (Trade-offs)
* **Velocidade vs. Legado:** Stark quer deletar tudo o que não é `src` para ganhar 200ms de build time. Logan quer saber se os clientes antigos ainda dependem dos módulos Angular antes de puxar o gatilho.
* **Design vs. Simplicidade:** Jobs quer animações complexas do Framer Motion em cada rota, Ramsay grita que isso vai poluir o bundle e quebrar a regra dos 14KB se não for feito com `lazy` cirúrgico.
---
### 🛠️ SOLUÇÃO "GOLD STANDARD"
**Decisão Unânime:** O projeto tem um motor de Ferrari (React 19 + Tailwind 4), mas está transportando sacos de cimento (Pastas Copia, Angular).
```powershell
# PROTOCOLO DE PURGA
rm -Recurse -Force "./src_2"
rm -Recurse -Force "./src - Copia"
rm -Recurse -Force "./Modulos Angular"
```
✅ **PLANO DE AÇÃO IMEDIATA**
🔴 **Crítico (Tech):** Implementar `Dockerfile` multi-stage (Build: Node / Serve: Nginx Alpine) - [Stark/Gus]
🔴 **Crítico (Frontend):** Fracionar `App.jsx` em módulos de rotas (`prafrot.routes.jsx`, etc) - [Ramsay]
🟡 **Melhoria (UX):** Unificar o Design System removendo estilos órfãos em `descontinuado` - [Jobs]

43
check-build.sh Normal file
View File

@ -0,0 +1,43 @@
#!/bin/bash
echo "=== Diagnóstico de Build ==="
echo ""
echo "1. Verificando estrutura de arquivos:"
echo " - index.html:"
ls -la index.html 2>/dev/null && echo " ✓ Existe" || echo " ✗ Não encontrado"
echo " - src/main.jsx:"
ls -la src/main.jsx 2>/dev/null && echo " ✓ Existe" || echo " ✗ Não encontrado"
echo " - vite.config.ts:"
ls -la vite.config.ts 2>/dev/null && echo " ✓ Existe" || echo " ✗ Não encontrado"
echo ""
echo "2. Conteúdo do index.html (últimas linhas):"
tail -5 index.html
echo ""
echo "3. Verificando node_modules:"
if [ -d "node_modules" ]; then
echo " ✓ node_modules existe"
echo " - Vite version:"
npm list vite 2>/dev/null | grep vite || echo " Vite não encontrado"
else
echo " ✗ node_modules não encontrado - execute 'npm install'"
fi
echo ""
echo "4. Limpando cache e reinstalando:"
echo " Executando: rm -rf node_modules dist .vite package-lock.json"
rm -rf node_modules dist .vite package-lock.json
echo " Executando: npm install"
npm install
echo ""
echo "5. Tentando build:"
npm run build
echo ""
echo "=== Fim do diagnóstico ==="

22
components.json Normal file
View File

@ -0,0 +1,22 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": false,
"tsx": false,
"tailwind": {
"config": "tailwind.config.js",
"css": "src/index.css",
"baseColor": "neutral",
"cssVariables": true,
"prefix": ""
},
"iconLibrary": "lucide",
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
},
"registries": {}
}

View File

@ -0,0 +1,101 @@
# 🤖 AI RULES - AMBIENTE DE DEBUG & COMPONENTES VERSIONADOS
## 🎯 OBJETIVO
Definir as regras, arquitetura e padrões obrigatórios para o desenvolvimento e manutenção do ambiente de Debug (`src/features/dev-tools`) e criação de componentes versionados no projeto Integra Finance.
## 🏗️ ARQUITETURA DE DEBUG (PLAYGROUND)
O ambiente de Debug é um espaço isolado para criar, testar e documentar componentes antes de integrá-los à produção.
**Localização Principal**: `src/features/dev-tools/views/PlaygroundView.jsx`
### Principais Funcionalidades:
1. **Toggle de Versão**: Permite alternar entre a versão `PRODUCTION` (estável) e `DEBUG` (laboratório) de um componente.
2. **Isolamento de Tema**: Testa componentes em Light/Dark mode sem afetar o resto da app.
3. **Preview Responsivo**: Modos Desktop, Tablet e Mobile.
---
## 🧬 PADRÃO DE VERSIONAMENTO DE COMPONENTES (DUAL-VERSION)
Para componentes complexos ou que exigem testes exaustivos de UI, adotamos o padrão de **Componente Versionado**. Isso separa o código de produção do código de laboratório.
### Estrutura de Pastas Obrigatória:
Todo componente versionado deve seguir esta estrutura exata:
```
src/features/[feature]/components/[NomeComponente]/
├── index.js # Entry point (Exporta a versão de Produção por padrão)
├── [Componente].jsx # Versão de PRODUÇÃO (Limpa, funcional, sem mocks visuais)
└── [Componente].debug.jsx # Versão de DEBUG (Wrapper com controles, knobs e mocks)
```
### Regras por Arquivo:
#### 1. `index.js`
Deve exportar o componente de produção como default para garantir importações limpas no resto do sistema.
```javascript
export { StatusBadge } from './StatusBadge';
export { StatusBadge as default } from './StatusBadge';
```
#### 2. `[Componente].jsx` (Produção)
- Deve ser **puro** e focado na funcionalidade final.
- Recebe props via interface definida.
- **NÃO** deve conter botões de teste, logs visuais ou dados mockados hard-coded na renderização final.
#### 3. `[Componente].debug.jsx` (Debug / Laboratório)
- Deve importar e renderizar o componente de produção.
- Pode (e deve) conter:
- Estado local para controlar props do componente filho.
- Botões para simular ações (ex: "Simular Erro API").
- Logs visuais de eventos (`onSelect`, `onClick`).
- Wrapper visual (Cards, Grids) para facilitar o teste.
---
## 📝 REGISTRO NO PLAYGROUND
Para que um componente apareça no Playground (`PlaygroundView.jsx`), adicione-o à constante `componentsList`.
### Contrato do Objeto de Componente:
```javascript
{
name: 'NomeDoComponente',
description: 'Descrição breve do que ele faz.',
props: { ...exemploDeProps }, // Usado para gerar a tabela de documentação e o snippet de código
// RENDERIZADOR PADRÃO (Produção)
// Obrigatório. Mostra como o componente é usado na vida real.
render: (props) => <MeuComponente {...props} />,
// RENDERIZADOR DE DEBUG (Opcional)
// Se definido, será usado quando o toggle "Debug" estiver ativado.
// Geralmente renderiza o componente .debug.jsx
debugRender: (props) => <MeuComponenteDebug {...props} />
}
```
---
## 🎨 DIRETRIZES DE UI/UX PARA O DEBUG
### 1. ExcelTable & Temas
- Componentes complexos como `ExcelTable` devem respeitar o tema `dark`/`light` propagado pelo container pai.
- Teste sempre a legibilidade em ambos os temas.
### 2. AutoFillInput & Formulários Dinâmicos
- Inputs de pesquisa (`AutoFillInput`) no modo Debug devem demonstrar fluxos reais.
- **Criação Dinâmica**: Ao invés de apenas logar "Criar", implemente uma lógica que capture o termo pesquisado e preencha um formulário de exemplo.
- **Feedback Visual**: Use cores de texto com alto contraste (Preto no Light, Branco no Dark) dentro dos inputs.
---
## 🚫 O QUE NÃO FAZER
1. **NUNCA** deixe código de debug (`console.log`, bordas de teste vermelhas) no arquivo `[Componente].jsx` (Produção). Use o arquivo `.debug.jsx` para isso.
2. **NUNCA** importe o arquivo `.debug.jsx` em views reais da aplicação (Dashboard, Relatórios). Ele deve ser importado APENAS no `PlaygroundView.jsx`.
3. **EVITE** quebrar o build de produção. O `PlaygroundView` e seus imports de debug devem ser isolados ou tree-shakeable se possível (embora em dev-tools internal isso seja menos crítico, mantenha a higiene).
---
**Última Atualização**: 2026-01-11 (Implementação do Sistema Dual-Version)

View File

@ -0,0 +1,197 @@
# 🔧 Ajustes Pendentes - Financeiro V2 - Cruzamentos
## 📊 Contexto
Os cruzamentos já estão usando corretamente a rota `/extrato/apresentar`:
- **Receitas**: `tipoOperacao === 'C'`
- **Despesas**: `tipoOperacao === 'D'`
## ✅ Implementado
### CruzamentoView (Receitas)
- Estados de filtros adicionados
- Lógica de filtragem implementada (`dadosFiltrados`)
- KPIs recalculados (`kpisFiltrados`)
- Gráficos atualizados para usar dados filtrados
## 🚧 Pendente
### 1. CruzamentoView (Receitas) - Finalizar UI
#### 1.1. Adicionar Import do Select
```javascript
// Linha 19, após Badge
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
```
#### 1.2. Substituir Barra de Filtros (linhas 223-253)
Substituir o conteúdo atual por:
```jsx
{/* Filter & Summary Bar */}
<div className="bg-[#0f172a]/60 backdrop-blur-xl p-3 sm:p-4 rounded-xl sm:rounded-2xl border border-slate-800/50 flex flex-col gap-3 shadow-2xl relative z-10">
{/* Primeira Linha: Filtros de Período */}
<div className="flex flex-col sm:flex-row items-stretch sm:items-center gap-2 flex-1 min-w-0">
<div className="flex items-center gap-2">
<div className="p-2 bg-slate-900 rounded-lg border border-slate-800 shrink-0">
<Filter className="w-3.5 h-3.5 sm:w-4 sm:h-4 text-emerald-400" />
</div>
<Select value={filtroTipo} onValueChange={setFiltroTipo}>
<SelectTrigger className="h-8 w-28 bg-slate-900/50 border-slate-800 text-[10px] sm:text-[11px] font-bold text-white">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="mes">Por Mês</SelectItem>
<SelectItem value="ano">Por Ano</SelectItem>
<SelectItem value="todos">Todos</SelectItem>
</SelectContent>
</Select>
</div>
{filtroTipo === 'mes' && (
<div className="flex items-center gap-2">
<Select value={filtroMes} onValueChange={setFiltroMes}>
<SelectTrigger className="h-8 w-32 bg-slate-900/50 border-slate-800 text-[10px] sm:text-[11px] font-bold text-white">
<SelectValue placeholder="Selecione o mês" />
</SelectTrigger>
<SelectContent>
<SelectItem value="01">Janeiro</SelectItem>
<SelectItem value="02">Fevereiro</SelectItem>
<SelectItem value="03">Março</SelectItem>
<SelectItem value="04">Abril</SelectItem>
<SelectItem value="05">Maio</SelectItem>
<SelectItem value="06">Junho</SelectItem>
<SelectItem value="07">Julho</SelectItem>
<SelectItem value="08">Agosto</SelectItem>
<SelectItem value="09">Setembro</SelectItem>
<SelectItem value="10">Outubro</SelectItem>
<SelectItem value="11">Novembro</SelectItem>
<SelectItem value="12">Dezembro</SelectItem>
</SelectContent>
</Select>
</div>
)}
{(filtroTipo === 'mes' || filtroTipo === 'ano') && (
<div className="flex items-center gap-2">
<Select value={filtroAno} onValueChange={setFiltroAno}>
<SelectTrigger className="h-8 w-24 bg-slate-900/50 border-slate-800 text-[10px] sm:text-[11px] font-bold text-white">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="2024">2024</SelectItem>
<SelectItem value="2025">2025</SelectItem>
<SelectItem value="2026">2026</SelectItem>
</SelectContent>
</Select>
</div>
)}
</div>
{/* Segunda Linha: Filtro de Caixa */}
<div className="flex items-center gap-2 flex-wrap">
<span className="text-[10px] font-bold text-slate-500 uppercase">Caixa:</span>
<Select value={filtroCaixa} onValueChange={setFiltroCaixa}>
<SelectTrigger className="h-8 w-40 bg-slate-900/50 border-slate-800 text-[10px] sm:text-[11px] font-bold text-white">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="todos">Todas as Caixas</SelectItem>
<SelectItem value="1">Caixa 1</SelectItem>
<SelectItem value="2">Caixa 2</SelectItem>
<SelectItem value="3">Caixa 3</SelectItem>
<SelectItem value="4">Caixa 4</SelectItem>
<SelectItem value="5">Caixa 5</SelectItem>
</SelectContent>
</Select>
<Badge variant="outline" className="h-8 px-3 rounded-lg bg-emerald-500/10 border-emerald-500/20 text-emerald-400 text-[10px] font-bold">
{dadosFiltrados.length} registros
</Badge>
</div>
</div>
```
#### 1.3. Atualizar KPIs para usar kpisFiltrados (linhas 257-281)
Substituir:
- `kpis?.totalRecebido` por `kpisFiltrados?.totalRecebido`
- `kpis?.totalPendente` por `kpisFiltrados?.totalPendente`
- `kpis?.totalGeral` por `kpisFiltrados?.totalGeral`
### 2. CruzamentoDespesasView (Despesas)
Aplicar as mesmas mudanças no arquivo `contas-pagar/CruzamentoDespesasView.jsx`:
#### 2.1. Adicionar Estados de Filtros (após linha 84)
```javascript
// Estados para filtros
const [filtroMes, setFiltroMes] = React.useState('');
const [filtroAno, setFiltroAno] = React.useState(new Date().getFullYear().toString());
const [filtroCaixa, setFiltroCaixa] = React.useState('todos');
const [filtroTipo, setFiltroTipo] = React.useState('mes'); // 'mes' | 'ano' | 'todos'
```
#### 2.2. Adicionar Lógica de Filtragem
```javascript
// Dados filtrados baseados nos filtros ativos
const dadosExecutadosFiltrados = React.useMemo(() => {
if (!Array.isArray(despesasExecutadas)) return [];
return despesasExecutadas.filter(item => {
// Filtro por período
if (filtroTipo === 'mes' && filtroMes && filtroAno) {
const dataItem = item?.dataEntrada || item?.data || '';
const [ano, mes] = dataItem.split('-');
if (ano !== filtroAno || mes !== filtroMes) return false;
} else if (filtroTipo === 'ano' && filtroAno) {
const dataItem = item?.dataEntrada || item?.data || '';
const [ano] = dataItem.split('-');
if (ano !== filtroAno) return false;
}
// Filtro por caixa
if (filtroCaixa !== 'todos' && item?.caixinha) {
if (item.caixinha !== filtroCaixa) return false;
}
return true;
});
}, [despesasExecutadas, filtroMes, filtroAno, filtroCaixa, filtroTipo]);
// KPIs recalculados
const kpisFiltrados = React.useMemo(() => {
const totalExecutado = dadosExecutadosFiltrados.reduce((acc, item) => acc + (item.valor || 0), 0);
return {
totalPlanejado: 0,
totalExecutado,
variacao: totalExecutado,
percentualVariacao: 0
};
}, [dadosExecutadosFiltrados]);
```
#### 2.3. Atualizar useMemo para usar dados filtrados
Substituir todas as referências a `despesasExecutadas` por `dadosExecutadosFiltrados` nos cálculos de:
- `comparativoCategoria`
- `timelineData`
- `categoriaData`
#### 2.4. Adicionar mesma UI de filtros (linhas 172-207)
#### 2.5. Atualizar KPIs para usar kpisFiltrados
## 🎯 Resultado Esperado
Após implementar essas mudanças:
- ✅ Filtros de mês/ano funcionais
- ✅ Filtro de caixa funcional
- ✅ KPIs atualizados dinamicamente conforme filtros
- ✅ Gráficos refletindo apenas dados filtrados
- ✅ Contador de registros filtrados visível
- ✅ Dados sempre vindos de `/extrato/apresentar`
## 📌 Observações
1. O campo `caixinha` pode não estar presente em todos os registros do extrato. Ajustar conforme necessário.
2. Os filtros são client-side. Para grandes volumes de dados, considerar filtros server-side.
3. O estado inicial do filtro de mês está vazio - o usuário precisa selecionar.
4. Considerar adicionar um botão "Limpar Filtros" para melhor UX.

View File

@ -0,0 +1,220 @@
# 🎨 Implementação do Tema Zoho no Financeiro V2
## 📋 Resumo da Implementação
**Data**: 02/02/2026
**Módulo**: `financeiro-v2`
**Objetivo**: Implementar tema com fontes estilo Zoho e converter medidas para vw/vh
---
## 🎯 Objetivos
### 1. **Sistema de Tipografia Adaptativa (Estilo Zoho)**
- ✅ Usar fonte **Inter** (similar ao Zoho Puvi)
- ✅ Implementar sistema de `clamp()` com vw/vh
- ✅ Pesos moderados (semibold/medium, não black/bold excessivo)
- ✅ Tamanhos adaptativos para todas as resoluções
### 2. **Conversão de Medidas**
- ✅ Converter **todas** as medidas fixas (px, rem) para vw/vh
- ✅ Usar `clamp(min, preferred, max)` para controle
- ✅ Garantir responsividade em resoluções menores
---
## 📐 Sistema de Medidas Adaptativas
### **Tipografia**
```css
/* Tiny */ clamp(0.75rem, 0.9vw, 0.875rem) /* 12px-14px */
/* Label */ clamp(0.875rem, 1vw, 0.9375rem) /* 14px-15px */
/* Body */ clamp(1rem, 1.4vw, 1.25rem) /* 16px-20px */
/* Subtitle */ clamp(1.125rem, 2vw, 1.5rem) /* 18px-24px */
/* Title */ clamp(1.5rem, 2.8vw, 2.25rem) /* 24px-36px */
/* Number */ clamp(1.75rem, 3.4vw, 2.5rem) /* 28px-40px */
```
### **Espaçamento**
```css
/* Small */ clamp(0.5rem, 1vw, 1rem) /* 8px-16px */
/* Medium */ clamp(1rem, 2vw, 1.5rem) /* 16px-24px */
/* Large */ clamp(1.5rem, 3vw, 2.5rem) /* 24px-40px */
```
### **Dimensões**
```css
/* Icon Small */ clamp(1rem, 1.5vw, 1.25rem) /* 16px-20px */
/* Icon Medium */ clamp(1.25rem, 2vw, 1.5rem) /* 20px-24px */
/* Icon Large */ clamp(1.5rem, 2.5vw, 2rem) /* 24px-32px */
/* Card Height */ clamp(8rem, 12vh, 14rem) /* 128px-224px */
/* Modal Width */ clamp(20rem, 40vw, 50rem) /* 320px-800px */
```
---
## 🎨 Pesos de Fonte (Estilo Zoho)
| Peso | Classe | Uso |
|------|--------|-----|
| **Normal (400)** | `font-normal` | Corpo de texto, valores |
| **Medium (500)** | `font-medium` | Labels, descrições |
| **Semibold (600)** | `font-semibold` | Títulos, números importantes |
| **Bold (700)** | `font-bold` | ⚠️ Apenas ênfase extrema |
| **Black (900)** | `font-black` | ❌ **EVITAR** |
---
## 📁 Arquivos para Modificar
### 1. **Componentes Principais**
- [ ] `src/features/financeiro-v2/components/ExcelTable.jsx`
- [ ] `src/features/financeiro-v2/components/FinanceiroV2Sidebar.jsx`
- [ ] `src/features/financeiro-v2/components/AdvancedFiltersModal.jsx`
### 2. **Views**
- [ ] `src/features/financeiro-v2/views/DashboardView.jsx`
- [ ] `src/features/financeiro-v2/views/FluxoCaixaView.jsx`
- [ ] `src/features/financeiro-v2/views/RelatoriosView.jsx`
- [ ] `src/features/financeiro-v2/views/contas-receber/*`
- [ ] `src/features/financeiro-v2/views/contas-pagar/*`
- [ ] `src/features/financeiro-v2/views/conciliacao-v2/*`
### 3. **Layout Principal**
- [ ] `src/features/financeiro-v2/index.jsx`
---
## 🔄 Padrões de Conversão
### **DE (antes):**
```jsx
// Tamanhos fixos
className="text-xl" // 1.25rem (20px)
className="text-sm" // 0.875rem (14px)
className="p-6" // 1.5rem (24px)
className="w-10" // 2.5rem (40px)
className="h-24" // 6rem (96px)
```
### **PARA (depois):**
```jsx
// Tamanhos adaptativos
className="text-[clamp(1rem,1.6vw,1.375rem)]" // Body Large (16px-22px)
className="text-[clamp(0.875rem,1vw,0.9375rem)]" // Label (14px-15px)
className="p-[clamp(1rem,2vw,1.5rem)]" // Padding adaptativo
className="w-[clamp(2rem,3vw,2.5rem)]" // Width adaptativa
className="h-[clamp(4rem,8vh,6rem)]" // Height adaptativa
```
---
## ✅ Checklist de Implementação
### **Fase 1: Componentes Base**
- [ ] Atualizar `ExcelTable.jsx`
- [ ] Converter tamanhos de fonte usando `clamp()`
- [ ] Ajustar padding/margin para vw/vh
- [ ] Reduzir peso de fontes (black → semibold)
- [ ] Ajustar ícones com dimensões adaptativas
### **Fase 2: Views Principais**
- [ ] Atualizar `DashboardView.jsx`
- [ ] Converter cards para dimensões adaptativas
- [ ] Ajustar gráficos com altura em vh
- [ ] Atualizar tipografia dos textos
- [ ] Atualizar `FluxoCaixaView.jsx`
- [ ] Converter filtros e controles
- [ ] Ajustar tabelas e gráficos
- [ ] Atualizar `RelatoriosView.jsx`
- [ ] Converter cards de relatórios
- [ ] Ajustar modais de exportação
### **Fase 3: Subviews**
- [ ] Atualizar views de `contas-receber`
- [ ] Atualizar views de `contas-pagar`
- [ ] Atualizar views de `conciliacao-v2`
### **Fase 4: Layout e Navegação**
- [ ] Atualizar `index.jsx`
- [ ] Converter header extras
- [ ] Ajustar layout containers
- [ ] Atualizar sidebar
---
## 🎨 Exemplos de Conversão
### **Card de KPI**
```jsx
// ANTES
<div className="p-5">
<div className="w-10 h-10 rounded-xl">
<Icon size={18} />
</div>
<span className="text-[10px] font-bold uppercase">TÍTULO</span>
<div className="text-xl font-black">R$ 1.234,56</div>
<p className="text-[10px]">Subtítulo</p>
</div>
// DEPOIS
<div className="p-[clamp(1rem,1.5vw,1.25rem)]">
<div className="w-[clamp(2rem,3vw,2.5rem)] h-[clamp(2rem,3vw,2.5rem)] rounded-xl">
<Icon size="clamp(1rem,1.5vw,1.125rem)" />
</div>
<span className="text-[clamp(0.625rem,0.8vw,0.75rem)] font-semibold uppercase">TÍTULO</span>
<div className="text-[clamp(1.5rem,2.8vw,2.25rem)] font-semibold">R$ 1.234,56</div>
<p className="text-[clamp(0.625rem,0.8vw,0.75rem)] font-medium">Subtítulo</p>
</div>
```
### **Tabela**
```jsx
// ANTES
<th className="h-[40px] px-3">
<span className="text-[clamp(0.75rem,0.9vw,0.8125rem)] font-bold">COLUNA</span>
</th>
// DEPOIS
<th className="h-[clamp(2rem,3vh,2.5rem)] px-[clamp(0.75rem,1vw,1rem)]">
<span className="text-[clamp(0.75rem,0.9vw,0.875rem)] font-semibold">COLUNA</span>
</th>
```
---
## 🧪 Testes Necessários
### **Resoluções para Testar**
1. **Mobile**: 375px (iPhone SE)
2. **Tablet**: 768px (iPad)
3. **Desktop Small**: 1366px
4. **Desktop Large**: 1920px
5. **4K**: 2560px
### **Validações**
- [ ] Textos legíveis em todas as resoluções
- [ ] Sem overflow ou cortes de conteúdo
- [ ] Botões e ícones com tamanhos proporcionais
- [ ] Gráficos se adaptam corretamente
- [ ] Modais e painéis responsivos
---
## 📊 Progresso
- [ ] **Componentes Base** (0/4)
- [ ] **Views Principais** (0/3)
- [ ] **Subviews** (0/20)
- [ ] **Layout** (0/1)
- [ ] **Testes** (0/5)
**Total**: 0/28 (0%)
---
**Status**: 🟡 Em Progresso
**Próximo Passo**: Iniciar conversão dos componentes base

View File

@ -0,0 +1,114 @@
# ✅ Implementação Completa - Filtros Financeiro V2
## 🎉 Status: CONCLUÍDO
Todos os filtros funcionais foram implementados com sucesso nos cruzamentos de Receitas e Despesas!
## 📊 Arquivos Modificados
### 1. ✅ CruzamentoView (Receitas)
**Arquivo**: `src/features/financeiro-v2/views/contas-receber/CruzamentoView.jsx`
**Mudanças Implementadas:**
- ✅ Import do Select component adicionado
- ✅ Estados de filtros criados (`filtroMes`, `filtroAno`, `filtroCaixa`, `filtroTipo`)
- ✅ Função `dadosFiltrados` implementada
- ✅ Função `kpisFiltrados` implementada
- ✅ Todos os useMemo atualizados para usar `dadosFiltrados`
- ✅ UI de filtros completa com Select de mês/ano e caixas
- ✅ Contador de registros filtrados
- ✅ KPIs atualizados para usar `kpisFiltrados`
### 2. ✅ CruzamentoDespesasView (Despesas)
**Arquivo**: `src/features/financeiro-v2/views/contas-pagar/CruzamentoDespesasView.jsx`
**Mudanças Implementadas:**
- ✅ Select component já estava importado
- ✅ Estados de filtros criados (`filtroMes`, `filtroAno`, `filtroCaixa`, `filtroTipo`)
- ✅ Função `dadosExecutadosFiltrados` implementada
- ✅ Função `kpisFiltrados` implementada
- ✅ Todos os useMemo atualizados para usar `dadosExecutadosFiltrados`
- ✅ UI de filtros completa com Select de mês/ano e caixas
- ✅ Contador de registros filtrados
- ✅ KPIs atualizados para usar `kpisFiltrados`
### 3. ✅ Hooks (Já estavam corretos)
**Arquivos**:
- `src/features/financeiro-v2/hooks/useContasReceber.js`
- `src/features/financeiro-v2/hooks/useContasPagar.js`
**Status**: Já estavam buscando corretamente de `/extrato/apresentar` com filtros de `tipoOperacao`
## 🎯 Funcionalidades Implementadas
### Filtros Disponíveis:
1. **Por Período**:
- Por Mês (seleciona mês e ano)
- Por Ano (seleciona apenas ano)
- Todos (sem filtro de período)
2. **Por Caixa**:
- Todas as Caixas
- Caixa 1, 2, 3, 4, 5
### Comportamento:
- ✅ Filtros são aplicados em tempo real
- ✅ KPIs recalculados automaticamente
- ✅ Gráficos atualizados dinamicamente
- ✅ Tabelas refletem dados filtrados
- ✅ Contador mostra quantidade de registros filtrados
## 📈 Dados Corretos
### Receitas (Contas a Receber):
- **Fonte**: `/extrato/apresentar` com `tipoOperacao === 'C'`
- **Valor Total**: R$ 249.808,86 ✅
- **Filtros**: Aplicados aos dados do extrato
### Despesas (Contas a Pagar):
- **Fonte**: `/extrato/apresentar` com `tipoOperacao === 'D'`
- **Valor Total**: R$ 251.802,92 ✅
- **Filtros**: Aplicados aos dados do extrato
## 🔍 Observações Importantes
1. **Campo `caixinha`**: O filtro de caixa verifica se o item possui o campo `caixinha`. Se não houver, o item não será filtrado por caixa.
2. **Filtros Client-Side**: Os filtros são aplicados no frontend. Para grandes volumes de dados, considere implementar filtros server-side no futuro.
3. **Estado Inicial**:
- Filtro de tipo: "mes"
- Filtro de mês: vazio (usuário precisa selecionar)
- Filtro de ano: ano atual
- Filtro de caixa: "todos"
4. **Planejado Zerado**: Como não há funcionalidade de planejamento implementada, os valores planejados estão zerados conforme especificado.
## 🚀 Próximos Passos (Opcional)
1. **Melhorias de UX**:
- Adicionar botão "Limpar Filtros"
- Salvar filtros no localStorage
- Adicionar indicador visual de filtros ativos
2. **Performance**:
- Implementar filtros server-side para grandes volumes
- Adicionar debounce nos filtros se necessário
3. **Funcionalidades Futuras**:
- Exportar dados filtrados para Excel
- Comparação entre períodos
- Filtros avançados (por categoria, por valor, etc.)
## ✨ Resultado Final
Os cruzamentos agora possuem:
- ✅ Filtros funcionais de mês/ano
- ✅ Filtros de caixas
- ✅ KPIs dinâmicos que refletem os filtros
- ✅ Gráficos e tabelas atualizados em tempo real
- ✅ Contador de registros filtrados
- ✅ Interface intuitiva e responsiva
- ✅ Dados corretos vindos de `/extrato/apresentar`
**Status**: 🎉 **IMPLEMENTAÇÃO COMPLETA E FUNCIONAL!**

View File

@ -0,0 +1,190 @@
# ✅ Implementação Final - Filtros Dinâmicos Financeiro V2
## 🎉 Status: 100% CONCLUÍDO
Todos os filtros dinâmicos foram implementados com sucesso, integrando com as rotas da API!
## 📊 Mudanças Implementadas
### 1. ✅ Integração com API
**Rotas Utilizadas:**
- `/categorias/apresentar` - Lista todas as categorias do sistema
- `/caixinhas/apresentar` - Lista todas as caixas financeiras
**Service Atualizado:**
- `src/services/extratoService.js` - Já possuía as funções `fetchCategorias()` e `fetchCaixinhas()`
### 2. ✅ Hooks Atualizados
#### **useContasReceber.js**
- ✅ Adicionados estados `categorias` e `caixas`
- ✅ useEffect para buscar categorias e caixas da API
- ✅ Campo `caixinha` adicionado ao mapeamento de receitas
- ✅ Categorias e caixas expostas no state
#### **useContasPagar.js**
- ✅ Adicionados estados `categorias` e `caixas`
- ✅ useEffect para buscar categorias e caixas da API
- ✅ Campo `caixinha` adicionado ao mapeamento de despesas
- ✅ Categorias e caixas expostas no state
### 3. ✅ Views Atualizadas
#### **CruzamentoView (Receitas)**
- ✅ Props atualizadas para receber `categorias` e `caixas`
- ✅ Select de Caixas agora é dinâmico (map das caixas da API)
- ✅ Filtros funcionam com IDs reais das caixas
#### **ContasReceberView**
- ✅ Extrai `categorias` e `caixas` do state
- ✅ Passa como props para CruzamentoView
#### **CruzamentoDespesasView**
- ✅ Props atualizadas para receber `categorias` e `caixas` do state
- ✅ Select de Caixas agora é dinâmico (map das caixas da API)
- ✅ Filtros funcionam com IDs reais das caixas
## 🎯 Funcionalidades Implementadas
### Filtros Dinâmicos:
1. **Caixas**:
- ✅ Carregadas dinamicamente de `/caixinhas/apresentar`
- ✅ Exibem o nome real da caixa (campo `caixinha`)
- ✅ Filtram por ID (campo `idcaixinhas_financeiro`)
- ✅ Opção "Todas as Caixas" sempre disponível
2. **Categorias** (preparado para uso futuro):
- ✅ Carregadas dinamicamente de `/categorias/apresentar`
- ✅ Disponíveis no state para implementações futuras
- ✅ Podem ser usadas para filtros adicionais
### Mapeamento de Dados:
- ✅ Campo `idcaixinhas_financeiro` do extrato mapeado para `caixinha`
- ✅ Filtro compara `caixinha` do item com ID selecionado
- ✅ Fallback para dados sem caixa definida
## 📁 Arquivos Modificados
1. ✅ `src/features/financeiro-v2/hooks/useContasReceber.js`
2. ✅ `src/features/financeiro-v2/hooks/useContasPagar.js`
3. ✅ `src/features/financeiro-v2/views/contas-receber/CruzamentoView.jsx`
4. ✅ `src/features/financeiro-v2/views/contas-receber/ContasReceberView.jsx`
5. ✅ `src/features/financeiro-v2/views/contas-pagar/CruzamentoDespesasView.jsx`
## 🔄 Fluxo de Dados
```
API (/caixinhas/apresentar)
extratoService.fetchCaixinhas()
useContasReceber/useContasPagar (useEffect)
state.caixas
ContasReceberView/ContasPagarView
CruzamentoView/CruzamentoDespesasView (props)
Select Component (map dinâmico)
```
## 🎨 Exemplo de Dados
### Caixas da API:
```json
[
{
"caixinha": "Padronizadosss",
"idcaixinhas_financeiro": 1
},
{
"caixinha": "a",
"idcaixinhas_financeiro": 4
},
{
"caixinha": "eu",
"idcaixinhas_financeiro": 6
}
]
```
### Categorias da API:
```json
[
{
"categoria": "Contas",
"idcategoria": 1
},
{
"categoria": "Folha de pagamento",
"idcategoria": 5
}
]
```
## 🚀 Como Funciona
1. **Ao carregar a tela**:
- Hook busca categorias e caixas da API
- Dados são armazenados no state
- Loading state gerenciado automaticamente
2. **No Select de Caixas**:
- Sempre mostra "Todas as Caixas" como primeira opção
- Mapeia array de caixas da API
- Cada item usa `idcaixinhas_financeiro` como value
- Exibe `caixinha` como label
3. **Ao filtrar**:
- Compara `caixinha` do item com ID selecionado
- Atualiza KPIs, gráficos e tabelas em tempo real
- Contador mostra quantidade de registros filtrados
## 💡 Melhorias Implementadas
1. **Dados Reais**: Filtros agora usam dados reais do sistema
2. **Flexibilidade**: Suporta qualquer quantidade de caixas
3. **Manutenibilidade**: Não precisa atualizar código ao adicionar novas caixas
4. **UX**: Nomes reais das caixas ao invés de "Caixa 1", "Caixa 2"
5. **Preparado para Futuro**: Categorias já carregadas para filtros futuros
## 🔍 Observações Técnicas
1. **Campo `caixinha`**:
- Vem do extrato como `idcaixinhas_financeiro`
- Convertido para string para comparação
- Fallback para `item.caixinha` se já vier mapeado
2. **Performance**:
- Busca única ao montar o componente
- Dados cacheados no state
- Não refaz requisição a cada filtro
3. **Error Handling**:
- Try/catch nos useEffect
- Fallback para array vazio em caso de erro
- Console.error para debugging
## ✨ Resultado Final
Os cruzamentos agora possuem:
- ✅ Filtros dinâmicos de caixas (dados reais da API)
- ✅ Categorias carregadas (prontas para uso futuro)
- ✅ Nomes reais das caixas exibidos
- ✅ Suporte a qualquer quantidade de caixas
- ✅ Código limpo e manutenível
- ✅ Performance otimizada
- ✅ Error handling robusto
**Status**: 🎉 **IMPLEMENTAÇÃO 100% CONCLUÍDA E INTEGRADA COM A API!**
---
## 📝 Próximos Passos Sugeridos (Opcional)
1. **Filtro de Categorias**: Adicionar Select de categorias nos filtros
2. **Filtro Combinado**: Permitir filtrar por múltiplas caixas simultaneamente
3. **Persistência**: Salvar filtros selecionados no localStorage
4. **Loading States**: Adicionar skeleton/spinner enquanto carrega caixas
5. **Validação**: Verificar se caixa selecionada ainda existe antes de filtrar

View File

@ -0,0 +1,221 @@
# Padrões de Rotas de Apresentação (BackFront)
**Objetivo**: Contrato único por rota de listagem: endpoint, resposta esperada e colunas sugeridas para o front.
**Uso**: Ao inserir ou alterar uma rota "apresentar", atualizar este documento; as views devem usar as colunas sugeridas aqui (ver comentário no código: "Ver docs/PADROES_ROTAS_APRESENTACAO.md § NomeDaRota").
---
## Ambiente: Prafrot (Prafrota)
### GET /cadastro_frota/apresentar
- **Descrição**: Lista veículos cadastrados na frota.
- **Service**: `prafrotService.getVehicles()`.
- **View**: Veículos / Status Frota.
**Resposta esperada**: array de objetos com campos, por exemplo:
`idveiculo_frota`, `placa`, `modelo`, `base`, `motorista`, `status`, `manutencao`, `atuacao`, `proprietario`, `vecfleet`, `obs`, `combustivel`, `tipo`, `marca`, `ano`, `cidade`, etc.
**Colunas sugeridas** (copiar para a view que usa ExcelTable):
```js
[
{ field: 'placa', header: 'Placa', width: '100px', className: 'font-mono font-bold text-emerald-600 dark:text-emerald-500' },
{ field: 'modelo', header: 'Modelo', width: '150px' },
{ field: 'base', header: 'Unidade', width: '120px' },
{ field: 'motorista', header: 'Motorista', width: '180px' },
{ field: 'status', header: 'Status', width: '140px' },
{ field: 'manutencao', header: 'Manutenção', width: '120px' },
{ field: 'atuacao', header: 'Atuação', width: '140px' },
{ field: 'proprietario', header: 'Proprietário', width: '140px' },
{ field: 'vecfleet', header: 'VecFleet', width: '140px' },
{ field: 'obs', header: 'OBS', width: '250px' }
]
```
**filterDefs sugeridos**: `[{ field: 'placa', label: 'Placa', type: 'text' }, { field: 'motorista', label: 'Motorista', type: 'text' }, { field: 'base', label: 'Unidade', type: 'select' }]`
---
### GET /manutencao_frota/apresentar
- **Descrição**: Lista todas as manutenções (total).
- **Service**: `prafrotService.getMaintenance()`.
- **View**: MaintenanceView (Manutenção).
**Resposta esperada**: array de objetos com campos:
`idmanutencao_frota`, `atendimento`, `placa`, `placa_reserva`, `modelo`, `oficina`, `base_frota`, `cidade`, `uf`, `proprietario`, `responsavel`, `motivo_atendimento`, `status`, `manutencao`, `status_frota_veiculo`, `data_solicitacao`, `data_agendamento`, `data_parada_veiculo`, `previcao_entrega`, `data_finalizacao`, `data_retirada`, `orcamento_inicial`, `orcamento_final`, `dif_orcamento`, `condicao_pagamento`, `validacao_financeiro`, `resp_aprovacao`, `sla_oficina`, `sla_pos_oficina`, `obs`, `endereco_prestador`, `pdf_orcamento`.
**Colunas sugeridas** (ver MaintenanceView.jsx já alinhado):
```js
[
{ field: 'idmanutencao_frota', header: 'ID', width: '80px' },
{ field: 'atendimento', header: 'ATENDIMENTO', width: '100px' },
{ field: 'placa', header: 'PLACA', width: '100px', className: 'font-mono font-bold text-emerald-600 dark:text-emerald-500' },
{ field: 'placa_reserva', header: 'PLACA RESERVA', width: '100px' },
{ field: 'modelo', header: 'MODELO', width: '110px' },
{ field: 'oficina', header: 'OFICINA', width: '160px' },
{ field: 'base_frota', header: 'BASE FROTA', width: '100px' },
{ field: 'cidade', header: 'CIDADE', width: '120px' },
{ field: 'uf', header: 'UF', width: '60px' },
{ field: 'proprietario', header: 'PROPRIETÁRIO', width: '110px' },
{ field: 'responsavel', header: 'RESPONSÁVEL', width: '120px' },
{ field: 'motivo_atendimento', header: 'MOTIVO ATEND.', width: '120px' },
{ field: 'status', header: 'STATUS', width: '140px' },
{ field: 'manutencao', header: 'MANUTENÇÃO', width: '90px' },
{ field: 'status_frota_veiculo', header: 'STATUS FROTA', width: '120px' },
{ field: 'data_solicitacao', header: 'DATA SOLIC.', width: '100px' },
{ field: 'data_agendamento', header: 'DATA AGEND.', width: '100px' },
{ field: 'data_parada_veiculo', header: 'DATA PARADA', width: '100px' },
{ field: 'previcao_entrega', header: 'PREV. ENTREGA', width: '100px' },
{ field: 'data_finalizacao', header: 'DATA FINAL.', width: '100px' },
{ field: 'data_retirada', header: 'DATA RETIRADA', width: '100px' },
{ field: 'orcamento_inicial', header: 'ORÇ. INICIAL', width: '110px' },
{ field: 'orcamento_final', header: 'ORÇ. FINAL', width: '110px' },
{ field: 'dif_orcamento', header: 'DIF. ORÇ.', width: '100px' },
{ field: 'condicao_pagamento', header: 'COND. PAG.', width: '100px' },
{ field: 'validacao_financeiro', header: 'VALID. FINANC.', width: '110px' },
{ field: 'resp_aprovacao', header: 'RESP. APROV.', width: '110px' },
{ field: 'sla_oficina', header: 'SLA OFICINA', width: '100px' },
{ field: 'sla_pos_oficina', header: 'SLA PÓS-OF.', width: '100px' },
{ field: 'obs', header: 'OBS', width: '180px' },
{ field: 'endereco_prestador', header: 'END. PRESTADOR', width: '180px' },
{ field: 'pdf_orcamento', header: 'PDF ORÇAMENTO', width: '100px' }
]
```
**filterDefs sugeridos**: `[{ field: 'placa', label: 'Placa', type: 'text' }, { field: 'oficina', label: 'Oficina', type: 'select' }, { field: 'status', label: 'Status', type: 'select' }, { field: 'motivo_atendimento', label: 'Motivo Atendimento', type: 'select' }, { field: 'responsavel', label: 'Responsável', type: 'select' }, { field: 'cidade', label: 'Cidade', type: 'select' }]`
---
### GET /manutencao_frota/aberto_fechado/apresentar
- **Descrição**: Lista manutenções agrupadas em aberto/fechado.
- **Service**: `prafrotService.getAbertoFechado()`.
- **Uso**: Filtro na MaintenanceView (statusFilter: total | aberta | fechada).
**Resposta esperada**: estrutura com listas ou grupos `aberta` e `fechada` (ou array com campo de status). Formato exato depende do backend; a view filtra localmente se receber array único.
---
### GET /disponibilidade_frota/apresentar
- **Descrição**: Lista disponibilidade de veículos.
- **Service**: `prafrotService.getAvailability()`.
**Resposta esperada**: array de objetos; campos típicos a confirmar com o backend. Colunas sugeridas: espelhar campos retornados (ex.: `placa`, `disponivel`, `periodo`, etc.).
---
### GET /moki_frota/apresentar
- **Descrição**: Lista checklists Moki.
- **Service**: `prafrotService.getMoki()`.
---
### GET /status_frota/apresentar
- **Descrição**: Lista status da frota.
- **Service**: `prafrotService.getStatus()`.
---
### GET /monitoramento_frota/apresentar
- **Descrição**: Lista monitoramento.
- **Service**: `prafrotService.getMonitoring()`.
---
### GET /sinistro_devolucao_venda_frota/apresentar
- **Descrição**: Lista sinistros/devoluções/vendas.
- **Service**: `prafrotService.getClaims()`.
---
### GET /oficinas_frota/apresentar
- **Descrição**: Lista oficinas.
- **Service**: `prafrotService.getWorkshops()`.
---
## Ambiente: Workspace / Financeiro-v2
### GET /extrato/apresentar
- **Descrição**: Extrato bancário; filtrar por `tipoOperacao`: "C" = receitas, "D" = despesas.
- **Service**: `extratoService.fetchExtrato()`.
**Resposta esperada**: array de objetos com campos, por exemplo:
`idextrato`, `dataEntrada` (ou `data`), `descricao`, `valor`, `tipoOperacao`, `categoria`, `beneficiario_pagador` (ou `beneficiario`), `caixinha`, etc.
**Colunas sugeridas** (transações):
```js
[
{ field: 'data', header: 'Data', width: '120px' },
{ field: 'descricao', header: 'Descrição', width: '400px' },
{ field: 'valor', header: 'Valor', width: '150px' },
{ field: 'tipo', header: 'Tipo', width: '120px' },
{ field: 'status', header: 'Status', width: '120px' }
]
```
---
### GET /categorias/apresentar
- **Descrição**: Lista categorias para conciliação/labels.
- **Service**: `extratoService.fetchCategorias()` ou `workspaceConciliacaoService`.
**Resposta esperada**: array de objetos (ex.: `id`, `nome`, `descricao`, `tipoMovimento`, `cor`).
---
### GET /caixinhas/apresentar
- **Descrição**: Lista caixinhas.
- **Service**: `extratoService.fetchCaixinhas()` ou `workspaceConciliacaoService`.
**Resposta esperada**: array de objetos (ex.: `id`, `nome`, `banco`, `agencia`, `conta`).
---
### GET /contas_a_pagar/apresentar
- **Descrição**: Contas a pagar planejadas.
- **Service**: `workspaceDespesasService` (ou equivalente).
**Resposta esperada**: array com campos do planejado (categoria, valor, data, etc.). Colunas sugeridas: espelhar campos retornados.
---
### GET /saldo/armazenado/apresentar
- **Descrição**: Saldos armazenados (histórico); usado para último saldo do mês anterior no fluxo de caixa.
- **Service**: `extratoService.fetchSaldoArmazenado()`.
**Resposta esperada**: array (ou objeto único) com `data_saldo`, `saldo_disponivel`, `mes`, `ano`, `idsaldos_mensais`, etc.
---
## Ambiente: GR
### GET /cadastro/drivers/apresentar
- **Descrição**: Lista motoristas (cadastro).
- **Service**: `grService` (getRegistrations ou equivalente).
### GET /contrato/drivers/apresentar
- **Descrição**: Lista motoristas em contrato ativo.
- **Service**: `grService`.
---
## Como usar este documento
1. **Nova rota de apresentação**: adicione um bloco acima com endpoint, resposta esperada e colunas sugeridas; na view, use as colunas do doc e comente: `// Ver docs/PADROES_ROTAS_APRESENTACAO.md § NomeDaRota`.
2. **Backend mudou**: atualize a "Resposta esperada" e as "Colunas sugeridas" aqui; depois ajuste a view para manter alinhamento.
3. **Playground**: a seção "Rotas e Ambientes" pode exibir este documento por ambiente para gerenciamento visual.

View File

@ -0,0 +1,49 @@
# Prafrot Manutenção: regras de backend
Regras que o **backend** deve implementar para alinhar com o frontend da tela de Manutenção (Prafrot).
---
## 1. Garantir que, ao atualizar um registro, as datas não fiquem vazias
- **Rota**: `PUT /manutencao_frota/:id`
- **Regra**: ao receber um payload de atualização, **não sobrescrever** com valor vazio campos de data que já existem no registro.
- **Campos de data**: `data_solicitacao`, `data_agendamento`, `data_parada_veiculo`, `previcao_entrega`, `data_finalizacao`, `data_retirada`.
- **Comportamento esperado**: se o cliente envia `data_finalizacao: ""` ou omite o campo, o backend mantém o valor atual em banco. Apenas valores não vazios (ex.: `"2025-01-15"`) devem alterar o registro.
O frontend já preserva datas existentes ao montar o payload de edição; o backend deve seguir a mesma lógica para evitar limpar datas acidentalmente.
---
## 2. Validar que todas as datas estejam preenchidas antes de permitir fechar uma manutenção
- **Rota**: `PUT /manutencao_frota/fechar_manutencao/:id`
- **Regra**: **recusar** o fechamento (ex.: 400) se alguma das datas abaixo estiver vazia:
- `data_solicitacao`
- `data_agendamento`
- `data_parada_veiculo`
- `previcao_entrega`
- `data_finalizacao`
- `data_retirada`
- **Resposta sugerida**: mensagem clara indicando quais datas estão faltando (ex.: `"Não é possível fechar: preencha Data Solicitação, Data Finalização."`).
O frontend já valida essas mesmas datas antes de chamar o fechamento; a validação no backend é obrigatória para segurança e consistência.
---
## 3. Formatar campos de orçamento como moeda (backend)
- **Campos**: `orcamento_inicial`, `orcamento_final`, `dif_orcamento`.
- **Regra**: armazenar e expor **valores numéricos** (ex.: `1234.56`). O frontend formata em pt-BR (R$ 1.234,56) na exibição.
- **APIs**: aceitar número em `POST /manutencao_frota` e `PUT /manutencao_frota/:id`; retornar número nos JSONs de listagem e detalhe.
---
## 4. Auto-preenchimento de datas no formulário (frontend)
O frontend já trata:
- Normalização de datas ao carregar para edição (ISO, `YYYY-MM-DD`, `DD/MM/YYYY``YYYY-MM-DD`).
- Uso de `type="date"` com valores normalizados para evitar campos vazios por formato incorreto.
O backend deve retornar datas em formato **ISO** ou **YYYY-MM-DD** quando possível, para facilitar o preenchimento correto no formulário.

191
docs/RH_Ajustes_Layout.md Normal file
View File

@ -0,0 +1,191 @@
# ✅ Ajustes Implementados no Ambiente RH
## 📋 Resumo das Alterações
### 1. ✨ Novo Header Integrado
**Arquivo**: `src/features/rh/components/layout/RhHeader.jsx`
- ✅ Criado componente de cabeçalho similar ao Prafrota
- ✅ Botão de mudança de tema posicionado no extremo direito
- ✅ Campo de busca rápida (desktop)
- ✅ Ícone de notificações
- ✅ Animações suaves no hover dos botões
**Características**:
- Tema adaptativo (dark/light)
- Backdrop blur para efeito premium
- Ícones animados (rotação no hover)
- Design consistente com outros ambientes
---
### 2. 🎨 Layout Otimizado
**Arquivo**: `src/features/rh/components/layout/RhLayout.jsx`
**Mudanças**:
- ✅ Integrado `RhHeader` no layout principal
- ✅ Removido margens excessivas que causavam corte de conteúdo
- ✅ Ajustado container para `flex-1` e `overflow-hidden`
- ✅ Melhor aproveitamento do espaço vertical
- ✅ Container de conteúdo com `rounded-2xl` para estética premium
**Antes**:
```jsx
<div style={{ marginRight: '20px', marginTop: '20px', marginBottom: '20px' }}>
<div className="rounded-[2rem]">
<Outlet />
</div>
</div>
```
**Depois**:
```jsx
<RhHeader />
<div className="flex-1 flex flex-col p-4 md:p-6">
<div className="flex-1 rounded-2xl overflow-hidden flex flex-col">
<Outlet />
</div>
</div>
```
---
### 3. 🔧 Sidebar Simplificada
**Arquivo**: `src/features/rh/components/layout/RhSidebar.jsx`
**Mudanças**:
- ✅ Removido botão de tema duplicado (agora apenas no header)
- ✅ Mantido apenas branding e informações do usuário no footer
- ✅ Interface mais limpa e focada
---
### 4. 📊 Tela de Colaboradores Corrigida
**Arquivo**: `src/features/rh/views/EmployeesView.jsx`
**Problemas Resolvidos**:
- ✅ **Conteúdo cortado**: Ajustado hierarquia de flex containers
- ✅ **Painel detalhado não aparecia**: Corrigido posicionamento absoluto
- ✅ **Overflow incorreto**: Implementado `overflow-auto` nos locais corretos
**Estrutura Corrigida**:
```jsx
<div className="flex-1 flex flex-col h-full w-full overflow-hidden">
{/* Header fixo */}
<div className="flex-shrink-0 h-16">...</div>
{/* Área de conteúdo com tabela e painel */}
<div className="flex-1 flex relative overflow-hidden">
{/* Tabela */}
<div className="flex-1 flex flex-col overflow-hidden">
<div className="flex-1 overflow-auto">
<ExcelTable />
</div>
</div>
{/* Painel lateral (AnimatePresence) */}
<motion.div className="absolute right-0 top-0 bottom-0">
<EmployeeDetailPanel />
</motion.div>
</div>
</div>
```
---
### 5. 🔗 Exportação de Componentes
**Arquivo**: `src/components/shared/index.js`
**Mudanças**:
- ✅ Adicionado export do `ItemDetailPanel`
- ✅ Garantido acesso via `@/components/shared`
---
## 🎯 Funcionalidades Implementadas
### Header RH
- [x] Busca rápida (visível em desktop)
- [x] Notificações com badge
- [x] Toggle de tema com animação
- [x] Suporte a dark/light mode
- [x] Backdrop blur premium
### Layout
- [x] Responsivo (mobile-first)
- [x] Sem cortes de conteúdo
- [x] Melhor aproveitamento de espaço
- [x] Transições suaves
### Painel Detalhado
- [x] Animação de entrada/saída
- [x] Backdrop em mobile
- [x] Posicionamento fixo correto
- [x] Scroll interno funcional
- [x] Abas de navegação
---
## 🧪 Testes Recomendados
1. **Navegação**:
- [ ] Clicar em "Colaboradores" no menu
- [ ] Clicar em "Ponto Eletrônico" no menu
- [ ] Verificar se não há cortes de conteúdo
2. **Tema**:
- [ ] Alternar tema no header
- [ ] Verificar se todos os componentes adaptam corretamente
3. **Painel Detalhado**:
- [ ] Clicar no ícone de edição de um colaborador
- [ ] Verificar se o painel aparece com animação
- [ ] Testar scroll interno do painel
- [ ] Fechar o painel (botão X ou backdrop em mobile)
4. **Responsividade**:
- [ ] Testar em diferentes resoluções
- [ ] Verificar comportamento em mobile
- [ ] Confirmar que tabela não é cortada
---
## 📝 Notas Técnicas
### Hierarquia de Containers
```
RhLayout
├── RhSidebar (fixed, z-index alto)
└── main (flex-1, ml ajustável)
├── RhHeader (sticky top-0)
└── Content Area (flex-1, p-4)
└── Rounded Container (flex-1, overflow-hidden)
└── <Outlet /> (Views)
└── EmployeesView
├── Header (flex-shrink-0)
└── Content (flex-1, relative)
├── Table (overflow-auto)
└── Panel (absolute, AnimatePresence)
```
### Classes Importantes
- `flex-1`: Ocupa espaço disponível
- `overflow-hidden`: Previne scroll indesejado no pai
- `overflow-auto`: Permite scroll apenas onde necessário
- `flex-shrink-0`: Previne compressão de headers
- `relative/absolute`: Para posicionamento do painel
---
## 🚀 Próximos Passos Sugeridos
1. Testar a funcionalidade de Ponto Eletrônico
2. Verificar se outros módulos do RH precisam de ajustes similares
3. Validar comportamento em diferentes navegadores
4. Adicionar testes automatizados para o layout
---
**Status**: ✅ Implementação Completa
**Data**: 17/01/2026
**Ambiente**: RH (Recursos Humanos)

129
docs/Regras_Dev.md Normal file
View File

@ -0,0 +1,129 @@
# Regras de Desenvolvimento - PRALOG (Integra Finance)
**Perfil**: Desenvolvedor Sênior Front-end | **Foco**: Automação e Reutilização
---
## Stack Técnico
- React 18 + Vite + JavaScript ES6+
- Shadcn UI + Tailwind CSS
- Zustand (global) + Context (módulos)
- Feature Folders modulares
---
## Regras Principais
### 1. **Sempre Pergunte o Ambiente**
Antes de qualquer alteração, pergunte qual ambiente (`rh`, `financeiro-v2`, `prafrota`, etc).
### 2. **Reutilizar Antes de Criar**
Use `node .agent/scripts/check-reuse.js [termo]` para buscar código existente.
### 3. **Isolamento Total**
- Componentes de um ambiente em `src/features/[ambiente]/components/`
- **Nunca** importe componentes privados entre ambientes
- Use `shared/` só para elementos universais
### 4. **Componentes: Produção + Dev**
- `[Nome].jsx` - produção (todos os ambientes)
- `[Nome].dev.jsx` - dev (só Playground)
- **Playground primeiro** - teste antes de usar em views
### 5. **Performance**
- Componentes < 150 linhas
- Lazy loading com `React.lazy()`
- `useMemo`/`useCallback` em tabelas/gráficos
---
## Estrutura
```
src/
├── components/ui/ # Shadcn (NÃO editar)
├── components/shared/ # Universais
├── features/[ambiente]/ # Isolados
│ ├── components/
│ ├── hooks/
│ ├── views/
│ └── [Nome]Service.js
├── hooks/ # Globais
├── services/ # API
└── utils/ # Formatadores
```
---
## Scripts de Automação
```bash
# Buscar código existente
node .agent/scripts/check-reuse.js [termo]
# Criar componente
node .agent/scripts/create-component.js [Nome] [ambiente?]
# Criar hook
node .agent/scripts/create-hook.js use[Nome] [ambiente?]
# Criar service
node .agent/scripts/create-service.js [Nome] [ambiente?]
```
**Documentação**: `.agent/scripts/README.md`
---
## Workflow
1. **Buscar** reutilização (`check-reuse.js`)
2. **Criar** service/hook/componente (scripts)
3. **Testar** no Playground
4. **Usar** em view
5. **Validar** (`npm run dev`)
**Workflow completo**: `.agent/workflows/create-feature.md` (use `/create-feature`)
---
## Nunca Fazer
❌ Importar entre ambientes
❌ Componentes > 150 linhas
❌ Duplicar lógica
❌ Criar sem buscar reutilização
❌ Usar componente novo sem Playground
---
## Sempre Fazer
✅ Perguntar ambiente
✅ Buscar reutilização (`check-reuse.js`)
✅ Scripts de automação
✅ Playground primeiro
✅ Validar build
---
## Referências
- **Base**: `.agent/instructions/CORE_INSTRUCTIONS.md`
- **Reutilização**: `.agent/instructions/REUSE_AND_MODULARITY.md`
- **PRALOG**: `.agent/instructions/PRALOG_CORE_RULES.md`
- **Quick Ref**: `.agent/QUICK_REFERENCE.md`
- **Scripts**: `.agent/scripts/README.md`
---
## Ambiente de Testes
**URL**: `https://dev.workspace.itguys.com.br/plataforma/`
**User**: `financeiro@pralog.com.br`
**Pass**: `123Mudar`
---
**IMPORTANTE**: Priorize automação, reutilização e isolamento. Use scripts para tarefas repetitivas.

118
docs/TESTE_FORMULARIO_GR.md Normal file
View File

@ -0,0 +1,118 @@
# 🧪 Teste Manual - Formulário de Cadastro de Motorista GR
## 📋 Objetivo
Verificar se o formulário está enviando corretamente os dados e imagens em formato binário para o endpoint `/api/cadastro/drivers/externo`.
## 🔧 Preparação
1. **Abra o navegador** em: https://dev.workspace.itguys.com.br/plataforma/cadastro-motorista
2. **Abra o DevTools** (F12 ou Ctrl+Shift+I)
3. **Vá para a aba Console** para ver os logs de debug
4. **Vá para a aba Network** e filtre por "Fetch/XHR"
## 📝 Passos do Teste
### Etapa 1: Identificação
1. Selecione "Como você deseja trabalhar": **Com meu veículo próprio**
2. Selecione "Tipo de Veículo": **Utilitário**
3. Preencha:
- Nome Completo: `Teste Motorista`
- CPF: `123.456.789-00`
- Telefone: `(21) 99999-9999`
- Data de Nascimento: `01/01/1990`
- CNH: `12345678900`
- Validade CNH: `31/12/2026`
- Placa do Veículo: `ABC1234`
- Modalidade: **Agregado**
- Nome Coordenador: `Teste Coordenador`
- E-mail: `teste@teste.com`
4. Clique em **Avançar**
### Etapa 2: Documentos
1. Anexe **qualquer imagem pequena** (pode ser a mesma para todos):
- CNH (FRENTE) ✅
- CNH (VERSO) ✅
- COMPROVANTE RESIDÊNCIA ✅
- DOCUMENTO DO VEÍCULO (CRLV) ✅
- CARTÃO CNPJ (MEI) ✅
2. Clique em **Avançar**
### Etapa 3: Dados Complementares
1. Preencha:
- CNPJ: `12.345.678/0001-00`
- CEP: `23059-650` (vai preencher automaticamente o endereço)
- Cidade: (preenchido automaticamente)
- Bairro: (preenchido automaticamente)
2. Clique em **Avançar**
### Etapa 4: Revisão e Envio
1. Marque a caixa: **"Li e concordo com os termos..."**
2. Clique em **Finalizar Cadastro**
## 🔍 O que Verificar
### No Console (aba Console do DevTools):
Você deve ver logs como:
```
GR Form: Iniciando submissão {nome_completo: "Teste Motorista", ...}
GR Form: Arquivo anexado - cnh_frente: imagem.jpg 12345 bytes
GR Form: Arquivo anexado - cnh_verso: imagem.jpg 12345 bytes
GR Form: Arquivo anexado - comprovante_residencia: imagem.jpg 12345 bytes
GR Form: Arquivo anexado - crlv: imagem.jpg 12345 bytes
GR Form: Arquivo anexado - cartao_cnpj: imagem.jpg 12345 bytes
GR Form: Total de arquivos anexados: 5
GR Form: Modo de envio: NOVO CADASTRO
GR Form: Resposta do servidor: {submission_id: "...", message: "..."}
```
### Na aba Network:
1. Procure pela requisição para `/api/cadastro/drivers/externo`
2. Clique nela e vá para a aba **Payload** ou **Request**
3. Você deve ver:
- `dados_json`: (string JSON com os dados do formulário)
- `cnh_frente`: (binary)
- `cnh_verso`: (binary)
- `comprovante_residencia`: (binary)
- `crlv`: (binary)
- `cartao_cnpj`: (binary)
### ✅ Resultado Esperado
- Status da requisição: **200 OK** ou **201 Created**
- Mensagem de sucesso: **"Cadastro realizado com sucesso!"**
- Tela de confirmação aparece
### ❌ Se der erro
1. Copie o erro completo do Console
2. Copie a aba **Response** da requisição no Network
3. Tire um print da aba **Payload** mostrando o que foi enviado
4. Me envie essas informações
## 🐛 Problemas Conhecidos Corrigidos
- ✅ Arquivos agora são convertidos de FileList para Array
- ✅ Campos de arquivo removidos do JSON para evitar `{}`
- ✅ Logs de debug adicionados para rastreamento
- ✅ Import do useEffect corrigido
## 📊 Formato Esperado no Backend
**Correto (como deve estar agora):**
```
FormData {
dados_json: '{"nome_completo":"Teste","cpf":"123.456.789-00",...}',
cnh_frente: File (binary),
cnh_verso: File (binary),
comprovante_residencia: File (binary),
crlv: File (binary),
cartao_cnpj: File (binary)
}
```
**Incorreto (problema anterior):**
```json
{
"dados_json": "{...}",
"cnh_frente": {},
"cnh_verso": {},
...
}
```

View File

@ -0,0 +1,156 @@
{
"ambiente": "prafrot",
"label": "Prafrot (Prafrota)",
"recursoBase": "/cadastro_frota",
"rotas": [
{
"id": "cadastro_frota-listar",
"recurso": "cadastro_frota",
"operations": [
{
"method": "GET",
"path": "/cadastro_frota/apresentar",
"descricao": "Lista veículos cadastrados na frota",
"responseShape": [
{ "field": "idveiculo_frota", "type": "number", "description": "ID do veículo" },
{ "field": "placa", "type": "string", "description": "Placa" },
{ "field": "modelo", "type": "string", "description": "Modelo" },
{ "field": "base", "type": "string", "description": "Unidade/Base" },
{ "field": "motorista", "type": "string", "description": "Motorista" },
{ "field": "status", "type": "string", "description": "Status" },
{ "field": "manutencao", "type": "string", "description": "Manutenção" },
{ "field": "atuacao", "type": "string", "description": "Atuação" },
{ "field": "proprietario", "type": "string", "description": "Proprietário" },
{ "field": "obs", "type": "string", "description": "Observações" }
],
"suggestedColumns": [
{ "field": "placa", "header": "Placa", "width": "100px" },
{ "field": "modelo", "header": "Modelo", "width": "150px" },
{ "field": "base", "header": "Unidade", "width": "120px" },
{ "field": "motorista", "header": "Motorista", "width": "180px" },
{ "field": "status", "header": "Status", "width": "140px" }
],
"filterDefs": [
{ "field": "placa", "label": "Placa", "type": "text" },
{ "field": "motorista", "label": "Motorista", "type": "text" },
{ "field": "base", "label": "Unidade", "type": "select" }
]
},
{
"method": "GET",
"path": "/cadastro_frota/:id",
"descricao": "Detalhe de um veículo",
"responseShape": [
{ "field": "idveiculo_frota", "type": "number", "description": "ID" },
{ "field": "placa", "type": "string", "description": "Placa" },
{ "field": "modelo", "type": "string", "description": "Modelo" },
{ "field": "chassi", "type": "string", "description": "Chassi" },
{ "field": "ano_fabricacao", "type": "number", "description": "Ano fabricação" }
]
},
{
"method": "POST",
"path": "/cadastro_frota",
"descricao": "Criar novo veículo",
"requestBody": [
{ "field": "placa", "type": "string", "required": true },
{ "field": "modelo", "type": "string", "required": true },
{ "field": "base", "type": "string", "required": false }
]
},
{
"method": "PUT",
"path": "/cadastro_frota/:id",
"descricao": "Atualizar veículo",
"requestBody": [
{ "field": "placa", "type": "string", "required": false },
{ "field": "modelo", "type": "string", "required": false },
{ "field": "status", "type": "string", "required": false }
]
}
]
},
{
"id": "manutencao_frota-listar",
"recurso": "manutencao_frota",
"operations": [
{
"method": "GET",
"path": "/manutencao_frota/apresentar",
"descricao": "Lista todas as manutenções",
"responseShape": [
{ "field": "idmanutencao_frota", "type": "number", "description": "ID manutenção" },
{ "field": "atendimento", "type": "string", "description": "Nº atendimento" },
{ "field": "placa", "type": "string", "description": "Placa" },
{ "field": "modelo", "type": "string", "description": "Modelo" },
{ "field": "oficina", "type": "string", "description": "Oficina" },
{ "field": "status", "type": "string", "description": "Status" },
{ "field": "data_solicitacao", "type": "string", "description": "Data solicitação" },
{ "field": "data_finalizacao", "type": "string", "description": "Data finalização" },
{ "field": "orcamento_inicial", "type": "number", "description": "Orçamento inicial" },
{ "field": "orcamento_final", "type": "number", "description": "Orçamento final" }
],
"suggestedColumns": [
{ "field": "idmanutencao_frota", "header": "ID", "width": "80px" },
{ "field": "placa", "header": "PLACA", "width": "100px" },
{ "field": "modelo", "header": "MODELO", "width": "110px" },
{ "field": "oficina", "header": "OFICINA", "width": "160px" },
{ "field": "status", "header": "STATUS", "width": "140px" }
],
"filterDefs": [
{ "field": "placa", "label": "Placa", "type": "text" },
{ "field": "oficina", "label": "Oficina", "type": "select" },
{ "field": "status", "label": "Status", "type": "select" }
]
},
{
"method": "GET",
"path": "/manutencao_frota/:id",
"descricao": "Detalhe de uma manutenção",
"responseShape": [
{ "field": "idmanutencao_frota", "type": "number", "description": "ID" },
{ "field": "placa", "type": "string", "description": "Placa" },
{ "field": "oficina", "type": "string", "description": "Oficina" },
{ "field": "status", "type": "string", "description": "Status" },
{ "field": "orcamento_final", "type": "number", "description": "Orçamento final" }
]
},
{
"method": "POST",
"path": "/manutencao_frota",
"descricao": "Criar nova manutenção",
"requestBody": [
{ "field": "placa", "type": "string", "required": true },
{ "field": "oficina", "type": "string", "required": true },
{ "field": "motivo_atendimento", "type": "string", "required": false }
]
},
{
"method": "PUT",
"path": "/manutencao_frota/:id",
"descricao": "Atualizar manutenção",
"requestBody": [
{ "field": "status", "type": "string", "required": false },
{ "field": "data_finalizacao", "type": "string", "required": false },
{ "field": "orcamento_final", "type": "number", "required": false }
]
}
]
},
{
"id": "disponibilidade_frota",
"recurso": "disponibilidade_frota",
"operations": [
{
"method": "GET",
"path": "/disponibilidade_frota/apresentar",
"descricao": "Lista disponibilidade de veículos",
"responseShape": [
{ "field": "placa", "type": "string", "description": "Placa" },
{ "field": "disponivel", "type": "boolean", "description": "Disponível" }
]
}
]
}
]
}

View File

@ -0,0 +1,83 @@
{
"ambiente": "workspace",
"label": "Workspace",
"rotas": [
{
"id": "extrato-listar",
"recurso": "extrato",
"operations": [
{
"method": "GET",
"path": "/extrato/apresentar",
"descricao": "Extrato bancário; filtrar por tipoOperacao C=receitas, D=despesas",
"responseShape": [
{ "field": "idextrato", "type": "number", "description": "ID transação" },
{ "field": "data", "type": "string", "description": "Data" },
{ "field": "descricao", "type": "string", "description": "Descrição" },
{ "field": "valor", "type": "number", "description": "Valor" },
{ "field": "tipoOperacao", "type": "string", "description": "C ou D" },
{ "field": "beneficiario_pagador", "type": "string", "description": "Beneficiário/Pagador" }
],
"suggestedColumns": [
{ "field": "data", "header": "Data", "width": "120px" },
{ "field": "descricao", "header": "Descrição", "width": "400px" },
{ "field": "valor", "header": "Valor", "width": "150px" },
{ "field": "tipo", "header": "Tipo", "width": "120px" }
]
}
]
},
{
"id": "categorias-listar",
"recurso": "categorias",
"operations": [
{
"method": "GET",
"path": "/categorias/apresentar",
"descricao": "Lista categorias para conciliação",
"responseShape": [
{ "field": "id", "type": "number", "description": "ID categoria" },
{ "field": "nome", "type": "string", "description": "Nome" },
{ "field": "descricao", "type": "string", "description": "Descrição" },
{ "field": "tipoMovimento", "type": "string", "description": "Entrada/Saída" }
]
}
]
},
{
"id": "caixinhas-listar",
"recurso": "caixinhas",
"operations": [
{
"method": "GET",
"path": "/caixinhas/apresentar",
"descricao": "Lista caixinhas",
"responseShape": [
{ "field": "id", "type": "number", "description": "ID" },
{ "field": "nome", "type": "string", "description": "Nome" },
{ "field": "banco", "type": "string", "description": "Banco" },
{ "field": "agencia", "type": "string", "description": "Agência" },
{ "field": "conta", "type": "string", "description": "Conta" }
]
}
]
},
{
"id": "contas_a_pagar-listar",
"recurso": "contas_a_pagar",
"operations": [
{
"method": "GET",
"path": "/contas_a_pagar/apresentar",
"descricao": "Contas a pagar planejadas",
"responseShape": [
{ "field": "id", "type": "number", "description": "ID" },
{ "field": "categoria", "type": "string", "description": "Categoria" },
{ "field": "valor", "type": "number", "description": "Valor" },
{ "field": "data", "type": "string", "description": "Data" }
]
}
]
}
]
}

View File

@ -0,0 +1,107 @@
# Guia de Integração Frontend-Backend: Módulo GR Operações
Este documento serve como guia técnico para o desenvolvimento da API backend que alimentará o novo módulo de GR Operações. O frontend foi construído de forma modular, utilizando uma camada de abstração que permite alternar entre dados simulados (mocks) e a API real através de uma flag.
---
## 1. Arquitetura do Frontend
O frontend segue um padrão de 3 camadas:
1. **Views (React Components):** Interface do usuário. Não conhecem a origem dos dados.
2. **Hooks (useXXX):** Encapsulam a lógica de negócio, caching básico e chamadas aos services.
3. **Services (xxxService):** Camada de comunicação com a rede (Fetch/Axios). Contêm a lógica de Mock.
### Como ativar a API Real
Em cada arquivo dentro de `src/features/gr/services/`, existe uma constante:
```javascript
const USE_MOCK = true; // Altere para false para usar a API real
const API_URL = import.meta.env.VITE_API_URL || 'http://localhost:3000';
```
Basta alterar `USE_MOCK` para `false` e configurar a URL da sua API no arquivo `.env`.
---
## 2. Contratos da API (Endpoints Esperados)
Abaixo estão os endpoints que os Services já tentam chamar quando `USE_MOCK = false`.
### 🚨 2.1 Monitoramento de Viagens
- **GET** `/api/gr/monitoring/requests`
- **Filtros (Query):** `status` (PENDING, LIBERADO, EM_ROTA, FINALIZADO)
- **POST** `/api/gr/monitoring/request/:id/attend`
- **Ação:** Marca supervisor como responsável pela análise.
- **POST** `/api/gr/monitoring/request/:id/approve`
- **Payload:** `{ cargoValue, cte, ae, pallet, routeImageUrl, customMessage }`
### 🛰️ 2.2 Telemetria e Rastreamento
- **GET** `/api/gr/telemetry/positions`
- **Retorno:** Array de veículos com `plate, lat, lng, speed, riskStatus, alert`.
- **GET** `/api/gr/telemetry/history/:plate`
- **Retorno:** Array de posições históricas (lat, lng, timestamp, speed).
### 📋 2.3 Checklist e Manutenção
- **GET** `/api/gr/checklist/vehicles`
- **Filtros:** `client`
- **POST** `/api/gr/checklist/renew/:id`
- **Ação:** Estende validade do checklist.
- **GET** `/api/gr/maintenance/orders`
- **Filtros:** `vehicleId`
- **POST** `/api/gr/maintenance/orders`
- **Payload:** `{ vehicleId, type, sensor, description }`
### 📄 2.4 Gestão de Documentos
- **GET** `/api/gr/documents`
- **Filtros:** `entityType` (MOTORISTA, VEÍCULO), `docType` (CNH, CRLV)
- **POST** `/api/gr/documents` (**Multipart/Form-Data**)
- **Payload:** `file, client, entityType, entityName, docType`
- **DELETE** `/api/gr/documents/:id`
### 📊 2.5 Planilhas e Importação
- **GET** `/api/gr/spreadsheets`
- **Filtros:** `clientId, archived` (boolean)
- **POST** `/api/gr/spreadsheets/import`
- **Payload:** `{ clientId, rows: [...] }`
- **PATCH** `/api/gr/spreadsheets/:id/archive`
---
## 3. Modelos de Dados (Exemplos JSON)
### Objeto de Solicitação de Monitoramento
```json
{
"id": "uuid",
"driverName": "String",
"plate": "AAA-0000",
"status": "PENDING",
"riskLevel": "LOW | MEDIUM | HIGH",
"cargoValue": 0,
"origin": "Cidade - UF",
"destination": "Cidade - UF"
}
```
### Objeto de Telemetria
```json
{
"id": "uuid",
"plate": "AAA-0000",
"lat": -22.90,
"lng": -43.17,
"speed": 80,
"riskStatus": "NORMAL | CRITICAL",
"alert": "EXCESS_SPEED | NO_SIGNAL"
}
```
---
## ⚡ 4. WebSockets (Socket.io)
O frontend está preparado para ouvir os seguintes eventos para atualizações em tempo real:
- `monitoring-update`: Quando uma nova solicitação chega.
- `positions-update`: Quando as posições de telemetria mudam.
- `request-approved`: Quando o status de uma viagem muda para LIBERADO.
---
*Documento gerado para auxiliar o time de backend na migração do módulo GR.*

View File

@ -0,0 +1,208 @@
# Relatório Zentulo System Deep Dive: Análise Técnica e Funcional
Este documento apresenta uma análise detalhada da arquitetura, lógica de negócios e fluxos operacionais do Sistema Zentulo, um ambiente de análise e simulação para a plataforma Zentulo.
## 1. Visão Geral da Arquitetura
O sistema Zentulo utiliza uma arquitetura **Híbrida Web/Electron**, projetada para operar tanto em navegadores quanto em ambiente desktop com permissões estendidas de sistema de arquivos.
* **Frontend:** React com Tailwind CSS.
* **Comunicação:** REST API e WebSockets (Socket.io) para atualizações em tempo real.
* **Persistência Local:** `localStorage` com lógica de sincronização offline personalizada.
* **Integração Nativa:** Electron Bridge (`window.electronAPI`) para processamento de arquivos XML locais e automação do Outlook.
---
## 2. Fluxos Visuais (Mermaid.js)
### Fluxo 1: Ciclo de Vida da Solicitação de Liberação
O coração do sistema é o fluxo de solicitações feitas por motoristas e aprovadas pela central de monitoramento.
```mermaid
sequenceDiagram
participant M as Motorista (Portal)
participant S as Socket.io / API
participant C as Central (Painel Monitoramento)
M->>S: Envia Solicitação (Placa, Operação, CTe/NF)
S-->>C: Notificação Real-time (monitoring-update)
C->>C: Supervisor clica em "Atender"
Note right of C: Status muda para "ANÁLISE"
C-->>M: Notificação: "Solicitação Atendida"
C->>C: Validação de Perímetro/SST/Fiscal
C->>S: Clica em "Aprovar" (Envia Rota/Mensagem)
S-->>M: Notificação: "LIBERADO" (Verde)
M->>M: Clica em "Saí em Rota"
Note left of M: Status muda para "EM ROTA"
```
### Fluxo 2: Processamento Fiscal e Automação de E-mail
Este fluxo descreve como o sistema extrai dados de documentos fiscais sem intervenção manual pesada.
```mermaid
graph TD
A[Outlook Automation] -->|Electron Select Folder| B[Download XMLs]
B --> C{Tipo de Documento?}
C -->|NF-e| D[FiscalAnalysis Component]
C -->|CT-e / MDF-e| E[CTE Component]
D -->|window.electronAPI.processFiscal| F[Validação contra Regras de Negócio]
E -->|window.electronAPI.processCTEs| G[Validação de CTE / MDF-e]
F --> H[Relatório de Divergências]
G --> I[Log de Processamento e Auditoria]
```
### Fluxo 3: Sincronização Offline de Documentos
O sistema garante que motoristas possam salvar comprovantes mesmo em áreas de sombra de sinal.
```mermaid
graph LR
A[Upload do Arquivo] --> B{Conexão Online?}
B -- Não --> C[Salva em localStorage 'pending_sync']
B -- Sim --> D[Envia para /api/documents]
C --> E[Monitora Evento 'online']
E --> F[syncPending Utility]
F --> D
D --> G[Cria Registro na Gestão de Documentos]
```
### Fluxo 4: Importação de Planilhas (Excel)
O sistema permite popular cadastros em massa via processamento local de arquivos `.xlsx`.
```mermaid
graph TD
A[Selecionar Arquivo .xlsx] --> B[FileReader.readAsBinaryString]
B --> C[XLSX.read Parser]
C --> D[Mapeamento de Colunas Dinâmico]
D --> E{Motorista Válido?}
E -->|Sim| F[Lista de Prévia para Conferência]
E -->|Não| G[Alerta de Erro de Formato]
F --> H[Loop: POST /api/drivers]
H --> I[Atualização Local da UI]
```
### Fluxo 5: Sistema de Telemetria e Rastreamento
Monitoramento em tempo real de veículos com integração a provedores externos.
```mermaid
sequenceDiagram
participant W as Worker (30s polling)
participant T as T4S API
participant S as Sascar API
participant DB as TelemetryDB (Memória)
participant IO as Socket.io
participant C as Cliente (Dashboard)
loop A cada 30 segundos
W->>T: Bulk Fetch (PRALOG + PETY)
T-->>W: Array de Posições
W->>S: Bulk Fetch (Se credenciais configuradas)
S-->>W: Array de Posições
W->>W: Normalização de Dados
W->>W: Validação Geofence (lat > -21.0?)
W->>W: Validação Velocidade (> 90 km/h?)
W->>DB: Atualiza Posições + Histórico
W->>IO: Emit 'positions-update'
IO-->>C: Atualização Real-time
end
Note over W,C: Alertas: FORA_DA_ROTA, EXCESS_SPEED, SIGNAL_LOST
```
---
## 3. Análise Detalhada dos Módulos
### 3.1 Painel de Monitoramento
* **Lógica de Status:** Transições coordenadas entre *Pending* -> *Analysis* -> *Approved* -> *In Progress* -> *Arrived*.
* **Validação de Rota:** Contém lógica específica para impedir rotas pela "Avenida Brasil" dependendo do valor da carga e destino, a menos que o destino seja na própria avenida.
* **Integração Real-time:** Uso intensivo de WebSockets para sincronizar os estados entre o supervisor e o motorista instantaneamente.
### 3.2 Gestão de Checklists e Manutenção
* **Auto-Renovação:** Implementa uma regra de +30 dias de validade ao renovar um checklist básico.
* **Cálculo de Status:** Status dinâmico (Válido, Alerta, Expirado) calculado em tempo real com base na data atual e datas de expiração.
* **Ordens de Serviço (OS):** Suporta criação de OS manuais ou automáticas (baseadas em sequencial interno).
### 3.3 Cadastro e Gestão de Documentos
* **Importação (Planilhas):** Utiliza a biblioteca `xlsx` para parsing de arquivos Excel. Possui lógica de mapeamento inteligente que busca por variações de nomes de colunas (ex: "Motoristas", "Nome", "CPF").
* **Hierarquia de Documentos:** Documentos são vinculados a Entidades (MOTORISTA ou CAVALO/VEÍCULO). Salvar um novo documento do mesmo tipo (ex: CRLV) substitui logicamente o anterior.
* **Módulo de Planilhas:** Existe uma rota dedicada (`/spreadsheets`) que se integra ao sistema de sincronização offline, permitindo a gestão de documentos de planilha associados à operação.
### 3.4 Administração e Segurança (RBAC)
* **Níveis de Acesso:** DEV, SUPERVISOR, GR, MONITORAMENTO.
* **Restrições de Hierarquia:** O código impede que usuários com nível SUPERVISOR editem ou excluam usuários com nível DEV.
* **Configuração de E-mail:** O e-mail de cadastro do usuário é a "chave" para as integrações de Outlook, servindo como credencial para a automação Electron.
---
## 4. Backend e Infraestrutura
### 4.1 Arquitetura do Backend
* **Stack:** Node.js + Express.js
* **Banco de Dados:** MongoDB Atlas (`mongodb+srv://pralog:pralog123@cluster0.aobkjaq.mongodb.net/pralog`)
* **Comunicação Real-time:** Socket.io v4.8.1
* **Autenticação:** JWT (jsonwebtoken) + bcrypt para hash de senhas
* **Segurança:** Helmet.js, express-rate-limit, CORS configurado
### 4.2 Sistema de Telemetria e Rastreamento
O sistema possui integração nativa com dois provedores de rastreamento veicular:
#### Integração T4S
* **Contas Configuradas:** PRALOG e PETY
* **Endpoint:** `https://integracaov2.t4stecnologia.com.br/api`
* **Autenticação:** Bearer Token com cache de 50 minutos
* **Polling:** A cada 30 segundos (configurável)
* **Dados Capturados:** Placa, lat/lng, velocidade, ignição, endereço, timestamp
#### Integração Sascar
* **Status:** Estrutura pronta, aguardando credenciais
* **Normalização:** Converte dados brutos para formato unificado
* **Fallback:** Retorna array vazio se credenciais não configuradas
#### Geofencing e Alertas Automáticos
* **Cerca Eletrônica:** Validação de latitude (alerta se `lat > -21.0`)
* **Alerta de Velocidade:** Dispara se velocidade > 90 km/h
* **Níveis de Risco:**
* `NORMAL` - Operação dentro dos parâmetros
* `HIGH` - Excesso de velocidade
* `CRITICAL` - Fora da rota autorizada
* **Perda de Sinal:** Monitora veículos sem atualização por > 5 minutos
* **Histórico:** Mantém últimas 50 posições em memória por veículo
### 4.3 Gestão de Planilhas (SpreadsheetData)
* **Clientes Suportados:** IMPERIO, ORTOBOM_RJ, ORTOBOM_SP, LIBFARMA
* **Funcionalidades:**
* Importação de dados via biblioteca `xlsx`
* Arquivamento de registros antigos
* Queries por `clientId` e status de arquivamento
* **Script de Verificação:** `check-spreadsheet.js` para auditoria de dados
### 4.4 Sistema de Auto-Update
* **Provedor:** GitHub Releases
* **Repositório:** `itguys/pralog-server`
* **Diretório de Cache:** `zentulo-systems-updater`
* **Componente Frontend:** `VersionChecker` + `ElectronUpdater`
* **Fluxo:** Verifica → Baixa → Notifica Usuário → Instala ao Reiniciar
### 4.5 Processamento de Arquivos
* **Upload:** Multer v2.0.2 para multipart/form-data
* **PDF:** Parsing com `pdf-parse` e geração com `pdfkit`
* **Excel:** Leitura e escrita com `xlsx` v0.18.5
* **Compressão:** Middleware `compression` para otimizar tráfego
---
## 5. Gaps e Pontos de Atenção
1. **Dependência do Electron:** Módulos de Fiscal, CTe e Outlook não funcionam nativamente na web devido às restrições de sandbox do navegador (necessitam do bridge native).
2. **Performance de Filtro:** A filtragem de solicitações no painel de monitoramento ocorre majoritariamente no lado do cliente (`client-side filtering`), o que pode degradar a performance com milhares de registros.
3. **Endpoint do Outlook:** O endpoint `/api/outlook-filter` é simulado/mockado, exigindo um serviço backend Azure AD robusto para operação real.
4. **Sincronização:** A lógica offline depende inteiramente do `localStorage`. Limpar os dados do navegador sem sincronização resultará em perda de dados "pendentes".
5. **Credenciais de Rastreamento:**
* **T4S:** Senhas pendentes para contas PRALOG e PETY (marcadas como `[AGUARDANDO_WHATSAPP_*]`)
* **Sascar:** Credenciais completamente ausentes (estrutura pronta, mas inativa)
6. **Segurança do Banco de Dados:** Credenciais do MongoDB expostas em arquivo `.env` sem criptografia adicional.
7. **Geofencing Simplificado:** Lógica de cerca eletrônica usa apenas validação de latitude (`lat > -21.0`), sem polígonos complexos ou múltiplas zonas.
8. **Telemetria em Memória:** Histórico de posições armazenado apenas em memória (não persistido), limitado a 50 posições por veículo.
---
*Relatório atualizado em 06 de Fevereiro de 2026.*

23
eslint.config.js Normal file
View File

@ -0,0 +1,23 @@
import js from '@eslint/js'
import globals from 'globals'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
import tseslint from 'typescript-eslint'
import { defineConfig, globalIgnores } from 'eslint/config'
export default defineConfig([
globalIgnores(['dist']),
{
files: ['**/*.{ts,tsx}'],
extends: [
js.configs.recommended,
tseslint.configs.recommended,
reactHooks.configs.flat.recommended,
reactRefresh.configs.vite,
],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
},
])

54
extract_logic.py Normal file
View File

@ -0,0 +1,54 @@
import re
FILE_PATH = "c:/Users/Daivid.alves/Desktop/Repositorios/PlatformSistemas/Sistema_zentulo_analise/Codigo/analysis_src/zentulo_index.js"
patterns = {
"FISCAL_XML": [
r"window\.electronAPI\.processFiscal",
r"DOMParser",
r"<placa>",
r"<vNF>",
r"<vtPrest>"
],
"OUTLOOK_EMAIL": [
r"outlook-filter",
r"socket\.on\(['\"]outlook",
r"OutlookAutomation"
],
"MONITORING": [
r"socket\.on\(['\"]update-request",
r"socket\.emit\(['\"]update-status",
r"PENDING",
r"APPROVED",
r"EM_ROTA"
],
"CHECKLIST": [
r"getStatusFromExpiry",
r"renovar",
r"nextOS",
r"ChecklistClient"
]
}
def extract_context(content, pattern_name, regex_list):
print(f"\n{'='*20} {pattern_name} {'='*20}")
for regex in regex_list:
print(f"\n--- Searching for: {regex} ---")
matches = list(re.finditer(regex, content, re.IGNORECASE))
print(f"Found {len(matches)} matches.")
for i, match in enumerate(matches[:3]): # Limit to first 3 matches per pattern
start = max(0, match.start() - 300)
end = min(len(content), match.end() + 300)
snippet = content[start:end].replace('\n', ' ')
print(f"[{i+1}] ...{snippet}...")
try:
with open(FILE_PATH, 'r', encoding='utf-8', errors='ignore') as f:
content = f.read()
for key, regexes in patterns.items():
extract_context(content, key, regexes)
except Exception as e:
print(f"Error: {e}")

15
extract_outlook.py Normal file
View File

@ -0,0 +1,15 @@
import re
file_path = "c:/Users/Daivid.alves/Desktop/Repositorios/PlatformSistemas/Sistema_zentulo_analise/Codigo/analysis_src/zentulo_index.js"
with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
content = f.read()
matches = list(re.finditer(r'outlook-filter', content))
for i, match in enumerate(matches):
start = max(0, match.start() - 500)
end = min(len(content), match.end() + 500)
print(f"--- MATCH {i+1} ---")
print(content[start:end])
print("-" * 50)

164
git-auto-sync.ps1 Normal file
View File

@ -0,0 +1,164 @@
# Git Auto-Sync - PlatformSistemas
# Branch: frontend_React
param(
[switch]$NoBuild = $false
)
$BRANCH_NAME = git branch --show-current
if ([string]::IsNullOrWhiteSpace($BRANCH_NAME)) { $BRANCH_NAME = "frontend_React" }
$DEBOUNCE_SECONDS = 10
$global:LastChangeTime = Get-Date
$global:PendingChanges = $false
$global:ChangedFiles = @()
function Test-ShouldIgnoreFile {
param([string]$FilePath)
$ignorePatterns = @("node_modules", ".git", "dist", ".env", ".log", "package-lock.json", ".tmp", ".cache", ".vscode", ".idea")
foreach ($pattern in $ignorePatterns) {
if ($FilePath -match [regex]::Escape($pattern)) {
return $true
}
}
return $false
}
function Invoke-GitSync {
if (-not $global:PendingChanges) {
return
}
Write-Host "`n========================================" -ForegroundColor Cyan
Write-Host "Iniciando sincronizacao Git..." -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
try {
$gitStatus = git status --porcelain
if ([string]::IsNullOrWhiteSpace($gitStatus)) {
Write-Host "Nenhuma alteracao para commitar." -ForegroundColor Yellow
$global:PendingChanges = $false
$global:ChangedFiles = @()
return
}
Write-Host "`nArquivos alterados:" -ForegroundColor Gray
$global:ChangedFiles | ForEach-Object { Write-Host " - $_" -ForegroundColor DarkGray }
if (-not $NoBuild) {
Write-Host "`nGerando build de producao..." -ForegroundColor Yellow
npm run build
if ($LASTEXITCODE -ne 0) {
Write-Host "Erro no build! Abortando commit." -ForegroundColor Red
return
}
Write-Host "Build concluido com sucesso!" -ForegroundColor Green
}
Write-Host "`nAdicionando arquivos ao stage..." -ForegroundColor Yellow
git add .
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$fileCount = ($global:ChangedFiles | Measure-Object).Count
$commitMessage = "Auto-deploy: $timestamp | $fileCount arquivo(s) alterado(s)"
if (-not $NoBuild) {
$commitMessage += " [Build included]"
}
Write-Host "Criando commit..." -ForegroundColor Yellow
git commit -m $commitMessage
if ($LASTEXITCODE -ne 0) {
Write-Host "Nada para commitar ou erro no commit." -ForegroundColor Yellow
$global:PendingChanges = $false
$global:ChangedFiles = @()
return
}
Write-Host "Enviando para o repositorio remoto (branch: $BRANCH_NAME)..." -ForegroundColor Yellow
git push origin $BRANCH_NAME
if ($LASTEXITCODE -eq 0) {
Write-Host "`nSincronizacao concluida com sucesso!" -ForegroundColor Green
Write-Host "========================================`n" -ForegroundColor Cyan
}
else {
Write-Host "`nErro ao fazer push para o repositorio remoto!" -ForegroundColor Red
Write-Host "========================================`n" -ForegroundColor Cyan
}
}
catch {
Write-Host "`nErro ao sincronizar com o Git: $_" -ForegroundColor Red
Write-Host "========================================`n" -ForegroundColor Cyan
}
finally {
$global:PendingChanges = $false
$global:ChangedFiles = @()
}
}
$Watcher = New-Object IO.FileSystemWatcher
$Watcher.Path = $PSScriptRoot
$Watcher.Filter = "*.*"
$Watcher.IncludeSubdirectories = $true
$Watcher.EnableRaisingEvents = $true
$Watcher.NotifyFilter = [System.IO.NotifyFilters]::FileName -bor [System.IO.NotifyFilters]::DirectoryName -bor [System.IO.NotifyFilters]::LastWrite
$Action = {
$path = $Event.SourceEventArgs.FullPath
$changeType = $Event.SourceEventArgs.ChangeType
if (Test-ShouldIgnoreFile -FilePath $path) {
return
}
$relativePath = $path.Replace($PSScriptRoot, "").TrimStart("\")
Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $changeType : $relativePath" -ForegroundColor DarkCyan
$global:LastChangeTime = Get-Date
$global:PendingChanges = $true
if ($global:ChangedFiles -notcontains $relativePath) {
$global:ChangedFiles += $relativePath
}
}
Register-ObjectEvent $Watcher "Changed" -Action $Action | Out-Null
Register-ObjectEvent $Watcher "Created" -Action $Action | Out-Null
Register-ObjectEvent $Watcher "Deleted" -Action $Action | Out-Null
Register-ObjectEvent $Watcher "Renamed" -Action $Action | Out-Null
Write-Host "`n============================================================" -ForegroundColor Green
Write-Host " Git Auto-Sync - PlatformSistemas" -ForegroundColor Green
Write-Host "============================================================" -ForegroundColor Green
Write-Host " Branch: $BRANCH_NAME" -ForegroundColor Cyan
Write-Host " Remote: https://git.itguys.com.br/itguys_dev/Workspace" -ForegroundColor Cyan
Write-Host " Debounce: $DEBOUNCE_SECONDS segundos" -ForegroundColor Cyan
Write-Host " Build automatico: $(if($NoBuild){'Desabilitado'}else{'Habilitado'})" -ForegroundColor Cyan
Write-Host "============================================================" -ForegroundColor Green
Write-Host " Status: Monitorando alteracoes..." -ForegroundColor Yellow
Write-Host " Pressione Ctrl+C para parar" -ForegroundColor Yellow
Write-Host "============================================================`n" -ForegroundColor Green
$lastHeartbeat = Get-Date
while ($true) {
Start-Sleep -Seconds 1
if ((Get-Date) - $lastHeartbeat -gt (New-TimeSpan -Minutes 5)) {
Write-Host "[$(Get-Date -Format 'HH:mm:ss')] Heartbeat: Script ativo e monitorando..." -ForegroundColor Gray
$lastHeartbeat = Get-Date
}
if ($global:PendingChanges) {
$timeSinceLastChange = (Get-Date) - $global:LastChangeTime
if ($timeSinceLastChange.TotalSeconds -ge $DEBOUNCE_SECONDS) {
Invoke-GitSync
}
}
}

33
git-sync-env.ps1 Normal file
View File

@ -0,0 +1,33 @@
# Git Sync Environment - PlatformSistemas Modelo
# Use este script dentro de uma branch de AMBIENTE (ex: env/rh) para puxar novidades do Núcleo.
param(
[string]$CoreBranch = "frontend_React"
)
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "Sincronizando Ambiente com o Nucleo..." -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
# 1. Verifica em qual branch estamos
$currentBranch = git branch --show-current
Write-Host "Branch atual: $currentBranch" -ForegroundColor Gray
if ($currentBranch -eq $CoreBranch) {
Write-Host "Voce ja esta na branch de Nucleo. Nada para sincronizar aqui." -ForegroundColor Yellow
return
}
# 2. Faz o merge do núcleo para o ambiente
Write-Host "Mesclando alteracoes da branch '$CoreBranch' para '$currentBranch'..." -ForegroundColor Yellow
git merge $CoreBranch
if ($LASTEXITCODE -eq 0) {
Write-Host "`nSincronizacao concluida! O ambiente agora esta atualizado com o nucleo." -ForegroundColor Green
Write-Host "Lembre-se de rodar 'npm install' se houver novas dependencias." -ForegroundColor White
}
else {
Write-Host "`nHouve conflitos durante a sincronizacao. Resolva-os manualmente." -ForegroundColor Red
}
Write-Host "========================================`n" -ForegroundColor Cyan

34
git-sync-fork.ps1 Normal file
View File

@ -0,0 +1,34 @@
# Git Sync Fork - PlatformSistemas Modelo
# Use este script dentro de um FORK para puxar as dependencias do repositório Principal (Upstream)
param(
[string]$UpstreamUrl = "https://git.itguys.com.br/itguys_dev/Workspace",
[string]$MainBranch = "frontend_React"
)
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "Sincronizando Fork com Upstream..." -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
# 1. Verifica se o upstream já existe
$remotes = git remote
if ($remotes -notcontains "upstream") {
Write-Host "Adicionando remote 'upstream': $UpstreamUrl" -ForegroundColor Yellow
git remote add upstream $UpstreamUrl
}
# 2. Busca atualizações do upstream
Write-Host "Buscando novidades do nucleo central..." -ForegroundColor Yellow
git fetch upstream
# 3. Faz o merge das dependencias e nucleo (na branch atual)
Write-Host "Mesclando alteracoes da branch $MainBranch para sua branch atual..." -ForegroundColor Yellow
git merge upstream/$MainBranch
if ($LASTEXITCODE -eq 0) {
Write-Host "`nSincronizacao concluida! Agora rode 'npm install' para atualizar dependencias." -ForegroundColor Green
} else {
Write-Host "`nHouve conflitos durante a sincronizacao. Resolva-os manualmente." -ForegroundColor Red
}
Write-Host "========================================`n" -ForegroundColor Cyan

14
index.html Normal file
View File

@ -0,0 +1,14 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>platformsistemas</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-icons/1.13.1/font/bootstrap-icons.min.css" />
</head>
<body>
<div id="root"></div>
<script type="module" src="./src/main.jsx"></script>
</body>
</html>

6935
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

69
package.json Normal file
View File

@ -0,0 +1,69 @@
{
"name": "platformsistemas",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"lint": "eslint .",
"preview": "vite preview",
"git:sync": "powershell -ExecutionPolicy Bypass -File ./git-auto-sync.ps1",
"git:sync:nobuild": "powershell -ExecutionPolicy Bypass -File ./git-auto-sync.ps1 -NoBuild",
"agent:git:commit": "node .agent/scripts/git-commit-by-day.js",
"agent:git:commit:dry": "node .agent/scripts/git-commit-by-day.js --dry-run",
"agent:docs:update": "node .agent/scripts/docs-update.js",
"agent:check": "node .agent/scripts/check-orchestrator.js",
"doc:sync": "node scripts/auto-sync-routes.js"
},
"dependencies": {
"@hookform/resolvers": "^5.2.2",
"@radix-ui/react-avatar": "^1.1.11",
"@radix-ui/react-checkbox": "^1.3.3",
"@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-dropdown-menu": "^2.1.16",
"@radix-ui/react-label": "^2.1.8",
"@radix-ui/react-radio-group": "^1.3.8",
"@radix-ui/react-scroll-area": "^1.2.10",
"@radix-ui/react-select": "^2.2.6",
"@radix-ui/react-separator": "^1.1.8",
"@radix-ui/react-slider": "^1.3.6",
"@radix-ui/react-slot": "^1.2.4",
"@radix-ui/react-switch": "^1.2.6",
"@radix-ui/react-tabs": "^1.1.13",
"axios": "^1.13.2",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"framer-motion": "^12.23.26",
"lucide-react": "^0.562.0",
"react": "^19.2.0",
"react-dom": "^19.2.0",
"react-hook-form": "^7.71.1",
"react-router-dom": "^7.11.0",
"recharts": "^3.6.0",
"sonner": "^2.0.7",
"tailwind-merge": "^3.4.0",
"tailwindcss-animate": "^1.0.7",
"zod": "^4.3.5",
"zustand": "^5.0.9"
},
"devDependencies": {
"@eslint/js": "^9.39.1",
"@tailwindcss/postcss": "^4.1.18",
"@tailwindcss/vite": "^4.1.18",
"@types/node": "^24.10.1",
"@types/react": "^19.2.5",
"@types/react-dom": "^19.2.3",
"@vitejs/plugin-react": "^5.1.1",
"autoprefixer": "^10.4.23",
"eslint": "^9.39.1",
"eslint-plugin-react-hooks": "^7.0.1",
"eslint-plugin-react-refresh": "^0.4.24",
"globals": "^16.5.0",
"postcss": "^8.5.6",
"tailwindcss": "^4.1.18",
"typescript": "~5.9.3",
"typescript-eslint": "^8.46.4",
"vite": "^7.2.4"
}
}

6
postcss.config.js Normal file
View File

@ -0,0 +1,6 @@
export default {
plugins: {
'@tailwindcss/postcss': {},
autoprefixer: {},
},
}

View File

@ -0,0 +1,246 @@
{
"ambiente": "prafrot",
"label": "Prafrot (Prafrota)",
"recursoBase": "/cadastro_frota",
"rotas": [
{
"id": "cadastro_frota-listar",
"recurso": "cadastro_frota",
"operations": [
{
"method": "GET",
"path": "/cadastro_frota/apresentar",
"descricao": "Lista veículos cadastrados na frota",
"responseShape": [
{
"field": "idveiculo_frota",
"type": "number",
"description": "ID do veículo"
},
{
"field": "placa",
"type": "string",
"description": "Placa"
},
{
"field": "modelo",
"type": "string",
"description": "Modelo"
},
{
"field": "base",
"type": "string",
"description": "Unidade/Base"
},
{
"field": "motorista",
"type": "string",
"description": "Motorista"
},
{
"field": "status",
"type": "string",
"description": "Status"
}
],
"suggestedColumns": [
{
"field": "placa",
"header": "Placa",
"width": "100px"
},
{
"field": "modelo",
"header": "Modelo",
"width": "150px"
}
],
"filterDefs": [
{
"field": "placa",
"label": "Placa",
"type": "text"
}
]
},
{
"method": "GET",
"path": "/cadastro_frota/:id",
"descricao": "Detalhe de um veículo",
"responseShape": [
{
"field": "idveiculo_frota",
"type": "number",
"description": "ID"
},
{
"field": "placa",
"type": "string",
"description": "Placa"
}
]
},
{
"method": "POST",
"path": "/cadastro_frota",
"descricao": "Criar novo veículo",
"requestBody": [
{
"field": "placa",
"type": "string",
"required": true
},
{
"field": "modelo",
"type": "string",
"required": true
}
]
},
{
"method": "PUT",
"path": "/cadastro_frota/:id",
"descricao": "Atualizar veículo",
"requestBody": [
{
"field": "placa",
"type": "string",
"required": false
},
{
"field": "status",
"type": "string",
"required": false
}
]
}
]
},
{
"id": "manutencao_frota-listar",
"recurso": "manutencao_frota",
"operations": [
{
"method": "GET",
"path": "/manutencao_frota/apresentar",
"descricao": "Lista todas as manutenções",
"responseShape": [
{
"field": "idmanutencao_frota",
"type": "number",
"description": "ID manutenção"
},
{
"field": "placa",
"type": "string",
"description": "Placa"
},
{
"field": "oficina",
"type": "string",
"description": "Oficina"
},
{
"field": "status",
"type": "string",
"description": "Status"
}
],
"suggestedColumns": [
{
"field": "idmanutencao_frota",
"header": "ID",
"width": "80px"
},
{
"field": "placa",
"header": "PLACA",
"width": "100px"
}
],
"filterDefs": [
{
"field": "placa",
"label": "Placa",
"type": "text"
},
{
"field": "status",
"label": "Status",
"type": "select"
}
]
},
{
"method": "GET",
"path": "/manutencao_frota/:id",
"descricao": "Detalhe de uma manutenção",
"responseShape": [
{
"field": "idmanutencao_frota",
"type": "number",
"description": "ID"
},
{
"field": "placa",
"type": "string",
"description": "Placa"
}
]
},
{
"method": "POST",
"path": "/manutencao_frota",
"descricao": "Criar nova manutenção",
"requestBody": [
{
"field": "placa",
"type": "string",
"required": true
},
{
"field": "oficina",
"type": "string",
"required": true
}
]
},
{
"method": "PUT",
"path": "/manutencao_frota/:id",
"descricao": "Atualizar manutenção",
"requestBody": [
{
"field": "status",
"type": "string",
"required": false
}
]
}
]
},
{
"id": "disponibilidade_frota",
"recurso": "disponibilidade_frota",
"operations": [
{
"method": "GET",
"path": "/disponibilidade_frota/apresentar",
"descricao": "Lista disponibilidade",
"responseShape": [
{
"field": "placa",
"type": "string",
"description": "Placa"
},
{
"field": "disponivel",
"type": "boolean",
"description": "Disponível"
}
]
}
]
}
]
}

View File

@ -0,0 +1 @@
{"ambiente":"workspace","label":"Workspace","rotas":[{"id":"extrato-listar","recurso":"extrato","operations":[{"method":"GET","path":"/extrato/apresentar","descricao":"Extrato bancário; C=receitas, D=despesas","responseShape":[{"field":"idextrato","type":"number","description":"ID"},{"field":"data","type":"string","description":"Data"},{"field":"descricao","type":"string","description":"Descrição"},{"field":"valor","type":"number","description":"Valor"}],"suggestedColumns":[{"field":"data","header":"Data","width":"120px"},{"field":"descricao","header":"Descrição","width":"400px"},{"field":"valor","header":"Valor","width":"150px"}]}]},{"id":"categorias-listar","recurso":"categorias","operations":[{"method":"GET","path":"/categorias/apresentar","descricao":"Lista categorias","responseShape":[{"field":"id","type":"number","description":"ID"},{"field":"nome","type":"string","description":"Nome"}]}]},{"id":"caixinhas-listar","recurso":"caixinhas","operations":[{"method":"GET","path":"/caixinhas/apresentar","descricao":"Lista caixinhas","responseShape":[{"field":"id","type":"number","description":"ID"},{"field":"nome","type":"string","description":"Nome"}]}]},{"id":"contas_a_pagar-listar","recurso":"contas_a_pagar","operations":[{"method":"GET","path":"/contas_a_pagar/apresentar","descricao":"Contas a pagar","responseShape":[{"field":"id","type":"number","description":"ID"},{"field":"categoria","type":"string","description":"Categoria"},{"field":"valor","type":"number","description":"Valor"}]}]}]}

1
public/vite.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

40
refactor_gr_service.py Normal file
View File

@ -0,0 +1,40 @@
import re
import sys
def refactor_file(filepath):
with open(filepath, 'r', encoding='utf-8') as f:
content = f.read()
# Pattern to find:
# try {
# const response = await ...
# return ...
# } catch (error) {
# throw new Error(...) or throw error
# }
# This regex matches the try/catch block and replaces it with the inner code
# It accounts for indentation and multi-line content
pattern = r'try\s*\{([\s\S]*?)\}\s*catch\s*\(error\)\s*\{[\s\S]*?\}'
def replacement(match):
inner_code = match.group(1)
# Strip one level of indentation (usually 2 spaces)
lines = inner_code.split('\n')
new_lines = []
for line in lines:
if line.startswith(' '):
new_lines.append(line[2:])
elif line.startswith(' '):
new_lines.append(line[2:])
else:
new_lines.append(line)
return '\n'.join(new_lines).strip()
new_content = re.sub(pattern, replacement, content)
with open(filepath, 'w', encoding='utf-8') as f:
f.write(new_content)
if __name__ == "__main__":
refactor_file(sys.argv[1])

110
scripts/auto-sync-routes.js Normal file
View File

@ -0,0 +1,110 @@
import fs from 'fs';
import path from 'path';
import https from 'https';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
/**
* AUTO-SYNC AGENT FOR ROUTE DOCUMENTATION
*/
const CONTRATOS_DIR = path.join(__dirname, '../src/features/dev-tools/data/contratos');
const MONITORED_ROUTES = [
{ env: 'prafrot', path: '/cadastro_frota/apresentar', method: 'GET', resource: 'cadastro_frota' },
{ env: 'prafrot', path: '/motoristas/listagem', method: 'GET', resource: 'motoristas' },
{ env: 'prafrot', path: '/dispatcher/apresentar', method: 'GET', resource: 'dispatcher' },
{ env: 'prafrot', path: '/oficinas_frota/apresentar', method: 'GET', resource: 'oficinas_frota' },
{ env: 'prafrot', path: '/monitoramento_frota/apresentar', method: 'GET', resource: 'monitoramento_frota' },
{ env: 'prafrot', path: '/status_frota/apresentar', method: 'GET', resource: 'status_frota' },
{ env: 'prafrot', path: '/manutencao_frota/apresentar', method: 'GET', resource: 'manutencao_frota' },
{ env: 'prafrot', path: '/sinistro_devolucao_venda_frota/apresentar', method: 'GET', resource: 'sinistro_devolucao_venda_frota' },
{ env: 'workspace', path: '/extrato/apresentar', method: 'GET', resource: 'extrato' },
{ env: 'workspace', path: '/categorias/apresentar', method: 'GET', resource: 'categorias' },
{ env: 'workspace', path: '/caixinhas/apresentar', method: 'GET', resource: 'caixinhas' },
{ env: 'workspace', path: '/contas_a_pagar/apresentar', method: 'GET', resource: 'contas_a_pagar' },
{ env: 'rh', path: '/colaboradores/apresentar', method: 'GET', resource: 'colaboradores' },
{ env: 'financeiro-v2', path: '/boletos/apresentar', method: 'GET', resource: 'boletos' },
{ env: 'gr', path: '/gr/contratos', method: 'GET', resource: 'contratos' },
];
function inferType(value) {
if (value === null) return 'object';
if (Array.isArray(value)) return 'array';
return typeof value;
}
function inferDescription(key, value) {
if (key.includes('data')) return 'Data';
if (typeof value === 'boolean' || (typeof value === 'string' && ['SIM', 'NÃO'].includes(value))) return "'SIM' ou 'NÃO' / Booleano";
if (value === null) return 'Pode ser null';
return '';
}
const MOCK_API_RESPONSES = {
'/cadastro_frota/apresentar': { "ano_fabricacao": "2", "idveiculo_frota": 3638, "placa": "ABC1234", "geotab": "SIM" },
'/motoristas/listagem': { "NOME_FAVORECIDO": "ACAUAN DUQUE", "idfavorecido": 1 },
'/dispatcher/apresentar': { "nome": "Rafael", "email": "rafael@pralog.com.br" },
'/oficinas_frota/apresentar': { "razao_social": "REPECOL LTDA", "idoficinas_frota": 2 },
'/monitoramento_frota/apresentar': { "placa": "XYZ5678", "idmonitoramento_frota": 738 },
'/status_frota/apresentar': { "status_frota": "Em Trânsito", "idstatus_frota": 2412 },
'/manutencao_frota/apresentar': { "oficina": "D CARROS CENTER", "idmanutencao_frota": 13176 },
'/sinistro_devolucao_venda_frota/apresentar': { "status": "Desmobilizado", "idsinistro_devolucao_frota": 871 },
'/extrato/apresentar': { "idextrato": 101, "descricao": "Venda Loja", "valor": 1500.50 },
'/categorias/apresentar': { "id": 1, "nome": "Vendas" },
'/caixinhas/apresentar': { "id": 1, "nome": "Principal" },
'/contas_a_pagar/apresentar': { "id": 1, "valor": 500.00 },
'/colaboradores/apresentar': { "id": 1, "nome": "João Silva", "cargo": "Analista" },
'/boletos/apresentar': { "id": 1, "valor": 1200.00 },
'/gr/contratos': { "id": 1, "cliente": "Empresa X" }
};
async function updateDocs() {
console.log(`🤖 Agente Auto-Sync Iniciado`);
const ENVS = [...new Set(MONITORED_ROUTES.map(r => r.env))];
for (const envId of ENVS) {
const targetFile = path.join(CONTRATOS_DIR, `${envId}-routes.json`);
let contractData = { ambiente: envId, label: envId, rotas: [] };
try {
if (fs.existsSync(targetFile)) {
contractData = JSON.parse(fs.readFileSync(targetFile, 'utf8'));
}
} catch (e) { console.error(`Erro ao ler ${envId}:`, e); continue; }
const envRoutes = MONITORED_ROUTES.filter(r => r.env === envId);
console.log(`\n📂 Ambiente: ${envId.toUpperCase()}`);
for (const route of envRoutes) {
console.log(` ⚡ Rota: ${route.method} ${route.path}`);
const responseData = MOCK_API_RESPONSES[route.path];
if (!responseData) continue;
const newResponseShape = Object.entries(responseData).map(([key, value]) => ({
field: key,
type: inferType(value),
description: inferDescription(key, value)
})).sort((a, b) => a.field.localeCompare(b.field));
let routeEntry = contractData.rotas.find(r => r.recurso === route.resource);
if (!routeEntry) {
routeEntry = { id: `${route.resource}-auto`, recurso: route.resource, operations: [] };
contractData.rotas.push(routeEntry);
}
let operation = routeEntry.operations.find(op => op.path === route.path && op.method === route.method);
if (!operation) {
operation = { method: route.method, path: route.path, descricao: `Auto-gerado`, responseShape: [] };
routeEntry.operations.push(operation);
}
operation.responseShape = newResponseShape;
}
fs.writeFileSync(targetFile, JSON.stringify(contractData, null, 2), 'utf8');
}
console.log(`\n✅ Sincronização concluída!`);
}
updateDocs();

View File

@ -0,0 +1,29 @@
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const SRC_FILE = path.join(__dirname, '../src/features/dev-tools/data/contratos/prafrot-routes.json');
const DOC_FILE = path.join(__dirname, '../docs/contratos/prafrot-routes.json');
const srcData = JSON.parse(fs.readFileSync(SRC_FILE, 'utf8'));
const docData = JSON.parse(fs.readFileSync(DOC_FILE, 'utf8'));
// Merge operations from DOC into SRC where SRC only has GET
docData.rotas.forEach(docRoute => {
const srcRoute = srcData.rotas.find(r => r.recurso === docRoute.recurso);
if (srcRoute) {
docRoute.operations.forEach(docOp => {
const hasOp = srcRoute.operations.some(op => op.path === docOp.path && op.method === docOp.method);
if (!hasOp) {
console.log(`Merging ${docOp.method} ${docOp.path} into ${docRoute.recurso}`);
srcRoute.operations.push(docOp);
}
});
}
});
fs.writeFileSync(SRC_FILE, JSON.stringify(srcData, null, 2), 'utf8');
console.log('Merge complete!');

42
src/App.css Normal file
View File

@ -0,0 +1,42 @@
#root {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
}
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.react:hover {
filter: drop-shadow(0 0 2em #61dafbaa);
}
@keyframes logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
@media (prefers-reduced-motion: no-preference) {
a:nth-of-type(2) .logo {
animation: logo-spin infinite 20s linear;
}
}
.card {
padding: 2em;
}
.read-the-docs {
color: #888;
}

210
src/App.jsx Normal file
View File

@ -0,0 +1,210 @@
import { lazy, Suspense } from 'react';
import { BrowserRouter as Router, Routes, Route, Navigate, useLocation } from 'react-router-dom';
import { Toaster } from 'sonner';
import { PortalHome } from './features/portal/components/PortalHome.jsx';
import AuthProvider, { useAuthContext } from '@/components/shared/AuthProvider';
import { Building, Zap } from 'lucide-react';
import { LoadingOverlay } from '@/components/shared/LoadingOverlay';
import { useGlobalLoading } from '@/hooks/useGlobalLoading';
// Lazy loading feature components
const FleetLogin = lazy(() => import('@/features/fleet').then(m => ({ default: m.FleetLogin })));
const FleetDashboard = lazy(() => import('@/features/fleet').then(m => ({ default: m.FleetDashboard })));
const HRLogin = lazy(() => import('@/features/rh').then(m => ({ default: m.HRLogin })));
const HRDashboard = lazy(() => import('@/features/rh').then(m => ({ default: m.HRDashboard })));
const PontoPage = lazy(() => import('@/features/rh').then(m => ({ default: m.PontoPage })));
const RhRoutes = lazy(() => import('@/features/rh/routes').then(m => ({ default: m.RhRoutes })));
const LoginPage = lazy(() => import('@/features/auth/login/LoginPage').then(m => ({ default: m.LoginPage })));
const FinanceLogin = lazy(() => import('@/features/auth/login-finance/LoginPage').then(m => ({ default: m.LoginPage })));
const CnabLogin = lazy(() => import('@/features/auth/login-cnab/LoginPage').then(m => ({ default: m.LoginPage })));
const FleetV2App = lazy(() => import('@/features/fleet-v2').then(m => ({ default: m.FleetV2App })));
const FinanceiroV2App = lazy(() => import('@/features/financeiro-v2').then(m => ({ default: m.FinanceiroV2App })));
const PrafrotRoutes = lazy(() => import('@/features/prafrot/routes').then(m => ({ default: m.PrafrotRoutes })));
const PrafrotLogin = lazy(() => import('@/features/prafrot/views/LoginView'));
const TableDebug = lazy(() => import('@/features/prafrot/views/TableDebug'));
const PlaygroundView = lazy(() => import('@/features/dev-tools/views/PlaygroundView'));
const WorkspaceLayout = lazy(() => import('@/features/workspace/components/WorkspaceLayout.jsx').then(m => ({ default: m.WorkspaceLayout })));
const LoginView = lazy(() => import('@/features/workspace/views/LoginView.jsx').then(m => ({ default: m.LoginView })));
const WorkspaceGuard = lazy(() => import('@/features/workspace/components/WorkspaceGuard.jsx').then(m => ({ default: m.WorkspaceGuard })));
const CnabRoutes = lazy(() => import('@/features/financeiro-cnab/routes').then(m => ({ default: m.CnabRoutes })));
const GrRoutes = lazy(() => import('@/features/gr/routes').then(m => ({ default: m.GrRoutes })));
const GrLogin = lazy(() => import('@/features/gr/views/LoginView'));
const GrResetPassword = lazy(() => import('@/features/gr/views/ResetPasswordView'));
const ExternalDriverRegistration = lazy(() => import('@/features/gr/views/ExternalDriverRegistrationView').then(m => ({ default: m.ExternalDriverRegistrationView })));
const DriverPortalView = lazy(() => import('@/features/prafrot/views/DriverPortalView').then(m => ({ default: m.DriverPortalView })));
const AutoLabRoutes = lazy(() => import('@/features/autolab/routes').then(m => ({ default: m.AutoLabRoutes })));
const AutoLabLogin = lazy(() => import('@/features/autolab/views/AutoLabLoginView'));
const OestPanRoutes = lazy(() => import('@/features/Oest_Pan/routes').then(m => ({ default: m.OestPanRoutes })));
const OestPanLogin = lazy(() => import('@/features/Oest_Pan/views/LoginView'));
// Loading component
const PageLoader = () => (
<LoadingOverlay isLoading={true} message="Carregando Aplicação..." fullScreen variant="premium" />
);
/**
* Componente de proteção de rotas.
* Redireciona para o login se o usuário não estiver autenticado.
*/
const ProtectedRoute = ({ children, loginPath = '/plataforma/auth/login', environment = 'global' }) => {
const { user, loading, isAuthorized } = useAuthContext();
const location = useLocation();
if (loading) return <PageLoader />;
// Verifica autorização - isAuthorized já verifica o usuário do módulo específico
if (!isAuthorized(environment)) {
return <Navigate to={loginPath} state={{ from: location }} replace />;
}
return children;
};
function App() {
return (
<AuthProvider>
<Toaster position="top-right" richColors closeButton />
<LoadingOverlayWrapper />
<Router>
<Suspense fallback={<PageLoader />}>
<Routes>
{/* Portal Home - System Selection */}
<Route path="/plataforma/" element={<PortalHome />} />
{/* 🔧 COMPONENT LABORATORY - Design System Testing */}
<Route path="/plataforma/debug/playground" element={
<Suspense fallback={<PageLoader />}>
<PlaygroundView />
</Suspense>
} />
{/* Auth Login - Explícitos */}
<Route path="/plataforma/auth/login" element={<LoginPage />} />
<Route path="/plataforma/auth/login-finance" element={<FinanceLogin />} />
<Route path="/plataforma/auth/login-cnab" element={<CnabLogin />} />
{/* Fleet Management Management (Legacy) */}
<Route path="/plataforma/fleet">
<Route path="login" element={<FleetLogin />} />
<Route path="dashboard" element={
<ProtectedRoute loginPath="/plataforma/fleet/login" environment="fleet">
<FleetDashboard />
</ProtectedRoute>
} />
<Route index element={<Navigate to="/plataforma/fleet/login" replace />} />
</Route>
{/* HR Management (Modern) */}
<Route path="/plataforma/rh/*" element={<RhRoutes />} />
{/* Fleet V2 Environment - Protegido */}
<Route path="/plataforma/fleet-v2/*" element={
<ProtectedRoute loginPath="/plataforma/auth/login" environment="fleet">
<FleetV2App />
</ProtectedRoute>
} />
{/* Financeiro V2 Environment - Protegido */}
<Route path="/plataforma/financeiro-v2/*" element={
<ProtectedRoute loginPath="/plataforma/auth/login-finance" environment="financeiro">
<FinanceiroV2App />
</ProtectedRoute>
} />
{/* Prafrot Environment */}
<Route path="/plataforma/prafrot">
<Route path="login" element={<PrafrotLogin />} />
<Route path="*" element={
<ProtectedRoute loginPath="/plataforma/prafrot/login" environment="prafrot">
<PrafrotRoutes />
</ProtectedRoute>
} />
<Route index element={<Navigate to="/plataforma/prafrot/login" replace />} />
</Route>
<Route path="/plataforma/solicitacao-viagem" element={
<Suspense fallback={<PageLoader />}>
<DriverPortalView />
</Suspense>
} />
{/* GR Environment (Gestão de Risco) */}
<Route path="/plataforma/gr">
<Route path="login" element={<GrLogin />} />
<Route path="reset-senha" element={<GrResetPassword />} />
<Route path="*" element={
<ProtectedRoute loginPath="/plataforma/gr/login" environment="gr">
<GrRoutes />
</ProtectedRoute>
} />
<Route index element={<Navigate to="/plataforma/gr/login" replace />} />
</Route>
{/* Workspace Environment - Novo Ambiente Modernizado */}
<Route path="/plataforma/workspace/login" element={<LoginView />} />
<Route path="/plataforma/workspace" element={
<WorkspaceGuard>
<WorkspaceLayout />
</WorkspaceGuard>
} />
<Route path="/plataforma/workspace/*" element={
<WorkspaceGuard>
<WorkspaceLayout />
</WorkspaceGuard>
} />
{/* Financeiro CNAB Environment */}
<Route path="/plataforma/financeiro-cnab/*" element={
<ProtectedRoute loginPath="/plataforma/auth/login-cnab" environment="financeiro">
<CnabRoutes />
</ProtectedRoute>
} />
{/* Auto Lab Environment */}
<Route path="/plataforma/autolab">
<Route path="login" element={<AutoLabLogin />} />
<Route path="*" element={
<ProtectedRoute loginPath="/plataforma/autolab/login" environment="autolab">
<AutoLabRoutes />
</ProtectedRoute>
} />
<Route index element={<Navigate to="/plataforma/autolab/login" replace />} />
</Route>
{/* Oeste Pan Environment */}
<Route path="/plataforma/oest-pan">
<Route path="login" element={<OestPanLogin />} />
<Route path="*" element={
<ProtectedRoute loginPath="/plataforma/oest-pan/login" environment="auth_oestepan">
<OestPanRoutes />
</ProtectedRoute>
} />
<Route index element={<Navigate to="/plataforma/oest-pan/login" replace />} />
</Route>
{/* Fallback */}
<Route path="*" element={<Navigate to="/plataforma/" replace />} />
{/* GR Public Routes */}
<Route path="/plataforma/cadastro-motorista" element={
<Suspense fallback={<PageLoader />}>
<ExternalDriverRegistration />
</Suspense>
} />
</Routes>
</Suspense>
</Router>
</AuthProvider>
);
}
// Wrapper component to use the hook inside the provider context if needed,
// though here it's at the top level so we just need to import the store.
const LoadingOverlayWrapper = () => {
const { isLoading, loadingMessage } = useGlobalLoading();
return <LoadingOverlay isLoading={isLoading} message={loadingMessage} fullScreen />;
};
export default App;

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,93 @@
Copyright (c) 2010-2014 by tyPoland Lukasz Dziedzic (team@latofonts.com) with Reserved Font Name "Lato"
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://openfontlicense.org
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Some files were not shown because too many files have changed in this diff Show More