// SplitBookModal - Modal for splitting one bank transaction to multiple accounts import { useState, useEffect, useMemo, useRef } from 'react'; import { Modal, Form, Input, InputNumber, Card, Table, Space, Typography, Alert, Divider, Tag, Button, Row, Col, } from 'antd'; import { CheckCircleOutlined, WarningOutlined, PlusOutlined, DeleteOutlined, } from '@ant-design/icons'; import { formatCurrency, formatDateShort } from '@/lib/formatters'; import { accountingColors } from '@/styles/theme'; import { generateSplitDoubleEntry, type SplitBookingInput, type SplitBookingLine } from '@/lib/accounting'; import type { VATCode } from '@/types/vat'; import type { Account } from '@/types/accounting'; import { AccountQuickPicker, VATCodePicker } from './AccountQuickPicker'; import { useBookingPreview, useIsBookingSaving, useSimpleBookingStore, } from '@/stores/simpleBookingStore'; const { Text } = Typography; interface SplitBookModalProps { accounts: Account[]; onSubmit: (transaction: ReturnType) => Promise; } export function SplitBookModal({ accounts, onSubmit }: SplitBookModalProps) { const { modal, closeModal, setPreview, splitState, addSplitLine, removeSplitLine, clearSplitLines, } = useSimpleBookingStore(); const preview = useBookingPreview(); const isSaving = useIsBookingSaving(); // New line form state const [newLineAccountId, setNewLineAccountId] = useState(); const [newLineAmount, setNewLineAmount] = useState(null); const [newLineVATCode, setNewLineVATCode] = useState('K25'); const [newLineDescription, setNewLineDescription] = useState(''); const bankTransaction = modal.bankTransaction; const isOpen = modal.isOpen && modal.type === 'split'; const isExpense = bankTransaction ? bankTransaction.amount < 0 : true; // Track previous open state to detect modal opening const wasOpenRef = useRef(false); const lastTransactionIdRef = useRef(null); // Reset form only when modal opens or transaction changes useEffect(() => { const isNewlyOpened = isOpen && !wasOpenRef.current; const isNewTransaction = bankTransaction && bankTransaction.id !== lastTransactionIdRef.current; if (isOpen && bankTransaction && (isNewlyOpened || isNewTransaction)) { // Calculate isExpense inside effect to avoid dependency const expense = bankTransaction.amount < 0; clearSplitLines(); setNewLineAccountId(undefined); setNewLineAmount(null); setNewLineVATCode(expense ? 'K25' : 'S25'); setNewLineDescription(''); setPreview(null); lastTransactionIdRef.current = bankTransaction.id; } wasOpenRef.current = isOpen; }, [isOpen, bankTransaction, clearSplitLines, setPreview]); // Generate preview when lines change useEffect(() => { if (!bankTransaction || splitState.lines.length === 0) { setPreview(null); return; } const input: SplitBookingInput = { bankTransaction: { id: bankTransaction.id, date: bankTransaction.date, amount: bankTransaction.amount, description: bankTransaction.description, counterparty: bankTransaction.counterparty, bankAccountId: bankTransaction.bankAccountId, bankAccountNumber: bankTransaction.bankAccountNumber, }, lines: splitState.lines, }; const result = generateSplitDoubleEntry(input); setPreview(result); }, [bankTransaction, splitState.lines, setPreview]); // Account options for picker const accountOptions = useMemo( () => accounts.map((a) => ({ id: a.id, accountNumber: a.accountNumber, name: a.name, type: a.type, })), [accounts] ); // Add a new split line const handleAddLine = () => { if (!newLineAccountId || !newLineAmount) return; const account = accounts.find((a) => a.id === newLineAccountId); if (!account) return; const newLine: SplitBookingLine = { accountId: account.id, accountNumber: account.accountNumber, accountName: account.name, amount: newLineAmount, vatCode: newLineVATCode, description: newLineDescription || undefined, }; addSplitLine(newLine); // Reset form for next line setNewLineAccountId(undefined); setNewLineAmount(null); setNewLineDescription(''); }; // Fill remaining amount const handleFillRemaining = () => { setNewLineAmount(splitState.remainingAmount); }; const handleSubmit = async () => { if (!preview || !preview.isValid) return; await onSubmit(preview); closeModal(); }; // Preview table columns const previewColumns = [ { title: 'Konto', key: 'account', render: (_: unknown, record: { accountNumber: string; accountName: string }) => ( {record.accountNumber} {record.accountName} ), }, { title: 'Debet', dataIndex: 'debit', key: 'debit', align: 'right' as const, render: (value: number) => value > 0 ? ( {formatCurrency(value)} ) : null, }, { title: 'Kredit', dataIndex: 'credit', key: 'credit', align: 'right' as const, render: (value: number) => value > 0 ? ( {formatCurrency(value)} ) : null, }, ]; // Split lines table columns const splitLinesColumns = [ { title: '#', key: 'index', width: 40, render: (_: unknown, __: unknown, index: number) => index + 1, }, { title: 'Konto', key: 'account', render: (_: unknown, record: SplitBookingLine) => ( {record.accountNumber} {record.accountName} ), }, { title: 'Beloeb', dataIndex: 'amount', key: 'amount', align: 'right' as const, render: (value: number) => formatCurrency(value), }, { title: 'Moms', dataIndex: 'vatCode', key: 'vatCode', render: (code: VATCode) => {code}, }, { title: '', key: 'actions', width: 50, render: (_: unknown, __: unknown, index: number) => (