// vita-services.jsx — Services hub + 4 modules: Telemedicina, Nutrición, Psicología, Diagnóstico const SERVICES = [ { id: 'citas', icon: 'video', titulo: 'Citas y telemedicina', desc: 'Agenda con tu EPS o plan. Vita lo gestiona.', tag: 'HealthSings' }, { id: 'nutricion', icon: 'food', titulo: 'Nutrición', desc: 'Tu plan y el nutriólogo ideal para ti.', tag: null }, { id: 'psicologia', icon: 'brain', titulo: 'Psicología', desc: 'Seguimiento de tu ánimo y tu tratamiento.', tag: null }, { id: 'diagnostico', icon: 'lab', titulo: 'Diagnóstico', desc: 'Laboratorios, estudios y dónde reclamar.', tag: null }, ]; function ServiceHeader({ t, persona, titulo, sub, onBack, right }) { return (
{Icon.chevron({ s: 18, c: t.textSoft, w: 2.5 })}
{titulo}
{sub &&
{sub}
}
{right}
); } // ── Hub ───────────────────────────────────────────────────────── function ServicesScreen({ t, persona, profile, onOpen, onTalk, onToggleTheme, onOpenHome, onOpenHistory, onOpenProfile }) { return (
Servicios
{t.dark ? Icon.sun({ s: 17 }) : Icon.moon({ s: 17 })}

Vita coordina todo por ti, con tu EPS y nuestros aliados. Tú solo dices qué necesitas.

{SERVICES.map(s => ( ))}
{}} />
); } // ════ 1. CITAS / TELEMEDICINA — agendadas de verdad contra el backend ════ const MOTIVOS_CITA = [ { k: 'general', label: 'Medicina general', icon: 'pulse' }, { k: 'especialista', label: 'Especialista', icon: 'heart' }, { k: 'control', label: 'Control', icon: 'calendar' }, { k: 'urgente', label: 'Me siento mal hoy', icon: 'alert' }, ]; function fmtFechaHora(iso) { try { const d = new Date(iso); return d.toLocaleDateString('es-CO', { day: 'numeric', month: 'short' }) + ' · ' + d.toLocaleTimeString('es-CO', { hour: 'numeric', minute: '2-digit' }); } catch (e) { return iso; } } // Formato que necesita, con una hora por // defecto razonable (mañana a las 10:00) para no arrancar en blanco. function proximaFechaSugerida() { const d = new Date(Date.now() + 24 * 3600 * 1000); d.setHours(10, 0, 0, 0); const pad = (n) => String(n).padStart(2, '0'); return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`; } function CitasService({ t, persona, profile, onBack, onSchedule, onEnterCall }) { const { api } = window.VitaCore.estado; const { data: misCitas } = api.citas.useObtenerMisCitasQuery(); const { data: medicosData, isLoading: cargandoMedicos } = api.citas.useObtenerMedicosQuery(); const [agendarCita] = api.citas.useAgendarMiCitaMutation(); const [step, setStep] = React.useState('motivo'); // motivo | medico | buscando | confirmada | error const [motivo, setMotivo] = React.useState(null); const [medicoId, setMedicoId] = React.useState(null); const [fechaHora, setFechaHora] = React.useState(proximaFechaSugerida()); const [citaCreada, setCitaCreada] = React.useState(null); const [error, setError] = React.useState(null); const accent = persona.accent; const cobertura = [profile.eps, profile.prepagada && profile.prepagada !== 'Ninguna' ? profile.prepagada : null].filter(Boolean).join(' · ') || 'Tu EPS'; const medicos = (medicosData && medicosData.data) || []; const confirmar = async () => { if (!medicoId) return; setStep('buscando'); setError(null); try { const cita = await agendarCita({ medicoId, fechaHora: new Date(fechaHora).toISOString(), motivo: (motivo && motivo.label) || 'Consulta', }).unwrap(); setCitaCreada(cita); setStep('confirmada'); } catch (e) { setError((e && e.data && e.data.message) || 'No pudimos agendar tu cita. Intenta de nuevo.'); setStep('error'); } }; const reiniciar = () => { setStep('motivo'); setMotivo(null); setMedicoId(null); setCitaCreada(null); setError(null); }; return (
{/* HealthSings partner banner */}
{Icon.video({ s: 20, c: accent })}
Telemedicina con IA · HealthSings
VITA gestiona y conecta con tu plan
{step === 'motivo' && ( <> {misCitas && misCitas.data.length > 0 && (
Tus próximas citas
{misCitas.data.slice(0, 3).map(c => (
{Icon.video({ s: 17, c: accent })}
Dr(a). {c.medico.usuario.nombre} {c.medico.usuario.apellido} · {c.medico.especialidad}
{fmtFechaHora(c.fechaHora)} · {c.estado.nombre}
{Icon.chevron({ s: 16, c: t.muted })}
))}
)}
¿Para qué necesitas la cita?
Vita busca el cupo y la gestiona con tu EPS.
{MOTIVOS_CITA.map(m => ( ))}
)} {step === 'medico' && (
Elige médico y horario
{motivo && motivo.label}
{cargandoMedicos &&
} {!cargandoMedicos && medicos.length === 0 && (
Por ahora no hay médicos disponibles en la plataforma. Intenta más tarde.
)}
{medicos.map(m => { const sel = m.id === medicoId; return ( ); })}
{medicoId && ( <>
¿Cuándo?
setFechaHora(e.target.value)} style={{ width: '100%', padding: '13px 14px', borderRadius: 14, border: `1.5px solid ${t.stroke}`, background: t.dark ? 'rgba(255,255,255,0.06)' : '#FFFFFF', color: t.text, fontSize: 14.5, fontFamily: "'Inter', system-ui, sans-serif", marginBottom: 18 }} /> )}
)} {step === 'buscando' && (
Agendando tu cita…
Confirmando con tu EPS y reservando el cupo.
)} {step === 'error' && (
{error}
)} {step === 'confirmada' && citaCreada && (
{Icon.check({ s: 14, c: t.green, w: 3 })} Cita confirmada
{Icon.video({ s: 26, c: t.onAccent })}
Dr(a). {citaCreada.medico.usuario.nombre} {citaCreada.medico.usuario.apellido}
{citaCreada.medico.especialidad} · Videollamada
{[['Cuándo', fmtFechaHora(citaCreada.fechaHora)], ['Estado', citaCreada.estado.nombre], ['Cobertura', cobertura]].map(([k, v], i) => (
{k}{v}
))}
)}
); } function ConnectingSteps({ t, accent, steps }) { const [n, setN] = React.useState(0); React.useEffect(() => { const iv = setInterval(() => setN(x => Math.min(steps.length, x + 1)), 750); return () => clearInterval(iv); }, []); return (
{steps.map((s, i) => (
= n ? `2px solid ${t.stroke}` : 'none' }}>{i < n && Icon.check({ s: 12, c: '#fff', w: 3 })} {s}
))}
); } Object.assign(window, { SERVICES, ServicesScreen, ServiceHeader, CitasService, ConnectingSteps });