// 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 (
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 && (
)}
{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 });