Initial commit from remix
This commit is contained in:
266
src/pages/dashboard/InvoiceDetail.tsx
Normal file
266
src/pages/dashboard/InvoiceDetail.tsx
Normal file
@@ -0,0 +1,266 @@
|
||||
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;
|
||||
Reference in New Issue
Block a user