"use client"; import React, { useState, useRef, useEffect } from "react"; import SignatureCanvas from "react-signature-canvas"; import Link from "next/link"; import ProtectedRoute from "@/components/ProtectedRoute"; import { useAuth } from "@/hooks/useAuth"; import { listarPacientes, buscarPacientePorId, type Paciente } from "@/lib/api"; import { useReports } from "@/hooks/useReports"; import { CreateReportData } from "@/types/report-types"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Textarea } from "@/components/ui/textarea"; import { SimpleThemeToggle } from "@/components/simple-theme-toggle"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar" import { User, FolderOpen, X, Users, MessageSquare, ClipboardList, Plus, Edit, Trash2, ChevronLeft, ChevronRight, Clock, FileCheck, Upload, Download, Eye, History, Stethoscope, Pill, Activity, Search } from "lucide-react" import { Calendar as CalendarIcon, FileText, Settings } from "lucide-react"; const pacientes = [ { nome: "Ana Souza", cpf: "123.456.789-00", idade: 42, statusLaudo: "Finalizado" }, { nome: "Bruno Lima", cpf: "987.654.321-00", idade: 33, statusLaudo: "Pendente" }, { nome: "Carla Menezes", cpf: "111.222.333-44", idade: 67, statusLaudo: "Rascunho" }, ]; const medico = { nome: "Dr. Carlos Andrade", identificacao: "CRM 000000 • Cardiologia e Dermatologia", fotoUrl: "", } const colorsByType = { Rotina: "#4dabf7", Cardiologia: "#f76c6c", Otorrino: "#f7b84d", Pediatria: "#6cf78b", Dermatologia: "#9b59b6", Oftalmologia: "#2ecc71" }; const ProfissionalPage = () => { const { logout, user } = useAuth(); const [activeSection, setActiveSection] = useState('calendario'); const [pacienteSelecionado, setPacienteSelecionado] = useState(null); // Estados para edição de laudo const [isEditingLaudoForPatient, setIsEditingLaudoForPatient] = useState(false); const [patientForLaudo, setPatientForLaudo] = useState(null); // Estados para o perfil do médico const [isEditingProfile, setIsEditingProfile] = useState(false); const [profileData, setProfileData] = useState({ nome: "Dr. Carlos Andrade", email: user?.email || "carlos.andrade@hospital.com", telefone: "(11) 99999-9999", endereco: "Rua das Flores, 123 - Centro", cidade: "São Paulo", cep: "01234-567", crm: "CRM 000000", especialidade: "Cardiologia e Dermatologia", biografia: "Médico especialista em cardiologia e dermatologia com mais de 15 anos de experiência em tratamentos clínicos e cirúrgicos." }); // Estados para relatórios médicos const [relatorioMedico, setRelatorioMedico] = useState({ pacienteNome: "", pacienteCpf: "", pacienteIdade: "", profissionalNome: medico.nome, profissionalCrm: medico.identificacao, motivoRelatorio: "", historicoClinico: "", sinaisSintomas: "", examesRealizados: "", resultadosExames: "", diagnosticos: "", prognostico: "", tratamentosRealizados: "", recomendacoes: "", cid: "", dataRelatorio: new Date().toISOString().split('T')[0] }); const [relatoriosMedicos, setRelatoriosMedicos] = useState([]); const [editandoRelatorio, setEditandoRelatorio] = useState(null); // Estados para integração com API de Relatórios const [pacientesReais, setPacientesReais] = useState([]); const [carregandoPacientes, setCarregandoPacientes] = useState(false); const [pacienteSelecionadoReport, setPacienteSelecionadoReport] = useState(null); // Hook personalizado para relatórios const reportsApi = useReports(); // Estados para funcionalidades do prontuário const [consultasRegistradas, setConsultasRegistradas] = useState([]); const [abaProntuarioAtiva, setAbaProntuarioAtiva] = useState('nova-consulta'); // Estados para campos principais da consulta const [consultaAtual, setConsultaAtual] = useState({ dataConsulta: new Date().toISOString().split('T')[0], anamnese: "", exameFisico: "", hipotesesDiagnosticas: "", condutaMedica: "", prescricoes: "", retornoAgendado: "", cid10: "" }); const [events, setEvents] = useState([ { id: 1, title: "Ana Souza", type: "Cardiologia", time: "09:00", date: new Date().toISOString().split('T')[0], pacienteId: "123.456.789-00", color: colorsByType.Cardiologia }, { id: 2, title: "Bruno Lima", type: "Cardiologia", time: "10:30", date: new Date().toISOString().split('T')[0], pacienteId: "987.654.321-00", color: colorsByType.Cardiologia }, { id: 3, title: "Carla Menezes", type: "Dermatologia", time: "14:00", date: new Date().toISOString().split('T')[0], pacienteId: "111.222.333-44", color: colorsByType.Dermatologia } ]); const [editingEvent, setEditingEvent] = useState(null); const [showPopup, setShowPopup] = useState(false); const [showActionModal, setShowActionModal] = useState(false); const [step, setStep] = useState(1); const [newEvent, setNewEvent] = useState({ title: "", type: "", time: "", pacienteId: "" }); const [selectedDate, setSelectedDate] = useState(null); const [selectedEvent, setSelectedEvent] = useState(null); const [currentCalendarDate, setCurrentCalendarDate] = useState(new Date()); const handleSave = (event: React.MouseEvent) => { event.preventDefault(); console.log("Laudo salvo!"); window.scrollTo({ top: 0, behavior: "smooth" }); }; const handleAbrirProntuario = (paciente: any) => { setPacienteSelecionado(paciente); const pacienteLaudo = document.getElementById('pacienteLaudo') as HTMLInputElement; if (pacienteLaudo) pacienteLaudo.value = paciente.nome; const destinatario = document.getElementById('destinatario') as HTMLInputElement; if (destinatario) destinatario.value = `${paciente.nome} - ${paciente.cpf}`; const prontuarioSection = document.getElementById('prontuario-paciente'); if (prontuarioSection) { prontuarioSection.scrollIntoView({ behavior: 'smooth' }); } }; const handleFecharProntuario = () => { setPacienteSelecionado(null); }; const navigateDate = (direction: 'prev' | 'next') => { const newDate = new Date(currentCalendarDate); newDate.setDate(newDate.getDate() + (direction === 'next' ? 1 : -1)); setCurrentCalendarDate(newDate); }; const goToToday = () => { setCurrentCalendarDate(new Date()); }; const formatDate = (date: Date) => { return date.toLocaleDateString('pt-BR', { weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' }); }; // Filtrar eventos do dia atual const getTodayEvents = () => { const today = currentCalendarDate.toISOString().split('T')[0]; return events .filter(event => event.date === today) .sort((a, b) => a.time.localeCompare(b.time)); }; const getStatusColor = (type: string) => { return colorsByType[type as keyof typeof colorsByType] || "#4dabf7"; }; // Funções para o perfil const handleProfileChange = (field: string, value: string) => { setProfileData(prev => ({ ...prev, [field]: value })); }; const handleSaveProfile = () => { setIsEditingProfile(false); alert('Perfil atualizado com sucesso!'); }; const handleCancelEdit = () => { setIsEditingProfile(false); }; // Funções para relatórios médicos const handleRelatorioChange = (field: string, value: string) => { setRelatorioMedico(prev => ({ ...prev, [field]: value })); }; const handleSalvarRelatorio = () => { if (!relatorioMedico.pacienteNome || !relatorioMedico.motivoRelatorio) { alert('Por favor, preencha pelo menos o nome do paciente e o motivo do relatório.'); return; } const novoRelatorio = { ...relatorioMedico, id: Date.now(), dataGeracao: new Date().toLocaleString() }; if (editandoRelatorio) { setRelatoriosMedicos(prev => prev.map(rel => rel.id === editandoRelatorio.id ? novoRelatorio : rel) ); setEditandoRelatorio(null); alert('Relatório médico atualizado com sucesso!'); } else { setRelatoriosMedicos(prev => [novoRelatorio, ...prev]); alert('Relatório médico salvo com sucesso!'); } // Limpar formulário setRelatorioMedico({ pacienteNome: "", pacienteCpf: "", pacienteIdade: "", profissionalNome: medico.nome, profissionalCrm: medico.identificacao, motivoRelatorio: "", historicoClinico: "", sinaisSintomas: "", examesRealizados: "", resultadosExames: "", diagnosticos: "", prognostico: "", tratamentosRealizados: "", recomendacoes: "", cid: "", dataRelatorio: new Date().toISOString().split('T')[0] }); }; const handleEditarRelatorio = (relatorio: any) => { setRelatorioMedico(relatorio); setEditandoRelatorio(relatorio); }; const handleExcluirRelatorio = (id: number) => { if (confirm('Tem certeza que deseja excluir este relatório médico?')) { setRelatoriosMedicos(prev => prev.filter(rel => rel.id !== id)); alert('Relatório médico excluído com sucesso!'); } }; const handleCancelarEdicaoRelatorio = () => { setEditandoRelatorio(null); setRelatorioMedico({ pacienteNome: "", pacienteCpf: "", pacienteIdade: "", profissionalNome: medico.nome, profissionalCrm: medico.identificacao, motivoRelatorio: "", historicoClinico: "", sinaisSintomas: "", examesRealizados: "", resultadosExames: "", diagnosticos: "", prognostico: "", tratamentosRealizados: "", recomendacoes: "", cid: "", dataRelatorio: new Date().toISOString().split('T')[0] }); }; // ===== FUNÇÕES PARA INTEGRAÇÃO COM API DE RELATÓRIOS ===== // Carregar pacientes reais do Supabase const carregarPacientesReais = async () => { setCarregandoPacientes(true); try { console.log('📋 [REPORTS] Carregando pacientes do Supabase...'); // Tentar primeiro usando a função da API que já existe try { console.log('📋 [REPORTS] Tentando função listarPacientes...'); const pacientes = await listarPacientes({ limit: 50 }); console.log('✅ [REPORTS] Pacientes do Supabase via API:', pacientes); if (pacientes && pacientes.length > 0) { setPacientesReais(pacientes); console.log('✅ [REPORTS] Usando pacientes do Supabase:', pacientes.length); return; } } catch (apiError) { console.warn('⚠️ [REPORTS] Erro na função listarPacientes:', apiError); } // Se a função da API falhar, tentar diretamente console.log('📋 [REPORTS] Tentando buscar diretamente do Supabase...'); const supabaseUrl = 'https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/patients'; console.log('📋 [REPORTS] URL do Supabase:', supabaseUrl); // Verificar se há token de autenticação const token = localStorage.getItem("auth_token") || localStorage.getItem("token") || sessionStorage.getItem("auth_token") || sessionStorage.getItem("token"); console.log('🔑 [REPORTS] Token encontrado:', token ? 'SIM' : 'NÃO'); const headers: Record = { 'apikey': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Inl1YW5xZnN3aGJlcmtvZXZ0bWZyIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NTQ5NTQzNjksImV4cCI6MjA3MDUzMDM2OX0.g8Fm4XAvtX46zifBZnYVH4tVuQkqUH6Ia9CXQj4DztQ', 'Accept': 'application/json', 'Content-Type': 'application/json' }; if (token) { headers['Authorization'] = `Bearer ${token}`; } const response = await fetch(supabaseUrl, { method: 'GET', headers }); console.log('📡 [REPORTS] Status da resposta do Supabase:', response.status, response.statusText); if (!response.ok) { const errorText = await response.text(); console.error('❌ [REPORTS] Erro detalhado do Supabase:', errorText); throw new Error(`Supabase HTTP ${response.status}: ${response.statusText} - ${errorText}`); } const data = await response.json(); console.log('✅ [REPORTS] Resposta completa do Supabase:', data); console.log('✅ [REPORTS] Tipo da resposta:', Array.isArray(data) ? 'Array' : typeof data); let pacientes: Paciente[] = []; if (Array.isArray(data)) { pacientes = data; } else if (data.data && Array.isArray(data.data)) { pacientes = data.data; } else { console.warn('⚠️ [REPORTS] Formato de resposta inesperado do Supabase:', data); pacientes = []; } console.log('✅ [REPORTS] Pacientes encontrados no Supabase:', pacientes.length); if (pacientes.length > 0) { console.log('✅ [REPORTS] Primeiro paciente:', pacientes[0]); console.log('✅ [REPORTS] Últimos 3 pacientes:', pacientes.slice(-3)); } setPacientesReais(pacientes); if (pacientes.length === 0) { console.warn('⚠️ [REPORTS] Nenhum paciente encontrado no Supabase - verifique se há dados na tabela patients'); } } catch (error) { console.error('❌ [REPORTS] Erro detalhado ao carregar pacientes:', { error, message: error instanceof Error ? error.message : String(error), stack: error instanceof Error ? error.stack : undefined }); setPacientesReais([]); alert('Erro ao carregar pacientes do Supabase: ' + (error instanceof Error ? error.message : String(error))); } finally { setCarregandoPacientes(false); } }; // Calcular idade do paciente baseado na data de nascimento const calcularIdade = (birthDate: string | null | undefined): string => { if (!birthDate) return ''; const hoje = new Date(); const nascimento = new Date(birthDate); let idade = hoje.getFullYear() - nascimento.getFullYear(); const mesAtual = hoje.getMonth(); const mesNascimento = nascimento.getMonth(); if (mesAtual < mesNascimento || (mesAtual === mesNascimento && hoje.getDate() < nascimento.getDate())) { idade--; } return idade.toString(); }; // Selecionar paciente para o relatório const selecionarPacienteParaRelatorio = (paciente: Paciente) => { setPacienteSelecionadoReport(paciente); // Atualizar o formulário de relatório com dados do paciente setRelatorioMedico(prev => ({ ...prev, pacienteNome: paciente.full_name, pacienteCpf: paciente.cpf || '', pacienteIdade: calcularIdade(paciente.birth_date), })); console.log('👤 [REPORTS] Paciente selecionado:', paciente); }; // Salvar relatório usando a API const salvarRelatorioAPI = async () => { if (!pacienteSelecionadoReport) { alert('Por favor, selecione um paciente.'); return; } if (!relatorioMedico.motivoRelatorio.trim()) { alert('Por favor, preencha o motivo do relatório.'); return; } try { console.log('💾 [REPORTS] Salvando relatório...'); // Dados para enviar à API const reportData: CreateReportData = { patient_id: pacienteSelecionadoReport.id, doctor_id: user?.id || 'temp-doctor-id', // Usar ID do usuário logado report_type: 'Relatório Médico', chief_complaint: relatorioMedico.motivoRelatorio, clinical_history: relatorioMedico.historicoClinico, symptoms_and_signs: relatorioMedico.sinaisSintomas, physical_examination: '', // Pode adicionar campo no formulário se necessário complementary_exams: relatorioMedico.examesRealizados, exam_results: relatorioMedico.resultadosExames, diagnosis: relatorioMedico.diagnosticos, prognosis: relatorioMedico.prognostico, treatment_performed: relatorioMedico.tratamentosRealizados, objective_recommendations: relatorioMedico.recomendacoes || '', icd_code: relatorioMedico.cid, report_date: relatorioMedico.dataRelatorio, }; const novoRelatorio = await reportsApi.createNewReport(reportData); console.log('✅ [REPORTS] Relatório salvo com sucesso:', novoRelatorio); // Recarregar a lista de relatórios para garantir que está sincronizada await reportsApi.loadReports(); alert('Relatório médico salvo com sucesso!'); // Limpar formulário limparFormularioRelatorio(); } catch (error) { console.error('❌ [REPORTS] Erro ao salvar relatório:', error); alert('Erro ao salvar relatório: ' + error); } }; // Limpar formulário de relatório const limparFormularioRelatorio = () => { setRelatorioMedico({ pacienteNome: "", pacienteCpf: "", pacienteIdade: "", profissionalNome: medico.nome, profissionalCrm: medico.identificacao, motivoRelatorio: "", historicoClinico: "", sinaisSintomas: "", examesRealizados: "", resultadosExames: "", diagnosticos: "", prognostico: "", tratamentosRealizados: "", recomendacoes: "", cid: "", dataRelatorio: new Date().toISOString().split('T')[0] }); setPacienteSelecionadoReport(null); }; // Carregar relatórios existentes const carregarRelatorios = async () => { try { await reportsApi.loadReports(); console.log('✅ [REPORTS] Relatórios carregados:', reportsApi.reports.length); } catch (error) { console.error('❌ [REPORTS] Erro ao carregar relatórios:', error); } }; // useEffect para carregar dados iniciais useEffect(() => { if (activeSection === 'relatorios-medicos') { console.log('🔄 [REPORTS] Seção de relatórios ativada - carregando dados...'); carregarPacientesReais(); carregarRelatorios(); } }, [activeSection]); // Buscar pacientes faltantes por patient_id após carregar relatórios e pacientes useEffect(() => { if (activeSection !== 'relatorios-medicos') return; if (!reportsApi.reports || reportsApi.reports.length === 0) return; // IDs de pacientes já carregados const idsPacientesReais = new Set(pacientesReais.map(p => String(p.id))); // IDs de pacientes presentes nos relatórios const idsRelatorios = Array.from(new Set(reportsApi.reports.map(r => String(r.patient_id)).filter(Boolean))); // IDs que faltam const idsFaltantes = idsRelatorios.filter(id => !idsPacientesReais.has(id)); if (idsFaltantes.length === 0) return; // Buscar pacientes faltantes individualmente, apenas se o ID for string/UUID (async () => { const novosPacientes: Paciente[] = []; for (const id of idsFaltantes) { // Só busca se for string e não for número if (typeof id === 'string' && isNaN(Number(id))) { try { const paciente = await buscarPacientePorId(id); if (paciente) novosPacientes.push(paciente); } catch (e) { console.warn('⚠️ [REPORTS] Paciente não encontrado para o relatório:', id); } } else { console.warn('⚠️ [REPORTS] Ignorando busca de paciente por ID não-string/UUID:', id); } } if (novosPacientes.length > 0) { setPacientesReais(prev => ([...prev, ...novosPacientes])); } })(); }, [activeSection, reportsApi.reports, pacientesReais]); const handleDateClick = (arg: any) => { setSelectedDate(arg.dateStr); setNewEvent({ title: "", type: "", time: "", pacienteId: "" }); setStep(1); setEditingEvent(null); setShowPopup(true); }; const handleAddEvent = () => { const paciente = pacientes.find(p => p.nome === newEvent.title); const eventToAdd = { id: Date.now(), title: newEvent.title, type: newEvent.type, time: newEvent.time, date: selectedDate || currentCalendarDate.toISOString().split('T')[0], pacienteId: paciente ? paciente.cpf : "", color: colorsByType[newEvent.type as keyof typeof colorsByType] || "#4dabf7" }; setEvents((prev) => [...prev, eventToAdd]); setShowPopup(false); }; const handleEditEvent = () => { setEvents((prevEvents) => prevEvents.map((ev) => ev.id.toString() === editingEvent.id.toString() ? { ...ev, title: newEvent.title, type: newEvent.type, time: newEvent.time, color: colorsByType[newEvent.type as keyof typeof colorsByType] || "#4dabf7" } : ev ) ); setEditingEvent(null); setShowPopup(false); setShowActionModal(false); }; const handleNextStep = () => { if (step < 3) setStep(step + 1); else editingEvent ? handleEditEvent() : handleAddEvent(); }; const handleEventClick = (clickInfo: any) => { setSelectedEvent(clickInfo.event); setShowActionModal(true); }; const handleDeleteEvent = () => { if (!selectedEvent) return; setEvents((prevEvents) => prevEvents.filter((ev: any) => ev.id.toString() !== selectedEvent.id.toString()) ); setShowActionModal(false); }; const handleStartEdit = () => { if (!selectedEvent) return; setEditingEvent(selectedEvent); setNewEvent({ title: selectedEvent.title, type: selectedEvent.extendedProps.type, time: selectedEvent.extendedProps.time, pacienteId: selectedEvent.extendedProps.pacienteId || "" }); setStep(1); setShowActionModal(false); setShowPopup(true); }; const renderCalendarioSection = () => { const todayEvents = getTodayEvents(); return (

Agenda do Dia

{/* Navegação de Data */}

{formatDate(currentCalendarDate)}

{todayEvents.length} consulta{todayEvents.length !== 1 ? 's' : ''} agendada{todayEvents.length !== 1 ? 's' : ''}
{/* Lista de Pacientes do Dia */}
{todayEvents.length === 0 ? (

Nenhuma consulta agendada para este dia

Agenda livre para este dia

) : ( todayEvents.map((appointment) => { const paciente = pacientes.find(p => p.nome === appointment.title); return (
{appointment.title}
{paciente && (
CPF: {paciente.cpf} • {paciente.idade} anos
)}
{appointment.time}
{appointment.type}
Ver informações do paciente
); }) )}
); }; function PacientesSection({ handleAbrirProntuario, setActiveSection, }: { handleAbrirProntuario: (paciente: any) => void; setActiveSection: (section: string) => void; }) { return (

Gerenciamento de Pacientes

{/* Tabela de pacientes padrão */}

Pacientes Recentes

Paciente CPF Idade Status do laudo Ações {pacientes.map((paciente) => ( {paciente.nome} {paciente.cpf} {paciente.idade} {paciente.statusLaudo}
Ver informações do paciente
))}
); }; const renderProntuarioSection = () => (

Prontuário do Paciente

{/* Informações do Paciente Selecionado */} {pacienteSelecionado && (

Dados do Paciente

Nome:

{pacienteSelecionado.nome}

CPF:

{pacienteSelecionado.cpf}

Idade:

{pacienteSelecionado.idade} anos

)} {/* Seletor de Paciente */} {!pacienteSelecionado && (

Selecionar Paciente

Escolha um paciente para visualizar o prontuário completo

{/* Cards de pacientes para seleção rápida */}

Ou selecione rapidamente:

{pacientes.map((paciente) => (
setPacienteSelecionado(paciente)} className="border rounded-lg p-4 hover:shadow-md hover:border-primary transition-all cursor-pointer group" >

{paciente.nome}

CPF: {paciente.cpf}

{paciente.idade} anos

{paciente.statusLaudo}
))}
)} {/* Tabs de Navegação do Prontuário */} {pacienteSelecionado && (
)} {/* Conteúdo das Abas */} {pacienteSelecionado && (
{abaProntuarioAtiva === 'nova-consulta' && renderNovaConsultaTab()} {abaProntuarioAtiva === 'consultas' && renderConsultasTab()} {abaProntuarioAtiva === 'historico' && renderHistoricoTab()} {abaProntuarioAtiva === 'prescricoes' && renderPrescricoesTab()} {abaProntuarioAtiva === 'exames' && renderExamesTab()} {abaProntuarioAtiva === 'diagnosticos' && renderDiagnosticosTab()} {abaProntuarioAtiva === 'evolucao' && renderEvolucaoTab()} {abaProntuarioAtiva === 'anexos' && renderAnexosTab()}
)}
); // Função para alterar campos da consulta atual const handleConsultaChange = (field: string, value: string) => { setConsultaAtual(prev => ({ ...prev, [field]: value })); }; // Função para salvar a consulta const handleSalvarConsulta = () => { if (!consultaAtual.anamnese || !consultaAtual.exameFisico) { alert('Por favor, preencha os campos que são obrigatórios.'); return; } const novaConsulta = { ...consultaAtual, id: Date.now(), paciente: pacienteSelecionado?.nome, dataCriacao: new Date().toLocaleString(), profissional: medico.nome }; setConsultasRegistradas(prev => [novaConsulta, ...prev]); setConsultaAtual({ dataConsulta: new Date().toISOString().split('T')[0], anamnese: "", exameFisico: "", hipotesesDiagnosticas: "", condutaMedica: "", prescricoes: "", retornoAgendado: "", cid10: "" }); alert('Consulta registrada com sucesso!'); }; // Funções para renderizar cada aba do prontuário const renderNovaConsultaTab = () => (

Registrar Nova Consulta

{/* Data da Consulta */}
handleConsultaChange('dataConsulta', e.target.value)} className="w-full" />
handleConsultaChange('cid10', e.target.value)} placeholder="Ex: I10, E11, etc." className="w-full" />
{/* Anamnese */}