266 lines
9.7 KiB
TypeScript
266 lines
9.7 KiB
TypeScript
import React from 'react';
|
|
import { useParams, useNavigate } from 'react-router-dom';
|
|
import { Button } from '@/components/ui/button';
|
|
import { Card, CardContent } from '@/components/ui/card';
|
|
import { Badge } from '@/components/ui/badge';
|
|
import {
|
|
ArrowLeft,
|
|
Download,
|
|
Send,
|
|
DollarSign,
|
|
Calendar,
|
|
Phone,
|
|
Mail,
|
|
MapPin,
|
|
CreditCard
|
|
} from 'lucide-react';
|
|
|
|
const InvoiceDetail = () => {
|
|
const { id } = useParams();
|
|
const navigate = useNavigate();
|
|
|
|
// Mock invoice data - in real app, fetch by ID
|
|
const invoice = {
|
|
id: id,
|
|
invoiceNumber: 'INV-0044777',
|
|
company: {
|
|
name: 'ListOn',
|
|
address: '1355 Market Street, Suite 900',
|
|
city: 'San Francisco, CA 94103',
|
|
phone: '(123) 456-7890',
|
|
email: 'billing@liston.com'
|
|
},
|
|
customer: {
|
|
name: 'Alexander Kamin',
|
|
email: 'first.last@example.com',
|
|
address: '1355 Market Street, Suite 900',
|
|
city: 'San Francisco, CA 94103',
|
|
phone: '(123) 456-7890'
|
|
},
|
|
issueDate: 'March 19th, 2017',
|
|
dueDate: 'April 21th, 2017',
|
|
status: 'paid',
|
|
items: [
|
|
{
|
|
description: 'Lorem Ipsum is simply dummy text',
|
|
details: 'Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots',
|
|
quantity: 1,
|
|
unitPrice: 39.00,
|
|
tax: 71.98,
|
|
totalPrice: 27.98
|
|
},
|
|
{
|
|
description: 'It is a long established fact that a reader will be',
|
|
details: 'There are many variations of passages of Lorem Ipsum available, but the majority',
|
|
quantity: 2,
|
|
unitPrice: 57.00,
|
|
tax: 56.80,
|
|
totalPrice: 112.80
|
|
},
|
|
{
|
|
description: 'The standard chunk of Lorem Ipsum used since',
|
|
details: 'It has survived not only five centuries, but also the leap into electronic.',
|
|
quantity: 3,
|
|
unitPrice: 645.00,
|
|
tax: 321.20,
|
|
totalPrice: 1286.20
|
|
},
|
|
{
|
|
description: 'The standard chunk of Lorem Ipsum used since',
|
|
details: 'It has survived not only five centuries, but also the leap into electronic.',
|
|
quantity: 3,
|
|
unitPrice: 486.00,
|
|
tax: 524.20,
|
|
totalPrice: 789.20
|
|
}
|
|
],
|
|
subtotal: 920.05,
|
|
discount: 12.9,
|
|
vat: 0,
|
|
grandTotal: 1248.9,
|
|
paymentNote: 'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry\'s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.',
|
|
thankNote: 'Thank you very much for choosing us. It was a pleasure to have worked with you.'
|
|
};
|
|
|
|
const getStatusColor = (status: string) => {
|
|
switch (status) {
|
|
case 'paid':
|
|
return 'bg-green-100 text-green-800 border-green-200';
|
|
case 'pending':
|
|
return 'bg-yellow-100 text-yellow-800 border-yellow-200';
|
|
case 'overdue':
|
|
return 'bg-red-100 text-red-800 border-red-200';
|
|
default:
|
|
return 'bg-gray-100 text-gray-800 border-gray-200';
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="p-6 max-w-5xl mx-auto">
|
|
{/* Header */}
|
|
<div className="flex items-center justify-between mb-6">
|
|
<Button
|
|
variant="outline"
|
|
onClick={() => navigate('/dashboard/invoices')}
|
|
className="flex items-center gap-2"
|
|
>
|
|
<ArrowLeft className="w-4 h-4" />
|
|
Back to Invoices
|
|
</Button>
|
|
|
|
<div className="flex items-center gap-3">
|
|
<Badge
|
|
variant="outline"
|
|
className={`capitalize ${getStatusColor(invoice.status)}`}
|
|
>
|
|
{invoice.status}
|
|
</Badge>
|
|
<Button variant="outline" size="sm">
|
|
<Download className="w-4 h-4 mr-2" />
|
|
Download PDF
|
|
</Button>
|
|
<Button variant="outline" size="sm">
|
|
<Send className="w-4 h-4 mr-2" />
|
|
Send Email
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Invoice Content */}
|
|
<Card className="p-8">
|
|
<CardContent className="p-0">
|
|
{/* Invoice Header */}
|
|
<div className="flex justify-between items-start mb-12">
|
|
<div>
|
|
<h1 className="text-4xl font-bold text-red-500 mb-4">
|
|
List<span className="text-black">On</span>.
|
|
</h1>
|
|
<div className="space-y-1 text-sm text-muted-foreground">
|
|
<p className="font-medium">{invoice.company.name}</p>
|
|
<p>{invoice.company.address}</p>
|
|
<p>{invoice.company.city}</p>
|
|
<p>P: {invoice.company.phone}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="text-right">
|
|
<h2 className="text-2xl font-bold mb-2">Invoice #{invoice.invoiceNumber}</h2>
|
|
<div className="space-y-1 text-sm">
|
|
<p><span className="font-medium">Issued</span> {invoice.issueDate}</p>
|
|
<p className="text-red-500"><span className="font-medium">Payment due</span> {invoice.dueDate}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Bill To Section */}
|
|
<div className="flex justify-between mb-8">
|
|
<div>
|
|
<h3 className="font-bold text-red-500 mb-3">Full Name</h3>
|
|
<p className="text-red-500 font-medium">{invoice.customer.email}</p>
|
|
</div>
|
|
|
|
<div className="text-right">
|
|
<div className="space-y-1 text-sm">
|
|
<p className="font-medium">{invoice.company.name}</p>
|
|
<p>{invoice.company.address}</p>
|
|
<p>{invoice.company.city}</p>
|
|
<p>P: {invoice.company.phone}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Items Table */}
|
|
<div className="mb-8">
|
|
<div className="bg-gray-50 rounded-t-lg">
|
|
<div className="grid grid-cols-12 gap-4 p-4 font-medium text-sm">
|
|
<div className="col-span-5">ITEM LIST</div>
|
|
<div className="col-span-2 text-center">QUANTITY</div>
|
|
<div className="col-span-2 text-center">UNIT PRICE</div>
|
|
<div className="col-span-1 text-center">TAX</div>
|
|
<div className="col-span-2 text-center">TOTAL PRICE</div>
|
|
</div>
|
|
</div>
|
|
|
|
{invoice.items.map((item, index) => (
|
|
<div key={index} className="grid grid-cols-12 gap-4 p-4 border-b border-gray-200">
|
|
<div className="col-span-5">
|
|
<h4 className="font-medium mb-1">{item.description}</h4>
|
|
<p className="text-sm text-muted-foreground">{item.details}</p>
|
|
</div>
|
|
<div className="col-span-2 text-center">{item.quantity}</div>
|
|
<div className="col-span-2 text-center">${item.unitPrice.toFixed(2)}</div>
|
|
<div className="col-span-1 text-center">${item.tax.toFixed(2)}</div>
|
|
<div className="col-span-2 text-center font-medium">${item.totalPrice.toFixed(2)}</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
{/* Payment Note */}
|
|
<div className="mb-8">
|
|
<p className="text-sm text-muted-foreground leading-relaxed">
|
|
{invoice.paymentNote}
|
|
</p>
|
|
</div>
|
|
|
|
{/* Totals */}
|
|
<div className="flex justify-end mb-8">
|
|
<div className="w-80 space-y-3">
|
|
<div className="flex justify-between">
|
|
<span>Sub - Total amount:</span>
|
|
<span className="font-medium">${invoice.subtotal.toFixed(2)}</span>
|
|
</div>
|
|
<div className="flex justify-between">
|
|
<span>Discount:</span>
|
|
<span className="font-medium">{invoice.discount}%</span>
|
|
</div>
|
|
<div className="flex justify-between">
|
|
<span>VAT:</span>
|
|
<span className="font-medium">---</span>
|
|
</div>
|
|
<div className="border-t pt-3">
|
|
<div className="flex justify-between text-lg font-bold">
|
|
<span>Grand Total:</span>
|
|
<span>${invoice.grandTotal.toFixed(2)}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Thank You Note */}
|
|
<div className="mb-8">
|
|
<p className="text-sm text-muted-foreground">
|
|
{invoice.thankNote}
|
|
</p>
|
|
</div>
|
|
|
|
{/* Payment Methods */}
|
|
<div className="flex items-center gap-4 mb-8">
|
|
<div className="flex items-center gap-2">
|
|
<img src="/placeholder.svg?text=PayPal" alt="PayPal" className="h-8 w-16 bg-blue-600 rounded" />
|
|
</div>
|
|
<div className="flex items-center gap-2">
|
|
<img src="/placeholder.svg?text=Visa" alt="Visa" className="h-8 w-12 bg-blue-800 rounded" />
|
|
<img src="/placeholder.svg?text=MC" alt="MasterCard" className="h-8 w-12 bg-red-600 rounded" />
|
|
<img src="/placeholder.svg?text=Maestro" alt="Maestro" className="h-8 w-12 bg-blue-500 rounded" />
|
|
<img src="/placeholder.svg?text=Amex" alt="American Express" className="h-8 w-12 bg-blue-400 rounded" />
|
|
</div>
|
|
</div>
|
|
|
|
{/* Action Buttons */}
|
|
<div className="flex items-center gap-4">
|
|
<Button size="sm" className="bg-blue-500 hover:bg-blue-600">
|
|
<Download className="w-4 h-4 mr-2" />
|
|
Download
|
|
</Button>
|
|
<Button size="sm" className="bg-green-500 hover:bg-green-600">
|
|
<DollarSign className="w-4 h-4 mr-2" />
|
|
Make A Payment
|
|
</Button>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default InvoiceDetail; |