/* Santos OS — Clientes (Club Santos loyalty: list, search, detail, canjes) */ function CustomerRow({ c, onSelect }) { const T = window.T; const initials = c.nombre.split(' ').map(w=>w[0]).slice(0,2).join(''); return (
{initials}
{c.nombre}
{c.whatsapp}
{c.sucursal}
{c.refill && {c.refill==='overdue'?'! Refill venc.':'◷ Refill próx.'}}
{[[`L. ${c.gasto.toLocaleString()}`,'Gasto anual'],[c.puntos.toLocaleString(),'Puntos'],[c.tx,'Compras']].map(([v,l],i)=>( {i>0 &&
}
{v}
{l}
))}
); } function CustomerDetail({ c, onClose, onToast }) { const T = window.T; const tc = T.tiers[c.tier]; const goal = {BRONCE:5000, PLATA:15000, ORO:40000, JADE:999999}[c.tier]; const remaining = Math.max(goal - c.gasto, 0); const pct = Math.min((c.gasto/goal)*100, 100); const initials = c.nombre.split(' ').map(w=>w[0]).slice(0,2).join(''); const Section = ({title, children, action}) => (
{title}
{action}
{children}
); return (
Perfil del Cliente
{initials}
{c.nombre}
Miembro · {c.sucursal}
{c.puntos.toLocaleString()}
puntos disponibles
onToast(`✦ ${c.nombre.split(' ')[0]} puede canjear L. ${Math.floor(c.puntos*0.1)}`)} style={{padding:'10px 18px'}}>Canjear
≈ L. {(c.puntos*0.1).toFixed(0)} en descuentos
Gasto anual acumuladoL. {c.gasto.toLocaleString()}
0?T.fg3:T.success, marginTop:8}}>{remaining>0?`Faltan L. ${remaining.toLocaleString()} para el siguiente tier`:'✓ Tier máximo alcanzado'}
{(c.condiciones.length || c.alergias.length || c.doctor) ? (
{c.condiciones.length>0 &&
Condiciones
{c.condiciones.map(x=>{x})}
} {c.alergias.length>0 &&
! Alergias
{c.alergias.map(x=>{x})}
} {c.doctor &&
Médico tratante{c.doctor}
} {c.seguro &&
Seguro médico{c.seguro}
}
) : null}
onToast('✆ Abriendo WhatsApp…')}>✆ WhatsApp onToast('✎ Disponible en versión completa')}>✎ Ajustar puntos
); } function Clientes({ onToast }) { const T = window.T; const [tab, setTab] = React.useState('club'); const [query, setQuery] = React.useState(''); const [selected, setSelected] = React.useState(null); const counts = {BRONCE:892, PLATA:285, ORO:56, JADE:14}; const filtered = query ? window.CUSTOMERS.filter(c=>c.nombre.toLowerCase().includes(query.toLowerCase())||c.whatsapp.includes(query)||c.dni.includes(query)||c.tier.toLowerCase().includes(query.toLowerCase())) : window.CUSTOMERS; if (selected) return setSelected(null)} onToast={onToast} />; return (
{/* tabs */}
{[['club','Club Santos'],['canjes',`Canjes (${window.CANJES.length})`]].map(([k,l])=>( ))}
{tab==='club' && <>
{['BRONCE','PLATA','ORO','JADE'].map(t=>(
{t} {counts[t]}
))}
setQuery(e.target.value)} placeholder="Nombre, WhatsApp, DNI o tier…" style={{flex:1, border:'none', outline:'none', background:'transparent', fontSize:14, color:T.fg1, fontFamily:T.font}} /> {query && setQuery('')} style={{cursor:'pointer', color:T.fg3}}>✕}
{filtered.map(c=>setSelected(c)} />)} {filtered.length===0 &&
Sin resultados para "{query}"
}
} {tab==='canjes' && (
{window.CANJES.map(k=>(
Rx
{k.customer}
{k.product}
{k.lab} · {k.sucursal}
{k.qty}
gratis
Listo desde {k.ready}
onToast('✆ Avisando al cliente…')} style={{padding:'10px 14px'}}>✆ onToast(' Verificando portal del laboratorio…')}> Verificar onToast('✓ Canje entregado y registrado')}>✓ Entregar
))}
)}
); } window.Clientes = Clientes;