import React, { useState, useEffect } from "react"; import { FaSave, FaTimes, FaPlus, FaTrash, FaFileAlt } from "react-icons/fa"; import { FiInvoice, FiInvoiceItem, InvoiceTypeEnum, InvoiceStatusEnum, PaymentStatusEnum, } from "../../../types/fi"; import { mockCurrentAccounts } from "../../../mocks/mockCurrentAccounts"; interface InvoiceFormProps { invoice?: FiInvoice; onSave: (invoice: Partial) => void; onCancel: () => void; isVisible: boolean; } const InvoiceForm: React.FC = ({ invoice, onSave, onCancel, isVisible, }) => { const [formData, setFormData] = useState>({ invoiceNumber: "", invoiceType: InvoiceTypeEnum.Sales, currentAccountId: "", invoiceDate: new Date(), dueDate: new Date(), deliveryDate: new Date(), subtotal: 0, taxAmount: 0, discountAmount: 0, totalAmount: 0, paidAmount: 0, remainingAmount: 0, currency: "TRY", status: InvoiceStatusEnum.Draft, paymentStatus: PaymentStatusEnum.Unpaid, items: [], waybillNumber: "", notes: "", }); const [newItem, setNewItem] = useState>({ description: "", quantity: 1, unitPrice: 0, taxRate: 18, discountRate: 0, unit: "Adet", }); useEffect(() => { if (invoice) { setFormData({ ...invoice, invoiceDate: new Date(invoice.invoiceDate), dueDate: new Date(invoice.dueDate), deliveryDate: invoice.deliveryDate ? new Date(invoice.deliveryDate) : new Date(), }); } else { // Generate new invoice number const now = new Date(); const year = now.getFullYear(); const month = String(now.getMonth() + 1).padStart(2, "0"); const invoiceNumber = `FT${year}${month}${String( Math.floor(Math.random() * 10000) ).padStart(4, "0")}`; setFormData((prev) => ({ ...prev, invoiceNumber, invoiceDate: now, dueDate: new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000), // 30 days deliveryDate: now, })); } }, [invoice]); const calculateItemTotal = (item: Partial) => { const subtotal = (item.quantity || 0) * (item.unitPrice || 0); const discountAmount = subtotal * ((item.discountRate || 0) / 100); const taxableAmount = subtotal - discountAmount; const taxAmount = taxableAmount * ((item.taxRate || 0) / 100); return taxableAmount + taxAmount; }; const calculateInvoiceTotals = (items: FiInvoiceItem[]) => { const subtotal = items.reduce( (sum, item) => sum + item.quantity * item.unitPrice, 0 ); const discountAmount = items.reduce( (sum, item) => sum + item.discountAmount, 0 ); const taxAmount = items.reduce((sum, item) => sum + item.taxAmount, 0); const totalAmount = items.reduce((sum, item) => sum + item.lineTotal, 0); return { subtotal, discountAmount, taxAmount, totalAmount, }; }; const handleAddItem = () => { if (!newItem.description || !newItem.quantity || !newItem.unitPrice) { alert("Lütfen ürün bilgilerini doldurun"); return; } const item: FiInvoiceItem = { id: Date.now().toString(), invoiceId: formData.id || "", description: newItem.description!, quantity: newItem.quantity!, unitPrice: newItem.unitPrice!, unit: newItem.unit || "Adet", taxRate: newItem.taxRate || 18, discountRate: newItem.discountRate || 0, lineTotal: calculateItemTotal(newItem), discountAmount: (newItem.quantity || 0) * (newItem.unitPrice || 0) * ((newItem.discountRate || 0) / 100), taxAmount: ((newItem.quantity || 0) * (newItem.unitPrice || 0) - (newItem.quantity || 0) * (newItem.unitPrice || 0) * ((newItem.discountRate || 0) / 100)) * ((newItem.taxRate || 0) / 100), netAmount: calculateItemTotal(newItem), }; const updatedItems = [...(formData.items || []), item]; const totals = calculateInvoiceTotals(updatedItems); setFormData((prev) => ({ ...prev, items: updatedItems, ...totals, remainingAmount: totals.totalAmount - (prev.paidAmount || 0), })); setNewItem({ description: "", quantity: 1, unitPrice: 0, taxRate: 18, discountRate: 0, unit: "Adet", }); }; const handleRemoveItem = (itemId: string) => { const updatedItems = formData.items?.filter((item) => item.id !== itemId) || []; const totals = calculateInvoiceTotals(updatedItems); setFormData((prev) => ({ ...prev, items: updatedItems, ...totals, remainingAmount: totals.totalAmount - (prev.paidAmount || 0), })); }; const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); if (!formData.currentAccountId) { alert("Lütfen cari hesap seçin"); return; } if (!formData.items?.length) { alert("Lütfen en az bir ürün ekleyin"); return; } onSave({ ...formData, id: invoice?.id || Date.now().toString(), creationTime: invoice?.creationTime || new Date(), lastModificationTime: new Date(), }); }; const formatCurrency = (amount: number) => { return amount.toLocaleString("tr-TR", { style: "currency", currency: "TRY", minimumFractionDigits: 2, }); }; if (!isVisible) return null; return (

{invoice ? "Fatura Düzenle" : "Yeni Fatura"}

{/* Basic Information */}
setFormData({ ...formData, invoiceNumber: e.target.value }) } className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" required />
setFormData({ ...formData, waybillNumber: e.target.value }) } className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" />
setFormData({ ...formData, invoiceDate: new Date(e.target.value), }) } className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" required />
setFormData({ ...formData, dueDate: new Date(e.target.value), }) } className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" required />
{/* Invoice Items */}

Fatura Kalemleri

{/* Add New Item */}
setNewItem({ ...newItem, description: e.target.value }) } className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="Ürün/Hizmet açıklaması" />
setNewItem({ ...newItem, quantity: parseFloat(e.target.value) || 0, }) } className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" step="0.01" min="0" />
setNewItem({ ...newItem, unitPrice: parseFloat(e.target.value) || 0, }) } className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" step="0.01" min="0" />
{/* Items List */} {formData.items && formData.items.length > 0 && (
{formData.items.map((item) => ( ))}
Açıklama Miktar Birim Fiyat KDV % Toplam İşlem
{item.description} {item.quantity.toLocaleString("tr-TR")} {formatCurrency(item.unitPrice)} %{item.taxRate} {formatCurrency(item.lineTotal)}
)}
{/* Totals */}