import React, { useMemo, useState } from "react"; import { z } from "zod"; import { useForm, Controller } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { Card as UICard, CardHeader, CardTitle, CardContent } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Label } from "@/components/ui/label"; import { Input } from "@/components/ui/input"; import { Textarea } from "@/components/ui/textarea"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs"; import { Switch } from "@/components/ui/switch"; import { Alert, AlertDescription } from "@/components/ui/alert"; import { Badge } from "@/components/ui/badge"; import { ScrollArea } from "@/components/ui/scroll-area"; import { ResponsiveContainer, LineChart, Line, XAxis, YAxis, Tooltip, ReferenceLine, BarChart, Bar, Legend, AreaChart, Area, } from "recharts"; import { Activity, Pill as PillIcon, ClipboardList, Calendar, FileText, Search, FileUp, Users, Stethoscope, Shield, TriangleAlert, QrCode, Settings, Brain, DollarSign, ListCheck, Sparkles, Layers, Share2, RadioTower, FileCheck, FolderLock, MessageSquare, SlidersHorizontal, Globe, Clock, Landmark, LifeBuoy, } from "lucide-react"; // ========= componentes base reutilizables ========= function Section({ title, children, actions }: any) { return ( {title} {actions} {children} ); } function FieldRow({ label, children, hint, id, required }: any) { return (
{label && ( )} {hint && {hint}}
{children}
); } function Kpi({ title, value, hint }: any) { return ( {title}
{value}
{hint &&
{hint}
}
); } function ChartCard({ title, children, height = 240 }: any) { return ( {title} {children} ); } function EmptyState({ icon: Icon, title, desc, action }: any) { return (
{Icon && }
{title}
{desc}
{action}
); } // ========= 01 Tablero ========= function Mod01Tablero() { const kpis = [ { t: "Adherencia (7d)", v: "86%" }, { t: "PA promedio", v: "132/84" }, { t: "Síntomas hoy", v: "1" }, ]; return (
{kpis.map((k, i) => ( ))}
{[ { m: "Losartán 50mg", h: "08:00", done: true }, { m: "Trazodona 100mg", h: "22:00", done: false }, ].map((r, i) => (
{r.h} {r.m}
{r.done ? "Tomado" : "Pendiente"}
))}
); } // ========= 02 Bitácora ========= const zSymptoms = z.object({ mood: z.enum(["bien", "neutral", "mal"]), symptom: z.string().min(2), intensity: z.coerce.number().min(1).max(10), }); function Mod02Bitacora() { const form = useForm({ resolver: zodResolver(zSymptoms), defaultValues: { intensity: 5 } }); const [saved, setSaved] = useState(); return (
{ setSaved(`${v.symptom} · registrado`); setTimeout(() => setSaved(undefined), 1800); })} className="grid md:grid-cols-3 gap-3" > ( )} />
{saved && ( {saved} )}
); } // ========= 03 Medicación ========= const zMed = z.object({ name: z.string().min(2), dose: z.string().min(1), hour: z.string().regex(/^\d{2}:\d{2}$/), }); function Mod03Medicamentos() { const form = useForm({ resolver: zodResolver(zMed) }); const [rows, setRows] = useState([ { name: "Trazodona", dose: "100mg", hour: "22:00" }, { name: "Armodafinilo", dose: "150mg", hour: "08:00" }, ]); return (
{rows.map((r, i) => ( ))}
Medicamento Dosis Hora
{r.name} {r.dose} {r.hour}
setRows((prev) => [...prev, v]))} className="grid md:grid-cols-4 gap-3" >
); } // ========= 04 Signos ========= const zVitals = z .object({ sys: z.coerce.number().min(80).max(220), dia: z.coerce.number().min(40).max(140), hr: z.coerce.number().min(30).max(200), }) .refine((v) => v.dia < v.sys, { path: ["dia"], message: "Diastólica < Sistólica" }); function Mod04Signos() { const form = useForm({ resolver: zodResolver(zVitals) }); const data = useMemo( () => [ { d: "Lun", pa: 136 }, { d: "Mar", pa: 134 }, { d: "Mié", pa: 133 }, { d: "Jue", pa: 135 }, { d: "Vie", pa: 132 }, { d: "Sáb", pa: 131 }, { d: "Dom", pa: 130 }, ], [] ); return (
{})} className="grid md:grid-cols-4 gap-3">
{form.formState.errors.dia && ( {String(form.formState.errors.dia.message)} )}
); } // ========= 05 a 34 (demo rápido) ========= function Mod05Consultas() { const f = useForm(); return (
{})} className="grid md:grid-cols-4 gap-3">
); } function Mod06Documentos() { return (
Subir } />
); } function Mod07Costos() { const data = [ { m: "Ene", v: 63200 }, { m: "Feb", v: 80400 }, { m: "Mar", v: 75400 }, { m: "Abr", v: 91200 }, ]; return ( ); } function Mod08Auditorias() { const logs = Array.from({ length: 12 }, (_, i) => ({ t: `2025-11-${String(i + 1).padStart(2, "0")} 08:${String(i % 60).padStart(2, "0")}`, e: i % 2 ? "Lectura de historial" : "Actualización de registro", a: i % 3 ? "Titular" : "Cuidador", })); return (
{logs.map((l, i) => (
{l.t}
{l.e}
{l.a}
))}
); } function Mod09Analisis() { return (
  • Registrar PA dos veces al día por 7 días.
  • Anotar rigidez matinal en bitácora si dura más de 30 minutos.
); } function Mod10Cotizacion() { const items = [ { f: "Farmacia A", p: 3990 }, { f: "Farmacia B", p: 4290 }, { f: "Farmacia C", p: 3890 }, ]; const best = items.reduce((a, b) => (a.p < b.p ? a : b)); return (
{items.map((x, i) => ( ))}
Farmacia Precio
{x.f} {x.f === best.f && Mejor precio} ${x.p}
); } function Mod11Reportes() { const [gen, setGen] = useState(false); return (
); } function Mod12Comunidad() { return ( Muro Grupos {["Hoy me sentí mejor", "Busco grupo de HTA"].map((p, i) => (
{p}
))}
{["Diabetes", "Hipertensión", "Rehabilitación"].map((g) => (
{g}
))}
); } function Mod13Agenda() { const [items, setItems] = useState([ { t: "Tomar Trazodona 100mg", h: "22:00", done: false }, { t: "Registrar PA", h: "08:00", done: true }, ]); return (
{items.map((it, i) => (
{it.h} {it.t}
setItems((prev) => prev.map((p, ix) => (ix === i ? { ...p, done: v } : p)) ) } />
))}
); } function Mod14Profesional() { const pts = [ { n: "Walter P.", p: "Alta", u: "hoy 08:10" }, { n: "Paciente demo", p: "Media", u: "ayer 19:40" }, ]; return (
Paciente
Prioridad
Última act.
Acciones
{pts.map((p, i) => (
{p.n}
{p.p}
{p.u}
))}
); } function Mod15Privacidad() { return (
Nombre Relación Alcance Vence Acción
Cuidador demo Familiar Red de apoyo 2025-12-01
); } function Mod16Ciclos() { return (
Fase: Inicio · Meta: TA < 140/90
Activa
Fase: Mantenimiento · Meta: 130–139/80–89
Próxima
Agregar evento} />
); } function Mod17Familiar() { const [list, setList] = useState([ { t: "Verificar toma de Trazodona", done: false }, { t: "Registrar PA en la app", done: false }, ]); return (
{list.map((x, i) => (
{x.t}
setList((prev) => prev.map((p, ix) => (ix === i ? { ...p, done: v } : p)) ) } />
))}
); } function Mod18Psico() { return (