mirror of
https://github.com/escalante29/WealthySmart.git
synced 2026-07-17 12:28:48 +02:00
Fix dashboard data findings from browser verification
- Próximas cuotas: headline is the upcoming billing batch (sum of every active plan's next cuota, using the rounding-absorbing last cuota when it's the pending one) — the in-cycle formula was ~always zero since cuotas bill on the 19th, day one of the next cycle. - useAgent must name the 'wealthysmart' agent (default crashed the page). - /transactions/recent excludes future-dated Tasa Cero cuotas. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -27,7 +27,7 @@ export default function Asistente() {
|
||||
// append it as a user message and run the agent once.
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
const { agent } = useAgent();
|
||||
const { agent } = useAgent({ agentId: "wealthysmart" });
|
||||
const { copilotkit } = useCopilotKit();
|
||||
const sentRef = useRef(false);
|
||||
useEffect(() => {
|
||||
|
||||
@@ -132,18 +132,21 @@ function ProximasCuotasCard() {
|
||||
const active = (q.data?.plans ?? []).filter(
|
||||
(p) => !p.is_completed && p.next_cuota_date,
|
||||
);
|
||||
const inCycle = active.filter((p) => {
|
||||
const d = new Date(p.next_cuota_date!);
|
||||
return d >= CYCLE.start && d < CYCLE.end;
|
||||
});
|
||||
const cycleTotal = inCycle.reduce((s, p) => s + p.installment_amount, 0);
|
||||
const upcoming = [...active]
|
||||
.sort(
|
||||
(a, b) =>
|
||||
new Date(a.next_cuota_date!).getTime() -
|
||||
new Date(b.next_cuota_date!).getTime(),
|
||||
)
|
||||
.slice(0, 3);
|
||||
// One cuota per plan per cycle, so the sum of every active plan's next
|
||||
// cuota is the load of the upcoming billing batch (next 19th). The last
|
||||
// cuota absorbs BAC's rounding, so use it when it's the one pending.
|
||||
const nextCuotaOf = (p: (typeof active)[number]) =>
|
||||
p.cuotas_billed === p.num_installments - 1
|
||||
? p.last_installment_amount
|
||||
: p.installment_amount;
|
||||
const nextBatchTotal = active.reduce((s, p) => s + nextCuotaOf(p), 0);
|
||||
const upcoming = [...active].sort(
|
||||
(a, b) =>
|
||||
new Date(a.next_cuota_date!).getTime() -
|
||||
new Date(b.next_cuota_date!).getTime(),
|
||||
);
|
||||
const nextDate = upcoming[0]?.next_cuota_date;
|
||||
const topThree = upcoming.slice(0, 3);
|
||||
|
||||
return (
|
||||
<StatCardShell to="/financiamientos" ariaLabel="Ver financiamientos">
|
||||
@@ -151,21 +154,25 @@ function ProximasCuotasCard() {
|
||||
<CardTitle className="text-sm font-medium text-muted-foreground">
|
||||
Próximas cuotas
|
||||
</CardTitle>
|
||||
<CardDescription>Tasa Cero en este ciclo</CardDescription>
|
||||
<CardDescription>
|
||||
{nextDate
|
||||
? `Tasa Cero · próximo cobro ${formatShortDate(nextDate)}`
|
||||
: "Tasa Cero"}
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-2">
|
||||
<StatValue
|
||||
loading={q.isPending}
|
||||
value={q.isError ? null : formatAmount(cycleTotal, "CRC")}
|
||||
value={q.isError ? null : formatAmount(nextBatchTotal, "CRC")}
|
||||
/>
|
||||
{upcoming.length > 0 && (
|
||||
{topThree.length > 0 && (
|
||||
<ul className="space-y-0.5 text-xs text-muted-foreground">
|
||||
{upcoming.map((p) => (
|
||||
{topThree.map((p) => (
|
||||
<li key={p.id} className="flex justify-between gap-2">
|
||||
<span className="truncate">{p.merchant}</span>
|
||||
<span data-sensitive className="font-mono shrink-0">
|
||||
{formatShortDate(p.next_cuota_date!)} ·{" "}
|
||||
{formatAmount(p.installment_amount, p.currency)}
|
||||
{formatAmount(nextCuotaOf(p), p.currency)}
|
||||
</span>
|
||||
</li>
|
||||
))}
|
||||
|
||||
Reference in New Issue
Block a user