Compare commits
No commits in common. "main" and "Cliente/OestPan" have entirely different histories.
main
...
Cliente/Oe
|
|
@ -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.
|
||||
|
|
@ -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."
|
||||
|
|
@ -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()
|
||||
|
|
@ -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."
|
||||
}
|
||||
}
|
||||
|
|
@ -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."
|
||||
}
|
||||
}
|
||||
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
@ -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"
|
||||
}
|
||||
]
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
```
|
||||
|
|
@ -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(', '));
|
||||
|
|
@ -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`);
|
||||
}
|
||||
|
|
@ -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`);
|
||||
|
|
@ -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`);
|
||||
|
|
@ -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`);
|
||||
|
|
@ -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);
|
||||
|
|
@ -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);
|
||||
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
|
@ -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`.
|
||||
|
|
@ -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;
|
||||
|
|
@ -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.
|
||||
|
|
@ -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".
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"setup-worktree": [
|
||||
"npm install"
|
||||
]
|
||||
}
|
||||
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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/
|
||||
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
@ -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**
|
||||
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
|
@ -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.**"
|
||||
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
|
@ -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`.
|
||||
|
|
@ -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]
|
||||
|
|
@ -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 ==="
|
||||
|
|
@ -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": {}
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
|
@ -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!**
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,221 @@
|
|||
# Padrões de Rotas de Apresentação (Back–Front)
|
||||
|
||||
**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.
|
||||
|
|
@ -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.
|
||||
|
|
@ -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)
|
||||
|
|
@ -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.
|
||||
|
|
@ -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": {},
|
||||
...
|
||||
}
|
||||
```
|
||||
|
|
@ -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" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -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" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -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.*
|
||||
|
|
@ -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.*
|
||||
|
|
@ -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,
|
||||
},
|
||||
},
|
||||
])
|
||||
|
|
@ -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}")
|
||||
|
|
@ -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)
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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>
|
||||
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
export default {
|
||||
plugins: {
|
||||
'@tailwindcss/postcss': {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
||||
|
|
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -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"}]}]}]}
|
||||
|
|
@ -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 |
|
|
@ -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])
|
||||
|
|
@ -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();
|
||||
|
|
@ -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!');
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
@ -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.
|
||||
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 7.2 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 17 KiB |