forked from RiseUP/riseup-squad20
fix-laudos-module
This commit is contained in:
parent
a43fdcc655
commit
0a7d3f3ae4
@ -528,6 +528,11 @@ export default function PacientePage() {
|
|||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<User className="h-6 w-6 text-primary" aria-hidden />
|
<User className="h-6 w-6 text-primary" aria-hidden />
|
||||||
<span className="font-bold">Portal do Paciente</span>
|
<span className="font-bold">Portal do Paciente</span>
|
||||||
|
<Button asChild variant="outline" className="ml-4">
|
||||||
|
<Link href="/">
|
||||||
|
<Home className="h-4 w-4 mr-1" /> Início
|
||||||
|
</Link>
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<SimpleThemeToggle />
|
<SimpleThemeToggle />
|
||||||
|
|||||||
@ -2033,14 +2033,40 @@ Nevo melanocítico benigno. Seguimento clínico recomendado.
|
|||||||
}
|
}
|
||||||
}, [laudo, isNewLaudo]);
|
}, [laudo, isNewLaudo]);
|
||||||
|
|
||||||
const formatText = (type: string) => {
|
// Histórico para desfazer/refazer
|
||||||
|
const [history, setHistory] = useState<string[]>([]);
|
||||||
|
const [historyIndex, setHistoryIndex] = useState(-1);
|
||||||
|
|
||||||
|
// Atualiza histórico ao digitar
|
||||||
|
useEffect(() => {
|
||||||
|
if (history[historyIndex] !== content) {
|
||||||
|
const newHistory = history.slice(0, historyIndex + 1);
|
||||||
|
setHistory([...newHistory, content]);
|
||||||
|
setHistoryIndex(newHistory.length);
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line
|
||||||
|
}, [content]);
|
||||||
|
|
||||||
|
const handleUndo = () => {
|
||||||
|
if (historyIndex > 0) {
|
||||||
|
setContent(history[historyIndex - 1]);
|
||||||
|
setHistoryIndex(historyIndex - 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handleRedo = () => {
|
||||||
|
if (historyIndex < history.length - 1) {
|
||||||
|
setContent(history[historyIndex + 1]);
|
||||||
|
setHistoryIndex(historyIndex + 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Formatação avançada
|
||||||
|
const formatText = (type: string, value?: any) => {
|
||||||
const textarea = document.querySelector('textarea') as HTMLTextAreaElement;
|
const textarea = document.querySelector('textarea') as HTMLTextAreaElement;
|
||||||
if (!textarea) return;
|
if (!textarea) return;
|
||||||
|
|
||||||
const start = textarea.selectionStart;
|
const start = textarea.selectionStart;
|
||||||
const end = textarea.selectionEnd;
|
const end = textarea.selectionEnd;
|
||||||
const selectedText = textarea.value.substring(start, end);
|
const selectedText = textarea.value.substring(start, end);
|
||||||
|
|
||||||
let formattedText = "";
|
let formattedText = "";
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case "bold":
|
case "bold":
|
||||||
@ -2050,13 +2076,44 @@ Nevo melanocítico benigno. Seguimento clínico recomendado.
|
|||||||
formattedText = selectedText ? `*${selectedText}*` : "*texto em itálico*";
|
formattedText = selectedText ? `*${selectedText}*` : "*texto em itálico*";
|
||||||
break;
|
break;
|
||||||
case "underline":
|
case "underline":
|
||||||
formattedText = selectedText ? `<u>${selectedText}</u>` : "<u>texto sublinhado</u>";
|
formattedText = selectedText ? `__${selectedText}__` : "__texto sublinhado__";
|
||||||
break;
|
break;
|
||||||
case "list":
|
case "list-ul":
|
||||||
formattedText = selectedText ? `• ${selectedText}` : "• item da lista";
|
formattedText = selectedText ? selectedText.split('\n').map(l => `• ${l}`).join('\n') : "• item da lista";
|
||||||
break;
|
break;
|
||||||
|
case "list-ol":
|
||||||
|
formattedText = selectedText ? selectedText.split('\n').map((l,i) => `${i+1}. ${l}`).join('\n') : "1. item da lista";
|
||||||
|
break;
|
||||||
|
case "indent":
|
||||||
|
formattedText = selectedText ? selectedText.split('\n').map(l => ` ${l}`).join('\n') : " ";
|
||||||
|
break;
|
||||||
|
case "outdent":
|
||||||
|
formattedText = selectedText ? selectedText.split('\n').map(l => l.replace(/^\s{1,4}/, "")).join('\n') : "";
|
||||||
|
break;
|
||||||
|
case "align-left":
|
||||||
|
formattedText = selectedText ? `[left]${selectedText}[/left]` : "[left]Texto à esquerda[/left]";
|
||||||
|
break;
|
||||||
|
case "align-center":
|
||||||
|
formattedText = selectedText ? `[center]${selectedText}[/center]` : "[center]Texto centralizado[/center]";
|
||||||
|
break;
|
||||||
|
case "align-right":
|
||||||
|
formattedText = selectedText ? `[right]${selectedText}[/right]` : "[right]Texto à direita[/right]";
|
||||||
|
break;
|
||||||
|
case "align-justify":
|
||||||
|
formattedText = selectedText ? `[justify]${selectedText}[/justify]` : "[justify]Texto justificado[/justify]";
|
||||||
|
break;
|
||||||
|
case "font-size":
|
||||||
|
formattedText = selectedText ? `[size=${value}]${selectedText}[/size]` : `[size=${value}]Texto tamanho ${value}[/size]`;
|
||||||
|
break;
|
||||||
|
case "font-family":
|
||||||
|
formattedText = selectedText ? `[font=${value}]${selectedText}[/font]` : `[font=${value}]${value}[/font]`;
|
||||||
|
break;
|
||||||
|
case "font-color":
|
||||||
|
formattedText = selectedText ? `[color=${value}]${selectedText}[/color]` : `[color=${value}]${value}[/color]`;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const newText = textarea.value.substring(0, start) + formattedText + textarea.value.substring(end);
|
const newText = textarea.value.substring(0, start) + formattedText + textarea.value.substring(end);
|
||||||
setContent(newText);
|
setContent(newText);
|
||||||
};
|
};
|
||||||
@ -2085,7 +2142,14 @@ Nevo melanocítico benigno. Seguimento clínico recomendado.
|
|||||||
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(/__(.*?)__/g, '<u>$1</u>')
|
||||||
|
.replace(/\[left\](.*?)\[\/left\]/gs, '<div style="text-align:left">$1</div>')
|
||||||
|
.replace(/\[center\](.*?)\[\/center\]/gs, '<div style="text-align:center">$1</div>')
|
||||||
|
.replace(/\[right\](.*?)\[\/right\]/gs, '<div style="text-align:right">$1</div>')
|
||||||
|
.replace(/\[justify\](.*?)\[\/justify\]/gs, '<div style="text-align:justify">$1</div>')
|
||||||
|
.replace(/\[size=(\d+)\](.*?)\[\/size\]/gs, '<span style="font-size:$1px">$2</span>')
|
||||||
|
.replace(/\[font=([^\]]+)\](.*?)\[\/font\]/gs, '<span style="font-family:$1">$2</span>')
|
||||||
|
.replace(/\[color=([^\]]+)\](.*?)\[\/color\]/gs, '<span style="color:$1">$2</span>')
|
||||||
.replace(/{{sexo_paciente}}/g, pacienteSelecionado?.sexo || laudo?.paciente?.sexo || '[SEXO]')
|
.replace(/{{sexo_paciente}}/g, pacienteSelecionado?.sexo || laudo?.paciente?.sexo || '[SEXO]')
|
||||||
.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]')
|
||||||
@ -2384,44 +2448,60 @@ Nevo melanocítico benigno. Seguimento clínico recomendado.
|
|||||||
<div className="flex-1 flex flex-col">
|
<div className="flex-1 flex flex-col">
|
||||||
{/* Toolbar */}
|
{/* Toolbar */}
|
||||||
<div className="p-3 border-b border-border">
|
<div className="p-3 border-b border-border">
|
||||||
<div className="flex flex-wrap gap-2">
|
<div className="flex flex-wrap gap-2 items-center">
|
||||||
<Button
|
{/* Tamanho da fonte */}
|
||||||
variant="outline"
|
<label className="text-xs mr-1">Tamanho</label>
|
||||||
size="sm"
|
<input
|
||||||
onClick={() => formatText("bold")}
|
type="number"
|
||||||
title="Negrito"
|
min={8}
|
||||||
className="hover:bg-blue-50 dark:hover:bg-accent"
|
max={32}
|
||||||
|
defaultValue={14}
|
||||||
|
onBlur={e => formatText('font-size', e.target.value)}
|
||||||
|
className="w-14 border rounded px-1 py-0.5 text-xs mr-2"
|
||||||
|
title="Tamanho da fonte"
|
||||||
|
/>
|
||||||
|
{/* Família da fonte */}
|
||||||
|
<label className="text-xs mr-1">Fonte</label>
|
||||||
|
<select
|
||||||
|
defaultValue={'Arial'}
|
||||||
|
onBlur={e => formatText('font-family', e.target.value)}
|
||||||
|
className="border rounded px-1 py-0.5 text-xs mr-2"
|
||||||
|
title="Família da fonte"
|
||||||
>
|
>
|
||||||
<strong>B</strong>
|
<option value="Arial">Arial</option>
|
||||||
</Button>
|
<option value="Helvetica">Helvetica</option>
|
||||||
<Button
|
<option value="Times New Roman">Times New Roman</option>
|
||||||
variant="outline"
|
<option value="Courier New">Courier New</option>
|
||||||
size="sm"
|
<option value="Verdana">Verdana</option>
|
||||||
onClick={() => formatText("italic")}
|
<option value="Georgia">Georgia</option>
|
||||||
title="Itálico"
|
</select>
|
||||||
className="hover:bg-blue-50 dark:hover:bg-accent"
|
{/* Cor da fonte */}
|
||||||
>
|
<label className="text-xs mr-1">Cor</label>
|
||||||
<em>I</em>
|
<input
|
||||||
</Button>
|
type="color"
|
||||||
<Button
|
defaultValue="#222222"
|
||||||
variant="outline"
|
onBlur={e => formatText('font-color', e.target.value)}
|
||||||
size="sm"
|
className="w-6 h-6 border rounded mr-2"
|
||||||
onClick={() => formatText("underline")}
|
title="Cor da fonte"
|
||||||
title="Sublinhado"
|
/>
|
||||||
className="hover:bg-blue-50 dark:hover:bg-accent"
|
{/* Alinhamento */}
|
||||||
>
|
<Button variant="outline" size="sm" onClick={() => formatText('align-left')} title="Alinhar à esquerda" className="px-1"><svg width="16" height="16" fill="none"><rect x="2" y="4" width="12" height="2" rx="1" fill="currentColor"/><rect x="2" y="7" width="8" height="2" rx="1" fill="currentColor"/><rect x="2" y="10" width="10" height="2" rx="1" fill="currentColor"/></svg></Button>
|
||||||
<u>U</u>
|
<Button variant="outline" size="sm" onClick={() => formatText('align-center')} title="Centralizar" className="px-1"><svg width="16" height="16" fill="none"><rect x="4" y="4" width="8" height="2" rx="1" fill="currentColor"/><rect x="2" y="7" width="12" height="2" rx="1" fill="currentColor"/><rect x="3" y="10" width="10" height="2" rx="1" fill="currentColor"/></svg></Button>
|
||||||
</Button>
|
<Button variant="outline" size="sm" onClick={() => formatText('align-right')} title="Alinhar à direita" className="px-1"><svg width="16" height="16" fill="none"><rect x="6" y="4" width="8" height="2" rx="1" fill="currentColor"/><rect x="2" y="7" width="12" height="2" rx="1" fill="currentColor"/><rect x="4" y="10" width="10" height="2" rx="1" fill="currentColor"/></svg></Button>
|
||||||
<Button
|
<Button variant="outline" size="sm" onClick={() => formatText('align-justify')} title="Justificar" className="px-1"><svg width="16" height="16" fill="none"><rect x="2" y="4" width="12" height="2" rx="1" fill="currentColor"/><rect x="2" y="7" width="12" height="2" rx="1" fill="currentColor"/><rect x="2" y="10" width="12" height="2" rx="1" fill="currentColor"/></svg></Button>
|
||||||
variant="outline"
|
{/* Listas */}
|
||||||
size="sm"
|
<Button variant="outline" size="sm" onClick={() => formatText('list-ol')} title="Lista numerada" className="px-1">1.</Button>
|
||||||
onClick={() => formatText("list")}
|
<Button variant="outline" size="sm" onClick={() => formatText('list-ul')} title="Lista com marcadores" className="px-1">•</Button>
|
||||||
title="Lista"
|
{/* Recuo */}
|
||||||
className="hover:bg-blue-50 dark:hover:bg-accent"
|
<Button variant="outline" size="sm" onClick={() => formatText('indent')} title="Aumentar recuo" className="px-1">→</Button>
|
||||||
>
|
<Button variant="outline" size="sm" onClick={() => formatText('outdent')} title="Diminuir recuo" className="px-1">←</Button>
|
||||||
•
|
{/* Desfazer/Refazer */}
|
||||||
</Button>
|
<Button variant="outline" size="sm" onClick={handleUndo} title="Desfazer" className="px-1">↺</Button>
|
||||||
|
<Button variant="outline" size="sm" onClick={handleRedo} title="Refazer" className="px-1">↻</Button>
|
||||||
|
{/* Negrito, itálico, sublinhado */}
|
||||||
|
<Button variant="outline" size="sm" onClick={() => formatText("bold") } title="Negrito" className="hover:bg-blue-50 dark:hover:bg-accent"><strong>B</strong></Button>
|
||||||
|
<Button variant="outline" size="sm" onClick={() => formatText("italic") } title="Itálico" className="hover:bg-blue-50 dark:hover:bg-accent"><em>I</em></Button>
|
||||||
|
<Button variant="outline" size="sm" onClick={() => formatText("underline") } title="Sublinhado" className="hover:bg-blue-50 dark:hover:bg-accent"><u>U</u></Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Templates */}
|
{/* Templates */}
|
||||||
@ -2444,12 +2524,13 @@ Nevo melanocítico benigno. Seguimento clínico recomendado.
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Editor */}
|
{/* Editor */}
|
||||||
<div className="flex-1 p-4">
|
<div className="flex-1 p-4 overflow-auto max-h-[500px]">
|
||||||
<Textarea
|
<Textarea
|
||||||
value={content}
|
value={content}
|
||||||
onChange={(e) => setContent(e.target.value)}
|
onChange={(e) => setContent(e.target.value)}
|
||||||
placeholder="Digite o conteúdo do laudo aqui. Use ** para negrito, * para itálico, <u></u> para sublinhado."
|
placeholder="Digite o conteúdo do laudo aqui. Use ** para negrito, * para itálico, <u></u> para sublinhado."
|
||||||
className="h-full min-h-[400px] resize-none"
|
className="h-full min-h-[400px] resize-none scrollbar-thin scrollbar-thumb-blue-400 scrollbar-track-blue-100"
|
||||||
|
style={{ maxHeight: 400, overflow: 'auto' }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user