chore: Eliminar scripts de transformacion temporales

This commit is contained in:
2026-08-12 20:39:53 +00:00
parent fce539abc2
commit ead841df6c
24 changed files with 0 additions and 957 deletions
-137
View File
@@ -1,137 +0,0 @@
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);
-23
View File
@@ -1,23 +0,0 @@
import js from '@eslint/js'
import globals from 'globals'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
import tseslint from 'typescript-eslint'
import { defineConfig, globalIgnores } from 'eslint/config'
export default defineConfig([
globalIgnores(['dist']),
{
files: ['**/*.{ts,tsx}'],
extends: [
js.configs.recommended,
tseslint.configs.recommended,
reactHooks.configs.flat.recommended,
reactRefresh.configs.vite,
],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
},
])
-24
View File
@@ -1,24 +0,0 @@
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);
-21
View File
@@ -1,21 +0,0 @@
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.
-46
View File
@@ -1,46 +0,0 @@
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);
-26
View File
@@ -1,26 +0,0 @@
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);
-38
View File
@@ -1,38 +0,0 @@
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);
-22
View File
@@ -1,22 +0,0 @@
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){}
-58
View File
@@ -1,58 +0,0 @@
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);
-39
View File
@@ -1,39 +0,0 @@
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
View File
@@ -1,45 +0,0 @@
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) {}
-10
View File
@@ -1,10 +0,0 @@
const fs = require('fs');
let code = fs.readFileSync('src/App.tsx', 'utf8');
code = code.replace(/store\.getLaboratoriosByPaciente\(paciente\.id\)/g, 'store.getLaboratoriosByInternacion(internacion.id)');
code = code.replace(/store\.getGlucemiasByPaciente\(paciente\.id\)/g, 'store.getGlucemiasByInternacion(internacion.id)');
code = code.replace(/store\.getAcidosBaseByPaciente\(paciente\.id\)/g, 'store.getAcidosBaseByInternacion(internacion.id)');
code = code.replace(/store\.getCultivosByPaciente\(paciente\.id\)/g, 'store.getCultivosByInternacion(internacion.id)');
code = code.replace(/store\.estudiosComplementarios\.filter\(e => e\.pacienteId === paciente\.id\)/g, 'store.estudiosComplementarios.filter(e => e.internacionId === internacion.id)');
fs.writeFileSync('src/App.tsx', code);
-109
View File
@@ -1,109 +0,0 @@
const fs = require('fs');
let code = fs.readFileSync('server/db.js', 'utf8');
// Add computeSector function
const computeSectorCode = `
function computeSector(numero) {
if (!numero) return 'En Área';
const parts = String(numero).trim().split('-');
if (parts.length === 0) return 'En Área';
const salaStr = parts[0].trim();
const salaNum = parseInt(salaStr, 10);
if (isNaN(salaNum)) return 'En Área';
if (salaNum >= 300 && salaNum < 400 && salaNum % 2 !== 0) {
return 'Fuera de Área';
}
if (salaNum >= 400 && salaNum < 500) {
return 'Fuera de Área';
}
return 'En Área';
}
`;
// Find where to insert computeSector
code = code.replace("export function createCama(cama) {", computeSectorCode + "\nexport function createCama(cama) {");
// Update createCama
code = code.replace(
/export function createCama\(cama\) \{\s*const gId = cama.grupoId \|\| cama.areaId \|\| null;\s*db.prepare\('INSERT INTO camas \(id, numero, grupoId, areaId, tipo, estado, pacienteId, internacionId\) VALUES \(\?, \?, \?, \?, \?, \?, \?, \?\)'\)\.run\(cama.id, cama.numero, gId, gId, cama.tipo \|\| 'Estándar', cama.estado \|\| 'Disponible', cama.pacienteId \|\| null, cama.internacionId \|\| null\);\s*\}/,
`export function createCama(cama) {
const gId = cama.grupoId || cama.areaId || null;
const sector = computeSector(cama.numero);
db.prepare('INSERT INTO camas (id, numero, grupoId, areaId, tipo, estado, pacienteId, internacionId, sector) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)').run(cama.id, cama.numero, gId, gId, cama.tipo || 'Estándar', cama.estado || 'Disponible', cama.pacienteId || null, cama.internacionId || null, sector);
}`
);
// Update updateCama
code = code.replace(
/export function updateCama\(id, updates\) \{[\s\S]*?if \(fields\.length > 0\) \{/,
`export function updateCama(id, updates) {
const fields = [];
const values = [];
if (updates.numero !== undefined) {
fields.push('numero = ?');
values.push(updates.numero);
fields.push('sector = ?');
values.push(computeSector(updates.numero));
}
if (updates.tipo !== undefined) {
fields.push('tipo = ?');
values.push(updates.tipo);
}
if (updates.grupoId !== undefined) {
fields.push('grupoId = ?');
values.push(updates.grupoId);
fields.push('areaId = ?');
values.push(updates.grupoId);
}
if (updates.estado !== undefined) {
fields.push('estado = ?');
values.push(updates.estado);
}
if (updates.pacienteId !== undefined) {
fields.push('pacienteId = ?');
values.push(updates.pacienteId);
}
if (updates.internacionId !== undefined) {
fields.push('internacionId = ?');
values.push(updates.internacionId);
}
if (fields.length > 0) {`
);
// Update table schema
code = code.replace(
/CREATE TABLE IF NOT EXISTS camas \(\s*id TEXT PRIMARY KEY,\s*numero TEXT NOT NULL,\s*grupoId TEXT,\s*areaId TEXT,\s*tipo TEXT DEFAULT 'Estándar',\s*estado TEXT DEFAULT 'Disponible',\s*pacienteId TEXT,\s*internacionId TEXT\s*\);/,
`CREATE TABLE IF NOT EXISTS camas (
id TEXT PRIMARY KEY,
numero TEXT NOT NULL,
grupoId TEXT,
areaId TEXT,
tipo TEXT DEFAULT 'Estándar',
estado TEXT DEFAULT 'Disponible',
pacienteId TEXT,
internacionId TEXT,
sector TEXT DEFAULT 'En Área'
);
try {
db.prepare("ALTER TABLE camas ADD COLUMN sector TEXT DEFAULT 'En Área'").run();
} catch(e) {}
try {
// Initialize existing beds with their sector
const rows = db.prepare('SELECT id, numero FROM camas WHERE sector IS NULL OR sector = "En Área"').all();
for (const row of rows) {
if (!row.numero) continue;
const salaStr = String(row.numero).trim().split('-')[0].trim();
const salaNum = parseInt(salaStr, 10);
let s = 'En Área';
if (!isNaN(salaNum)) {
if (salaNum >= 300 && salaNum < 400 && salaNum % 2 !== 0) s = 'Fuera de Área';
else if (salaNum >= 400 && salaNum < 500) s = 'Fuera de Área';
}
db.prepare('UPDATE camas SET sector = ? WHERE id = ?').run(s, row.id);
}
} catch(e) {}`
);
fs.writeFileSync('server/db.js', code);
-10
View File
@@ -1,10 +0,0 @@
const fs = require('fs');
let code = fs.readFileSync('server/db.js', 'utf8');
code = code.replace(
/const __dirname = dirname\(fileURLToPath\(import\.meta\.url\)\);/,
`const currentDir = typeof __dirname !== 'undefined' ? __dirname : dirname(fileURLToPath(import.meta.url));`
);
code = code.replace(/__dirname/g, "currentDir");
fs.writeFileSync('server/db.js', code);
-9
View File
@@ -1,9 +0,0 @@
const fs = require('fs');
let code = fs.readFileSync('server/db.js', 'utf8');
code = code.replace(
/const currentDir = typeof currentDir !== 'undefined' \? currentDir : dirname\(fileURLToPath\(import\.meta\.url\)\);/,
`const currentDir = typeof __dirname !== 'undefined' ? __dirname : dirname(fileURLToPath(import.meta.url));`
);
fs.writeFileSync('server/db.js', code);
-40
View File
@@ -1,40 +0,0 @@
const fs = require('fs');
let code = fs.readFileSync('server/index.js', 'utf8');
const computeSectorCode = `
function computeSector(numero) {
if (!numero) return 'En Área';
const parts = String(numero).trim().split('-');
if (parts.length === 0) return 'En Área';
const salaStr = parts[0].trim();
const salaNum = parseInt(salaStr, 10);
if (isNaN(salaNum)) return 'En Área';
if (salaNum >= 300 && salaNum < 400 && salaNum % 2 !== 0) return 'Fuera de Área';
if (salaNum >= 400 && salaNum < 500) return 'Fuera de Área';
return 'En Área';
}
`;
// Insert computeSector somewhere at the top
code = code.replace("const PORT = process.env.PORT || 3000;", computeSectorCode + "\nconst PORT = process.env.PORT || 3000;");
code = code.replace(
/const stmt = db\.prepare\('INSERT OR IGNORE INTO camas \(id, numero, grupoId, areaId, tipo, estado\) VALUES \(\?, \?, \?, \?, \?, \?\)'\);\s*for \(const c of state\.camas\) \{\s*const gId = c\.grupoId \|\| c\.areaId \|\| null;\s*stmt\.run\(c\.id, c\.numero, gId, gId, c\.tipo, c\.estado\);\s*\}/,
`const stmt = db.prepare('INSERT OR IGNORE INTO camas (id, numero, grupoId, areaId, tipo, estado, sector) VALUES (?, ?, ?, ?, ?, ?, ?)');
for (const c of state.camas) {
const gId = c.grupoId || c.areaId || null;
const sector = computeSector(c.numero);
stmt.run(c.id, c.numero, gId, gId, c.tipo, c.estado, sector);
}`
);
code = code.replace(
/const stmt = db\.prepare\('INSERT INTO camas \(id, numero, areaId, tipo, estado\) VALUES \(\?, \?, \?, \?, \?\)'\);\s*for \(const c of updates\.camas\) \{\s*stmt\.run\(c\.id, c\.numero, c\.areaId, c\.tipo, c\.estado\);\s*\}/,
`const stmt = db.prepare('INSERT INTO camas (id, numero, grupoId, areaId, tipo, estado, sector) VALUES (?, ?, ?, ?, ?, ?, ?)');
for (const c of updates.camas) {
const sector = computeSector(c.numero);
stmt.run(c.id, c.numero, c.grupoId || c.areaId || null, c.grupoId || c.areaId || null, c.tipo, c.estado, sector);
}`
);
fs.writeFileSync('server/index.js', code);
-31
View File
@@ -1,31 +0,0 @@
const fs = require('fs');
let code = fs.readFileSync('server/db.js', 'utf8');
code = code.replace(
/ \);\n try \{\n db\.prepare\("ALTER TABLE camas ADD COLUMN sector TEXT DEFAULT 'En Área'"\)\.run\(\);\n \} catch\(e\) \{\}\n try \{\n \/\/ Initialize existing beds with their sector\n const rows = db\.prepare\('SELECT id, numero FROM camas WHERE sector IS NULL OR sector = "En Área"'\)\.all\(\);\n for \(const row of rows\) \{\n if \(\!row\.numero\) continue;\n const salaStr = String\(row\.numero\)\.trim\(\)\.split\('-'\)\[0\]\.trim\(\);\n const salaNum = parseInt\(salaStr, 10\);\n let s = 'En Área';\n if \(\!isNaN\(salaNum\)\) \{\n if \(salaNum >= 300 && salaNum < 400 && salaNum % 2 !== 0\) s = 'Fuera de Área';\n else if \(salaNum >= 400 && salaNum < 500\) s = 'Fuera de Área';\n \}\n db\.prepare\('UPDATE camas SET sector = \? WHERE id = \?'\)\.run\(s, row\.id\);\n \}\n \} catch\(e\) \{\}/,
` );`
);
code = code.replace(
/\/\/ Seed default 4 grupos if empty/,
`try { db.exec("ALTER TABLE camas ADD COLUMN sector TEXT DEFAULT 'En Área'"); } catch (_) {}
try {
// Initialize existing beds with their sector
const rows = db.prepare('SELECT id, numero FROM camas WHERE sector IS NULL OR sector = "En Área"').all();
for (const row of rows) {
if (!row.numero) continue;
const salaStr = String(row.numero).trim().split('-')[0].trim();
const salaNum = parseInt(salaStr, 10);
let s = 'En Área';
if (!isNaN(salaNum)) {
if (salaNum >= 300 && salaNum < 400 && salaNum % 2 !== 0) s = 'Fuera de Área';
else if (salaNum >= 400 && salaNum < 500) s = 'Fuera de Área';
}
db.prepare('UPDATE camas SET sector = ? WHERE id = ?').run(s, row.id);
}
} catch(e) {}
// Seed default 4 grupos if empty`
);
fs.writeFileSync('server/db.js', code);
-21
View File
@@ -1,21 +0,0 @@
const fs = require('fs');
let code = fs.readFileSync('src/hooks/useHospitalStore.ts', 'utf8');
code = code.replace(/getLaboratoriosByPaciente = useCallback\(\(pacienteId: string\)/g, 'getLaboratoriosByInternacion = useCallback((internacionId: string)');
code = code.replace(/\.filter\(l => l\.pacienteId === pacienteId\)/g, '.filter(l => l.internacionId === internacionId)');
code = code.replace(/getGlucemiasByPaciente = useCallback\(\(pacienteId: string\)/g, 'getGlucemiasByInternacion = useCallback((internacionId: string)');
code = code.replace(/\.filter\(g => g\.pacienteId === pacienteId\)/g, '.filter(g => g.internacionId === internacionId)');
code = code.replace(/getAcidosBaseByPaciente = useCallback\(\(pacienteId: string\)/g, 'getAcidosBaseByInternacion = useCallback((internacionId: string)');
code = code.replace(/\.filter\(a => a\.pacienteId === pacienteId\)/g, '.filter(a => a.internacionId === internacionId)');
code = code.replace(/getCultivosByPaciente = useCallback\(\(pacienteId: string\)/g, 'getCultivosByInternacion = useCallback((internacionId: string)');
code = code.replace(/\.filter\(c => c\.pacienteId === pacienteId\)/g, '.filter(c => c.internacionId === internacionId)');
code = code.replace(/getLaboratoriosByPaciente,/g, 'getLaboratoriosByInternacion,');
code = code.replace(/getGlucemiasByPaciente,/g, 'getGlucemiasByInternacion,');
code = code.replace(/getAcidosBaseByPaciente,/g, 'getAcidosBaseByInternacion,');
code = code.replace(/getCultivosByPaciente,/g, 'getCultivosByInternacion,');
fs.writeFileSync('src/hooks/useHospitalStore.ts', code);
-13
View File
@@ -1,13 +0,0 @@
const fs = require('fs');
let code = fs.readFileSync('src/hooks/useHospitalStore.ts', 'utf8');
code = code.replace(
/try \{\s*await apiCall\('PUT', `\/camas\/\$\{id\}`/,
`try {
if (datos.numero !== undefined) {
datos.sector = computeSector(datos.numero);
}
await apiCall('PUT', \`/camas/\${id}\``
);
fs.writeFileSync('src/hooks/useHospitalStore.ts', code);
-16
View File
@@ -1,16 +0,0 @@
const fs = require('fs');
let code = fs.readFileSync('src/lib/utils.ts', 'utf8');
code = code.replace(
/export function isCamaFueraDeGrupo\([\s\S]*?return false;\n\}/,
`export function isCamaFueraDeGrupo(
cama: { numero: string; grupoId?: string; areaId?: string; sector?: string },
gruposOrAreas?: { id: string; nombre: string }[]
): boolean {
if (cama.sector === 'Fuera de Área') return true;
if (cama.sector === 'En Área') return false;
return computeSector(cama.numero) === 'Fuera de Área';
}`
);
fs.writeFileSync('src/lib/utils.ts', code);
-6
View File
@@ -1,6 +0,0 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
-84
View File
@@ -1,84 +0,0 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
darkMode: ["class"],
content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
theme: {
extend: {
colors: {
border: "hsl(var(--border))",
input: "hsl(var(--input))",
ring: "hsl(var(--ring))",
background: "hsl(var(--background))",
foreground: "hsl(var(--foreground))",
primary: {
DEFAULT: "hsl(var(--primary))",
foreground: "hsl(var(--primary-foreground))",
},
secondary: {
DEFAULT: "hsl(var(--secondary))",
foreground: "hsl(var(--secondary-foreground))",
},
destructive: {
DEFAULT: "hsl(var(--destructive) / <alpha-value>)",
foreground: "hsl(var(--destructive-foreground) / <alpha-value>)",
},
muted: {
DEFAULT: "hsl(var(--muted))",
foreground: "hsl(var(--muted-foreground))",
},
accent: {
DEFAULT: "hsl(var(--accent))",
foreground: "hsl(var(--accent-foreground))",
},
popover: {
DEFAULT: "hsl(var(--popover))",
foreground: "hsl(var(--popover-foreground))",
},
card: {
DEFAULT: "hsl(var(--card))",
foreground: "hsl(var(--card-foreground))",
},
sidebar: {
DEFAULT: "hsl(var(--sidebar-background))",
foreground: "hsl(var(--sidebar-foreground))",
primary: "hsl(var(--sidebar-primary))",
"primary-foreground": "hsl(var(--sidebar-primary-foreground))",
accent: "hsl(var(--sidebar-accent))",
"accent-foreground": "hsl(var(--sidebar-accent-foreground))",
border: "hsl(var(--sidebar-border))",
ring: "hsl(var(--sidebar-ring))",
},
},
borderRadius: {
xl: "calc(var(--radius) + 4px)",
lg: "var(--radius)",
md: "calc(var(--radius) - 2px)",
sm: "calc(var(--radius) - 4px)",
xs: "calc(var(--radius) - 6px)",
},
boxShadow: {
xs: "0 1px 2px 0 rgb(0 0 0 / 0.05)",
},
keyframes: {
"accordion-down": {
from: { height: "0" },
to: { height: "var(--radix-accordion-content-height)" },
},
"accordion-up": {
from: { height: "var(--radix-accordion-content-height)" },
to: { height: "0" },
},
"caret-blink": {
"0%,70%,100%": { opacity: "1" },
"20%,50%": { opacity: "0" },
},
},
animation: {
"accordion-down": "accordion-down 0.2s ease-out",
"accordion-up": "accordion-up 0.2s ease-out",
"caret-blink": "caret-blink 1.25s ease-out infinite",
},
},
},
plugins: [require("tailwindcss-animate")],
}
-92
View File
@@ -1,92 +0,0 @@
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);
-37
View File
@@ -1,37 +0,0 @@
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);