add-dark-mode-and-removing-pages #35

Merged
Jonasbomfim merged 10 commits from feature/fix-erros into develop 2025-10-03 17:28:33 +00:00
Showing only changes of commit d975e0f554 - Show all commits

View File

@ -1,6 +1,6 @@
"use client"; "use client";
import React, { useState, useRef } from "react"; import React, { useState, useRef, useEffect } from "react";
import SignatureCanvas from "react-signature-canvas"; import SignatureCanvas from "react-signature-canvas";
import Link from "next/link"; import Link from "next/link";
import ProtectedRoute from "@/components/ProtectedRoute"; import ProtectedRoute from "@/components/ProtectedRoute";
@ -73,6 +73,10 @@ const ProfissionalPage = () => {
const [activeSection, setActiveSection] = useState('calendario'); const [activeSection, setActiveSection] = useState('calendario');
const [pacienteSelecionado, setPacienteSelecionado] = useState<any>(null); const [pacienteSelecionado, setPacienteSelecionado] = useState<any>(null);
// Estados para edição de laudo
const [isEditingLaudoForPatient, setIsEditingLaudoForPatient] = useState(false);
const [patientForLaudo, setPatientForLaudo] = useState<any>(null);
// Estados para o perfil do médico // Estados para o perfil do médico
const [isEditingProfile, setIsEditingProfile] = useState(false); const [isEditingProfile, setIsEditingProfile] = useState(false);
const [profileData, setProfileData] = useState({ const [profileData, setProfileData] = useState({
@ -199,6 +203,12 @@ const ProfissionalPage = () => {
setPacienteSelecionado(null); setPacienteSelecionado(null);
}; };
const handleEditarLaudo = (paciente: any) => {
setPatientForLaudo(paciente);
setIsEditingLaudoForPatient(true);
setActiveSection('laudos');
};
const navigateDate = (direction: 'prev' | 'next') => { const navigateDate = (direction: 'prev' | 'next') => {
const newDate = new Date(currentCalendarDate); const newDate = new Date(currentCalendarDate);
@ -553,6 +563,7 @@ const ProfissionalPage = () => {
<div className="absolute top-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-l-4 border-r-4 border-t-4 border-transparent border-t-gray-900 dark:border-t-gray-100"></div> <div className="absolute top-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-l-4 border-r-4 border-t-4 border-transparent border-t-gray-900 dark:border-t-gray-100"></div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
@ -688,17 +699,28 @@ const ProfissionalPage = () => {
<p className="font-medium">{paciente.nome}</p> <p className="font-medium">{paciente.nome}</p>
<p className="text-sm text-muted-foreground">CPF: {paciente.cpf} Idade: {paciente.idade} anos</p> <p className="text-sm text-muted-foreground">CPF: {paciente.cpf} Idade: {paciente.idade} anos</p>
</div> </div>
<Button <div className="flex items-center gap-2">
size="sm" <Button
onClick={() => { size="sm"
handleAbrirProntuario(paciente); onClick={() => {
setActiveSection('prontuario'); handleAbrirProntuario(paciente);
}} setActiveSection('prontuario');
className="flex items-center gap-2" }}
> className="flex items-center gap-2"
<FolderOpen className="h-4 w-4" /> >
Abrir Prontuário <FolderOpen className="h-4 w-4" />
</Button> Prontuário
</Button>
<Button
size="sm"
variant="outline"
onClick={() => handleEditarLaudo(paciente)}
className="flex items-center gap-2 border-green-600 text-green-600 hover:bg-green-600 hover:text-white"
>
<FileText className="h-4 w-4" />
Editar Laudo
</Button>
</div>
</div> </div>
))} ))}
</div> </div>
@ -732,7 +754,7 @@ const ProfissionalPage = () => {
<Button <Button
variant="outline" variant="outline"
size="sm" size="sm"
className="border-primary text-primary hover:bg-primary hover:text-white cursor-pointer" className="border-primary text-primary hover:bg-primary hover:text-white cursor-pointer mr-2"
onClick={() => { onClick={() => {
handleAbrirProntuario(paciente); handleAbrirProntuario(paciente);
setActiveSection('prontuario'); setActiveSection('prontuario');
@ -745,6 +767,20 @@ const ProfissionalPage = () => {
<div className="absolute top-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-l-4 border-r-4 border-t-4 border-transparent border-t-gray-900 dark:border-t-gray-100"></div> <div className="absolute top-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-l-4 border-r-4 border-t-4 border-transparent border-t-gray-900 dark:border-t-gray-100"></div>
</div> </div>
</div> </div>
<div className="relative group">
<Button
variant="outline"
size="sm"
className="border-green-600 text-green-600 hover:bg-green-600 hover:text-white cursor-pointer"
onClick={() => handleEditarLaudo(paciente)}
>
<FileText className="h-4 w-4" />
</Button>
<div className="absolute bottom-full left-1/2 transform -translate-x-1/2 mb-2 px-3 py-1 bg-gray-900 dark:bg-gray-100 text-white dark:text-gray-900 text-xs rounded-md opacity-0 group-hover:opacity-100 transition-opacity duration-200 pointer-events-none whitespace-nowrap z-50">
Editar laudo do paciente
<div className="absolute top-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-l-4 border-r-4 border-t-4 border-transparent border-t-gray-900 dark:border-t-gray-100"></div>
</div>
</div>
</div> </div>
</TableCell> </TableCell>
</TableRow> </TableRow>
@ -1651,12 +1687,19 @@ const ProfissionalPage = () => {
const renderLaudosSection = () => ( const renderLaudosSection = () => (
<div className="space-y-6"> <div className="space-y-6">
<LaudoManager /> <LaudoManager
isEditingForPatient={isEditingLaudoForPatient}
selectedPatientForLaudo={patientForLaudo}
onClosePatientEditor={() => {
setIsEditingLaudoForPatient(false);
setPatientForLaudo(null);
}}
/>
</div> </div>
); );
// --- NOVO SISTEMA DE LAUDOS COMPLETO --- // --- NOVO SISTEMA DE LAUDOS COMPLETO ---
function LaudoManager() { function LaudoManager({ isEditingForPatient, selectedPatientForLaudo, onClosePatientEditor }: { isEditingForPatient?: boolean; selectedPatientForLaudo?: any; onClosePatientEditor?: () => void }) {
const [pacientesDisponiveis] = useState([ const [pacientesDisponiveis] = useState([
{ id: "95170038", nome: "Ana Souza", cpf: "123.456.789-00", idade: 42, sexo: "Feminino" }, { 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: "93203056", nome: "Bruno Lima", cpf: "987.654.321-00", idade: 33, sexo: "Masculino" },
@ -1788,6 +1831,9 @@ Nevo melanocítico benigno. Seguimento clínico recomendado.
const [isViewing, setIsViewing] = useState(false); const [isViewing, setIsViewing] = useState(false);
const [isCreatingNew, setIsCreatingNew] = useState(false); const [isCreatingNew, setIsCreatingNew] = useState(false);
return ( return (
<div className="space-y-6"> <div className="space-y-6">
{/* Header */} {/* Header */}
@ -1938,18 +1984,33 @@ Nevo melanocítico benigno. Seguimento clínico recomendado.
<TableCell className="text-sm">{laudo.executante}</TableCell> <TableCell className="text-sm">{laudo.executante}</TableCell>
<TableCell className="text-sm">{laudo.exame || "-"}</TableCell> <TableCell className="text-sm">{laudo.exame || "-"}</TableCell>
<TableCell> <TableCell>
<Button <div className="flex items-center gap-2">
variant="outline" <Button
size="sm" variant="outline"
onClick={() => { size="sm"
setLaudoSelecionado(laudo); onClick={() => {
setIsViewing(true); setLaudoSelecionado(laudo);
}} setIsViewing(true);
className="flex items-center gap-1" }}
> className="flex items-center gap-1"
<Eye className="w-4 h-4" /> >
Ver Laudo <Eye className="w-4 h-4" />
</Button> Ver Laudo
</Button>
<Button
variant="default"
size="sm"
onClick={() => {
setPatientForLaudo(laudo);
setIsEditingLaudoForPatient(true);
}}
className="flex items-center gap-1 bg-green-600 hover:bg-green-700 text-white"
title="Editar laudo para este paciente"
>
<Edit className="w-4 h-4" />
Editar Laudo
</Button>
</div>
</TableCell> </TableCell>
</TableRow> </TableRow>
))} ))}
@ -1971,6 +2032,17 @@ Nevo melanocítico benigno. Seguimento clínico recomendado.
isNewLaudo={true} isNewLaudo={true}
/> />
)} )}
{/* Editor para Paciente Específico */}
{isEditingForPatient && selectedPatientForLaudo && (
<LaudoEditor
pacientes={[selectedPatientForLaudo.paciente || selectedPatientForLaudo]}
laudo={selectedPatientForLaudo.conteudo ? selectedPatientForLaudo : null}
onClose={onClosePatientEditor || (() => {})}
isNewLaudo={!selectedPatientForLaudo.conteudo}
preSelectedPatient={selectedPatientForLaudo.paciente || selectedPatientForLaudo}
/>
)}
</div> </div>
); );
} }
@ -2069,17 +2141,17 @@ Nevo melanocítico benigno. Seguimento clínico recomendado.
} }
// Editor de Laudo Avançado (para novos laudos) // Editor de Laudo Avançado (para novos laudos)
function LaudoEditor({ pacientes, laudo, onClose, isNewLaudo }: { pacientes?: any[]; laudo?: any; onClose: () => void; isNewLaudo?: boolean }) { function LaudoEditor({ pacientes, laudo, onClose, isNewLaudo, preSelectedPatient }: { pacientes?: any[]; laudo?: any; onClose: () => void; isNewLaudo?: boolean; preSelectedPatient?: any }) {
const [activeTab, setActiveTab] = useState("editor"); const [activeTab, setActiveTab] = useState("editor");
const [content, setContent] = useState(""); const [content, setContent] = useState(laudo?.conteudo || "");
const [showPreview, setShowPreview] = useState(false); const [showPreview, setShowPreview] = useState(false);
const [pacienteSelecionado, setPacienteSelecionado] = useState<any>(null); const [pacienteSelecionado, setPacienteSelecionado] = useState<any>(preSelectedPatient || null);
const [campos, setCampos] = useState({ const [campos, setCampos] = useState({
cid: "", cid: laudo?.cid || "",
diagnostico: "", diagnostico: laudo?.diagnostico || "",
conclusao: "", conclusao: laudo?.conclusao || "",
exame: "", exame: laudo?.exame || "",
especialidade: "", especialidade: laudo?.especialidade || "",
mostrarData: true, mostrarData: true,
mostrarAssinatura: true mostrarAssinatura: true
}); });
@ -2095,6 +2167,23 @@ Nevo melanocítico benigno. Seguimento clínico recomendado.
const sigCanvasRef = useRef<any>(null); const sigCanvasRef = useRef<any>(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 formatText = (type: string) => {
const textarea = document.querySelector('textarea') as HTMLTextAreaElement; const textarea = document.querySelector('textarea') as HTMLTextAreaElement;
if (!textarea) return; if (!textarea) return;
@ -2124,12 +2213,7 @@ Nevo melanocítico benigno. Seguimento clínico recomendado.
}; };
const insertTemplate = (template: string) => { const insertTemplate = (template: string) => {
setContent(prev => prev ? `${prev}\n\n${template}` : template); setContent((prev: string) => prev ? `${prev}\n\n${template}` : template);
};
const insertCampo = (campo: string) => {
const placeholder = `{{${campo}}}`;
setContent(prev => prev ? `${prev} ${placeholder}` : placeholder);
}; };
const handleImageUpload = (e: React.ChangeEvent<HTMLInputElement>) => { const handleImageUpload = (e: React.ChangeEvent<HTMLInputElement>) => {
@ -2149,15 +2233,11 @@ Nevo melanocítico benigno. Seguimento clínico recomendado.
}; };
const processContent = (content: string) => { const processContent = (content: string) => {
const paciente = isNewLaudo ? pacienteSelecionado : laudo?.paciente;
return content return content
.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>') .replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
.replace(/\*(.*?)\*/g, '<em>$1</em>') .replace(/\*(.*?)\*/g, '<em>$1</em>')
.replace(/<u>(.*?)<\/u>/g, '<u>$1</u>') .replace(/<u>(.*?)<\/u>/g, '<u>$1</u>')
.replace(/{{nome_paciente}}/g, paciente?.nome || '[NOME_PACIENTE]') .replace(/{{sexo_paciente}}/g, pacienteSelecionado?.sexo || laudo?.paciente?.sexo || '[SEXO]')
.replace(/{{idade_paciente}}/g, paciente?.idade?.toString() || '[IDADE]')
.replace(/{{sexo_paciente}}/g, paciente?.sexo || '[SEXO]')
.replace(/{{cid}}/g, campos.cid || '[CID]')
.replace(/{{diagnostico}}/g, campos.diagnostico || '[DIAGNÓSTICO]') .replace(/{{diagnostico}}/g, campos.diagnostico || '[DIAGNÓSTICO]')
.replace(/{{conclusao}}/g, campos.conclusao || '[CONCLUSÃO]') .replace(/{{conclusao}}/g, campos.conclusao || '[CONCLUSÃO]')
.replace(/\n/g, '<br>'); .replace(/\n/g, '<br>');
@ -2171,7 +2251,7 @@ Nevo melanocítico benigno. Seguimento clínico recomendado.
<div className="flex items-center justify-between p-4"> <div className="flex items-center justify-between p-4">
<div> <div>
<h2 className="text-xl font-bold text-foreground"> <h2 className="text-xl font-bold text-foreground">
{isNewLaudo ? "Novo Laudo Médico" : "Editor de Laudo"} {isNewLaudo ? "Novo Laudo Médico" : "Editar Laudo Existente"}
</h2> </h2>
{isNewLaudo ? ( {isNewLaudo ? (
<p className="text-sm text-muted-foreground"> <p className="text-sm text-muted-foreground">
@ -2179,7 +2259,7 @@ Nevo melanocítico benigno. Seguimento clínico recomendado.
</p> </p>
) : ( ) : (
<p className="text-sm text-muted-foreground"> <p className="text-sm text-muted-foreground">
Paciente: {laudo?.paciente?.nome} | Pedido: {laudo?.id} Paciente: {laudo?.paciente?.nome} | Pedido: {laudo?.id} | {laudo?.especialidade}
</p> </p>
)} )}
</div> </div>
@ -2220,13 +2300,15 @@ Nevo melanocítico benigno. Seguimento clínico recomendado.
CPF: {pacienteSelecionado.cpf} | Idade: {pacienteSelecionado.idade} anos | Sexo: {pacienteSelecionado.sexo} CPF: {pacienteSelecionado.cpf} | Idade: {pacienteSelecionado.idade} anos | Sexo: {pacienteSelecionado.sexo}
</div> </div>
</div> </div>
<Button {!preSelectedPatient && (
variant="outline" <Button
size="sm" variant="outline"
onClick={() => setPacienteSelecionado(null)} size="sm"
> onClick={() => setPacienteSelecionado(null)}
Trocar Paciente >
</Button> Trocar Paciente
</Button>
)}
</div> </div>
)} )}
</div> </div>
@ -2412,32 +2494,6 @@ Nevo melanocítico benigno. Seguimento clínico recomendado.
</Button> </Button>
<div className="h-6 w-px bg-border mx-1"></div>
<Button
variant="outline"
size="sm"
onClick={() => insertCampo("nome_paciente")}
title="Nome do Paciente"
>
Nome
</Button>
<Button
variant="outline"
size="sm"
onClick={() => insertCampo("idade_paciente")}
title="Idade do Paciente"
>
Idade
</Button>
<Button
variant="outline"
size="sm"
onClick={() => insertCampo("cid")}
title="CID"
>
CID
</Button>
</div> </div>
{/* Templates */} {/* Templates */}
@ -2699,7 +2755,7 @@ Nevo melanocítico benigno. Seguimento clínico recomendado.
Salvar Rascunho Salvar Rascunho
</Button> </Button>
<Button variant="default"> <Button variant="default">
Liberar Laudo {isNewLaudo ? "Liberar Laudo" : "Atualizar Laudo"}
</Button> </Button>
</div> </div>
</div> </div>