-
-
-
Laudo Médico
-
- {!pacienteSelecionado ? (
-
-
-
Selecionar Paciente
-
Escolha um paciente para visualizar o prontuário completo
-
-
-
-
-
-
-
-
-
-
- ) : (
-
-
-
{pacienteSelecionado.nome}
-
CPF: {pacienteSelecionado.cpf}
-
Idade: {pacienteSelecionado.idade}
-
Sexo: {pacienteSelecionado.sexo}
-
-
-
- )}
-
-
-
-
-
-
Histórico de Laudos
- {laudos.length === 0 ? (
-
Nenhum laudo registrado.
- ) : (
- laudos.map((laudo: any, idx: number) => (
-
-
-
-
Idade: {laudo.idade}
-
Sexo: {laudo.sexo}
-
Status: {laudo.status}
-
CID: {laudo.cid}
-
Data: {laudo.data}
-
- {laudo.assinatura && (
-
-
Assinatura Digital:
-

-
- )}
- {laudo.imagem && (
-
-
Imagem:
-

-
- )}
-
-
- ))
- )}
-
-
+
+ {
+ setIsEditingLaudoForPatient(false);
+ setPatientForLaudo(null);
+ }}
+ />
);
-}
+
+ // --- NOVO SISTEMA DE LAUDOS COMPLETO ---
+ function LaudoManager({ isEditingForPatient, selectedPatientForLaudo, onClosePatientEditor }: { isEditingForPatient?: boolean; selectedPatientForLaudo?: any; onClosePatientEditor?: () => void }) {
+ const [pacientesDisponiveis] = useState([
+ { id: "95170038", nome: "Ana Souza", cpf: "123.456.789-00", idade: 42, sexo: "Feminino" },
+ { id: "93203056", nome: "Bruno Lima", cpf: "987.654.321-00", idade: 33, sexo: "Masculino" },
+ { id: "92953542", nome: "Carla Menezes", cpf: "111.222.333-44", idade: 67, sexo: "Feminino" },
+ ]);
+
+ const [laudos] = useState([
+ {
+ id: "306494942",
+ data: "29/07/2025",
+ prazo: "29/07/2025",
+ paciente: { id: "95170038", nome: "Ana Souza", cpf: "123.456.789-00", idade: 42, sexo: "Feminino" },
+ executante: "Carlos Andrade",
+ exame: "Ecocardiograma",
+ status: "Entregue",
+ urgente: true,
+ especialidade: "Cardiologia",
+ conteudo: `**ECOCARDIOGRAMA TRANSTORÁCICO**
+
+**Dados do Paciente:**
+Nome: Ana Souza
+Idade: 42 anos
+Sexo: Feminino
+
+**Indicação Clínica:**
+Investigação de sopro cardíaco
+
+**Técnica:**
+Ecocardiograma transtorácico bidimensional com Doppler colorido e espectral.
+
+**Resultados:**
+- Átrio esquerdo: dimensões normais
+- Ventrículo esquerdo: função sistólica preservada, FEVE = 65%
+- Valvas cardíacas: sem alterações significativas
+- Pericárdio: sem derrame
+
+**Conclusão:**
+Exame ecocardiográfico dentro dos limites da normalidade.
+
+**CID:** I25.9`,
+ cid: "I25.9",
+ diagnostico: "Exame ecocardiográfico normal",
+ conclusao: "Função cardíaca preservada, sem alterações estruturais significativas."
+ },
+ {
+ id: "306463987",
+ data: "29/07/2025",
+ prazo: "29/07/2025",
+ paciente: { id: "93203056", nome: "Bruno Lima", cpf: "987.654.321-00", idade: 33, sexo: "Masculino" },
+ executante: "Carlos Andrade",
+ exame: "Eletrocardiograma",
+ status: "Entregue",
+ urgente: true,
+ especialidade: "Cardiologia",
+ conteudo: `**ELETROCARDIOGRAMA DE REPOUSO**
+
+**Dados do Paciente:**
+Nome: Bruno Lima
+Idade: 33 anos
+Sexo: Masculino
+
+**Indicação Clínica:**
+Dor precordial atípica
+
+**Técnica:**
+Eletrocardiograma de 12 derivações em repouso.
+
+**Resultados:**
+- Ritmo: sinusal regular
+- Frequência cardíaca: 72 bpm
+- Eixo elétrico: normal
+- Intervalos PR, QRS e QT: dentro dos limites normais
+- Ondas Q patológicas: ausentes
+- Alterações de ST-T: não observadas
+
+**Conclusão:**
+Eletrocardiograma normal.
+
+**CID:** Z01.8`,
+ cid: "Z01.8",
+ diagnostico: "ECG normal",
+ conclusao: "Traçado eletrocardiográfico dentro dos parâmetros de normalidade."
+ },
+ {
+ id: "306452545",
+ data: "29/07/2025",
+ prazo: "29/07/2025",
+ paciente: { id: "92953542", nome: "Carla Menezes", cpf: "111.222.333-44", idade: 67, sexo: "Feminino" },
+ executante: "Carlos Andrade",
+ exame: "Dermatoscopia",
+ status: "Entregue",
+ urgente: true,
+ especialidade: "Dermatologia",
+ conteudo: `**DERMATOSCOPIA DIGITAL**
+
+**Dados do Paciente:**
+Nome: Carla Menezes
+Idade: 67 anos
+Sexo: Feminino
+
+**Indicação Clínica:**
+Avaliação de lesão pigmentada em dorso
+
+**Técnica:**
+Dermatoscopia digital com magnificação de 10x e 20x.
+
+**Localização:**
+Região dorsal, região escapular direita
+
+**Achados Dermatoscópicos:**
+- Lesão melanocítica benigna
+- Padrão reticular típico
+- Bordas regulares e simétricas
+- Pigmentação homogênea
+- Ausência de estruturas atípicas
+
+**Conclusão:**
+Nevo melanocítico benigno. Seguimento clínico recomendado.
+
+**CID:** D22.5`,
+ cid: "D22.5",
+ diagnostico: "Nevo melanocítico benigno",
+ conclusao: "Lesão benigna, recomenda-se acompanhamento dermatológico de rotina."
+ },
+ ]);
+
+ const [activeTab, setActiveTab] = useState("entregue");
+ const [laudoSelecionado, setLaudoSelecionado] = useState
(null);
+ const [isViewing, setIsViewing] = useState(false);
+ const [isCreatingNew, setIsCreatingNew] = useState(false);
+
+
+
+
+ return (
+
+ {/* Header */}
+
+
+
+
Gerenciamento de Laudo
+
Nesta seção você pode gerenciar todos os laudos gerados através da integração.
+
+
+
+
+
+ {/* Tabs */}
+
+
+
+
+
+
+
+ {/* Filtros */}
+
+
+
+
+
+
+
+ 01/07/2025
+ -
+ 31/07/2025
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* Tabela */}
+
+
+
+
+ Pedido
+ Data
+ Prazo
+ Paciente
+ Executante/Solicitante
+ Exame/Classificação
+ Ação
+
+
+
+ {laudos.map((laudo) => (
+
+
+
+ {laudo.urgente && (
+
+ )}
+
{laudo.id}
+
+
+
+
+
+
+
+
{laudo.prazo}
+
11:48
+
+
+
+
+
+
+ {laudo.paciente.id}
+
+
{laudo.paciente.nome}
+
+
+ {laudo.executante}
+ {laudo.exame || "-"}
+
+
+
+
+
+
+
+ ))}
+
+
+
+
+
+ {/* Visualizador de Laudo */}
+ {isViewing && laudoSelecionado && (
+
setIsViewing(false)} />
+ )}
+
+ {/* Editor para Novo Laudo */}
+ {isCreatingNew && (
+ setIsCreatingNew(false)}
+ isNewLaudo={true}
+ />
+ )}
+
+ {/* Editor para Paciente Específico */}
+ {isEditingForPatient && selectedPatientForLaudo && (
+ {})}
+ isNewLaudo={!selectedPatientForLaudo.conteudo}
+ preSelectedPatient={selectedPatientForLaudo.paciente || selectedPatientForLaudo}
+ />
+ )}
+
+ );
+ }
+
+ // Visualizador de Laudo (somente leitura)
+ function LaudoViewer({ laudo, onClose }: { laudo: any; onClose: () => void }) {
+ return (
+
+
+ {/* Header */}
+
+
+
Visualizar Laudo
+
+ Paciente: {laudo.paciente.nome} | Pedido: {laudo.id} | {laudo.especialidade}
+
+
+
+
+
+ {/* Content */}
+
+
+ {/* Header do Laudo */}
+
+
LAUDO MÉDICO - {laudo.especialidade.toUpperCase()}
+
+ Data: {laudo.data}
+
+
+
+ {/* Dados do Paciente */}
+
+
Dados do Paciente:
+
+
Nome: {laudo.paciente.nome}
+
ID: {laudo.paciente.id}
+
CPF: {laudo.paciente.cpf}
+
Idade: {laudo.paciente.idade} anos
+
Sexo: {laudo.paciente.sexo}
+
CID: {laudo.cid}
+
+
+
+ {/* Conteúdo do Laudo */}
+
+
')
+ }}
+ />
+
+
+ {/* Diagnóstico e Conclusão */}
+ {laudo.diagnostico && (
+
+
Diagnóstico:
+
{laudo.diagnostico}
+
+ )}
+
+ {laudo.conclusao && (
+
+
Conclusão:
+
{laudo.conclusao}
+
+ )}
+
+ {/* Assinatura */}
+
+
+
Dr. Carlos Andrade
+
CRM 000000 - {laudo.especialidade}
+
Data: {laudo.data}
+
+
+
+
+ {/* Footer */}
+
+
+
+ Status: {laudo.status} | Executante: {laudo.executante}
+
+
+
+
+
+
+ );
+ }
+
+ // Editor de Laudo Avançado (para novos laudos)
+ function LaudoEditor({ pacientes, laudo, onClose, isNewLaudo, preSelectedPatient }: { pacientes?: any[]; laudo?: any; onClose: () => void; isNewLaudo?: boolean; preSelectedPatient?: any }) {
+ const [activeTab, setActiveTab] = useState("editor");
+ const [content, setContent] = useState(laudo?.conteudo || "");
+ const [showPreview, setShowPreview] = useState(false);
+ const [pacienteSelecionado, setPacienteSelecionado] = useState
(preSelectedPatient || null);
+ const [campos, setCampos] = useState({
+ cid: laudo?.cid || "",
+ diagnostico: laudo?.diagnostico || "",
+ conclusao: laudo?.conclusao || "",
+ exame: laudo?.exame || "",
+ especialidade: laudo?.especialidade || "",
+ mostrarData: true,
+ mostrarAssinatura: true
+ });
+ const [imagens, setImagens] = useState([]);
+ const [templates] = useState([
+ "Exame normal, sem alterações significativas",
+ "Paciente em acompanhamento ambulatorial",
+ "Recomenda-se retorno em 30 dias",
+ "Alterações compatíveis com processo inflamatório",
+ "Resultado dentro dos parâmetros de normalidade",
+ "Recomendo seguimento com especialista"
+ ]);
+
+ const sigCanvasRef = useRef(null);
+
+ // Carregar dados do laudo existente quando disponível
+ useEffect(() => {
+ if (laudo && !isNewLaudo) {
+ setContent(laudo.conteudo || "");
+ setCampos({
+ cid: laudo.cid || "",
+ diagnostico: laudo.diagnostico || "",
+ conclusao: laudo.conclusao || "",
+ exame: laudo.exame || "",
+ especialidade: laudo.especialidade || "",
+ mostrarData: true,
+ mostrarAssinatura: true
+ });
+ setPacienteSelecionado(laudo.paciente);
+ }
+ }, [laudo, isNewLaudo]);
+
+ const formatText = (type: string) => {
+ const textarea = document.querySelector('textarea') as HTMLTextAreaElement;
+ if (!textarea) return;
+
+ const start = textarea.selectionStart;
+ const end = textarea.selectionEnd;
+ const selectedText = textarea.value.substring(start, end);
+
+ let formattedText = "";
+ switch(type) {
+ case "bold":
+ formattedText = selectedText ? `**${selectedText}**` : "**texto em negrito**";
+ break;
+ case "italic":
+ formattedText = selectedText ? `*${selectedText}*` : "*texto em itálico*";
+ break;
+ case "underline":
+ formattedText = selectedText ? `${selectedText}` : "texto sublinhado";
+ break;
+ case "list":
+ formattedText = selectedText ? `• ${selectedText}` : "• item da lista";
+ break;
+ }
+
+ const newText = textarea.value.substring(0, start) + formattedText + textarea.value.substring(end);
+ setContent(newText);
+ };
+
+ const insertTemplate = (template: string) => {
+ setContent((prev: string) => prev ? `${prev}\n\n${template}` : template);
+ };
+
+ const handleImageUpload = (e: React.ChangeEvent) => {
+ const files = Array.from(e.target.files || []);
+ files.forEach(file => {
+ const reader = new FileReader();
+ reader.onload = (e) => {
+ setImagens(prev => [...prev, {
+ id: Date.now() + Math.random(),
+ name: file.name,
+ url: e.target?.result,
+ type: file.type
+ }]);
+ };
+ reader.readAsDataURL(file);
+ });
+ };
+
+ const processContent = (content: string) => {
+ return content
+ .replace(/\*\*(.*?)\*\*/g, '$1')
+ .replace(/\*(.*?)\*/g, '$1')
+ .replace(/(.*?)<\/u>/g, '$1')
+ .replace(/{{sexo_paciente}}/g, pacienteSelecionado?.sexo || laudo?.paciente?.sexo || '[SEXO]')
+ .replace(/{{diagnostico}}/g, campos.diagnostico || '[DIAGNÓSTICO]')
+ .replace(/{{conclusao}}/g, campos.conclusao || '[CONCLUSÃO]')
+ .replace(/\n/g, '
');
+ };
+
+ return (
+
+
+ {/* Header */}
+
+
+
+
+ {isNewLaudo ? "Novo Laudo Médico" : "Editar Laudo Existente"}
+
+ {isNewLaudo ? (
+
+ Crie um novo laudo selecionando um paciente
+
+ ) : (
+
+ Paciente: {laudo?.paciente?.nome} | Pedido: {laudo?.id} | {laudo?.especialidade}
+
+ )}
+
+
+
+
+ {/* Seleção de Paciente (apenas para novos laudos) */}
+ {isNewLaudo && (
+
+ {!pacienteSelecionado ? (
+
+
+
+
+ ) : (
+
+
+
{pacienteSelecionado.nome}
+
+ CPF: {pacienteSelecionado.cpf} | Idade: {pacienteSelecionado.idade} anos | Sexo: {pacienteSelecionado.sexo}
+
+
+ {!preSelectedPatient && (
+
+ )}
+
+ )}
+
+ )}
+
+
+ {/* Tabs */}
+
+ {isNewLaudo && (
+
+ )}
+
+
+
+
+
+
+ {/* Content */}
+
+ {/* Left Panel */}
+
+ {activeTab === "info" && isNewLaudo && (
+
+ {!pacienteSelecionado ? (
+
+
+
+
Selecione um paciente primeiro
+
+
+ ) : (
+
+
+
Informações do Exame
+
+
+
+
+
+
+
+
+
+ setCampos(prev => ({ ...prev, exame: e.target.value }))}
+ placeholder="Ex: Ecocardiograma, Dermatoscopia, etc."
+ />
+
+
+
+
+
+
Dados do Paciente
+
+
+
+ Nome: {pacienteSelecionado.nome}
+
+
+ ID: {pacienteSelecionado.id}
+
+
+ CPF: {pacienteSelecionado.cpf}
+
+
+ Idade: {pacienteSelecionado.idade} anos
+
+
+ Sexo: {pacienteSelecionado.sexo}
+
+
+
+
+
+
+
+
+
+ )}
+
+ )}
+
+ {activeTab === "editor" && (
+
+ {/* Toolbar */}
+
+
+
+
+
+
+
+
+
+ {/* Templates */}
+
+
Frases rápidas:
+
+ {templates.map((template, idx) => (
+
+ ))}
+
+
+
+
+ {/* Editor */}
+
+
+
+ )}
+
+ {activeTab === "imagens" && (
+
+
+
+
+
+
+
+ {imagens.map((img) => (
+
+ {img.type.startsWith('image/') ? (
+

+ ) : (
+
+
+
+ )}
+
{img.name}
+
+
+ ))}
+
+
+ )}
+
+ {activeTab === "campos" && (
+
+
+
+ setCampos(prev => ({ ...prev, cid: e.target.value }))}
+ placeholder="Ex: M25.5, I10, etc."
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* Assinatura Digital */}
+
+
+
+
+
+
+
+
+
+
+ )}
+
+
+ {/* Preview Panel */}
+ {showPreview && (
+
+
+
Pré-visualização do Laudo
+
+
+
+ {/* Header do Laudo */}
+
+
+ LAUDO MÉDICO {campos.especialidade ? `- ${campos.especialidade.toUpperCase()}` : ''}
+
+ {campos.exame && (
+
{campos.exame}
+ )}
+ {campos.mostrarData && (
+
+ Data: {new Date().toLocaleDateString('pt-BR')}
+
+ )}
+
+
+ {/* Dados do Paciente */}
+ {(isNewLaudo ? pacienteSelecionado : laudo?.paciente) && (
+
+
Dados do Paciente:
+ {isNewLaudo && pacienteSelecionado ? (
+ <>
+
Nome: {pacienteSelecionado.nome}
+
ID: {pacienteSelecionado.id}
+
CPF: {pacienteSelecionado.cpf}
+
Idade: {pacienteSelecionado.idade} anos
+
Sexo: {pacienteSelecionado.sexo}
+ {campos.cid &&
CID: {campos.cid}
}
+ >
+ ) : (
+ <>
+
Nome: {laudo?.paciente?.nome}
+
ID: {laudo?.paciente?.id}
+ {campos.cid &&
CID: {campos.cid}
}
+ >
+ )}
+
+ )}
+
+ {/* Conteúdo */}
+
+
+ {/* Imagens */}
+ {imagens.length > 0 && (
+
+
Imagens:
+
+ {imagens.map((img) => (
+

+ ))}
+
+
+ )}
+
+ {/* Assinatura */}
+ {campos.mostrarAssinatura && (
+
+
+
Dr. Carlos Andrade
+
CRM 000000
+
+ )}
+
+
+
+ )}
+
+
+ {/* Footer */}
+
+
+
+ Este editor permite escrever relatórios de forma livre, com formatação de texto rica.
+
+
+
+
+
+
+
+
+
+
+ );
+ }
const renderComunicacaoSection = () => (
-
-
Comunicação com o Paciente
+
+
Comunicação com o Paciente
-
+
@@ -1919,11 +2723,11 @@ function LaudoEditor() {
-
- Lembrete de Consulta
- Resultado de Exame
- Instruções Pós-Consulta
- Outro
+
+ Lembrete de Consulta
+ Resultado de Exame
+ Instruções Pós-Consulta
+ Outro
@@ -1956,17 +2760,17 @@ function LaudoEditor() {
const renderRelatoriosMedicosSection = () => (
-
Relatórios Médicos
+ Relatórios Médicos
{editandoRelatorio && (
-
{/* Formulário de Relatório Médico */}
-
-
+
+
{editandoRelatorio ? 'Editar Relatório Médico' : 'Novo Relatório Médico'}
@@ -1981,7 +2785,7 @@ function LaudoEditor() {
id="profissionalNome"
value={relatorioMedico.profissionalNome}
disabled
- className="bg-gray-100"
+ className="bg-muted"
/>
@@ -1990,7 +2794,7 @@ function LaudoEditor() {
id="profissionalCrm"
value={relatorioMedico.profissionalCrm}
disabled
- className="bg-gray-100"
+ className="bg-muted"
/>
@@ -2178,7 +2982,7 @@ function LaudoEditor() {
{/* Botões de Ação */}
-
+
Cancelar
@@ -2190,12 +2994,12 @@ function LaudoEditor() {
{/* Lista de Relatórios Existentes */}
-
-
Relatórios Médicos Salvos
+
+
Relatórios Médicos Salvos
{relatoriosMedicos.length === 0 ? (
-
-
+
+
Nenhum relatório médico encontrado
Os relatórios salvos aparecerão aqui
@@ -2206,9 +3010,9 @@ function LaudoEditor() {
{relatorio.pacienteNome}
-
CPF: {relatorio.pacienteCpf} • Idade: {relatorio.pacienteIdade} anos
-
Data do relatório: {new Date(relatorio.dataRelatorio).toLocaleDateString('pt-BR')}
-
Gerado em: {relatorio.dataGeracao}
+
CPF: {relatorio.pacienteCpf} • Idade: {relatorio.pacienteIdade} anos
+
Data do relatório: {new Date(relatorio.dataRelatorio).toLocaleDateString('pt-BR')}
+
Gerado em: {relatorio.dataGeracao}
Motivo:
-
{relatorio.motivoRelatorio}
+
{relatorio.motivoRelatorio}
{relatorio.diagnosticos && (
Diagnóstico(s):
-
{relatorio.diagnosticos}
+
{relatorio.diagnosticos}
)}
{relatorio.recomendacoes && (
Recomendações:
-
{relatorio.recomendacoes}
+
{relatorio.recomendacoes}
)}
@@ -2263,7 +3067,7 @@ function LaudoEditor() {
const renderPerfilSection = () => (
-
Meu Perfil
+ Meu Perfil
{!isEditingProfile ? (
setIsEditingProfile(true)} className="flex items-center gap-2">
@@ -2274,7 +3078,7 @@ function LaudoEditor() {
Salvar
-
+
Cancelar
@@ -2284,12 +3088,12 @@ function LaudoEditor() {
{/* Informações Pessoais */}
-
Informações Pessoais
+
Informações Pessoais
-
{profileData.nome}
-
Este campo não pode ser alterado
+
{profileData.nome}
+
Este campo não pode ser alterado
@@ -2302,7 +3106,7 @@ function LaudoEditor() {
onChange={(e) => handleProfileChange('email', e.target.value)}
/>
) : (
-
{profileData.email}
+
{profileData.email}
)}
@@ -2315,14 +3119,14 @@ function LaudoEditor() {
onChange={(e) => handleProfileChange('telefone', e.target.value)}
/>
) : (
-
{profileData.telefone}
+
{profileData.telefone}
)}
-
{profileData.crm}
-
Este campo não pode ser alterado
+
{profileData.crm}
+
Este campo não pode ser alterado
@@ -2334,14 +3138,14 @@ function LaudoEditor() {
onChange={(e) => handleProfileChange('especialidade', e.target.value)}
/>
) : (
-
{profileData.especialidade}
+
{profileData.especialidade}
)}
{/* Endereço e Contato */}
-
Endereço e Contato
+
Endereço e Contato
@@ -2352,7 +3156,7 @@ function LaudoEditor() {
onChange={(e) => handleProfileChange('endereco', e.target.value)}
/>
) : (
-
{profileData.endereco}
+
{profileData.endereco}
)}
@@ -2365,7 +3169,7 @@ function LaudoEditor() {
onChange={(e) => handleProfileChange('cidade', e.target.value)}
/>
) : (
-
{profileData.cidade}
+
{profileData.cidade}
)}
@@ -2378,7 +3182,7 @@ function LaudoEditor() {
onChange={(e) => handleProfileChange('cep', e.target.value)}
/>
) : (
-
{profileData.cep}
+
{profileData.cep}
)}
@@ -2393,15 +3197,15 @@ function LaudoEditor() {
placeholder="Descreva sua experiência profissional..."
/>
) : (
-
{profileData.biografia}
+
{profileData.biografia}
)}
{/* Foto do Perfil */}
-
-
Foto do Perfil
+
+
Foto do Perfil
@@ -2413,7 +3217,7 @@ function LaudoEditor() {
Alterar Foto
-
+
Formatos aceitos: JPG, PNG (máx. 2MB)
@@ -2448,7 +3252,7 @@ function LaudoEditor() {
return (
-
+
@@ -2468,7 +3272,7 @@ function LaudoEditor() {
Sair
@@ -2477,10 +3281,10 @@ function LaudoEditor() {
{}