feat(web): telas de Documentos e Ponto Eletrônico — cobertura completa do EDEN Core

Última leva desta sequência, sem parar para autorização. 2 subagentes
eden-frontend em paralelo.

- Documentos: templates com ciclo draft→publish (edição por texto com
  {{variavel}}, sem editor Tiptap real ainda), preview do HTML
  publicado, geração de documento com extração automática de variáveis
  via regex e aviso de missingVariables. Achado do agente corrigindo
  meu brief: regra de key aceita minúsculas+dígitos+underscore, não só
  minúsculas+underscore.
- Ponto Eletrônico (fundação): dispositivos Control iD (senha nunca
  retornada, só hasCredential), import de AFD com decodificação
  ISO-8859-1 explícita documentada no código, registros AFD só-leitura
  (sem nenhuma ação de edição — imutabilidade legal respeitada também
  na UI). 2 discrepâncias reais encontradas e corrigidas pelo agente:
  reimportar retorna 409 estruturado (não 200), e a listagem de
  registros é um envelope paginado (não array simples).

Reconciliação manual de App.tsx/AuthenticatedLayout.tsx entre os 2
agentes. Verificado: pnpm turbo run typecheck build (28/28); containers
eden-api/eden-core reconstruídos; testado ao vivo através do proxy
same-origin (porta 3001) incluindo confirmação de que a senha do
dispositivo nunca aparece na resposta; trilha de auditoria conferida.

Com esta leva, o EDEN Core tem UI real para todo o backend construído
nesta sessão, exceto Assinatura Eletrônica e apuração/fechamento de
ponto (nenhum dos dois existe no backend ainda).

Claude-Session: https://claude.ai/code/session_01BcWWuKfykGtUweXmHD6cKx

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-04 06:14:23 -03:00
parent 828e6e8ddb
commit 012c00fa4d
17 changed files with 2577 additions and 0 deletions

View File

@@ -44,6 +44,15 @@ import { OperationNaturesListPage } from "./routes/fiscal/OperationNaturesListPa
import { TicketsListPage } from "./routes/support/TicketsListPage.js";
import { TicketFormPage } from "./routes/support/TicketFormPage.js";
import { TicketDetailPage } from "./routes/support/TicketDetailPage.js";
import { TemplatesListPage } from "./routes/documents/TemplatesListPage.js";
import { TemplateFormPage } from "./routes/documents/TemplateFormPage.js";
import { TemplateDetailPage } from "./routes/documents/TemplateDetailPage.js";
import { GenerationsListPage } from "./routes/documents/GenerationsListPage.js";
import { GenerationFormPage } from "./routes/documents/GenerationFormPage.js";
import { DevicesListPage } from "./routes/hr-timeclock/DevicesListPage.js";
import { DeviceFormPage } from "./routes/hr-timeclock/DeviceFormPage.js";
import { AfdImportPage } from "./routes/hr-timeclock/AfdImportPage.js";
import { AfdRecordsListPage } from "./routes/hr-timeclock/AfdRecordsListPage.js";
export function App() {
return (
@@ -112,6 +121,18 @@ export function App() {
<Route path="/support/tickets" element={<TicketsListPage />} />
<Route path="/support/tickets/new" element={<TicketFormPage />} />
<Route path="/support/tickets/:id" element={<TicketDetailPage />} />
<Route path="/documents/templates" element={<TemplatesListPage />} />
<Route path="/documents/templates/new" element={<TemplateFormPage />} />
<Route path="/documents/templates/:id" element={<TemplateDetailPage />} />
<Route path="/documents/generations" element={<GenerationsListPage />} />
<Route path="/documents/generations/new" element={<GenerationFormPage />} />
<Route path="/hr-timeclock/devices" element={<DevicesListPage />} />
<Route path="/hr-timeclock/devices/new" element={<DeviceFormPage />} />
<Route path="/hr-timeclock/devices/:id/edit" element={<DeviceFormPage />} />
<Route path="/hr-timeclock/afd-imports" element={<AfdImportPage />} />
<Route path="/hr-timeclock/afd-records" element={<AfdRecordsListPage />} />
</Route>
</Route>
</Routes>