'use client' import { useEffect, useState } from 'react' import { useTranslations } from 'next-intl' import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, } from '@/components/ui/dialog' import { Button } from '@/components/ui/button' import { Loader2 } from 'lucide-react' import { cn } from '@/lib/utils' import type { CashAccount } from '@/types' interface MoveTransactionCashAccountDialogProps { open: boolean onOpenChange: (open: boolean) => void /** Enabled cash accounts to offer (the page's /api/cash-accounts?enabled_only=true list). */ cashAccounts: CashAccount[] /** cash_accounts.id the transaction is currently bound to (null = unassigned). */ currentCashAccountId: string | null /** Transaction currency: accounts in another currency cannot be picked * (the server hard-rejects a cross-currency move). */ currency: string /** Persist the move (PATCH). Resolves true on success (dialog closes), * false to keep the dialog open (e.g. the request failed). */ onMove: (accountNumber: string) => Promise } /** * Move an unbooked bank transaction to another of the company's cash accounts. * Radio list of the enabled accounts (name + ledger account); the current * account is preselected and disabled so the user picks where the row should * go. Gating (only unbooked/unmatched rows) is enforced server-side; callers * only open this for movable rows. */ export default function MoveTransactionCashAccountDialog({ open, onOpenChange, cashAccounts, currentCashAccountId, currency, onMove, }: MoveTransactionCashAccountDialogProps) { const t = useTranslations('tx_inbox_card') const currentLedger = cashAccounts.find((a) => a.id === currentCashAccountId)?.ledger_account ?? null const [selected, setSelected] = useState(currentLedger) const [isSaving, setIsSaving] = useState(false) // Re-seed the selection each time the dialog opens for a (possibly different) row. useEffect(() => { if (open) setSelected(currentLedger) // eslint-disable-next-line react-hooks/exhaustive-deps }, [open, currentCashAccountId]) const canSave = selected !== null && selected !== currentLedger && !isSaving async function persist() { if (!canSave || selected === null) return setIsSaving(true) try { const ok = await onMove(selected) if (ok) onOpenChange(false) } finally { setIsSaving(false) } } return ( { if (isSaving) return onOpenChange(v) }} > {t('move_account_dialog_title')} {t('move_account_dialog_description')}
{cashAccounts.map((account) => { const isCurrent = account.id === currentCashAccountId const currencyMismatch = account.currency.toUpperCase() !== currency.toUpperCase() const disabled = isCurrent || currencyMismatch || isSaving return ( ) })}
) }