// vita-care.jsx — Proactive care: today's plan, reminders, therapy follow-up, post-cita check-in, controls // ── Build today's care plan from the patient's state ──────────── function buildTodayPlan({ profile, asis, pic, seguimiento }) { const tasks = []; const meds = Array.isArray(profile.medicamentos) ? profile.medicamentos : (profile.medicamentos ? [profile.medicamentos] : []); // Medications — morning dose for each, plus a night dose for the first meds.forEach((m, i) => { tasks.push({ id: 'med-am-' + i, tipo: 'medicamento', titulo: m, sub: 'Con el desayuno', hora: '08:00', bloque: 'mañana', icon: 'pill' }); }); if (meds.length) tasks.push({ id: 'med-pm-0', tipo: 'medicamento', titulo: meds[0], sub: 'Con la cena', hora: '20:00', bloque: 'noche', icon: 'pill' }); // Hydration (all day) tasks.push({ id: 'agua', tipo: 'habito', titulo: 'Tomar agua', sub: '8 vasos en el día', hora: 'Todo el día', bloque: 'mañana', icon: 'droplet' }); // Activity — from PIC or ASIS priorities const wantsMove = (asis && asis.prioridades || []).some(p => /camin|ejerci|mover|activ/i.test(p)) || (pic && (pic.areas || []).some(a => /activ|ejerci/i.test(a.nombre || ''))); tasks.push({ id: 'caminar', tipo: 'actividad', titulo: 'Caminar 15 minutos', sub: wantsMove ? 'Tu meta de hoy' : 'Mueve el cuerpo', hora: '17:00', bloque: 'tarde', icon: 'walk' }); // Therapy / emotional check-in (if in psychology context — always offer a calm evening one) tasks.push({ id: 'animo', tipo: 'terapia', titulo: 'Registrar cómo te sientes', sub: 'Seguimiento emocional', hora: '21:00', bloque: 'noche', icon: 'brain' }); // Appointment today? const citaHoy = (seguimiento || []).find(s => s.tipo === 'cita' && s.estado === 'agendado' && /hoy/i.test(s.detalle || '')); if (citaHoy) tasks.unshift({ id: 'cita-hoy', tipo: 'cita', titulo: citaHoy.titulo, sub: 'Tu cita de hoy', hora: '10:30', bloque: 'mañana', icon: 'video', fijo: true }); return tasks; } const BLOQUES = [ { k: 'mañana', label: 'Mañana', icon: 'sunrise' }, { k: 'tarde', label: 'Tarde', icon: 'sundial' }, { k: 'noche', label: 'Noche', icon: 'moon' }, ]; const CARE_COLOR = (t, tipo) => ({ medicamento: t.accent, habito: '#5BC0EB', actividad: t.green, terapia: '#A98CD9', cita: t.accent }[tipo] || t.accent); function todayKey() { const d = new Date(); return d.getFullYear() + '-' + (d.getMonth() + 1) + '-' + d.getDate(); } // ── Home card: Tu cuidado de hoy ──────────────────────────────── function TodayCard({ t, persona, tasks, done, onToggle, onOpenCare }) { const total = tasks.length; const completed = tasks.filter(x => done[x.id]).length; const pct = total ? Math.round(completed / total * 100) : 0; const next = tasks.find(x => !done[x.id]); const accent = persona.accent; return (
{completed}/{total}
Tu cuidado de hoy
{pct === 100 ? '¡Lo lograste todo hoy! 💚' : next ? 'Sigue: ' + next.titulo : 'Vamos bien'}
{tasks.slice(0, 3).map(task => ( onToggle(task.id)} compact /> ))}
); } function CareRow({ t, persona, task, done, onToggle, compact }) { const color = CARE_COLOR(t, task.tipo); return (
{Icon[task.icon]({ s: 19, c: color })}
{task.titulo}
{task.hora} · {task.sub}
{task.fijo ? ( Cita ) : ( )}
); } // ── Post-cita proactive check-in card (home) ──────────────────── function PostCitaCard({ t, persona, cita, onOpen, onDismiss }) { return (
¿Cómo te fue en tu cita?
{cita.titulo}. Cuéntame y me encargo de lo que sigue: controles, órdenes o fórmulas.
); } // ── Post-cita guided check-in sheet ───────────────────────────── const ORDEN_OPCIONES = [ { k: 'medicamento', label: 'Me formularon un medicamento', icon: 'pill' }, { k: 'examen', label: 'Me ordenaron exámenes', icon: 'lab' }, { k: 'control', label: 'Quedé con cita de control', icon: 'stethoscope' }, { k: 'terapia', label: 'Me mandaron terapias', icon: 'walk' }, { k: 'nada', label: 'Todo bien, sin órdenes nuevas', icon: 'check' }, ]; function PostCitaSheet({ t, persona, cita, voice, tts, onClose, onResolve }) { const accent = persona.accent; const [step, setStep] = React.useState(0); // 0 asistió, 1 órdenes, 2 done const [asistio, setAsistio] = React.useState(null); const [ordenes, setOrdenes] = React.useState({}); const spokenRef = React.useRef(-1); const prompts = ['¿Alcanzaste a ir a tu cita?', '¿El médico te dejó alguna orden? Marca lo que aplique.', '']; React.useEffect(() => { if (!tts || step >= 2 || step === spokenRef.current) return; spokenRef.current = step; voice && voice.speak(prompts[step], persona); }, [step]); const toggleOrden = (k) => setOrdenes(o => k === 'nada' ? { nada: !o.nada } : { ...o, [k]: !o[k], nada: false }); const finish = () => { const nuevos = []; const eps = 'tu EPS'; if (ordenes.medicamento) nuevos.push({ id: 'pc-med-' + Date.now(), tipo: 'medicamento', titulo: 'Nuevo medicamento formulado', detalle: 'Vita te recuerda tomarlo', estado: 'activo' }); if (ordenes.examen) nuevos.push({ id: 'pc-exa-' + Date.now(), tipo: 'examen', titulo: 'Exámenes ordenados', detalle: 'Vita los agenda con ' + eps, estado: 'pendiente' }); if (ordenes.control) nuevos.push({ id: 'pc-ctl-' + Date.now(), tipo: 'cita', titulo: 'Cita de control', detalle: 'En 2 meses · Vita te recuerda', estado: 'pendiente' }); if (ordenes.terapia) nuevos.push({ id: 'pc-ter-' + Date.now(), tipo: 'examen', titulo: 'Plan de terapias', detalle: 'Vita coordina las sesiones', estado: 'pendiente' }); onResolve(nuevos); setStep(2); }; return (
{[0, 1, 2].map(i => )}
{step < 2 && (
{prompts[step]}
)} {step === 0 && (
)} {step === 1 && (
{ORDEN_OPCIONES.map(o => { const on = ordenes[o.k]; return ( ); })}
)} {step === 2 && (
{Icon.check({ s: 36, c: '#fff', w: 3 })}
Yo me encargo

Actualicé tu seguimiento y tu historia. Te voy recordando cada cosa a su tiempo. No tienes que estar pendiente. 💚

)}
); } function btnPrimary(t, persona) { return { width: '100%', padding: '14px', borderRadius: 14, border: 'none', cursor: 'pointer', background: `linear-gradient(135deg, ${persona.accent}, ${persona.accentDeep})`, color: t.onAccent, fontFamily: 'Hanken Grotesk, sans-serif', fontSize: 15, fontWeight: 700, display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8 }; } function btnGhost(t) { return { width: '100%', padding: '14px', borderRadius: 14, cursor: 'pointer', border: `1.5px solid ${t.strokeStrong}`, background: 'transparent', color: t.text, fontFamily: 'Hanken Grotesk, sans-serif', fontSize: 15, fontWeight: 600 }; } Object.assign(window, { buildTodayPlan, BLOQUES, CARE_COLOR, todayKey, TodayCard, CareRow, PostCitaCard, PostCitaSheet, btnPrimary, btnGhost });