'use client' import { useState } from 'react' import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from '@/components/ui/dialog' import { Button } from '@/components/ui/button' import { Label } from '@/components/ui/label' import { useToast } from '@/components/ui/use-toast' import { formatCurrency, formatDate } from '@/lib/utils' import { ArrowUpRight, ArrowDownRight, ChevronDown, ChevronUp, Paperclip } from 'lucide-react' import JournalEntryForm from '@/components/bookkeeping/JournalEntryForm' import DocumentUploadZone from '@/components/bookkeeping/DocumentUploadZone' import type { UploadedFile } from '@/components/bookkeeping/DocumentUploadZone' import type { FormLine } from '@/components/bookkeeping/JournalEntryForm' import { resolveSekAmount, buildCurrencyMetadata } from '@/lib/bookkeeping/currency-utils' import type { TransactionWithInvoice } from './transaction-types' interface TransactionBookingDialogProps { open: boolean onOpenChange: (open: boolean) => void transaction: TransactionWithInvoice | null onBooked: (transactionId: string, journalEntryId: string) => void } function buildInitialLines(transaction: TransactionWithInvoice): FormLine[] { const sekAmount = Math.round(Math.abs(resolveSekAmount( transaction.amount, transaction.amount_sek, transaction.currency, transaction.exchange_rate )) * 100) / 100 const amountStr = sekAmount.toFixed(2) const isExpense = transaction.amount < 0 const isForeign = !!transaction.currency && transaction.currency !== 'SEK' const currencyMeta = isForeign ? buildCurrencyMetadata( transaction.currency, Math.abs(transaction.amount), transaction.exchange_rate ) : {} const bankLine: FormLine = { account_number: '1930', debit_amount: isExpense ? '' : amountStr, credit_amount: isExpense ? amountStr : '', line_description: 'Företagskonto', ...currencyMeta, } const counterLine: FormLine = { account_number: '', debit_amount: isExpense ? amountStr : '', credit_amount: isExpense ? '' : amountStr, line_description: '', } return isExpense ? [bankLine, counterLine] : [bankLine, counterLine] } export default function TransactionBookingDialog({ open, onOpenChange, transaction, onBooked, }: TransactionBookingDialogProps) { const { toast } = useToast() const [uploadedFiles, setUploadedFiles] = useState([]) const [showUploadZone, setShowUploadZone] = useState(false) if (!transaction) return null const isIncome = transaction.amount > 0 const handleBooked = async (transactionId: string, journalEntryId: string) => { // Link any uploaded documents to the new journal entry const filesToLink = uploadedFiles.filter((f) => f.status === 'uploaded' && f.id) if (filesToLink.length > 0) { let linkFailCount = 0 for (const file of filesToLink) { try { await fetch(`/api/documents/${file.id}/link`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ journal_entry_id: journalEntryId }), }) } catch { linkFailCount++ } } if (linkFailCount > 0) { toast({ title: 'Underlag kunde inte bifogas', description: `${linkFailCount} fil(er) kunde inte länkas till verifikationen. Försök igen via bokföringssidan.`, variant: 'destructive', }) } } setUploadedFiles([]) setShowUploadZone(false) onBooked(transactionId, journalEntryId) } return ( { if (!o) { setUploadedFiles([]) setShowUploadZone(false) } onOpenChange(o) }}> Bokför transaktion Skapa en verifikation för transaktionen {/* Transaction summary */}
{isIncome ? ( ) : ( )}

{transaction.description}

{formatDate(transaction.date)}

{isIncome ? '+' : ''} {formatCurrency(transaction.amount, transaction.currency)}

{/* Document upload section */}
{showUploadZone && (
)}
handleBooked(transaction.id, entryId)} />
) }