feat(contratos): sistema completo de contratos odontológicos

- Tabelas contratos e contrato_itens com migrações automáticas
- Endpoints CRUD com itens em transação
- ContratosView: listagem, filtro por status, cards, stats
- ContratoModal: wizard 3 abas (Dados/Itens/Cláusulas), catálogo de
  procedimentos, DnD para reordenar, financeiro completo, print A4
- Sidebar: novo item CONTRATOS
- App.tsx: nova rota /contratos com permissões dentista/funcionario
- PatientsView: botão CONTRATOS no menu financeiro

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
VPS 4 Builder
2026-05-14 20:04:57 +02:00
parent d6d2bc1e78
commit d064aa9058
12 changed files with 2178 additions and 9 deletions
+4 -3
View File
@@ -1,7 +1,7 @@
import React from 'react';
import {
Users, Calendar as CalendarIcon, LayoutDashboard, Stethoscope,
DollarSign, RefreshCw, Database, Activity, BookOpen, Award, Megaphone, LogOut, ClipboardList, Bell, Building2, User, BarChart3, Settings
DollarSign, RefreshCw, Database, Activity, BookOpen, Award, Megaphone, LogOut, ClipboardList, Bell, Building2, User, BarChart3, Settings, FileText
} from 'lucide-react';
import { HybridBackend } from '../services/backend.ts';
@@ -27,6 +27,7 @@ export const Sidebar: React.FC<SidebarProps> = ({ activeTab, setActiveTab }) =>
{ id: 'agenda', label: 'AGENDA', icon: CalendarIcon },
{ id: 'ortodontia', label: 'ORTODONTIA', icon: Activity },
{ id: 'financeiro', label: 'FINANCEIRO', icon: DollarSign },
{ id: 'contratos', label: 'CONTRATOS', icon: FileText },
{ id: 'relatorios', label: 'RELATÓRIOS', icon: BarChart3 },
{ id: 'dentistas', label: 'DENTISTAS', icon: Stethoscope },
{ id: 'especialidades', label: 'ESPECIALIDADES', icon: Award },
@@ -38,8 +39,8 @@ export const Sidebar: React.FC<SidebarProps> = ({ activeTab, setActiveTab }) =>
].filter(item => {
if (['admin', 'donoclinica'].includes(currentRole)) return true;
if (currentRole === 'paciente') return ['tratamentos', 'notificacoes', 'configuracoes'].includes(item.id);
if (currentRole === 'dentista') return ['dashboard', 'pacientes', 'tratamentos', 'agenda', 'ortodontia', 'notificacoes', 'clinicas', 'configuracoes'].includes(item.id);
if (currentRole === 'funcionario') return ['dashboard', 'leads', 'pacientes', 'tratamentos', 'lancar-gto', 'agenda', 'financeiro', 'relatorios', 'notificacoes', 'clinicas', 'configuracoes'].includes(item.id);
if (currentRole === 'dentista') return ['dashboard', 'pacientes', 'tratamentos', 'agenda', 'ortodontia', 'notificacoes', 'clinicas', 'configuracoes', 'contratos'].includes(item.id);
if (currentRole === 'funcionario') return ['dashboard', 'leads', 'pacientes', 'tratamentos', 'lancar-gto', 'agenda', 'financeiro', 'relatorios', 'notificacoes', 'clinicas', 'configuracoes', 'contratos'].includes(item.id);
return false;
});