'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 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 amount = Math.round(Math.abs(transaction.amount_sek ?? transaction.amount) * 100) / 100 const amountStr = amount.toFixed(2) const isExpense = transaction.amount < 0 if (isExpense) { return [ { account_number: '1930', debit_amount: '', credit_amount: amountStr, line_description: 'Företagskonto' }, { account_number: '', debit_amount: amountStr, credit_amount: '', line_description: '' }, ] } return [ { account_number: '1930', debit_amount: amountStr, credit_amount: '', line_description: 'Företagskonto' }, { account_number: '', debit_amount: '', credit_amount: amountStr, line_description: '' }, ] } 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 (linkErr) { console.error('[TransactionBookingDialog] Failed to link document:', linkErr) 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)} />
) }