Add bank account templates and default invoice payment text.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
8465a29ce1
commit
ff419603bf
@@ -1,8 +1,9 @@
|
||||
import { Pencil, Plus, X } from 'lucide-react'
|
||||
import type { InvoiceItemTemplate } from '../types/invoice'
|
||||
import type { InvoiceAccountTemplate, InvoiceItemTemplate } from '../types/invoice'
|
||||
import { formatIrtInput, formatIrtPrice } from '../utils/irtPrice'
|
||||
import type { DraftAccount, DraftKeyPoint, DraftLineItem, DraftPaymentMethod } from '../utils/invoiceDraft'
|
||||
import {
|
||||
draftAccountFromAccountTemplate,
|
||||
draftItemFromItemTemplate,
|
||||
emptyDraftAccount,
|
||||
emptyDraftItem,
|
||||
@@ -26,32 +27,40 @@ function focusPaymentMethodInput(index: number) {
|
||||
|
||||
type Props = {
|
||||
itemTemplates: InvoiceItemTemplate[]
|
||||
accountTemplates: InvoiceAccountTemplate[]
|
||||
items: DraftLineItem[]
|
||||
keyPoints: DraftKeyPoint[]
|
||||
paymentMethods: DraftPaymentMethod[]
|
||||
accounts: DraftAccount[]
|
||||
selectedItemTemplateId: string
|
||||
onSelectedItemTemplateId: (id: string) => void
|
||||
selectedAccountTemplateId: string
|
||||
onSelectedAccountTemplateId: (id: string) => void
|
||||
onItemsChange: (items: DraftLineItem[]) => void
|
||||
onKeyPointsChange: (points: DraftKeyPoint[]) => void
|
||||
onPaymentMethodsChange: (methods: DraftPaymentMethod[]) => void
|
||||
onAccountsChange: (accounts: DraftAccount[]) => void
|
||||
showItemTemplatePicker?: boolean
|
||||
showAccountTemplatePicker?: boolean
|
||||
}
|
||||
|
||||
export function InvoiceDraftFields({
|
||||
itemTemplates,
|
||||
accountTemplates,
|
||||
items,
|
||||
keyPoints,
|
||||
paymentMethods,
|
||||
accounts,
|
||||
selectedItemTemplateId,
|
||||
onSelectedItemTemplateId,
|
||||
selectedAccountTemplateId,
|
||||
onSelectedAccountTemplateId,
|
||||
onItemsChange,
|
||||
onKeyPointsChange,
|
||||
onPaymentMethodsChange,
|
||||
onAccountsChange,
|
||||
showItemTemplatePicker = true,
|
||||
showAccountTemplatePicker = true,
|
||||
}: Props) {
|
||||
function updateItem(key: string, patch: Partial<DraftLineItem>) {
|
||||
onItemsChange(items.map((item) => (item.key === key ? { ...item, ...patch } : item)))
|
||||
@@ -74,6 +83,13 @@ export function InvoiceDraftFields({
|
||||
onSelectedItemTemplateId('')
|
||||
}
|
||||
|
||||
function addFromAccountTemplate() {
|
||||
const template = accountTemplates.find((t) => t.id === selectedAccountTemplateId)
|
||||
if (!template) return
|
||||
onAccountsChange([...accounts, draftAccountFromAccountTemplate(template)])
|
||||
onSelectedAccountTemplateId('')
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={styles.itemsStack}>
|
||||
@@ -314,14 +330,44 @@ export function InvoiceDraftFields({
|
||||
<div className={styles.blockSection}>
|
||||
<div className={styles.blockHeader}>
|
||||
<h4 className={styles.blockTitle}>Account numbers</h4>
|
||||
<button
|
||||
type="button"
|
||||
className={`${tableStyles.btn} ${tableStyles.btnGhost}`}
|
||||
onClick={() => onAccountsChange([...accounts, emptyDraftAccount()])}
|
||||
>
|
||||
<Plus size={16} />
|
||||
Add account
|
||||
</button>
|
||||
<div className={styles.blockHeaderActions}>
|
||||
{showAccountTemplatePicker ? (
|
||||
<div className={styles.itemActionsLeft}>
|
||||
<select
|
||||
id="account-template-pick"
|
||||
className={styles.compactSelect}
|
||||
value={selectedAccountTemplateId}
|
||||
onChange={(e) => onSelectedAccountTemplateId(e.target.value)}
|
||||
aria-label="Add from account template"
|
||||
>
|
||||
<option value="">Add from account template…</option>
|
||||
{accountTemplates.map((template) => (
|
||||
<option key={template.id} value={template.id}>
|
||||
{template.bankName}
|
||||
{template.accountHolderName ? ` — ${template.accountHolderName}` : ''}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<button
|
||||
type="button"
|
||||
className={`${tableStyles.btn} ${tableStyles.btnGhost} ${styles.compactBtn}`}
|
||||
onClick={addFromAccountTemplate}
|
||||
disabled={!selectedAccountTemplateId}
|
||||
>
|
||||
<Plus size={14} />
|
||||
Add
|
||||
</button>
|
||||
</div>
|
||||
) : null}
|
||||
<button
|
||||
type="button"
|
||||
className={`${tableStyles.btn} ${tableStyles.btnGhost}`}
|
||||
onClick={() => onAccountsChange([...accounts, emptyDraftAccount()])}
|
||||
>
|
||||
<Plus size={16} />
|
||||
Add account
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{accounts.length === 0 ? (
|
||||
<p className={styles.templateHint}>No bank accounts yet.</p>
|
||||
|
||||
Reference in New Issue
Block a user