style(HistoriaClinica): Agrupar tabs en menu select unificado y mostrar botones de accion en linea
This commit is contained in:
+137
@@ -0,0 +1,137 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
const patterns = [
|
||||||
|
{
|
||||||
|
// Glucemias
|
||||||
|
find: `<div className="flex justify-between">\n <div className="flex gap-2">\n {canEdit && (\n <Button variant="outline" onClick={() => { reset(); setDialog(true); }}>\n <Plus className="h-4 w-4 mr-2" />Nueva\n </Button>\n )}\n <Button variant="outline" onClick={() => setEvolDialog(true)} disabled={listGlucemias.length === 0}>\n <TrendingUp className="h-4 w-4 mr-2" />Evolución\n </Button>\n </div>\n </div>`,
|
||||||
|
replace: `{portalNode ? createPortal(\n <>\n {canEdit && (\n <Button variant="outline" onClick={() => { reset(); setDialog(true); }}>\n <Plus className="h-4 w-4 mr-2" />Nueva\n </Button>\n )}\n <Button variant="outline" onClick={() => setEvolDialog(true)} disabled={listGlucemias.length === 0}>\n <TrendingUp className="h-4 w-4 mr-2" />Evolución\n </Button>\n </>,\n portalNode\n ) : (\n <div className="flex justify-between mb-4">\n <div className="flex gap-2">\n {canEdit && (\n <Button variant="outline" onClick={() => { reset(); setDialog(true); }}>\n <Plus className="h-4 w-4 mr-2" />Nueva\n </Button>\n )}\n <Button variant="outline" onClick={() => setEvolDialog(true)} disabled={listGlucemias.length === 0}>\n <TrendingUp className="h-4 w-4 mr-2" />Evolución\n </Button>\n </div>\n </div>\n )}`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Laboratorios
|
||||||
|
find: `<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">\n {canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}><Plus className="h-4 w-4 mr-2" />Nuevo Laboratorio</Button>}\n <Input placeholder="Buscar por código..." value={searchTerm} onChange={e => setSearchTerm(e.target.value)} className="max-w-xs" />\n </div>`,
|
||||||
|
replace: `
|
||||||
|
{portalNode ? createPortal(
|
||||||
|
<>
|
||||||
|
{canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}><Plus className="h-4 w-4 mr-2" />Nuevo Laboratorio</Button>}
|
||||||
|
<Input placeholder="Buscar..." value={searchTerm} onChange={e => setSearchTerm(e.target.value)} className="max-w-[150px] h-9" />
|
||||||
|
</>,
|
||||||
|
portalNode
|
||||||
|
) : (
|
||||||
|
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-4">
|
||||||
|
{canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}><Plus className="h-4 w-4 mr-2" />Nuevo Laboratorio</Button>}
|
||||||
|
<Input placeholder="Buscar por código..." value={searchTerm} onChange={e => setSearchTerm(e.target.value)} className="max-w-xs" />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
`.trim()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Evoluciones
|
||||||
|
find: `<div className="flex">\n {canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}><Plus className="h-4 w-4 mr-2" />Nueva Evolución</Button>}\n </div>`,
|
||||||
|
replace: `
|
||||||
|
{portalNode ? createPortal(
|
||||||
|
canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}><Plus className="h-4 w-4 mr-2" />Nueva Evolución</Button>,
|
||||||
|
portalNode
|
||||||
|
) : (
|
||||||
|
<div className="flex mb-4">
|
||||||
|
{canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}><Plus className="h-4 w-4 mr-2" />Nueva Evolución</Button>}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
`.trim()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// EAB
|
||||||
|
find: `<div className="flex">\n {canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}><Plus className="h-4 w-4 mr-2" />Nueva Gasometría</Button>}\n </div>`,
|
||||||
|
replace: `
|
||||||
|
{portalNode ? createPortal(
|
||||||
|
canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}><Plus className="h-4 w-4 mr-2" />Nueva Gasometría</Button>,
|
||||||
|
portalNode
|
||||||
|
) : (
|
||||||
|
<div className="flex mb-4">
|
||||||
|
{canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}><Plus className="h-4 w-4 mr-2" />Nueva Gasometría</Button>}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
`.trim()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Cultivos
|
||||||
|
find: `<div className="flex">\n {canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}><Plus className="h-4 w-4 mr-2" />Nuevo Cultivo</Button>}\n </div>`,
|
||||||
|
replace: `
|
||||||
|
{portalNode ? createPortal(
|
||||||
|
canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}><Plus className="h-4 w-4 mr-2" />Nuevo Cultivo</Button>,
|
||||||
|
portalNode
|
||||||
|
) : (
|
||||||
|
<div className="flex mb-4">
|
||||||
|
{canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}><Plus className="h-4 w-4 mr-2" />Nuevo Cultivo</Button>}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
`.trim()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Estudios
|
||||||
|
find: `<div className="flex">\n {canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}><Plus className="h-4 w-4 mr-2" />Nuevo Estudio</Button>}\n </div>`,
|
||||||
|
replace: `
|
||||||
|
{portalNode ? createPortal(
|
||||||
|
canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}><Plus className="h-4 w-4 mr-2" />Nuevo Estudio</Button>,
|
||||||
|
portalNode
|
||||||
|
) : (
|
||||||
|
<div className="flex mb-4">
|
||||||
|
{canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}><Plus className="h-4 w-4 mr-2" />Nuevo Estudio</Button>}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
`.trim()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Interconsultas
|
||||||
|
find: `<div className="flex">\n {canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}><Plus className="h-4 w-4 mr-2" />Nueva Interconsulta</Button>}\n </div>`,
|
||||||
|
replace: `
|
||||||
|
{portalNode ? createPortal(
|
||||||
|
canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}><Plus className="h-4 w-4 mr-2" />Nueva Interconsulta</Button>,
|
||||||
|
portalNode
|
||||||
|
) : (
|
||||||
|
<div className="flex mb-4">
|
||||||
|
{canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}><Plus className="h-4 w-4 mr-2" />Nueva Interconsulta</Button>}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
`.trim()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// ATB
|
||||||
|
find: `<div className="flex">\n {canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}><Plus className="h-4 w-4 mr-2" />Nuevo ATB</Button>}\n </div>`,
|
||||||
|
replace: `
|
||||||
|
{portalNode ? createPortal(
|
||||||
|
canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}><Plus className="h-4 w-4 mr-2" />Nuevo ATB</Button>,
|
||||||
|
portalNode
|
||||||
|
) : (
|
||||||
|
<div className="flex mb-4">
|
||||||
|
{canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}><Plus className="h-4 w-4 mr-2" />Nuevo ATB</Button>}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
`.trim()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Pendientes
|
||||||
|
find: `<div className="flex items-center gap-2">\n {canEdit && <Button variant="outline" onClick={() => { setPendienteEditar(null); resetForm(); setModalAbierto(true); }}><Plus className="h-4 w-4 mr-2" />Nuevo Pendiente</Button>}\n </div>`,
|
||||||
|
replace: `
|
||||||
|
{portalNode ? createPortal(
|
||||||
|
canEdit && <Button variant="outline" onClick={() => { setPendienteEditar(null); resetForm(); setModalAbierto(true); }}><Plus className="h-4 w-4 mr-2" />Nuevo Pendiente</Button>,
|
||||||
|
portalNode
|
||||||
|
) : (
|
||||||
|
<div className="flex items-center gap-2 mb-4">
|
||||||
|
{canEdit && <Button variant="outline" onClick={() => { setPendienteEditar(null); resetForm(); setModalAbierto(true); }}><Plus className="h-4 w-4 mr-2" />Nuevo Pendiente</Button>}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
`.trim()
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
let code = fs.readFileSync('src/sections/HistoriaClinica.tsx', 'utf8');
|
||||||
|
|
||||||
|
for (let p of patterns) {
|
||||||
|
if (code.includes(p.find)) {
|
||||||
|
code = code.replace(p.find, p.replace);
|
||||||
|
} else {
|
||||||
|
console.log("NOT FOUND:", p.find.substring(0, 50));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.writeFileSync('src/sections/HistoriaClinica.tsx', code);
|
||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
let code = fs.readFileSync('src/sections/HistoriaClinica.tsx', 'utf8');
|
||||||
|
|
||||||
|
const repl = `
|
||||||
|
{portalNode ? createPortal(
|
||||||
|
canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}>
|
||||||
|
<Plus className="h-4 w-4 mr-2" />Nuevo
|
||||||
|
</Button>,
|
||||||
|
portalNode
|
||||||
|
) : (
|
||||||
|
<div className="flex justify-between mb-4">
|
||||||
|
{canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}>
|
||||||
|
<Plus className="h-4 w-4 mr-2" />Nuevo
|
||||||
|
</Button>}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
`.trim();
|
||||||
|
|
||||||
|
code = code.replace(
|
||||||
|
/<div className="flex justify-between">\s*\{canEdit && <Button variant="outline" onClick=\{\(\) => \{ reset\(\); setDialog\(true\); \}\}>\s*<Plus className="h-4 w-4 mr-2" \/>Nuevo\s*<\/Button>\}\s*<\/div>/g,
|
||||||
|
repl
|
||||||
|
);
|
||||||
|
|
||||||
|
fs.writeFileSync('src/sections/HistoriaClinica.tsx', code);
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
function fix(filename) {
|
||||||
|
let code = fs.readFileSync(filename, 'utf8');
|
||||||
|
|
||||||
|
// Regex to find the <div className="flex">...</div> or similar that wraps the add button.
|
||||||
|
// We can just find `{canEdit && <Button ...` and wrap it in a portal.
|
||||||
|
// Actually, some have multiple buttons, like SeccionGlucemias has `<Button>Nueva</Button>` and `<Button>Evolución</Button>`
|
||||||
|
|
||||||
|
// A more robust approach:
|
||||||
|
// Instead of replacing the JSX, let's just create a string replacement loop for known patterns.
|
||||||
|
code = code.replace(
|
||||||
|
/<div className="flex">\s*(\{canEdit && <Button variant="outline" onClick=\{.*?>.*?<\/Button>\})\s*<\/div>/g,
|
||||||
|
`{portalNode ? createPortal($1, portalNode) : <div className="flex mb-4">$1</div>}`
|
||||||
|
);
|
||||||
|
|
||||||
|
// Wait, some use `<div className="flex justify-between">` ... Let's just find the first `<div className="flex` block in each Seccion.
|
||||||
|
|
||||||
|
fs.writeFileSync(filename, code);
|
||||||
|
}
|
||||||
|
// This might be too brittle. I'll edit each manually using sed or perl, or precise strings.
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
let code = fs.readFileSync('src/sections/HistoriaClinica.tsx', 'utf8');
|
||||||
|
|
||||||
|
const regex = /<div className="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4">\s*<div className="flex gap-2">\s*\{canEdit && <Button variant="outline" onClick=\{\(\) => \{ reset\(\); setDialog\(true\); \}\}>\s*<Plus className="h-4 w-4 mr-2" \/>\s*Nuevo Estudio\s*<\/Button>\}\s*<\/div>\s*<Select value=\{filtro\} onValueChange=\{\(v: 'todos' \| 'internacion'\) => setFiltro\(v\)\}>\s*<SelectTrigger className="w-\[180px\]">\s*<SelectValue placeholder="Filtrar" \/>\s*<\/SelectTrigger>\s*<SelectContent>\s*<SelectItem value="todos">Todos los estudios<\/SelectItem>\s*<SelectItem value="internacion">Solo esta internación<\/SelectItem>\s*<\/SelectContent>\s*<\/Select>\s*<\/div>/g;
|
||||||
|
|
||||||
|
const repl = `
|
||||||
|
{portalNode ? createPortal(
|
||||||
|
<>
|
||||||
|
{canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}>
|
||||||
|
<Plus className="h-4 w-4 mr-2" />
|
||||||
|
Nuevo Estudio
|
||||||
|
</Button>}
|
||||||
|
<Select value={filtro} onValueChange={(v: 'todos' | 'internacion') => setFiltro(v)}>
|
||||||
|
<SelectTrigger className="w-[180px]">
|
||||||
|
<SelectValue placeholder="Filtrar" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="todos">Todos los estudios</SelectItem>
|
||||||
|
<SelectItem value="internacion">Solo esta internación</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</>,
|
||||||
|
portalNode
|
||||||
|
) : (
|
||||||
|
<div className="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4 mb-4">
|
||||||
|
<div className="flex gap-2">
|
||||||
|
{canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}>
|
||||||
|
<Plus className="h-4 w-4 mr-2" />
|
||||||
|
Nuevo Estudio
|
||||||
|
</Button>}
|
||||||
|
</div>
|
||||||
|
<Select value={filtro} onValueChange={(v: 'todos' | 'internacion') => setFiltro(v)}>
|
||||||
|
<SelectTrigger className="w-[180px]">
|
||||||
|
<SelectValue placeholder="Filtrar" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="todos">Todos los estudios</SelectItem>
|
||||||
|
<SelectItem value="internacion">Solo esta internación</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
`.trim();
|
||||||
|
|
||||||
|
code = code.replace(regex, repl);
|
||||||
|
fs.writeFileSync('src/sections/HistoriaClinica.tsx', code);
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
let code = fs.readFileSync('src/sections/HistoriaClinica.tsx', 'utf8');
|
||||||
|
|
||||||
|
const replIC = `
|
||||||
|
{portalNode ? createPortal(
|
||||||
|
canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}>
|
||||||
|
<Plus className="h-4 w-4 mr-2" />
|
||||||
|
Nueva IC
|
||||||
|
</Button>,
|
||||||
|
portalNode
|
||||||
|
) : (
|
||||||
|
<div className="flex justify-between items-center mb-4">
|
||||||
|
{canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}>
|
||||||
|
<Plus className="h-4 w-4 mr-2" />
|
||||||
|
Nueva IC
|
||||||
|
</Button>}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
`.trim();
|
||||||
|
|
||||||
|
code = code.replace(
|
||||||
|
/<div className="flex justify-between items-center">\s*\{canEdit && <Button variant="outline" onClick=\{\(\) => \{ reset\(\); setDialog\(true\); \}\}>\s*<Plus className="h-4 w-4 mr-2" \/>\s*Nueva IC\s*<\/Button>\}\s*<\/div>/g,
|
||||||
|
replIC
|
||||||
|
);
|
||||||
|
|
||||||
|
fs.writeFileSync('src/sections/HistoriaClinica.tsx', code);
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
let code = fs.readFileSync('src/sections/HistoriaClinica.tsx', 'utf8');
|
||||||
|
|
||||||
|
const regex = /<div className="flex items-center gap-2 w-full sm:w-auto justify-end">\s*<Button variant="outline" size="sm" onClick=\{handleCopiarPendientes\} title="Copiar pendientes activos">\s*<Copy className="h-4 w-4 mr-1\.5" \/>\s*Copiar\s*<\/Button>\s*\{canEdit && \(\s*<Button size="sm" onClick=\{\(\) => \{ resetForm\(\); setModalAbierto\(true\); \}\}>\s*<Plus className="h-4 w-4 mr-1\.5" \/>\s*Nuevo Pendiente\s*<\/Button>\s*\)\}\s*<\/div>/g;
|
||||||
|
|
||||||
|
const repl = `
|
||||||
|
{portalNode ? createPortal(
|
||||||
|
<>
|
||||||
|
<Button variant="outline" size="sm" onClick={handleCopiarPendientes} title="Copiar pendientes activos">
|
||||||
|
<Copy className="h-4 w-4 mr-1.5" />
|
||||||
|
Copiar
|
||||||
|
</Button>
|
||||||
|
{canEdit && (
|
||||||
|
<Button size="sm" onClick={() => { resetForm(); setModalAbierto(true); }}>
|
||||||
|
<Plus className="h-4 w-4 mr-1.5" />
|
||||||
|
Nuevo Pendiente
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</>,
|
||||||
|
portalNode
|
||||||
|
) : (
|
||||||
|
<div className="flex items-center gap-2 w-full sm:w-auto justify-end mb-4">
|
||||||
|
<Button variant="outline" size="sm" onClick={handleCopiarPendientes} title="Copiar pendientes activos">
|
||||||
|
<Copy className="h-4 w-4 mr-1.5" />
|
||||||
|
Copiar
|
||||||
|
</Button>
|
||||||
|
{canEdit && (
|
||||||
|
<Button size="sm" onClick={() => { resetForm(); setModalAbierto(true); }}>
|
||||||
|
<Plus className="h-4 w-4 mr-1.5" />
|
||||||
|
Nuevo Pendiente
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
`.trim();
|
||||||
|
|
||||||
|
code = code.replace(regex, repl);
|
||||||
|
fs.writeFileSync('src/sections/HistoriaClinica.tsx', code);
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
function fix(filename) {
|
||||||
|
let code = fs.readFileSync(filename, 'utf8');
|
||||||
|
|
||||||
|
// Fix duplicate portalNode
|
||||||
|
code = code.replace(/portalNode , portalNode/g, 'portalNode');
|
||||||
|
|
||||||
|
// Add type definition: replace `canEdit?: boolean;` with `canEdit?: boolean; portalNode?: HTMLDivElement | null;`
|
||||||
|
code = code.replace(/canEdit\?: boolean;/g, 'canEdit?: boolean;\n portalNode?: HTMLDivElement | null;');
|
||||||
|
|
||||||
|
// For SeccionPendientes which has `canEdit: boolean })`
|
||||||
|
code = code.replace(/canEdit: boolean \}\)/g, 'canEdit: boolean; portalNode?: HTMLDivElement | null; })');
|
||||||
|
|
||||||
|
// For SeccionIndicaciones (if it uses `canEdit?: boolean`)
|
||||||
|
|
||||||
|
fs.writeFileSync(filename, code);
|
||||||
|
}
|
||||||
|
|
||||||
|
fix('src/sections/HistoriaClinica.tsx');
|
||||||
|
try { fix('src/sections/SeccionIndicaciones.tsx'); } catch(e){}
|
||||||
|
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
let code = fs.readFileSync('src/sections/HistoriaClinica.tsx', 'utf8');
|
||||||
|
|
||||||
|
code = code.replace("import { useState } from 'react';", "import { useState } from 'react';\nimport { createPortal } from 'react-dom';");
|
||||||
|
|
||||||
|
const portalState = "const [tabActivo, setTabActivo] = useState('evoluciones');\n const [portalNode, setPortalNode] = useState<HTMLDivElement | null>(null);";
|
||||||
|
code = code.replace("const [tabActivo, setTabActivo] = useState('evoluciones');", portalState);
|
||||||
|
|
||||||
|
const tabsListRegex = /<ScrollArea className="w-full rounded-md border bg-background whitespace-nowrap">([\s\S]*?)<\/ScrollArea>/;
|
||||||
|
const newTabsList = `
|
||||||
|
<div className="flex flex-col sm:flex-row sm:items-center gap-4 mb-4">
|
||||||
|
<Select value={tabActivo} onValueChange={setTabActivo}>
|
||||||
|
<SelectTrigger className="w-full sm:w-[280px] font-semibold bg-gray-50 border-gray-300">
|
||||||
|
<SelectValue placeholder="Menú de Secciones" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectGroup>
|
||||||
|
<SelectLabel>Menú</SelectLabel>
|
||||||
|
<SelectItem value="evoluciones">Evoluciones ({evoluciones.length})</SelectItem>
|
||||||
|
<SelectItem value="indicaciones">Indicaciones ({indicacionesActivas.length})</SelectItem>
|
||||||
|
<SelectItem value="glucemias">Glucemias ({glucemias.length})</SelectItem>
|
||||||
|
<SelectItem value="laboratorios">Laboratorio ({laboratorios.length})</SelectItem>
|
||||||
|
<SelectItem value="acidobase">EAB ({acidosBase.length})</SelectItem>
|
||||||
|
<SelectItem value="cultivos">Cultivos ({cultivos.length})</SelectItem>
|
||||||
|
<SelectItem value="atb">ATB ({atb.length})</SelectItem>
|
||||||
|
<SelectItem value="estudios">Estudios ({estudiosComplementarios.length})</SelectItem>
|
||||||
|
<SelectItem value="interconsultas">Interconsultas ({interconsultas.length})</SelectItem>
|
||||||
|
<SelectItem value="pendientes">Pendientes ({pendientesActivos.length})</SelectItem>
|
||||||
|
</SelectGroup>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
|
||||||
|
<div ref={setPortalNode} id="menu-actions" className="flex flex-1 items-center gap-2 overflow-x-auto min-h-[40px]"></div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
code = code.replace(tabsListRegex, newTabsList.trim());
|
||||||
|
|
||||||
|
// We also need to add portalNode={portalNode} to all SeccionXXX components
|
||||||
|
code = code.replace(/<SeccionGlucemias (.*?)\/>/g, '<SeccionGlucemias portalNode={portalNode} $1/>');
|
||||||
|
code = code.replace(/<SeccionLaboratorios (.*?)\/>/g, '<SeccionLaboratorios portalNode={portalNode} $1/>');
|
||||||
|
code = code.replace(/<SeccionEvoluciones (.*?)\/>/g, '<SeccionEvoluciones portalNode={portalNode} $1/>');
|
||||||
|
code = code.replace(/<SeccionAcidosBase (.*?)\/>/g, '<SeccionAcidosBase portalNode={portalNode} $1/>');
|
||||||
|
code = code.replace(/<SeccionCultivos (.*?)\/>/g, '<SeccionCultivos portalNode={portalNode} $1/>');
|
||||||
|
code = code.replace(/<SeccionATB (.*?)\/>/g, '<SeccionATB portalNode={portalNode} $1/>');
|
||||||
|
code = code.replace(/<SeccionIndicaciones (.*?)\/>/g, '<SeccionIndicaciones portalNode={portalNode} $1/>');
|
||||||
|
code = code.replace(/<SeccionEstudiosComplementarios (.*?)\/>/g, '<SeccionEstudiosComplementarios portalNode={portalNode} $1/>');
|
||||||
|
code = code.replace(/<SeccionInterconsultas (.*?)\/>/g, '<SeccionInterconsultas portalNode={portalNode} $1/>');
|
||||||
|
code = code.replace(/<SeccionPendientes (.*?)\/>/g, '<SeccionPendientes portalNode={portalNode} $1/>');
|
||||||
|
|
||||||
|
// Update signatures
|
||||||
|
function updateSignature(name) {
|
||||||
|
const regex = new RegExp(`function ${name}\\(\\{ (.*?)canEdit \\}: \\{([\\s\\S]*?)canEdit\\?: boolean;([\\s\\S]*?)\\}\\) \\{`, 'g');
|
||||||
|
// Wait, some might not have canEdit?: boolean optional.
|
||||||
|
}
|
||||||
|
// Actually, it's easier to do this individually or just with a regex
|
||||||
|
|
||||||
|
fs.writeFileSync('src/sections/HistoriaClinica.tsx', code);
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
let code = fs.readFileSync('src/sections/HistoriaClinica.tsx', 'utf8');
|
||||||
|
|
||||||
|
code = code.replace("import { useState } from 'react';", "import { useState } from 'react';\nimport { createPortal } from 'react-dom';");
|
||||||
|
|
||||||
|
const portalState = "const [tabActivo, setTabActivo] = useState('evoluciones');\n const [portalNode, setPortalNode] = useState<HTMLDivElement | null>(null);";
|
||||||
|
code = code.replace("const [tabActivo, setTabActivo] = useState('evoluciones');", portalState);
|
||||||
|
|
||||||
|
const tabsListRegex = /<ScrollArea className="w-full rounded-md border bg-background whitespace-nowrap">([\s\S]*?)<\/ScrollArea>/;
|
||||||
|
const newTabsList = `
|
||||||
|
<div className="flex flex-col sm:flex-row sm:items-center gap-4 mb-4">
|
||||||
|
<Select value={tabActivo} onValueChange={setTabActivo}>
|
||||||
|
<SelectTrigger className="w-full sm:w-[280px] font-semibold bg-gray-50 border-gray-300">
|
||||||
|
<SelectValue placeholder="Menú de Secciones" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectGroup>
|
||||||
|
<SelectLabel>Menú</SelectLabel>
|
||||||
|
<SelectItem value="evoluciones">Evoluciones ({evoluciones.length})</SelectItem>
|
||||||
|
<SelectItem value="indicaciones">Indicaciones ({indicacionesActivas.length})</SelectItem>
|
||||||
|
<SelectItem value="glucemias">Glucemias ({glucemias.length})</SelectItem>
|
||||||
|
<SelectItem value="laboratorios">Laboratorio ({laboratorios.length})</SelectItem>
|
||||||
|
<SelectItem value="acidobase">EAB ({acidosBase.length})</SelectItem>
|
||||||
|
<SelectItem value="cultivos">Cultivos ({cultivos.length})</SelectItem>
|
||||||
|
<SelectItem value="atb">ATB ({atb.length})</SelectItem>
|
||||||
|
<SelectItem value="estudios">Estudios ({estudiosComplementarios.length})</SelectItem>
|
||||||
|
<SelectItem value="interconsultas">Interconsultas ({interconsultas.length})</SelectItem>
|
||||||
|
<SelectItem value="pendientes">Pendientes ({pendientesActivos.length})</SelectItem>
|
||||||
|
</SelectGroup>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
|
||||||
|
<div ref={setPortalNode} id="menu-actions" className="flex flex-1 items-center gap-2 overflow-x-auto min-h-[40px]"></div>
|
||||||
|
</div>
|
||||||
|
`.trim();
|
||||||
|
|
||||||
|
code = code.replace(tabsListRegex, newTabsList);
|
||||||
|
|
||||||
|
fs.writeFileSync('src/sections/HistoriaClinica.tsx', code);
|
||||||
+45
@@ -0,0 +1,45 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
function processFile(filename) {
|
||||||
|
let code = fs.readFileSync(filename, 'utf8');
|
||||||
|
|
||||||
|
// Add import if not present
|
||||||
|
if (!code.includes("import { createPortal }")) {
|
||||||
|
code = code.replace("import { useState }", "import { useState } from 'react';\nimport { createPortal }");
|
||||||
|
if (!code.includes("import { createPortal }")) {
|
||||||
|
code = "import { createPortal } from 'react-dom';\n" + code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update component signatures
|
||||||
|
const components = [
|
||||||
|
'SeccionGlucemias', 'SeccionLaboratorios', 'SeccionEvoluciones',
|
||||||
|
'SeccionAcidosBase', 'SeccionCultivos', 'SeccionATB',
|
||||||
|
'SeccionEstudiosComplementarios', 'SeccionInterconsultas', 'SeccionPendientes',
|
||||||
|
'SeccionIndicaciones'
|
||||||
|
];
|
||||||
|
|
||||||
|
components.forEach(name => {
|
||||||
|
// 1. Add portalNode to the destructured props
|
||||||
|
const regex1 = new RegExp(`function ${name}\\(\\{ (.*?) \\}: \\{`, 'g');
|
||||||
|
code = code.replace(regex1, `function ${name}({ $1, portalNode }: {`);
|
||||||
|
|
||||||
|
// Some don't have spaces around the brackets
|
||||||
|
const regex1b = new RegExp(`function ${name}\\(\\{(.*?)\\}: \\{`, 'g');
|
||||||
|
code = code.replace(regex1b, `function ${name}({$1, portalNode}: {`);
|
||||||
|
|
||||||
|
// 2. Add portalNode?: HTMLDivElement | null; to the type definition
|
||||||
|
// Usually ends with canEdit?: boolean; }) or canEdit: boolean })
|
||||||
|
const regex2 = new RegExp(`(canEdit\\??: boolean;?\\s*)\\}\\)`, 'g');
|
||||||
|
// Actually we can just find the end of the props type definition for that component.
|
||||||
|
// It's safer to just replace `canEdit` or something similar, but let's do a more robust approach.
|
||||||
|
});
|
||||||
|
|
||||||
|
fs.writeFileSync(filename, code);
|
||||||
|
}
|
||||||
|
|
||||||
|
processFile('src/sections/HistoriaClinica.tsx');
|
||||||
|
try {
|
||||||
|
processFile('src/sections/SeccionIndicaciones.tsx');
|
||||||
|
} catch (e) {}
|
||||||
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
import { createPortal } from 'react-dom';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import { User } from 'lucide-react';
|
import { User } from 'lucide-react';
|
||||||
import { useHospitalStore } from '@/hooks/useHospitalStore';
|
import { useHospitalStore } from '@/hooks/useHospitalStore';
|
||||||
@@ -249,6 +250,7 @@ export function HistoriaClinica({
|
|||||||
canEdit,
|
canEdit,
|
||||||
}: HistoriaClinicaProps) {
|
}: HistoriaClinicaProps) {
|
||||||
const [tabActivo, setTabActivo] = useState('evoluciones');
|
const [tabActivo, setTabActivo] = useState('evoluciones');
|
||||||
|
const [portalNode, setPortalNode] = useState<HTMLDivElement | null>(null);
|
||||||
const { pendientes } = useHospitalStore();
|
const { pendientes } = useHospitalStore();
|
||||||
const indicacionesActivas = (indicadores || []).filter(i => i.estado === 'Activa');
|
const indicacionesActivas = (indicadores || []).filter(i => i.estado === 'Activa');
|
||||||
const pendientesActivos = (pendientes || []).filter(p => p.pacienteId === paciente.id && p.estado === 'pendiente');
|
const pendientesActivos = (pendientes || []).filter(p => p.pacienteId === paciente.id && p.estado === 'pendiente');
|
||||||
@@ -536,81 +538,49 @@ export function HistoriaClinica({
|
|||||||
<div className="grid grid-cols-1 w-full">
|
<div className="grid grid-cols-1 w-full">
|
||||||
<div className="w-full overflow-x-auto rounded-md pb-2">
|
<div className="w-full overflow-x-auto rounded-md pb-2">
|
||||||
<Tabs className="w-full" value={tabActivo} onValueChange={setTabActivo}>
|
<Tabs className="w-full" value={tabActivo} onValueChange={setTabActivo}>
|
||||||
<ScrollArea className="w-full rounded-md border bg-background whitespace-nowrap">
|
<div className="flex flex-col sm:flex-row sm:items-center gap-4 mb-4">
|
||||||
<TabsList className="w-full">
|
<Select value={tabActivo} onValueChange={setTabActivo}>
|
||||||
<TabsTrigger value="evoluciones">
|
<SelectTrigger className="w-full sm:w-[280px] font-semibold bg-gray-50 border-gray-300">
|
||||||
<FileText className="h-3 w-3 sm:h-4 sm:w-4" />
|
<SelectValue placeholder="Menú de Secciones" />
|
||||||
<span>Evoluciones</span>
|
</SelectTrigger>
|
||||||
({evoluciones.length})
|
<SelectContent>
|
||||||
</TabsTrigger>
|
<SelectGroup>
|
||||||
|
<SelectLabel>Menú</SelectLabel>
|
||||||
|
<SelectItem value="evoluciones">Evoluciones ({evoluciones.length})</SelectItem>
|
||||||
|
<SelectItem value="indicaciones">Indicaciones ({indicacionesActivas.length})</SelectItem>
|
||||||
|
<SelectItem value="glucemias">Glucemias ({glucemias.length})</SelectItem>
|
||||||
|
<SelectItem value="laboratorios">Laboratorio ({laboratorios.length})</SelectItem>
|
||||||
|
<SelectItem value="acidobase">EAB ({acidosBase.length})</SelectItem>
|
||||||
|
<SelectItem value="cultivos">Cultivos ({cultivos.length})</SelectItem>
|
||||||
|
<SelectItem value="atb">ATB ({atb.length})</SelectItem>
|
||||||
|
<SelectItem value="estudios">Estudios ({estudiosComplementarios.length})</SelectItem>
|
||||||
|
<SelectItem value="interconsultas">Interconsultas ({interconsultas.length})</SelectItem>
|
||||||
|
<SelectItem value="pendientes">Pendientes ({pendientesActivos.length})</SelectItem>
|
||||||
|
</SelectGroup>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
|
||||||
<TabsTrigger value="indicaciones">
|
<div ref={setPortalNode} id="menu-actions" className="flex flex-1 items-center gap-2 overflow-x-auto min-h-[40px]"></div>
|
||||||
<List className="h-3 w-3 sm:h-4 sm:w-4" />
|
</div>
|
||||||
<span>Indicaciones</span>
|
|
||||||
({indicacionesActivas.length})
|
|
||||||
</TabsTrigger>
|
|
||||||
<TabsTrigger value="glucemias">
|
|
||||||
<Droplet className="h-3 w-3 sm:h-4 sm:w-4" />
|
|
||||||
<span>Glucemias</span>
|
|
||||||
({glucemias.length})
|
|
||||||
</TabsTrigger>
|
|
||||||
<TabsTrigger value="laboratorios">
|
|
||||||
<FlaskConical className="h-3 w-3 sm:h-4 sm:w-4" />
|
|
||||||
<span>Laboratorio</span>
|
|
||||||
({laboratorios.length})
|
|
||||||
</TabsTrigger>
|
|
||||||
<TabsTrigger value="acidobase">
|
|
||||||
<Activity className="h-3 w-3 sm:h-4 sm:w-4" />
|
|
||||||
<span>EAB</span>
|
|
||||||
({acidosBase.length})
|
|
||||||
</TabsTrigger>
|
|
||||||
<TabsTrigger value="cultivos">
|
|
||||||
<Microscope className="h-3 w-3 sm:h-4 sm:w-4" />
|
|
||||||
<span>Cultivos</span>
|
|
||||||
({cultivos.length})
|
|
||||||
</TabsTrigger>
|
|
||||||
<TabsTrigger value="atb">
|
|
||||||
<Pill className="h-3 w-3 sm:h-4 sm:w-4" />
|
|
||||||
<span>ATB</span>
|
|
||||||
({atb.length})
|
|
||||||
</TabsTrigger>
|
|
||||||
<TabsTrigger value="estudios">
|
|
||||||
<ClipboardList className="h-3 w-3 sm:h-4 sm:w-4" />
|
|
||||||
<span>Estudios</span>
|
|
||||||
({estudiosComplementarios.length})
|
|
||||||
</TabsTrigger>
|
|
||||||
<TabsTrigger value="interconsultas">
|
|
||||||
<Users className="h-3 w-3 sm:h-4 sm:w-4" />
|
|
||||||
<span>Interconsultas</span>
|
|
||||||
({interconsultas.length})
|
|
||||||
</TabsTrigger>
|
|
||||||
<TabsTrigger value="pendientes">
|
|
||||||
<ListTodo className="h-3 w-3 sm:h-4 sm:w-4" />
|
|
||||||
<span>Pendientes</span>
|
|
||||||
({pendientesActivos.length})
|
|
||||||
</TabsTrigger>
|
|
||||||
</TabsList>
|
|
||||||
<ScrollBar orientation="horizontal" />
|
|
||||||
</ScrollArea>
|
|
||||||
|
|
||||||
<TabsContent value="glucemias" className="mt-4 min-w-0 w-full overflow-hidden">
|
<TabsContent value="glucemias" className="mt-4 min-w-0 w-full overflow-hidden">
|
||||||
<SeccionGlucemias glucemias={glucemias} patientId={paciente.id} internacionId={internacion.id} add={onAgregarGlucemia} update={onActualizarGlucemia} del={onEliminarGlucemia} canEdit={canEdit} />
|
<SeccionGlucemias portalNode={portalNode} glucemias={glucemias} patientId={paciente.id} internacionId={internacion.id} add={onAgregarGlucemia} update={onActualizarGlucemia} del={onEliminarGlucemia} canEdit={canEdit} />
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
|
|
||||||
<TabsContent value="laboratorios" className="mt-4 min-w-0 w-full overflow-hidden">
|
<TabsContent value="laboratorios" className="mt-4 min-w-0 w-full overflow-hidden">
|
||||||
<SeccionLaboratorios lab={laboratorios} patientId={paciente.id} internacionId={internacion.id} add={onAgregarLaboratorio} update={onActualizarLaboratorio} del={onEliminarLaboratorio} addAcidoBase={onAgregarAcidoBase} canEdit={canEdit} />
|
<SeccionLaboratorios portalNode={portalNode} lab={laboratorios} patientId={paciente.id} internacionId={internacion.id} add={onAgregarLaboratorio} update={onActualizarLaboratorio} del={onEliminarLaboratorio} addAcidoBase={onAgregarAcidoBase} canEdit={canEdit} />
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
|
|
||||||
<TabsContent value="evoluciones" className="mt-4">
|
<TabsContent value="evoluciones" className="mt-4">
|
||||||
<SeccionEvoluciones evos={evoluciones} internacionId={internacion.id} add={onAgregarEvolucion} update={onActualizarEvolucion} del={onEliminarEvolucion} canEdit={canEdit} />
|
<SeccionEvoluciones portalNode={portalNode} evos={evoluciones} internacionId={internacion.id} add={onAgregarEvolucion} update={onActualizarEvolucion} del={onEliminarEvolucion} canEdit={canEdit} />
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
|
|
||||||
<TabsContent value="acidobase" className="mt-4">
|
<TabsContent value="acidobase" className="mt-4">
|
||||||
<SeccionAcidosBase ab={acidosBase} patientId={paciente.id} internacionId={internacion.id} add={onAgregarAcidoBase} update={onActualizarAcidoBase} del={onEliminarAcidoBase} canEdit={canEdit} />
|
<SeccionAcidosBase portalNode={portalNode} ab={acidosBase} patientId={paciente.id} internacionId={internacion.id} add={onAgregarAcidoBase} update={onActualizarAcidoBase} del={onEliminarAcidoBase} canEdit={canEdit} />
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
|
|
||||||
<TabsContent value="cultivos" className="mt-4">
|
<TabsContent value="cultivos" className="mt-4">
|
||||||
<SeccionCultivos cults={cultivos} patient={paciente} internacionId={internacion.id} add={onAgregarCultivo} update={onActualizarCultivo} del={onEliminarCultivo} canEdit={canEdit} />
|
<SeccionCultivos portalNode={portalNode} cults={cultivos} patient={paciente} internacionId={internacion.id} add={onAgregarCultivo} update={onActualizarCultivo} del={onEliminarCultivo} canEdit={canEdit} />
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
|
|
||||||
<TabsContent value="atb" className="mt-4">
|
<TabsContent value="atb" className="mt-4">
|
||||||
@@ -680,7 +650,7 @@ export function HistoriaClinica({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function SeccionGlucemias({ glucemias, patientId, internacionId, add, update, del, canEdit }: {
|
function SeccionGlucemias({ glucemias, patientId, internacionId, add, update, del, canEdit, portalNode}: {
|
||||||
glucemias: Glucemia[];
|
glucemias: Glucemia[];
|
||||||
patientId: string;
|
patientId: string;
|
||||||
internacionId: string;
|
internacionId: string;
|
||||||
@@ -688,6 +658,7 @@ function SeccionGlucemias({ glucemias, patientId, internacionId, add, update, de
|
|||||||
update: (id: string, data: Partial<Glucemia>) => void;
|
update: (id: string, data: Partial<Glucemia>) => void;
|
||||||
del: (id: string) => void;
|
del: (id: string) => void;
|
||||||
canEdit?: boolean;
|
canEdit?: boolean;
|
||||||
|
portalNode?: HTMLDivElement | null;
|
||||||
}) {
|
}) {
|
||||||
const [dialog, setDialog] = useState(false);
|
const [dialog, setDialog] = useState(false);
|
||||||
const [evolDialog, setEvolDialog] = useState(false);
|
const [evolDialog, setEvolDialog] = useState(false);
|
||||||
@@ -768,7 +739,20 @@ function SeccionGlucemias({ glucemias, patientId, internacionId, add, update, de
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4 w-full max-w-full min-w-0">
|
<div className="space-y-4 w-full max-w-full min-w-0">
|
||||||
<div className="flex justify-between">
|
{portalNode ? createPortal(
|
||||||
|
<>
|
||||||
|
{canEdit && (
|
||||||
|
<Button variant="outline" onClick={() => { reset(); setDialog(true); }}>
|
||||||
|
<Plus className="h-4 w-4 mr-2" />Nueva
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
<Button variant="outline" onClick={() => setEvolDialog(true)} disabled={listGlucemias.length === 0}>
|
||||||
|
<TrendingUp className="h-4 w-4 mr-2" />Evolución
|
||||||
|
</Button>
|
||||||
|
</>,
|
||||||
|
portalNode
|
||||||
|
) : (
|
||||||
|
<div className="flex justify-between mb-4">
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
{canEdit && (
|
{canEdit && (
|
||||||
<Button variant="outline" onClick={() => { reset(); setDialog(true); }}>
|
<Button variant="outline" onClick={() => { reset(); setDialog(true); }}>
|
||||||
@@ -780,6 +764,7 @@ function SeccionGlucemias({ glucemias, patientId, internacionId, add, update, de
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<Dialog open={dialog} onOpenChange={setDialog}>
|
<Dialog open={dialog} onOpenChange={setDialog}>
|
||||||
<DialogContent className="sm:max-w-md">
|
<DialogContent className="sm:max-w-md">
|
||||||
@@ -940,7 +925,7 @@ function SeccionGlucemias({ glucemias, patientId, internacionId, add, update, de
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function SeccionLaboratorios({ lab, patientId, internacionId, add, update, del, addAcidoBase, canEdit }: {
|
function SeccionLaboratorios({ lab, patientId, internacionId, add, update, del, addAcidoBase, canEdit, portalNode}: {
|
||||||
lab: Laboratorio[];
|
lab: Laboratorio[];
|
||||||
patientId: string;
|
patientId: string;
|
||||||
internacionId: string;
|
internacionId: string;
|
||||||
@@ -949,6 +934,7 @@ function SeccionLaboratorios({ lab, patientId, internacionId, add, update, del,
|
|||||||
del: (id: string) => void;
|
del: (id: string) => void;
|
||||||
addAcidoBase?: (a: Omit<AcidoBase, 'id'>) => void;
|
addAcidoBase?: (a: Omit<AcidoBase, 'id'>) => void;
|
||||||
canEdit?: boolean;
|
canEdit?: boolean;
|
||||||
|
portalNode?: HTMLDivElement | null;
|
||||||
}) {
|
}) {
|
||||||
const [dialog, setDialog] = useState(false);
|
const [dialog, setDialog] = useState(false);
|
||||||
const [obsDialog, setObsDialog] = useState(false);
|
const [obsDialog, setObsDialog] = useState(false);
|
||||||
@@ -1864,13 +1850,14 @@ function SeccionLaboratorios({ lab, patientId, internacionId, add, update, del,
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function SeccionEvoluciones({ evos, internacionId, add, update, del, canEdit }: {
|
function SeccionEvoluciones({ evos, internacionId, add, update, del, canEdit, portalNode}: {
|
||||||
evos: Evolucion[];
|
evos: Evolucion[];
|
||||||
internacionId: string;
|
internacionId: string;
|
||||||
add: (e: Omit<Evolucion, 'id'>) => void;
|
add: (e: Omit<Evolucion, 'id'>) => void;
|
||||||
update: (id: string, data: Partial<Evolucion>) => void;
|
update: (id: string, data: Partial<Evolucion>) => void;
|
||||||
del: (id: string) => void;
|
del: (id: string) => void;
|
||||||
canEdit?: boolean;
|
canEdit?: boolean;
|
||||||
|
portalNode?: HTMLDivElement | null;
|
||||||
}) {
|
}) {
|
||||||
const { currentUser } = useHospitalStore();
|
const { currentUser } = useHospitalStore();
|
||||||
const [dialog, setDialog] = useState(false);
|
const [dialog, setDialog] = useState(false);
|
||||||
@@ -1974,9 +1961,14 @@ function SeccionEvoluciones({ evos, internacionId, add, update, del, canEdit }:
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="flex">
|
{portalNode ? createPortal(
|
||||||
|
canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}><Plus className="h-4 w-4 mr-2" />Nueva Evolución</Button>,
|
||||||
|
portalNode
|
||||||
|
) : (
|
||||||
|
<div className="flex mb-4">
|
||||||
{canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}><Plus className="h-4 w-4 mr-2" />Nueva Evolución</Button>}
|
{canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}><Plus className="h-4 w-4 mr-2" />Nueva Evolución</Button>}
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
<Dialog open={dialog} onOpenChange={setDialog}>
|
<Dialog open={dialog} onOpenChange={setDialog}>
|
||||||
<DialogContent className="sm:max-w-3xl max-h-[90vh] overflow-y-auto">
|
<DialogContent className="sm:max-w-3xl max-h-[90vh] overflow-y-auto">
|
||||||
<DialogHeader><DialogTitle>{edit ? 'Editar' : 'Nueva'} Evolución</DialogTitle></DialogHeader>
|
<DialogHeader><DialogTitle>{edit ? 'Editar' : 'Nueva'} Evolución</DialogTitle></DialogHeader>
|
||||||
@@ -2181,7 +2173,7 @@ function SeccionEvoluciones({ evos, internacionId, add, update, del, canEdit }:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function SeccionAcidosBase({ ab, patientId, internacionId, add, update, del, canEdit }: {
|
function SeccionAcidosBase({ ab, patientId, internacionId, add, update, del, canEdit, portalNode}: {
|
||||||
ab: AcidoBase[];
|
ab: AcidoBase[];
|
||||||
patientId: string;
|
patientId: string;
|
||||||
internacionId: string;
|
internacionId: string;
|
||||||
@@ -2189,6 +2181,7 @@ function SeccionAcidosBase({ ab, patientId, internacionId, add, update, del, can
|
|||||||
update: (id: string, datos: Partial<AcidoBase>) => void;
|
update: (id: string, datos: Partial<AcidoBase>) => void;
|
||||||
del: (id: string) => void;
|
del: (id: string) => void;
|
||||||
canEdit?: boolean;
|
canEdit?: boolean;
|
||||||
|
portalNode?: HTMLDivElement | null;
|
||||||
}) {
|
}) {
|
||||||
const [dialog, setDialog] = useState(false);
|
const [dialog, setDialog] = useState(false);
|
||||||
const [editDialog, setEditDialog] = useState(false);
|
const [editDialog, setEditDialog] = useState(false);
|
||||||
@@ -2260,9 +2253,14 @@ function SeccionAcidosBase({ ab, patientId, internacionId, add, update, del, can
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="flex">
|
{portalNode ? createPortal(
|
||||||
|
canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}><Plus className="h-4 w-4 mr-2" />Nueva Gasometría</Button>,
|
||||||
|
portalNode
|
||||||
|
) : (
|
||||||
|
<div className="flex mb-4">
|
||||||
{canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}><Plus className="h-4 w-4 mr-2" />Nueva Gasometría</Button>}
|
{canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}><Plus className="h-4 w-4 mr-2" />Nueva Gasometría</Button>}
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
<Dialog open={dialog} onOpenChange={setDialog}>
|
<Dialog open={dialog} onOpenChange={setDialog}>
|
||||||
<DialogContent className="sm:max-w-2xl max-h-[90vh] overflow-y-auto">
|
<DialogContent className="sm:max-w-2xl max-h-[90vh] overflow-y-auto">
|
||||||
<DialogHeader><DialogTitle>Nueva Gasometría Arterial</DialogTitle></DialogHeader>
|
<DialogHeader><DialogTitle>Nueva Gasometría Arterial</DialogTitle></DialogHeader>
|
||||||
@@ -2400,7 +2398,7 @@ function SeccionAcidosBase({ ab, patientId, internacionId, add, update, del, can
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function SeccionCultivos({ cults, patient, internacionId, add, update, del, canEdit }: {
|
function SeccionCultivos({ cults, patient, internacionId, add, update, del, canEdit, portalNode}: {
|
||||||
cults: Cultivo[];
|
cults: Cultivo[];
|
||||||
patient: Paciente;
|
patient: Paciente;
|
||||||
internacionId: string;
|
internacionId: string;
|
||||||
@@ -2408,6 +2406,7 @@ function SeccionCultivos({ cults, patient, internacionId, add, update, del, canE
|
|||||||
update: (id: string, data: Partial<Cultivo>) => void;
|
update: (id: string, data: Partial<Cultivo>) => void;
|
||||||
del: (id: string) => void;
|
del: (id: string) => void;
|
||||||
canEdit?: boolean;
|
canEdit?: boolean;
|
||||||
|
portalNode?: HTMLDivElement | null;
|
||||||
}) {
|
}) {
|
||||||
const [dialog, setDialog] = useState(false);
|
const [dialog, setDialog] = useState(false);
|
||||||
const [resDialog, setResDialog] = useState(false);
|
const [resDialog, setResDialog] = useState(false);
|
||||||
@@ -2505,9 +2504,14 @@ function SeccionCultivos({ cults, patient, internacionId, add, update, del, canE
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="flex">
|
{portalNode ? createPortal(
|
||||||
|
canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}><Plus className="h-4 w-4 mr-2" />Nuevo Cultivo</Button>,
|
||||||
|
portalNode
|
||||||
|
) : (
|
||||||
|
<div className="flex mb-4">
|
||||||
{canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}><Plus className="h-4 w-4 mr-2" />Nuevo Cultivo</Button>}
|
{canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}><Plus className="h-4 w-4 mr-2" />Nuevo Cultivo</Button>}
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
<Dialog open={dialog} onOpenChange={setDialog}>
|
<Dialog open={dialog} onOpenChange={setDialog}>
|
||||||
<DialogContent className="sm:max-w-lg">
|
<DialogContent className="sm:max-w-lg">
|
||||||
<DialogHeader><DialogTitle>Nuevo Cultivo</DialogTitle></DialogHeader>
|
<DialogHeader><DialogTitle>Nuevo Cultivo</DialogTitle></DialogHeader>
|
||||||
@@ -2698,7 +2702,7 @@ function SeccionCultivos({ cults, patient, internacionId, add, update, del, canE
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function SeccionEstudiosComplementarios({ estudios, internacionId, pacienteId, add, update, del, canEdit }: {
|
function SeccionEstudiosComplementarios({ estudios, internacionId, pacienteId, add, update, del, canEdit, portalNode}: {
|
||||||
estudios: EstudioComplementario[];
|
estudios: EstudioComplementario[];
|
||||||
internacionId: string;
|
internacionId: string;
|
||||||
pacienteId: string;
|
pacienteId: string;
|
||||||
@@ -2706,6 +2710,7 @@ function SeccionEstudiosComplementarios({ estudios, internacionId, pacienteId, a
|
|||||||
update: (id: string, datos: Partial<EstudioComplementario>) => void;
|
update: (id: string, datos: Partial<EstudioComplementario>) => void;
|
||||||
del: (id: string) => void;
|
del: (id: string) => void;
|
||||||
canEdit?: boolean;
|
canEdit?: boolean;
|
||||||
|
portalNode?: HTMLDivElement | null;
|
||||||
}) {
|
}) {
|
||||||
const [dialog, setDialog] = useState(false);
|
const [dialog, setDialog] = useState(false);
|
||||||
const [filtro, setFiltro] = useState<'todos' | 'internacion'>('internacion');
|
const [filtro, setFiltro] = useState<'todos' | 'internacion'>('internacion');
|
||||||
@@ -2847,7 +2852,7 @@ function SeccionEstudiosComplementarios({ estudios, internacionId, pacienteId, a
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function SeccionInterconsultas({ interconsultas, pacienteId, internacionId, add, update, del, canEdit }: {
|
function SeccionInterconsultas({ interconsultas, pacienteId, internacionId, add, update, del, canEdit, portalNode}: {
|
||||||
interconsultas: Interconsulta[];
|
interconsultas: Interconsulta[];
|
||||||
pacienteId: string;
|
pacienteId: string;
|
||||||
internacionId: string;
|
internacionId: string;
|
||||||
@@ -2855,6 +2860,7 @@ function SeccionInterconsultas({ interconsultas, pacienteId, internacionId, add,
|
|||||||
update: (id: string, datos: Partial<Interconsulta>) => void;
|
update: (id: string, datos: Partial<Interconsulta>) => void;
|
||||||
del: (id: string) => void;
|
del: (id: string) => void;
|
||||||
canEdit?: boolean;
|
canEdit?: boolean;
|
||||||
|
portalNode?: HTMLDivElement | null;
|
||||||
}) {
|
}) {
|
||||||
const [dialog, setDialog] = useState(false);
|
const [dialog, setDialog] = useState(false);
|
||||||
const [fecha, setFecha] = useState(getLocalToday());
|
const [fecha, setFecha] = useState(getLocalToday());
|
||||||
@@ -2902,12 +2908,20 @@ function SeccionInterconsultas({ interconsultas, pacienteId, internacionId, add,
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="flex justify-between items-center">
|
{portalNode ? createPortal(
|
||||||
|
canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}>
|
||||||
|
<Plus className="h-4 w-4 mr-2" />
|
||||||
|
Nueva IC
|
||||||
|
</Button>,
|
||||||
|
portalNode
|
||||||
|
) : (
|
||||||
|
<div className="flex justify-between items-center mb-4">
|
||||||
{canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}>
|
{canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}>
|
||||||
<Plus className="h-4 w-4 mr-2" />
|
<Plus className="h-4 w-4 mr-2" />
|
||||||
Nueva IC
|
Nueva IC
|
||||||
</Button>}
|
</Button>}
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<Dialog open={dialog} onOpenChange={setDialog}>
|
<Dialog open={dialog} onOpenChange={setDialog}>
|
||||||
<DialogContent className="sm:max-w-lg">
|
<DialogContent className="sm:max-w-lg">
|
||||||
@@ -3020,7 +3034,7 @@ function SeccionInterconsultas({ interconsultas, pacienteId, internacionId, add,
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function SeccionATB({ atb, internacionId, pacienteId, add, update, del, canEdit }: {
|
function SeccionATB({ atb, internacionId, pacienteId, add, update, del, canEdit, portalNode}: {
|
||||||
atb: ATB[];
|
atb: ATB[];
|
||||||
internacionId: string;
|
internacionId: string;
|
||||||
pacienteId: string;
|
pacienteId: string;
|
||||||
@@ -3028,6 +3042,7 @@ function SeccionATB({ atb, internacionId, pacienteId, add, update, del, canEdit
|
|||||||
update: (id: string, data: Partial<ATB>) => void;
|
update: (id: string, data: Partial<ATB>) => void;
|
||||||
del: (id: string) => void;
|
del: (id: string) => void;
|
||||||
canEdit?: boolean;
|
canEdit?: boolean;
|
||||||
|
portalNode?: HTMLDivElement | null;
|
||||||
}) {
|
}) {
|
||||||
const [dialog, setDialog] = useState(false);
|
const [dialog, setDialog] = useState(false);
|
||||||
const [edit, setEdit] = useState<ATB | null>(null);
|
const [edit, setEdit] = useState<ATB | null>(null);
|
||||||
@@ -3085,11 +3100,18 @@ function SeccionATB({ atb, internacionId, pacienteId, add, update, del, canEdit
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="flex justify-between">
|
{portalNode ? createPortal(
|
||||||
|
canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}>
|
||||||
|
<Plus className="h-4 w-4 mr-2" />Nuevo
|
||||||
|
</Button>,
|
||||||
|
portalNode
|
||||||
|
) : (
|
||||||
|
<div className="flex justify-between mb-4">
|
||||||
{canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}>
|
{canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}>
|
||||||
<Plus className="h-4 w-4 mr-2" />Nuevo
|
<Plus className="h-4 w-4 mr-2" />Nuevo
|
||||||
</Button>}
|
</Button>}
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<Dialog open={dialog} onOpenChange={setDialog}>
|
<Dialog open={dialog} onOpenChange={setDialog}>
|
||||||
<DialogContent className="sm:max-w-md">
|
<DialogContent className="sm:max-w-md">
|
||||||
@@ -3159,7 +3181,7 @@ function SeccionATB({ atb, internacionId, pacienteId, add, update, del, canEdit
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function SeccionPendientes({ pacienteId, internacionId, canEdit }: { pacienteId: string; internacionId: string; canEdit: boolean }) {
|
function SeccionPendientes({ pacienteId, internacionId, canEdit, portalNode}: { pacienteId: string; internacionId: string; canEdit: boolean; portalNode?: HTMLDivElement | null; }) {
|
||||||
const { pendientes, agregarPendiente, actualizarPendiente, eliminarPendiente, currentUser } = useHospitalStore();
|
const { pendientes, agregarPendiente, actualizarPendiente, eliminarPendiente, currentUser } = useHospitalStore();
|
||||||
const [modalAbierto, setModalAbierto] = useState(false);
|
const [modalAbierto, setModalAbierto] = useState(false);
|
||||||
const [pendienteEditar, setPendienteEditar] = useState<Pendiente | null>(null);
|
const [pendienteEditar, setPendienteEditar] = useState<Pendiente | null>(null);
|
||||||
@@ -3368,7 +3390,22 @@ function SeccionPendientes({ pacienteId, internacionId, canEdit }: { pacienteId:
|
|||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center gap-2 w-full sm:w-auto justify-end">
|
{portalNode ? createPortal(
|
||||||
|
<>
|
||||||
|
<Button variant="outline" size="sm" onClick={handleCopiarPendientes} title="Copiar pendientes activos">
|
||||||
|
<Copy className="h-4 w-4 mr-1.5" />
|
||||||
|
Copiar
|
||||||
|
</Button>
|
||||||
|
{canEdit && (
|
||||||
|
<Button size="sm" onClick={() => { resetForm(); setModalAbierto(true); }}>
|
||||||
|
<Plus className="h-4 w-4 mr-1.5" />
|
||||||
|
Nuevo Pendiente
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</>,
|
||||||
|
portalNode
|
||||||
|
) : (
|
||||||
|
<div className="flex items-center gap-2 w-full sm:w-auto justify-end mb-4">
|
||||||
<Button variant="outline" size="sm" onClick={handleCopiarPendientes} title="Copiar pendientes activos">
|
<Button variant="outline" size="sm" onClick={handleCopiarPendientes} title="Copiar pendientes activos">
|
||||||
<Copy className="h-4 w-4 mr-1.5" />
|
<Copy className="h-4 w-4 mr-1.5" />
|
||||||
Copiar
|
Copiar
|
||||||
@@ -3380,6 +3417,7 @@ function SeccionPendientes({ pacienteId, internacionId, canEdit }: { pacienteId:
|
|||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* List of Pendientes */}
|
{/* List of Pendientes */}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
import { createPortal } from 'react';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import { Badge } from '@/components/ui/badge';
|
import { Badge } from '@/components/ui/badge';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
@@ -13,7 +14,7 @@ import type { Indicacion, IndicacionTipo, ViaAdministracion, TipoPlanHidratacion
|
|||||||
import { useHospitalStore } from '@/hooks/useHospitalStore';
|
import { useHospitalStore } from '@/hooks/useHospitalStore';
|
||||||
import { getNombreProfesional, getLocalToday } from '@/lib/utils';
|
import { getNombreProfesional, getLocalToday } from '@/lib/utils';
|
||||||
|
|
||||||
export function SeccionIndicaciones({ recomendaciones, internacionId, pacienteId, add, update, del, movimientos, onAgregarMovimiento, canEdit, atbList = [], addATB, updateATB }: {
|
export function SeccionIndicaciones({ recomendaciones, internacionId, pacienteId, add, update, del, movimientos, onAgregarMovimiento, canEdit, atbList = [], addATB, updateATB, portalNode}: {
|
||||||
recomendaciones: Indicacion[];
|
recomendaciones: Indicacion[];
|
||||||
internacionId: string;
|
internacionId: string;
|
||||||
pacienteId?: string;
|
pacienteId?: string;
|
||||||
@@ -23,6 +24,7 @@ export function SeccionIndicaciones({ recomendaciones, internacionId, pacienteId
|
|||||||
movimientos?: unknown[];
|
movimientos?: unknown[];
|
||||||
onAgregarMovimiento?: (m: unknown) => void;
|
onAgregarMovimiento?: (m: unknown) => void;
|
||||||
canEdit?: boolean;
|
canEdit?: boolean;
|
||||||
|
portalNode?: HTMLDivElement | null;
|
||||||
atbList?: ATB[];
|
atbList?: ATB[];
|
||||||
addATB?: (a: Omit<ATB, 'id'>) => Promise<unknown>;
|
addATB?: (a: Omit<ATB, 'id'>) => Promise<unknown>;
|
||||||
updateATB?: (id: string, datos: Partial<ATB>) => void;
|
updateATB?: (id: string, datos: Partial<ATB>) => void;
|
||||||
@@ -283,7 +285,18 @@ export function SeccionIndicaciones({ recomendaciones, internacionId, pacienteId
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-2.5">
|
<div className="space-y-2.5">
|
||||||
<div className="flex justify-between items-center">
|
{portalNode ? createPortal(
|
||||||
|
<>
|
||||||
|
{canEdit && <Button size="sm" variant="outline" onClick={() => { reset(); setDialog(true); }}>
|
||||||
|
<Plus className="h-4 w-4 mr-1.5" />Nueva Indicación
|
||||||
|
</Button>}
|
||||||
|
<Button size="sm" variant="ghost" onClick={() => setShowHistorial(!showHistorial)}>
|
||||||
|
{showHistorial ? 'Ocultar Historial' : `Ver Historial (${movs.length})`}
|
||||||
|
</Button>
|
||||||
|
</>,
|
||||||
|
portalNode
|
||||||
|
) : (
|
||||||
|
<div className="flex justify-between items-center mb-4">
|
||||||
{canEdit && <Button size="sm" variant="outline" onClick={() => { reset(); setDialog(true); }}>
|
{canEdit && <Button size="sm" variant="outline" onClick={() => { reset(); setDialog(true); }}>
|
||||||
<Plus className="h-4 w-4 mr-1.5" />Nueva Indicación
|
<Plus className="h-4 w-4 mr-1.5" />Nueva Indicación
|
||||||
</Button>}
|
</Button>}
|
||||||
@@ -291,6 +304,7 @@ export function SeccionIndicaciones({ recomendaciones, internacionId, pacienteId
|
|||||||
{showHistorial ? 'Ocultar Historial' : `Ver Historial (${movs.length})`}
|
{showHistorial ? 'Ocultar Historial' : `Ver Historial (${movs.length})`}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<Dialog open={dialog} onOpenChange={setDialog}>
|
<Dialog open={dialog} onOpenChange={setDialog}>
|
||||||
<DialogContent className="sm:max-w-lg">
|
<DialogContent className="sm:max-w-lg">
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
let hc = fs.readFileSync('src/sections/HistoriaClinica.tsx', 'utf8');
|
||||||
|
|
||||||
|
// Laboratorios
|
||||||
|
hc = hc.replace(
|
||||||
|
/<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">\s*\{canEdit && <Button variant="outline" onClick=\{\(\) => \{ reset\(\); setDialog\(true\); \}\}><Plus className="h-4 w-4 mr-2" \/>Nuevo Laboratorio<\/Button>\}\s*<Input placeholder="Buscar por código..." value=\{searchTerm\} onChange=\{e => setSearchTerm\(e\.target\.value\)\} className="max-w-xs" \/>\s*<\/div>/g,
|
||||||
|
`{portalNode ? createPortal(
|
||||||
|
<>
|
||||||
|
{canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}><Plus className="h-4 w-4 mr-2" />Nuevo Laboratorio</Button>}
|
||||||
|
<Input placeholder="Buscar por código..." value={searchTerm} onChange={e => setSearchTerm(e.target.value)} className="max-w-xs" />
|
||||||
|
</>,
|
||||||
|
portalNode
|
||||||
|
) : (
|
||||||
|
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-4">
|
||||||
|
{canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}><Plus className="h-4 w-4 mr-2" />Nuevo Laboratorio</Button>}
|
||||||
|
<Input placeholder="Buscar por código..." value={searchTerm} onChange={e => setSearchTerm(e.target.value)} className="max-w-xs" />
|
||||||
|
</div>
|
||||||
|
)}`
|
||||||
|
);
|
||||||
|
|
||||||
|
// General pattern for those inside `<div className="flex">`
|
||||||
|
const blocks = [
|
||||||
|
'Nueva Evolución',
|
||||||
|
'Nueva Gasometría',
|
||||||
|
'Nuevo Cultivo',
|
||||||
|
'Nuevo Estudio',
|
||||||
|
'Nueva Interconsulta',
|
||||||
|
'Nuevo ATB'
|
||||||
|
];
|
||||||
|
|
||||||
|
blocks.forEach(text => {
|
||||||
|
const regex = new RegExp(`<div className="flex">\\s*\\{canEdit && <Button variant="outline" onClick=\\{\\(\\) => \\{ reset\\(\\); setDialog\\(true\\); \\}\\}\\><Plus className="h-4 w-4 mr-2" \\/>${text}<\\/Button>\\}\\s*<\\/div>`, 'g');
|
||||||
|
|
||||||
|
hc = hc.replace(regex, `{portalNode ? createPortal(
|
||||||
|
canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}><Plus className="h-4 w-4 mr-2" />${text}</Button>,
|
||||||
|
portalNode
|
||||||
|
) : (
|
||||||
|
<div className="flex mb-4">
|
||||||
|
{canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}><Plus className="h-4 w-4 mr-2" />${text}</Button>}
|
||||||
|
</div>
|
||||||
|
)}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Pendientes
|
||||||
|
hc = hc.replace(
|
||||||
|
/<div className="flex items-center gap-2">\s*\{canEdit && <Button variant="outline" onClick=\{\(\) => \{ setPendienteEditar\(null\); resetForm\(\); setModalAbierto\(true\); \}\}><Plus className="h-4 w-4 mr-2" \/>Nuevo Pendiente<\/Button>\}\s*<\/div>/g,
|
||||||
|
`{portalNode ? createPortal(
|
||||||
|
canEdit && <Button variant="outline" onClick={() => { setPendienteEditar(null); resetForm(); setModalAbierto(true); }}><Plus className="h-4 w-4 mr-2" />Nuevo Pendiente</Button>,
|
||||||
|
portalNode
|
||||||
|
) : (
|
||||||
|
<div className="flex items-center gap-2 mb-4">
|
||||||
|
{canEdit && <Button variant="outline" onClick={() => { setPendienteEditar(null); resetForm(); setModalAbierto(true); }}><Plus className="h-4 w-4 mr-2" />Nuevo Pendiente</Button>}
|
||||||
|
</div>
|
||||||
|
)}`
|
||||||
|
);
|
||||||
|
|
||||||
|
fs.writeFileSync('src/sections/HistoriaClinica.tsx', hc);
|
||||||
|
|
||||||
|
|
||||||
|
let si = fs.readFileSync('src/sections/SeccionIndicaciones.tsx', 'utf8');
|
||||||
|
|
||||||
|
// Also import createPortal
|
||||||
|
if (!si.includes("createPortal")) {
|
||||||
|
si = si.replace("import { useState }", "import { useState } from 'react';\nimport { createPortal }");
|
||||||
|
}
|
||||||
|
|
||||||
|
si = si.replace(
|
||||||
|
/<div className="flex justify-between items-center">\s*\{canEdit && <Button size="sm" variant="outline" onClick=\{\(\) => \{ reset\(\); setDialog\(true\); \}\}>\s*<Plus className="h-4 w-4 mr-1\.5" \/>Nueva Indicación\s*<\/Button>\}\s*<Button size="sm" variant="ghost" onClick=\{\(\) => setShowHistorial\(!showHistorial\)\}>\s*\{showHistorial \? 'Ocultar Historial' : \`Ver Historial \(\$\{movs\.length\}\)\`\}\s*<\/Button>\s*<\/div>/g,
|
||||||
|
`{portalNode ? createPortal(
|
||||||
|
<>
|
||||||
|
{canEdit && <Button size="sm" variant="outline" onClick={() => { reset(); setDialog(true); }}>
|
||||||
|
<Plus className="h-4 w-4 mr-1.5" />Nueva Indicación
|
||||||
|
</Button>}
|
||||||
|
<Button size="sm" variant="ghost" onClick={() => setShowHistorial(!showHistorial)}>
|
||||||
|
{showHistorial ? 'Ocultar Historial' : \`Ver Historial (\${movs.length})\`}
|
||||||
|
</Button>
|
||||||
|
</>,
|
||||||
|
portalNode
|
||||||
|
) : (
|
||||||
|
<div className="flex justify-between items-center mb-4">
|
||||||
|
{canEdit && <Button size="sm" variant="outline" onClick={() => { reset(); setDialog(true); }}>
|
||||||
|
<Plus className="h-4 w-4 mr-1.5" />Nueva Indicación
|
||||||
|
</Button>}
|
||||||
|
<Button size="sm" variant="ghost" onClick={() => setShowHistorial(!showHistorial)}>
|
||||||
|
{showHistorial ? 'Ocultar Historial' : \`Ver Historial (\${movs.length})\`}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
)}`
|
||||||
|
);
|
||||||
|
|
||||||
|
fs.writeFileSync('src/sections/SeccionIndicaciones.tsx', si);
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
let code = fs.readFileSync('src/sections/HistoriaClinica.tsx', 'utf8');
|
||||||
|
|
||||||
|
const regex = /<div className="flex justify-between">\s*<div className="flex gap-2">\s*\{canEdit && \(\s*<Button variant="outline" onClick=\{.*?>\s*<Plus className="h-4 w-4 mr-2" \/>Nueva\s*<\/Button>\s*\)\}\s*<Button variant="outline" onClick=\{.*?\} disabled=\{listGlucemias.length === 0\}>\s*<TrendingUp className="h-4 w-4 mr-2" \/>Evolución\s*<\/Button>\s*<\/div>\s*<\/div>/g;
|
||||||
|
|
||||||
|
const replacement = `
|
||||||
|
{portalNode ? createPortal(
|
||||||
|
<>
|
||||||
|
{canEdit && (
|
||||||
|
<Button variant="outline" onClick={() => { reset(); setDialog(true); }}>
|
||||||
|
<Plus className="h-4 w-4 mr-2" />Nueva
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
<Button variant="outline" onClick={() => setEvolDialog(true)} disabled={listGlucemias.length === 0}>
|
||||||
|
<TrendingUp className="h-4 w-4 mr-2" />Evolución
|
||||||
|
</Button>
|
||||||
|
</>,
|
||||||
|
portalNode
|
||||||
|
) : (
|
||||||
|
<div className="flex justify-between mb-4">
|
||||||
|
<div className="flex gap-2">
|
||||||
|
{canEdit && (
|
||||||
|
<Button variant="outline" onClick={() => { reset(); setDialog(true); }}>
|
||||||
|
<Plus className="h-4 w-4 mr-2" />Nueva
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
<Button variant="outline" onClick={() => setEvolDialog(true)} disabled={listGlucemias.length === 0}>
|
||||||
|
<TrendingUp className="h-4 w-4 mr-2" />Evolución
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
`.trim();
|
||||||
|
|
||||||
|
code = code.replace(regex, replacement);
|
||||||
|
fs.writeFileSync('src/sections/HistoriaClinica.tsx', code);
|
||||||
Reference in New Issue
Block a user