import React, { useState } from 'react'; import { Plus, Trash2, Printer, Upload, RefreshCcw, FileText, User, Briefcase, Calendar, DollarSign, Settings } from 'lucide-react'; const InvoiceGenerator = () => { // --- State Management --- const [invoiceNumber, setInvoiceNumber] = useState('INV-001'); const [date, setDate] = useState(new Date().toISOString().split('T')[0]); const [dueDate, setDueDate] = useState(''); const [senderDetails, setSenderDetails] = useState({ name: 'Your Business Name', address: '123 Business Rd, Suite 100', cityState: 'New York, NY 10001', email: 'contact@yourbusiness.com' }); const [recipientDetails, setRecipientDetails] = useState({ name: 'Client Company Name', address: '456 Client Avenue', cityState: 'San Francisco, CA 94105', email: 'billing@client.com' }); const [items, setItems] = useState([ { id: 1, description: 'Web Development Services', quantity: 1, price: 1500.00 }, { id: 2, description: 'Hosting & Maintenance (Annual)', quantity: 1, price: 300.00 }, ]); const [taxRate, setTaxRate] = useState(10); const [notes, setNotes] = useState('Thank you for your business. Payment is due within 30 days.'); const [currencySymbol, setCurrencySymbol] = useState('$'); const [logo, setLogo] = useState(null); // --- Actions --- const handleFileUpload = (e) => { const file = e.target.files[0]; if (file) { const reader = new FileReader(); reader.onloadend = () => { setLogo(reader.result); }; reader.readAsDataURL(file); } }; const addItem = () => { setItems([...items, { id: Date.now(), description: '', quantity: 1, price: 0 }]); }; const removeItem = (id) => { setItems(items.filter(item => item.id !== id)); }; const updateItem = (id, field, value) => { setItems(items.map(item => item.id === id ? { ...item, [field]: value } : item )); }; const handlePrint = () => { window.print(); }; // --- Calculations --- const subtotal = items.reduce((sum, item) => sum + (item.quantity * item.price), 0); const taxAmount = subtotal * (taxRate / 100); const total = subtotal + taxAmount; // --- Formatters --- const formatCurrency = (amount) => { return new Intl.NumberFormat('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2, }).format(amount); }; return (
{/* Top Navigation Bar - Hidden on print */}

Invoice Generator

{/* LEFT COLUMN: FORM EDITOR */}
{/* Section: Company Info */}

From (Your Business)

setSenderDetails({...senderDetails, name: e.target.value})} className="w-full px-3 py-2 border border-slate-300 rounded-md text-sm focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 outline-none" /> setSenderDetails({...senderDetails, address: e.target.value})} className="w-full px-3 py-2 border border-slate-300 rounded-md text-sm focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 outline-none" />
setSenderDetails({...senderDetails, cityState: e.target.value})} className="w-full px-3 py-2 border border-slate-300 rounded-md text-sm focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 outline-none" /> setSenderDetails({...senderDetails, email: e.target.value})} className="w-full px-3 py-2 border border-slate-300 rounded-md text-sm focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 outline-none" />
{/* Section: Client Info */}

To (Client)

setRecipientDetails({...recipientDetails, name: e.target.value})} className="w-full px-3 py-2 border border-slate-300 rounded-md text-sm focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 outline-none" /> setRecipientDetails({...recipientDetails, address: e.target.value})} className="w-full px-3 py-2 border border-slate-300 rounded-md text-sm focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 outline-none" />
setRecipientDetails({...recipientDetails, cityState: e.target.value})} className="w-full px-3 py-2 border border-slate-300 rounded-md text-sm focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 outline-none" /> setRecipientDetails({...recipientDetails, email: e.target.value})} className="w-full px-3 py-2 border border-slate-300 rounded-md text-sm focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 outline-none" />
{/* Section: Invoice Details */}

Invoice Details

setInvoiceNumber(e.target.value)} className="w-full px-3 py-2 border border-slate-300 rounded-md text-sm focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 outline-none" />
setCurrencySymbol(e.target.value)} className="w-full px-3 py-2 border border-slate-300 rounded-md text-sm focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 outline-none" />
setDate(e.target.value)} className="w-full px-3 py-2 border border-slate-300 rounded-md text-sm focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 outline-none" />
setDueDate(e.target.value)} className="w-full px-3 py-2 border border-slate-300 rounded-md text-sm focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 outline-none" />
{/* Section: Line Items */}

Line Items

{items.map((item, index) => (
updateItem(item.id, 'description', e.target.value)} className="flex-grow px-3 py-2 border border-slate-300 rounded-md text-sm focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 outline-none" />
updateItem(item.id, 'quantity', parseFloat(e.target.value))} className="w-full px-3 py-2 border border-slate-300 rounded-md text-sm focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 outline-none" />
updateItem(item.id, 'price', parseFloat(e.target.value))} className="w-full px-3 py-2 border border-slate-300 rounded-md text-sm focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 outline-none" />
{formatCurrency(item.quantity * item.price)}
))} {items.length === 0 && (
No items added yet.
)}
{/* Section: Settings */}

Settings & Notes

setTaxRate(parseFloat(e.target.value))} className="w-full px-3 py-2 border border-slate-300 rounded-md text-sm focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 outline-none" />