Files
karibeo_backend_admin/src/pages/dashboard/InvoiceDetail.tsx
gpt-engineer-app[bot] 5ddc52658d Initial commit from remix
2025-09-25 16:01:00 +00:00

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;