// Pagos screens — "Pagos" tab + Factura detail
// Relies on window.loadBilling / saveBilling, facturaSaldo, facturaEstado, etc.
const ESTADO_META = {
'por-pagar': { label: 'Por pagar', color: 'oklch(0.55 0.05 75)', bg: 'oklch(0.94 0.01 75)' },
'pago-pendiente':{ label: 'Verificando', color: 'oklch(0.55 0.14 75)', bg: 'oklch(0.95 0.06 85)' },
'abonada': { label: 'Abonada', color: 'oklch(0.52 0.14 155)', bg: 'oklch(0.94 0.06 155)' },
'vencida': { label: 'Vencida', color: 'oklch(0.5 0.18 25)', bg: 'oklch(0.94 0.07 25)' },
'pagada': { label: 'Pagada', color: 'oklch(0.48 0.14 155)', bg: 'oklch(0.94 0.06 155)' },
'retirado': { label: 'Retirado', color: T_or('inkMute'), bg: T_or('paperAlt') },
};
function T_or(k) { return (window.T && window.T[k]) || '#888'; }
function PagosTab({ vendedora, onOpenFactura }) {
const T = window.T;
const { Icon } = window;
const billing = window.useBilling
? window.useBilling(vendedora?.id)
: { state: window.loadBilling(), loading: false };
const state = billing.state;
const facturas = state.facturas;
const pagos = state.pagos;
if (billing.loading && facturas.length === 0) {
return (
);
}
const deuda = window.totalDeuda(facturas, pagos);
const vencida = window.totalDeudaVencida(facturas, pagos);
const proximoPago = (() => {
const upcoming = [];
facturas.forEach(f => {
const saldo = window.facturaSaldo(f, pagos);
if (saldo <= 0.01) return;
f.cuotas.forEach(c => {
if (c.status !== 'pagada' && new Date(c.fecha) >= new Date()) upcoming.push({ fecha: c.fecha, monto: c.monto });
});
});
upcoming.sort((a, b) => new Date(a.fecha) - new Date(b.fecha));
return upcoming[0];
})();
const sortedFac = [...facturas].sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt));
return (
{/* Header */}
{/* Deuda hero */}
0 ? 'oklch(0.42 0.18 25)' : T.ink,
color: '#fff', borderRadius: 24, padding: 24,
position: 'relative', overflow: 'hidden',
}}>
{deuda > 0 ? 'Debes' : 'Estás al día'}
${deuda.toFixed(2)}
{vencida > 0 && (
${vencida.toFixed(2)} vencido
)}
{proximoPago && deuda > 0 && (
0 ? 8 : 14,
fontFamily: T.sans, fontSize: 13, color: 'rgba(255,255,255,0.75)',
}}>
Próxima cuota {window.fmtDate(proximoPago.fecha)} · {window.fmtMoney(proximoPago.monto)}
)}
{/* Empresa contact */}
{deuda > 0 && (
)}
{/* Facturas list */}
{sortedFac.length === 0 ? (
Aún no tienes facturas.
Arma tu primer pedido.
) : sortedFac.map(f => {
const saldo = window.facturaSaldo(f, pagos);
const estado = window.facturaEstado(f, pagos);
const meta = ESTADO_META[estado] || ESTADO_META['por-pagar'];
const pct = Math.round((1 - Math.max(0, saldo) / f.aPagar) * 100);
const camp = state.campaigns.find(c => c.id === f.campaignId);
return (
);
})}
);
}
function InfoRow({ label, value }) {
const T = window.T;
return (
);
}
function CuotaDot({ cuota }) {
const T = window.T;
const isPagada = cuota.status === 'pagada';
const now = new Date();
const isVencida = !isPagada && new Date(cuota.fecha) < now;
const bg = isPagada ? 'oklch(0.6 0.14 155)' : isVencida ? 'oklch(0.55 0.18 25)' : T.hairlineStrong;
return (
{window.fmtDate(cuota.fecha)}
${cuota.monto.toFixed(2)}
);
}
// ——— Factura detail ———
function FacturaDetail({ factura, vendedora, onClose, onRegistrarPago }) {
const T = window.T;
const { Icon } = window;
const billing = window.useBilling
? window.useBilling(vendedora?.id)
: { state: window.loadBilling(), loading: false };
const state = billing.state;
const pagos = state.pagos.filter(p => p.facturaId === factura.id);
const saldo = window.facturaSaldo(factura, pagos);
const estado = window.facturaEstado(factura, pagos);
const meta = ESTADO_META[estado] || ESTADO_META['por-pagar'];
const camp = state.campaigns.find(c => c.id === factura.campaignId);
const pagoStatusColor = (s) =>
s === 'verificado' ? 'oklch(0.5 0.14 155)'
: s === 'rechazado' ? 'oklch(0.55 0.18 25)'
: 'oklch(0.55 0.14 75)';
return (
{/* Top bar */}
{camp?.nombre || factura.campaignId}
Factura {factura.id.slice(-5)}
{/* Hero saldo */}
0.01 ? (estado === 'vencida' ? 'oklch(0.42 0.18 25)' : T.ink) : 'oklch(0.45 0.14 155)',
color: '#fff', borderRadius: 22, padding: 22,
}}>
{meta.label}
{saldo > 0.01 ? 'Saldo pendiente' : 'Pagado completo'}
${Math.max(0, saldo).toFixed(2)}
{factura.retiroCodigo && (
Código de retiro
{factura.retiroCodigo}
)}
{/* Desglose */}
{/* Cuotas */}
{factura.cuotas.map((c, i) => {
const isPagada = c.status === 'pagada';
const isVencida = !isPagada && new Date(c.fecha) < new Date();
return (
{isPagada ? '✓' : i + 1}
{window.fmtMoney(c.monto)}
{new Date(c.fecha).toLocaleDateString('es', { weekday: 'short', day: 'numeric', month: 'long' })}
{isPagada ? 'Pagada' : isVencida ? 'Vencida' : 'Próxima'}
);
})}
{/* Pagos registrados */}
{pagos.length > 0 && (
{pagos.slice().sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt)).map(p => (
{window.fmtMoney(p.monto)}
{p.status === 'verificado' ? '✓ Verificado' : p.status === 'rechazado' ? 'Rechazado' : 'Verificando…'}
{p.metodo}{p.banco ? ` · ${p.banco}` : ''}{p.referencia ? ` · Ref ${p.referencia}` : ''}
{window.fmtDate(p.fecha)} · {new Date(p.createdAt).toLocaleDateString('es', { day: '2-digit', month: 'short' })}
{p.rejectReason && (
Razón: {p.rejectReason}
)}
))}
)}
{/* Register payment button */}
{saldo > 0.01 && (
)}
);
}
function Row({ label, value, accent, bold }) {
const T = window.T;
return (
{label}
{value}
);
}
Object.assign(window, { PagosTab, FacturaDetail });