From c61e3d84a5cf445118334fa6e225b1e10e84a2ae Mon Sep 17 00:00:00 2001 From: null Date: Fri, 3 Jul 2026 19:16:10 -0500 Subject: [PATCH] refactor(bill-modal): extract PaymentFormFields (BM2, 4/n) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The add/edit manual-payment form (+ its PAYMENT_METHODS list) moves to its own presentational component; the parent keeps the form state + submit handler. Behavior-preserving — BillModal 1502 -> 1432 lines; build + client tests green. Co-Authored-By: Claude Opus 4.8 --- client/components/BillModal.jsx | 94 ++-------------- .../bill-modal/PaymentFormFields.jsx | 103 ++++++++++++++++++ 2 files changed, 115 insertions(+), 82 deletions(-) create mode 100644 client/components/bill-modal/PaymentFormFields.jsx diff --git a/client/components/BillModal.jsx b/client/components/BillModal.jsx index 54d9c64..037785b 100644 --- a/client/components/BillModal.jsx +++ b/client/components/BillModal.jsx @@ -22,6 +22,7 @@ import BillMerchantRules from '@/components/BillMerchantRules'; import DebtDetailsSection from '@/components/bill-modal/DebtDetailsSection'; import AutopayTrustIndicator from '@/components/bill-modal/AutopayTrustIndicator'; import PaymentHistoryList from '@/components/bill-modal/PaymentHistoryList'; +import PaymentFormFields from '@/components/bill-modal/PaymentFormFields'; import { BILLING_SCHEDULE_OPTIONS, billingCycleForSchedule, @@ -41,15 +42,6 @@ function getOrdinalSuffix(day) { // Radix Select crashes on empty string value const CAT_NONE = 'none'; -const PAYMENT_METHODS = [ - ['manual', 'Manual'], - ['bank', 'Bank Transfer'], - ['card', 'Card'], - ['autopay', 'Autopay'], - ['check', 'Check'], - ['cash', 'Cash'], -]; - const DEBT_KEYWORDS = ['credit', 'loan', 'mortgage', 'housing', 'debt']; const SNOWBALL_KEYWORDS = ['credit', 'loan', 'debt', 'mortgage', 'housing']; const SUBSCRIPTION_TYPES = [ @@ -1091,79 +1083,17 @@ export default function BillModal({ bill, initialBill, categories, onClose, onSa {paymentFormOpen && ( -
-
-

- {editingPayment ? 'Edit payment' : 'Add payment'} -

- - manual - -
-
-
- - setPaymentAmount(e.target.value)} - className={cn(inp, 'font-mono')} - required - /> -
-
- - setPaymentDate(e.target.value)} - className={cn(inp, 'font-mono')} - required - /> -
-
- - -
-
- - setPaymentNotes(e.target.value)} - className={inp} - placeholder="Paid from checking" - /> -
-
-
- - -
-
+ { resetPaymentForm(); setPaymentFormOpen(false); }} + /> )} )} diff --git a/client/components/bill-modal/PaymentFormFields.jsx b/client/components/bill-modal/PaymentFormFields.jsx new file mode 100644 index 0000000..e439670 --- /dev/null +++ b/client/components/bill-modal/PaymentFormFields.jsx @@ -0,0 +1,103 @@ +import { cn } from '@/lib/utils'; +import { Label } from '@/components/ui/label'; +import { Input } from '@/components/ui/input'; +import { + Select, SelectContent, SelectItem, SelectTrigger, SelectValue, +} from '@/components/ui/select'; +import { Button } from '@/components/ui/button'; + +const PAYMENT_METHODS = [ + ['manual', 'Manual'], + ['bank', 'Bank Transfer'], + ['card', 'Card'], + ['autopay', 'Autopay'], + ['check', 'Check'], + ['cash', 'Cash'], +]; + +// Add/edit form for a manual payment on a bill (edit mode). Presentational — +// the parent owns the form state, the submit handler, and open/close. +export default function PaymentFormFields({ + inp, + editingPayment, + paymentBusy, + amount, setAmount, + date, setDate, + method, setMethod, + notes, setNotes, + onSubmit, + onCancel, +}) { + return ( +
+
+

+ {editingPayment ? 'Edit payment' : 'Add payment'} +

+ + manual + +
+
+
+ + setAmount(e.target.value)} + className={cn(inp, 'font-mono')} + required + /> +
+
+ + setDate(e.target.value)} + className={cn(inp, 'font-mono')} + required + /> +
+
+ + +
+
+ + setNotes(e.target.value)} + className={inp} + placeholder="Paid from checking" + /> +
+
+
+ + +
+
+ ); +}