fix-visual-adjustments
This commit is contained in:
parent
d966e40608
commit
f6fad55ff3
@ -309,7 +309,7 @@ export default function AgendamentoPage() {
|
||||
</div>
|
||||
|
||||
{/* legenda dinâmica: mostra as cores presentes nos agendamentos do dia atual */}
|
||||
<div className="sm:absolute sm:top-2 sm:right-2 mt-2 sm:mt-0 z-40">
|
||||
<div className="sm:absolute sm:top-2 sm:right-2 mt-2 sm:mt-0 z-10">
|
||||
<DynamicLegend events={managerEvents} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -178,6 +178,33 @@ export default function LaudosEditorPage() {
|
||||
}
|
||||
}, []);
|
||||
|
||||
// Auto-salvar no localStorage sempre que houver mudanças (com debounce)
|
||||
useEffect(() => {
|
||||
const timeoutId = setTimeout(() => {
|
||||
// Capturar conteúdo atual do editor antes de salvar
|
||||
const currentContent = editorRef.current?.innerHTML || content;
|
||||
|
||||
const draft = {
|
||||
pacienteSelecionado,
|
||||
content: currentContent,
|
||||
campos,
|
||||
solicitanteId,
|
||||
solicitanteNome,
|
||||
prazoDate,
|
||||
prazoTime,
|
||||
imagens,
|
||||
lastSaved: new Date().toISOString(),
|
||||
};
|
||||
|
||||
// Só salvar se houver conteúdo ou dados preenchidos
|
||||
if (currentContent || pacienteSelecionado || campos.exame || campos.diagnostico || imagens.length > 0) {
|
||||
localStorage.setItem('laudoDraft', JSON.stringify(draft));
|
||||
}
|
||||
}, 1000); // Aguarda 1 segundo após última mudança
|
||||
|
||||
return () => clearTimeout(timeoutId);
|
||||
}, [pacienteSelecionado, content, campos, solicitanteId, solicitanteNome, prazoDate, prazoTime, imagens]);
|
||||
|
||||
// Tentar obter o registro de médico correspondente ao usuário autenticado
|
||||
useEffect(() => {
|
||||
let mounted = true;
|
||||
@ -247,6 +274,23 @@ export default function LaudosEditorPage() {
|
||||
}
|
||||
}, [content]);
|
||||
|
||||
// Função para trocar de aba salvando conteúdo antes
|
||||
const handleTabChange = (newTab: string) => {
|
||||
// Salvar conteúdo do editor antes de trocar
|
||||
if (editorRef.current) {
|
||||
const editorContent = editorRef.current.innerHTML;
|
||||
setContent(editorContent);
|
||||
}
|
||||
setActiveTab(newTab);
|
||||
};
|
||||
|
||||
// Restaurar conteúdo do editor quando voltar para a aba editor
|
||||
useEffect(() => {
|
||||
if (activeTab === 'editor' && editorRef.current && content) {
|
||||
editorRef.current.innerHTML = content;
|
||||
}
|
||||
}, [activeTab]);
|
||||
|
||||
// Desfazer
|
||||
const handleUndo = () => {
|
||||
if (historyIndex > 0) {
|
||||
@ -321,11 +365,15 @@ export default function LaudosEditorPage() {
|
||||
|
||||
// Salvar rascunho no localStorage
|
||||
const saveDraft = () => {
|
||||
// Capturar conteúdo atual do editor antes de salvar
|
||||
const currentContent = editorRef.current?.innerHTML || content;
|
||||
|
||||
const draft = {
|
||||
pacienteSelecionado,
|
||||
content,
|
||||
content: currentContent,
|
||||
campos,
|
||||
solicitanteId,
|
||||
solicitanteNome,
|
||||
prazoDate,
|
||||
prazoTime,
|
||||
imagens,
|
||||
@ -389,6 +437,9 @@ export default function LaudosEditorPage() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Capturar conteúdo atual do editor antes de salvar
|
||||
const currentContent = editorRef.current?.innerHTML || content;
|
||||
|
||||
const userId = user?.id || '00000000-0000-0000-0000-000000000001';
|
||||
|
||||
let composedDueAt = undefined;
|
||||
@ -404,7 +455,7 @@ export default function LaudosEditorPage() {
|
||||
diagnosis: campos.diagnostico || '',
|
||||
conclusion: campos.conclusao || '',
|
||||
cid_code: campos.cid || '',
|
||||
content_html: content,
|
||||
content_html: currentContent,
|
||||
content_json: {},
|
||||
requested_by: solicitanteId || userId,
|
||||
due_at: composedDueAt ?? new Date().toISOString(),
|
||||
@ -414,6 +465,10 @@ export default function LaudosEditorPage() {
|
||||
|
||||
if (createNewReport) {
|
||||
await createNewReport(payload as any);
|
||||
|
||||
// Limpar rascunho salvo após sucesso
|
||||
localStorage.removeItem('laudoDraft');
|
||||
|
||||
toast({
|
||||
title: 'Laudo criado com sucesso!',
|
||||
description: 'O laudo foi liberado e salvo.',
|
||||
@ -536,7 +591,7 @@ export default function LaudosEditorPage() {
|
||||
{/* Tabs */}
|
||||
<div className="flex border-b border-border bg-card overflow-x-auto flex-shrink-0">
|
||||
<button
|
||||
onClick={() => setActiveTab('editor')}
|
||||
onClick={() => handleTabChange('editor')}
|
||||
className={`px-2 sm:px-4 py-2 text-xs sm:text-sm font-medium border-b-2 transition-colors whitespace-nowrap ${
|
||||
activeTab === 'editor'
|
||||
? 'border-blue-500 text-blue-600'
|
||||
@ -547,7 +602,7 @@ export default function LaudosEditorPage() {
|
||||
Editor
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setActiveTab('imagens')}
|
||||
onClick={() => handleTabChange('imagens')}
|
||||
className={`px-2 sm:px-4 py-2 text-xs sm:text-sm font-medium border-b-2 transition-colors whitespace-nowrap ${
|
||||
activeTab === 'imagens'
|
||||
? 'border-blue-500 text-blue-600'
|
||||
@ -558,7 +613,7 @@ export default function LaudosEditorPage() {
|
||||
Imagens ({imagens.length})
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setActiveTab('campos')}
|
||||
onClick={() => handleTabChange('campos')}
|
||||
className={`px-2 sm:px-4 py-2 text-xs sm:text-sm font-medium border-b-2 transition-colors whitespace-nowrap ${
|
||||
activeTab === 'campos'
|
||||
? 'border-blue-500 text-blue-600'
|
||||
|
||||
@ -69,32 +69,47 @@ export default function EditarLaudoPage() {
|
||||
// Estado para rastrear alinhamento ativo
|
||||
const [activeAlignment, setActiveAlignment] = useState('left');
|
||||
|
||||
// Salvar conteúdo no localStorage sempre que muda
|
||||
// Salvar conteúdo no localStorage sempre que muda (com debounce)
|
||||
useEffect(() => {
|
||||
if (content && laudoId) {
|
||||
localStorage.setItem(`laudo-draft-${laudoId}`, content);
|
||||
}
|
||||
}, [content, laudoId]);
|
||||
const timeoutId = setTimeout(() => {
|
||||
if (laudoId) {
|
||||
// Capturar conteúdo atual do editor antes de salvar
|
||||
const currentContent = editorRef.current?.innerHTML || content;
|
||||
|
||||
const draft = {
|
||||
content: currentContent,
|
||||
campos,
|
||||
lastSaved: new Date().toISOString(),
|
||||
};
|
||||
|
||||
localStorage.setItem(`laudo-draft-${laudoId}`, JSON.stringify(draft));
|
||||
}
|
||||
}, 1000); // Aguarda 1 segundo após última mudança
|
||||
|
||||
return () => clearTimeout(timeoutId);
|
||||
}, [content, campos, laudoId]);
|
||||
|
||||
// Sincronizar conteúdo com o editor
|
||||
useEffect(() => {
|
||||
if (editorRef.current && content) {
|
||||
if (editorRef.current.innerHTML !== content) {
|
||||
editorRef.current.innerHTML = content;
|
||||
}
|
||||
editorRef.current.innerHTML = content;
|
||||
}
|
||||
}, [content]);
|
||||
|
||||
// Função para trocar de aba salvando conteúdo antes
|
||||
const handleTabChange = (newTab: string) => {
|
||||
// Salvar conteúdo do editor antes de trocar
|
||||
if (editorRef.current) {
|
||||
const editorContent = editorRef.current.innerHTML;
|
||||
setContent(editorContent);
|
||||
}
|
||||
setActiveTab(newTab);
|
||||
};
|
||||
|
||||
// Restaurar conteúdo quando volta para a aba editor
|
||||
useEffect(() => {
|
||||
if (activeTab === 'editor' && editorRef.current && content) {
|
||||
editorRef.current.focus();
|
||||
const range = document.createRange();
|
||||
const sel = window.getSelection();
|
||||
range.setStart(editorRef.current, editorRef.current.childNodes.length);
|
||||
range.collapse(true);
|
||||
sel?.removeAllRanges();
|
||||
sel?.addRange(range);
|
||||
editorRef.current.innerHTML = content;
|
||||
}
|
||||
}, [activeTab]);
|
||||
|
||||
@ -166,20 +181,36 @@ export default function EditarLaudoPage() {
|
||||
const contentHtml = r.content_html || r.conteudo_html || '';
|
||||
|
||||
// Verificar se existe rascunho salvo no localStorage
|
||||
const draftContent = typeof window !== 'undefined' ? localStorage.getItem(`laudo-draft-${laudoId}`) : null;
|
||||
const finalContent = draftContent || contentHtml;
|
||||
let finalContent = contentHtml;
|
||||
let finalCampos = {
|
||||
cid: r.cid_code || r.cid || '',
|
||||
diagnostico: r.diagnosis || r.diagnostico || '',
|
||||
conclusao: r.conclusion || r.conclusao || '',
|
||||
exame: r.exam || r.exame || '',
|
||||
especialidade: r.especialidade || '',
|
||||
mostrarData: !r.hide_date,
|
||||
mostrarAssinatura: !r.hide_signature,
|
||||
};
|
||||
|
||||
if (typeof window !== 'undefined') {
|
||||
const draftData = localStorage.getItem(`laudo-draft-${laudoId}`);
|
||||
if (draftData) {
|
||||
try {
|
||||
const draft = JSON.parse(draftData);
|
||||
if (draft.content) finalContent = draft.content;
|
||||
if (draft.campos) finalCampos = { ...finalCampos, ...draft.campos };
|
||||
} catch (err) {
|
||||
// Se falhar parse, tentar como string simples (formato antigo)
|
||||
finalContent = draftData;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setCampos(finalCampos);
|
||||
setContent(finalContent);
|
||||
|
||||
if (editorRef.current) {
|
||||
editorRef.current.innerHTML = finalContent;
|
||||
// Colocar cursor no final do texto
|
||||
editorRef.current.focus();
|
||||
const range = document.createRange();
|
||||
const sel = window.getSelection();
|
||||
range.setStart(editorRef.current, editorRef.current.childNodes.length);
|
||||
range.collapse(true);
|
||||
sel?.removeAllRanges();
|
||||
sel?.addRange(range);
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn('Erro ao carregar laudo:', err);
|
||||
@ -357,7 +388,7 @@ export default function EditarLaudoPage() {
|
||||
{/* Tabs */}
|
||||
<div className="flex border-b border-border bg-card overflow-x-auto flex-shrink-0">
|
||||
<button
|
||||
onClick={() => setActiveTab('editor')}
|
||||
onClick={() => handleTabChange('editor')}
|
||||
className={`px-2 sm:px-4 py-2 text-xs sm:text-sm font-medium border-b-2 transition-colors whitespace-nowrap ${
|
||||
activeTab === 'editor'
|
||||
? 'border-blue-500 text-blue-600'
|
||||
@ -368,7 +399,7 @@ export default function EditarLaudoPage() {
|
||||
Editor
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setActiveTab('campos')}
|
||||
onClick={() => handleTabChange('campos')}
|
||||
className={`px-2 sm:px-4 py-2 text-xs sm:text-sm font-medium border-b-2 transition-colors whitespace-nowrap ${
|
||||
activeTab === 'campos'
|
||||
? 'border-blue-500 text-blue-600'
|
||||
|
||||
@ -876,17 +876,6 @@ export default function ResultadosClient() {
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
{/* Mais filtros / Voltar */}
|
||||
<div className="sm:col-span-4">
|
||||
<Button
|
||||
variant="outline"
|
||||
className="h-10 w-full rounded-full border border-primary/30 bg-primary/5 text-primary hover:bg-primary hover:text-primary-foreground"
|
||||
>
|
||||
<Filter className="mr-2 h-4 w-4" />
|
||||
Mais filtros
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* Voltar */}
|
||||
<div className="sm:col-span-12">
|
||||
<Button
|
||||
|
||||
@ -1396,13 +1396,13 @@ const ProfissionalPage = () => {
|
||||
|
||||
{/* Filtros */}
|
||||
<div className="p-4 border-b border-border">
|
||||
<div className="flex flex-wrap items-center gap-4">
|
||||
<div className="flex flex-wrap items-start gap-4">
|
||||
<div className="relative flex-1 min-w-[200px]">
|
||||
{/* Search input integrado com busca por ID */}
|
||||
<SearchBox />
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex items-center gap-2 mt-0">
|
||||
<div className="flex items-center gap-1 text-sm">
|
||||
<CalendarIcon className="w-4 h-4" />
|
||||
<Input type="date" value={startDate ?? ''} onChange={(e) => { setStartDate(e.target.value); setSelectedRange('custom'); }} className="p-1 text-sm h-10" />
|
||||
@ -1411,7 +1411,7 @@ const ProfissionalPage = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-2 items-center">
|
||||
<div className="flex gap-2 items-center mt-0">
|
||||
{/* date range buttons: Semana / Mês */}
|
||||
<DateRangeButtons />
|
||||
</div>
|
||||
|
||||
@ -79,7 +79,7 @@ export function PagesHeader({ title = "", subtitle = "" }: { title?: string, sub
|
||||
</Avatar>
|
||||
</Button>
|
||||
{dropdownOpen && (
|
||||
<div className="absolute right-0 mt-2 w-64 sm:w-80 bg-popover border border-border rounded-md shadow-lg z-50 text-popover-foreground animate-in fade-in slide-in-from-top-2">
|
||||
<div className="absolute right-0 mt-2 w-64 sm:w-80 bg-popover border border-border rounded-md shadow-lg z-[100] text-popover-foreground animate-in fade-in slide-in-from-top-2">
|
||||
<div className="p-3 sm:p-4 border-b border-border">
|
||||
<div className="flex flex-col space-y-1">
|
||||
<p className="text-xs sm:text-sm font-semibold leading-none">
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user