{loading ? (
diff --git a/client/components/tracker/TrackerRow.jsx b/client/components/tracker/TrackerRow.jsx
index 78d6279..1127604 100644
--- a/client/components/tracker/TrackerRow.jsx
+++ b/client/components/tracker/TrackerRow.jsx
@@ -70,11 +70,26 @@ export function TrackerRow({ row, year, month, refresh, index, onEditBill, moveC
const val = parseFloat(amountRef.current?.value);
if (!val || val <= 0) { toast.error('Enter a payment amount'); return; }
try {
- await api.quickPay({ bill_id: row.id, amount: val, paid_date: defaultPaymentDate });
- toast.success('Payment added');
+ const payment = await api.quickPay({ bill_id: row.id, amount: val, paid_date: defaultPaymentDate });
+ // Specific message + Undo, matching the un-pay affordance (quick-pay is
+ // just as reversible — deleting the payment we just created).
+ toast.success(`${row.name} — ${fmt(val)} paid`, {
+ action: {
+ label: 'Undo',
+ onClick: async () => {
+ try {
+ await api.deletePayment(payment.id);
+ toast.success('Payment removed');
+ refresh?.();
+ } catch (err) {
+ toast.error(err.message || 'Failed to undo payment.');
+ }
+ },
+ },
+ });
refresh();
} catch (err) {
- toast.error(err.message);
+ toast.error(err.message || 'Failed to add payment.');
}
}
@@ -102,7 +117,7 @@ export function TrackerRow({ row, year, month, refresh, index, onEditBill, moveC
},
});
} else {
- toast.success('Payment recorded');
+ toast.success(`${row.name} — ${fmt(threshold)} paid`);
}
refresh?.();
} catch (err) {