import { useEffect, useMemo, useState } from 'react' import { FeatureCallout } from '../components/FeatureState.jsx' import { medicalRecordRepository } from '../repositories/medicalRecordRepository.js' import { patientRepository } from '../repositories/patientRepository.js' import { reportRepository } from '../repositories/reportRepository.js' const inputClass = 'h-10 w-full rounded-lg border border-[#404040] bg-[#1a1a1a] px-3 text-sm text-[#e5e5e5] outline-none transition placeholder:text-[#a3a3a3] focus:border-[#3b82f6] focus:ring-1 focus:ring-[#3b82f6]' const textareaClass = 'min-h-28 w-full rounded-lg border border-[#404040] bg-[#1a1a1a] px-3 py-2 text-sm leading-6 text-[#e5e5e5] outline-none transition placeholder:text-[#a3a3a3] focus:border-[#3b82f6] focus:ring-1 focus:ring-[#3b82f6]' const labelClass = 'mb-1 block text-xs font-medium text-[#e5e5e5]' const cardClass = 'rounded-2xl border border-[#404040] bg-[#262626] shadow-sm' const emptyRecord = { patientId: '', patient: '', patientDocument: '', patientEmail: '', patientPhone: '', dateTime: '', doctor: '', type: 'Primeira Consulta', cid: '', status: 'completo', diagnosticReasoning: '', diagnosticHypotheses: '', definitiveDiagnosis: '', prescriptions: '', procedures: '', surgeries: '', orientations: '', labResults: '', imageResults: '', multiprofessionalNotes: '', signature: '', professionalStamp: '', } const requiredFields = [ ['patient', 'paciente'], ['dateTime', 'data e hora'], ['doctor', 'profissional'], ['cid', 'CID ou referência diagnóstica'], ['diagnosticReasoning', 'raciocínio médico'], ['diagnosticHypotheses', 'hipóteses diagnósticas'], ['definitiveDiagnosis', 'diagnóstico definitivo'], ['prescriptions', 'prescrição médica'], ['procedures', 'procedimentos realizados'], ['surgeries', 'cirurgias'], ['orientations', 'orientações'], ['labResults', 'laudos laboratoriais'], ['imageResults', 'laudos de imagem'], ['multiprofessionalNotes', 'notas multiprofissionais'], ['signature', 'assinatura/carimbo'], ['professionalStamp', 'carimbo profissional'], ] export function MedicalRecordsPage({ navigate, mode = 'list', recordId = '' }) { const recordTypes = medicalRecordRepository.getRecordTypes() const [records, setRecords] = useState(() => medicalRecordRepository.getAll()) const [patients, setPatients] = useState([]) const [search, setSearch] = useState('') useEffect(() => { let active = true patientRepository .getDirectoryRows() .then((data) => { if (active) setPatients(data || []) }) .catch(() => { if (active) setPatients([]) }) return () => { active = false } }, []) const filteredRecords = useMemo(() => { const query = normalizeSearch(search) return records.filter((record) => { if (!query) return true return normalizeSearch([record.patient, record.cid, record.doctor, record.type, record.summary].join(' ')).includes(query) }) }, [records, search]) const selectedRecord = records.find((record) => String(record.id) === String(recordId)) || null const selectedPatient = selectedRecord ? findPatient(patients, selectedRecord) : null function refreshRecords() { setRecords(medicalRecordRepository.getAll()) } function handleCreateRecord(data) { const created = medicalRecordRepository.create(data) refreshRecords() navigate(`/prontuario/${created.id}`) } function handleUpdateRecord(data) { const updated = medicalRecordRepository.update(recordId, data) refreshRecords() navigate(`/prontuario/${updated?.id || recordId}`) } if (mode === 'new') { return ( ) } if (mode === 'edit') { return selectedRecord ? ( ) : ( ) } if (mode === 'detail') { return selectedRecord ? ( ) : ( ) } return (

Prontuário Médico

Registros cronológicos, diagnósticos, condutas e resultados de exames

setSearch(event.target.value)} placeholder="Buscar por paciente, CID, médico ou tipo de registro..." value={search} />
{filteredRecords.length ? ( filteredRecords.map((record) => ( navigate(`/prontuario/${record.id}/editar`)} onOpen={() => navigate(`/prontuario/${record.id}`)} onPrint={() => printRecordAsPdf(record)} record={record} /> )) ) : (
Nenhum registro encontrado nos dados locais.
)}
) } function RecordCard({ onEdit, onOpen, onPrint, record }) { const statusClass = record.status === 'completo' ? 'bg-emerald-500/20 text-emerald-400' : 'bg-amber-500/20 text-amber-400' return (

{record.patient}

{record.status === 'completo' ? 'Completo' : 'Rascunho'}
{formatDateTime(record.dateTime)} {record.doctor} {record.type}

{record.cid}

{record.summary}

) } function RecordDetailPage({ navigate, patient, record }) { const [reports, setReports] = useState(() => medicalRecordRepository.getMockReportHistory(record.patientId, record.patient)) useEffect(() => { let active = true loadReportsForPatient(record.patientId, record.patient).then((data) => { if (active) setReports(data) }) return () => { active = false } }, [record.patientId, record.patient]) const chronology = buildChronology(record, reports) return (

Prontuário de {record.patient}

Registro cronológico inverso com assinatura profissional e histórico contínuo.

) } function RecordEditorPage({ navigate, onSave, patients, record, recordTypes }) { const [patientSearch, setPatientSearch] = useState(record?.patient || '') const [formData, setFormData] = useState(() => ({ ...emptyRecord, dateTime: toDateTimeLocal(new Date()), doctor: 'Dr. Henrique Cardoso', signature: 'Dr. Henrique Cardoso - CRM não informado', professionalStamp: 'Assinado digitalmente por Dr. Henrique Cardoso', ...record, })) const filteredPatients = useMemo(() => { const query = normalizeSearch(patientSearch) if (!query) return patients.slice(0, 8) return patients .filter((patient) => normalizeSearch([patient.name, patient.full_name, patient.nome, patient.cpf, patient.document, patient.email].filter(Boolean).join(' ')).includes(query), ) .slice(0, 8) }, [patientSearch, patients]) function updateField(event) { const { name, value } = event.target setFormData((currentData) => ({ ...currentData, [name]: value })) } function selectPatient(patient) { const patientName = getPatientName(patient) setPatientSearch(patientName) setFormData((currentData) => ({ ...currentData, patientId: String(patient.id || ''), patient: patientName, patientDocument: patient.document || patient.cpf || '', patientEmail: patient.email || '', patientPhone: patient.phone || patient.phone_mobile || patient.telefone || '', })) } function handleSubmit(event) { event.preventDefault() const missing = requiredFields.filter(([field]) => !String(formData[field] || '').trim()) if (missing.length) { alert(`Preencha os campos obrigatórios: ${missing.map(([, label]) => label).join(', ')}.`) return } const summary = formData.definitiveDiagnosis || formData.diagnosticReasoning onSave({ ...formData, summary, date: formatDateTime(formData.dateTime), }) } return (

{record ? 'Editar prontuário' : 'Novo prontuário'}

Preencha os dados clínicos, legais e multiprofissionais obrigatórios do registro.

{ setPatientSearch(event.target.value) setFormData((currentData) => ({ ...currentData, patientId: '', patient: event.target.value })) }} placeholder="Buscar paciente..." type="search" value={patientSearch} />