import { Document, Page, Text, View, StyleSheet, } from '@react-pdf/renderer' import type { Invoice, InvoiceItem, Customer, CompanySettings } from '@/types' // Create styles const styles = StyleSheet.create({ page: { padding: 40, fontSize: 10, fontFamily: 'Helvetica', }, header: { flexDirection: 'row', justifyContent: 'space-between', marginBottom: 30, }, title: { fontSize: 24, fontWeight: 'bold', color: '#1a1a1a', }, companyInfo: { textAlign: 'right', }, companyName: { fontSize: 14, fontWeight: 'bold', marginBottom: 4, }, section: { marginBottom: 20, }, sectionTitle: { fontSize: 11, fontWeight: 'bold', marginBottom: 8, color: '#666', textTransform: 'uppercase', letterSpacing: 0.5, }, row: { flexDirection: 'row', justifyContent: 'space-between', marginBottom: 4, }, label: { color: '#666', }, value: { fontWeight: 'bold', }, customerBox: { backgroundColor: '#f5f5f5', padding: 15, borderRadius: 4, marginBottom: 20, }, customerName: { fontSize: 12, fontWeight: 'bold', marginBottom: 4, }, table: { marginTop: 10, }, tableHeader: { flexDirection: 'row', borderBottomWidth: 1, borderBottomColor: '#ddd', paddingBottom: 8, marginBottom: 8, }, tableRow: { flexDirection: 'row', paddingVertical: 6, borderBottomWidth: 1, borderBottomColor: '#eee', }, colDescription: { flex: 4, }, colQty: { flex: 1, textAlign: 'right', }, colUnit: { flex: 1, textAlign: 'center', }, colPrice: { flex: 1.5, textAlign: 'right', }, colTotal: { flex: 1.5, textAlign: 'right', }, tableHeaderText: { fontWeight: 'bold', color: '#666', fontSize: 9, textTransform: 'uppercase', }, totalsSection: { marginTop: 20, paddingTop: 15, borderTopWidth: 2, borderTopColor: '#ddd', }, totalRow: { flexDirection: 'row', justifyContent: 'flex-end', marginBottom: 4, }, totalLabel: { width: 120, textAlign: 'right', paddingRight: 15, color: '#666', }, totalValue: { width: 100, textAlign: 'right', }, grandTotal: { flexDirection: 'row', justifyContent: 'flex-end', marginTop: 10, paddingTop: 10, borderTopWidth: 1, borderTopColor: '#333', }, grandTotalLabel: { width: 120, textAlign: 'right', paddingRight: 15, fontSize: 14, fontWeight: 'bold', }, grandTotalValue: { width: 100, textAlign: 'right', fontSize: 14, fontWeight: 'bold', }, paymentSection: { marginTop: 30, padding: 15, backgroundColor: '#f8f9fa', borderRadius: 4, }, paymentTitle: { fontSize: 11, fontWeight: 'bold', marginBottom: 10, color: '#333', }, paymentRow: { flexDirection: 'row', marginBottom: 4, }, paymentLabel: { width: 100, color: '#666', }, paymentValue: { flex: 1, }, reverseChargeBox: { marginTop: 20, padding: 12, backgroundColor: '#fff3cd', borderRadius: 4, borderWidth: 1, borderColor: '#ffc107', }, reverseChargeText: { fontSize: 9, color: '#856404', }, notesBox: { marginTop: 20, padding: 12, backgroundColor: '#e8f4fd', borderRadius: 4, }, notesText: { fontSize: 9, color: '#0c5460', }, creditNoteBox: { marginBottom: 20, padding: 12, backgroundColor: '#f8d7da', borderRadius: 4, borderWidth: 1, borderColor: '#f5c6cb', }, creditNoteText: { fontSize: 10, color: '#721c24', }, creditNoteTitle: { color: '#721c24', }, footer: { position: 'absolute', bottom: 30, left: 40, right: 40, borderTopWidth: 1, borderTopColor: '#ddd', paddingTop: 10, }, footerText: { fontSize: 8, color: '#999', textAlign: 'center', }, twoColumn: { flexDirection: 'row', justifyContent: 'space-between', }, column: { width: '48%', }, }) // Format currency function formatCurrency(amount: number, currency: string = 'SEK'): string { return new Intl.NumberFormat('sv-SE', { style: 'currency', currency, minimumFractionDigits: 2, maximumFractionDigits: 2, }).format(amount) } // Format date function formatDate(date: string): string { return new Date(date).toLocaleDateString('sv-SE') } // Format org number function formatOrgNumber(orgNumber: string): string { const cleaned = orgNumber.replace(/\D/g, '') if (cleaned.length === 10) { return `${cleaned.slice(0, 6)}-${cleaned.slice(6)}` } return orgNumber } interface InvoicePDFProps { invoice: Invoice customer: Customer items: InvoiceItem[] company: CompanySettings originalInvoiceNumber?: string } export function InvoicePDF({ invoice, customer, items, company, originalInvoiceNumber }: InvoicePDFProps) { const isCreditNote = !!invoice.credited_invoice_id return ( {/* Header */} {isCreditNote ? 'KREDITFAKTURA' : 'FAKTURA'} {invoice.invoice_number} {company.company_name} {company.address_line1 && {company.address_line1}} {(company.postal_code || company.city) && ( {company.postal_code} {company.city} )} {company.org_number && ( Org.nr: {formatOrgNumber(company.org_number)} )} {company.vat_number && VAT: {company.vat_number}} {/* Credit note reference */} {isCreditNote && originalInvoiceNumber && ( Denna kreditfaktura avser och krediterar faktura nr {originalInvoiceNumber} )} {/* Invoice details and Customer - two columns */} {/* Invoice details */} Fakturainformation Fakturadatum: {formatDate(invoice.invoice_date)} Förfallodatum: {formatDate(invoice.due_date)} {invoice.your_reference && ( Er referens: {invoice.your_reference} )} {invoice.our_reference && ( Vår referens: {invoice.our_reference} )} {/* Customer */} Faktureras till {customer.name} {customer.address_line1 && {customer.address_line1}} {customer.address_line2 && {customer.address_line2}} {(customer.postal_code || customer.city) && ( {customer.postal_code} {customer.city} )} {customer.country && customer.country !== 'SE' && ( {customer.country} )} {customer.org_number && ( Org.nr: {customer.org_number} )} {customer.vat_number && VAT: {customer.vat_number}} {/* Items table */} Specifikation {/* Table header */} Beskrivning Antal Enhet à-pris Summa {/* Table rows */} {items.map((item, index) => ( {item.description} {item.quantity} {item.unit} {formatCurrency(item.unit_price, invoice.currency)} {formatCurrency(item.line_total, invoice.currency)} ))} {/* Totals */} Delsumma: {formatCurrency(invoice.subtotal, invoice.currency)} Moms ({invoice.vat_rate}%): {formatCurrency(invoice.vat_amount, invoice.currency)} {isCreditNote ? 'Att kreditera:' : 'Att betala:'} {formatCurrency(invoice.total, invoice.currency)} {invoice.currency !== 'SEK' && invoice.total_sek && ( I SEK (kurs {invoice.exchange_rate}): {formatCurrency(invoice.total_sek, 'SEK')} )} {/* Payment information - not shown for credit notes */} {!isCreditNote && ( Betalningsinformation {company.bank_name && ( Bank: {company.bank_name} )} {(company.clearing_number || company.account_number) && ( Kontonummer: {company.clearing_number}-{company.account_number} )} {company.iban && ( IBAN: {company.iban} )} {company.bic && ( BIC/SWIFT: {company.bic} )} Förfallodatum: {formatDate(invoice.due_date)} OCR/Referens: {invoice.invoice_number} )} {/* Reverse charge notice */} {invoice.reverse_charge_text && ( {invoice.reverse_charge_text} )} {/* Notes */} {invoice.notes && ( {invoice.notes} )} {/* Footer */} {company.company_name} {company.org_number ? ` | Org.nr: ${formatOrgNumber(company.org_number)}` : ''} {company.f_skatt ? ' | Godkänd för F-skatt' : ''} {company.vat_number ? ` | Momsreg.nr: ${company.vat_number}` : ''} ) }