Iterar la definición de estructuras_plan #39

fix #39
This commit is contained in:
2026-01-27 10:21:13 -06:00
parent 01742a1a74
commit 2b5e9e14f9
2 changed files with 92 additions and 44 deletions

View File

@@ -6,6 +6,12 @@ import type { DatosGeneralesField } from '@/types/plan'
import { Button } from '@/components/ui/button'
import { Textarea } from '@/components/ui/textarea'
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from '@/components/ui/tooltip'
import { usePlan } from '@/data'
// import { toast } from 'sonner' // Asegúrate de tener sonner instalado o quita la línea
export const Route = createFileRoute('/planes/$planId/_detalle/datos')({
@@ -28,24 +34,41 @@ function DatosGeneralesPage() {
// Efecto para transformar data?.datos en el arreglo de campos
useEffect(() => {
// 2. Validación de seguridad para sourceData
const sourceData = data?.datos
const properties = data?.estructuras_plan?.definicion?.properties
if (sourceData && typeof sourceData === 'object') {
const valores = data?.datos as Record<string, unknown>
if (properties && typeof properties === 'object') {
const datosTransformados: Array<DatosGeneralesField> = Object.entries(
sourceData,
).map(([key, value], index) => ({
properties,
).map(([key, schema], index) => {
const rawValue = valores[key]
return {
id: (index + 1).toString(),
label: formatLabel(key),
// Forzamos el valor a string de forma segura
value: typeof value === 'string' ? value : value?.toString() || '',
label: schema?.title || formatLabel(key),
helperText: schema?.description || '',
holder: schema?.examples || '',
value:
rawValue !== undefined && rawValue !== null ? String(rawValue) : '',
requerido: true,
tipo: 'texto',
}))
// 👇 TIPO DE CAMPO
tipo: Array.isArray(schema?.enum)
? 'select'
: schema?.type === 'number'
? 'number'
: 'texto',
opciones: schema?.enum || [],
}
})
setCampos(datosTransformados)
}
console.log(data)
console.log(properties)
}, [data])
// 3. Manejadores de acciones (Ahora como funciones locales)
@@ -105,11 +128,20 @@ function DatosGeneralesPage() {
}`}
>
{/* Header de la Card */}
<TooltipProvider>
<div className="flex items-center justify-between border-b bg-slate-50/50 px-5 py-3">
<div className="flex items-center gap-2">
<h3 className="text-sm font-medium text-slate-700">
<Tooltip>
<TooltipTrigger asChild>
<h3 className="cursor-help text-sm font-medium text-slate-700">
{campo.label}
</h3>
</TooltipTrigger>
<TooltipContent className="max-w-xs text-xs">
{campo.helperText || 'Información del campo'}
</TooltipContent>
</Tooltip>
{campo.requerido && (
<span className="text-xs text-red-500">*</span>
)}
@@ -117,6 +149,8 @@ function DatosGeneralesPage() {
{!isEditing && (
<div className="flex gap-1">
<Tooltip>
<TooltipTrigger asChild>
<Button
variant="ghost"
size="icon"
@@ -125,6 +159,12 @@ function DatosGeneralesPage() {
>
<Sparkles size={14} />
</Button>
</TooltipTrigger>
<TooltipContent>Generar con IA</TooltipContent>
</Tooltip>
<Tooltip>
<TooltipTrigger asChild>
<Button
variant="ghost"
size="icon"
@@ -133,9 +173,13 @@ function DatosGeneralesPage() {
>
<Pencil size={14} />
</Button>
</TooltipTrigger>
<TooltipContent>Editar campo</TooltipContent>
</Tooltip>
</div>
)}
</div>
</TooltipProvider>
{/* Contenido de la Card */}
<div className="p-5">
@@ -145,6 +189,7 @@ function DatosGeneralesPage() {
value={editValue}
onChange={(e) => setEditValue(e.target.value)}
className="min-h-[120px]"
placeholder={campo.holder}
/>
<div className="flex justify-end gap-2">
<Button

View File

@@ -65,12 +65,15 @@ export interface Plan {
estadoActual: PlanStatus
}
export interface DatosGeneralesField {
export type DatosGeneralesField = {
id: string
label: string
helperText?: string
holder?: string
value: string
tipo: 'texto' | 'lista' | 'parrafo'
requerido: boolean
tipo: 'texto' | 'parrafo' | 'lista' | 'number' | 'select'
opciones?: Array<string>
}
export interface CambioPlan {