195 lines
12 KiB
TypeScript
195 lines
12 KiB
TypeScript
import { Badge } from '@/components/ui/badge';
|
|
import { Button } from '@/components/ui/button';
|
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
|
import { Separator } from '@/components/ui/separator';
|
|
import {
|
|
Table,
|
|
TableBody,
|
|
TableCell,
|
|
TableHead,
|
|
TableHeader,
|
|
TableRow,
|
|
} from '@/components/ui/table';
|
|
import { Head, Link } from '@inertiajs/react';
|
|
import { ArrowLeft, Mail } from 'lucide-react';
|
|
import type { Order } from '@/types/order';
|
|
import { ORDER_STATUS, PAYMENT_METHOD, ORDER_CHANNEL } from '@/types/order';
|
|
import * as orderRoutes from '@/routes/order';
|
|
import type { GeneralSetting } from '@/types/general-setting';
|
|
|
|
interface ShowProps {
|
|
order: Order;
|
|
setting: GeneralSetting;
|
|
}
|
|
|
|
export default function OrderShow({ order, setting }: ShowProps) {
|
|
return (
|
|
<div className="flex flex-col gap-6 p-6 print:p-8">
|
|
<Head title={`Invoice #${order.order_number}`} />
|
|
|
|
{/* Header / Actions */}
|
|
<div className="relative z-10 flex items-center justify-between print:hidden">
|
|
<div className="flex items-center gap-4">
|
|
<Link
|
|
href={orderRoutes.index().url}
|
|
className="flex h-10 w-10 items-center justify-center rounded-full border border-input bg-background text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground"
|
|
>
|
|
<ArrowLeft className="size-4" />
|
|
</Link>
|
|
<div>
|
|
<h1 className="text-2xl font-bold tracking-tight text-foreground">
|
|
Detail Pesanan
|
|
</h1>
|
|
<p className="text-sm text-muted-foreground">
|
|
Invoice #{order.order_number}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div className="flex items-center gap-2">
|
|
{/* Actions removed as requested */}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Invoice Card */}
|
|
<Card className="relative mx-auto w-full max-w-4xl overflow-hidden border-none bg-card shadow-xl print:shadow-none print:border print:max-w-none">
|
|
<div className="pointer-events-none absolute inset-0 bg-grid-slate-100 [mask-image:linear-gradient(0deg,#fff,rgba(255,255,255,0.6))] dark:bg-grid-slate-700/25 dark:[mask-image:linear-gradient(0deg,rgba(255,255,255,0.1),rgba(255,255,255,0.5))] print:hidden" />
|
|
|
|
<CardHeader className="relative space-y-6 pb-8 pt-10">
|
|
<div className="flex flex-col justify-between gap-6 md:flex-row md:items-start">
|
|
<div className="space-y-4">
|
|
<div className="flex items-center gap-3">
|
|
{setting?.logo_light_url ? (
|
|
<img src={setting.logo_light_url} alt="Logo" className="h-10 w-auto" />
|
|
) : (
|
|
<div className="flex h-12 w-12 items-center justify-center rounded-xl bg-primary text-2xl font-bold text-primary-foreground">
|
|
{setting?.site_name?.charAt(0) || 'V'}
|
|
</div>
|
|
)}
|
|
<div>
|
|
<h2 className="text-2xl font-bold text-foreground">{setting?.site_name || 'VN Grup'}</h2>
|
|
<p className="text-sm text-muted-foreground italic">Your Style, Our Passion</p>
|
|
</div>
|
|
</div>
|
|
<div className="max-w-xs space-y-1 text-sm text-muted-foreground">
|
|
<p>{setting?.site_address || 'Alamat Toko Belum Diatur'}</p>
|
|
<p>{setting?.site_phone || '-'}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="space-y-4 text-left md:text-right">
|
|
<div className="space-y-1">
|
|
<h3 className="text-3xl font-black uppercase tracking-tighter text-primary">INVOICE</h3>
|
|
<p className="text-lg font-mono font-medium">#{order.order_number}</p>
|
|
</div>
|
|
<div className="space-y-1 text-sm text-muted-foreground">
|
|
<p>Tanggal Pesanan: <span className="font-medium text-foreground">{order.created_at_formatted}</span></p>
|
|
<p>Channel: <span className="font-medium text-foreground">{ORDER_CHANNEL[order.order_channel] || order.order_channel}</span></p>
|
|
<div className="flex items-center gap-2 md:justify-end">
|
|
<span>Status:</span>
|
|
<Badge variant={ORDER_STATUS[order.order_status]?.color ?? 'outline'}>
|
|
{ORDER_STATUS[order.order_status]?.label ?? order.order_status}
|
|
</Badge>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<Separator className="bg-primary/10" />
|
|
|
|
<div className="grid gap-8 md:grid-cols-2">
|
|
<div className="space-y-3">
|
|
<h4 className="text-xs font-bold uppercase tracking-wider text-muted-foreground">Tagihan Untuk:</h4>
|
|
<div className="space-y-1">
|
|
<p className="text-lg font-bold text-foreground">{order.customer_name}</p>
|
|
<p className="text-sm text-muted-foreground">Pelanggan Setia</p>
|
|
</div>
|
|
</div>
|
|
<div className="space-y-3 text-left md:text-right">
|
|
<h4 className="text-xs font-bold uppercase tracking-wider text-muted-foreground">Pembayaran:</h4>
|
|
<div className="space-y-1">
|
|
<p className="text-lg font-bold text-foreground">{PAYMENT_METHOD[order.payment_method] || order.payment_method}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</CardHeader>
|
|
|
|
<CardContent className="relative space-y-8 pb-12">
|
|
<div className="rounded-xl border bg-card/50 overflow-hidden shadow-sm">
|
|
<Table>
|
|
<TableHeader className="bg-muted/50">
|
|
<TableRow>
|
|
<TableHead className="w-[50px] text-center">#</TableHead>
|
|
<TableHead>Produk</TableHead>
|
|
<TableHead className="text-right">Harga</TableHead>
|
|
<TableHead className="text-center">Jumlah</TableHead>
|
|
<TableHead className="text-right">Total</TableHead>
|
|
</TableRow>
|
|
</TableHeader>
|
|
<TableBody>
|
|
{order.items?.map((item, index) => (
|
|
<TableRow key={item.id} className="hover:bg-muted/30">
|
|
<TableCell className="text-center text-muted-foreground">{index + 1}</TableCell>
|
|
<TableCell>
|
|
<div className="font-medium">{item.product?.name || 'Produk Tidak Diketahui'}</div>
|
|
<div className="text-xs text-muted-foreground uppercase">{item.price_type}</div>
|
|
</TableCell>
|
|
<TableCell className="text-right">{item.price_formatted}</TableCell>
|
|
<TableCell className="text-center">{item.qty}</TableCell>
|
|
<TableCell className="text-right font-medium">{item.total_formatted}</TableCell>
|
|
</TableRow>
|
|
))}
|
|
</TableBody>
|
|
</Table>
|
|
</div>
|
|
|
|
<div className="flex flex-col justify-between gap-8 md:flex-row">
|
|
<div className="flex-1 space-y-4">
|
|
<div className="rounded-xl bg-muted/30 p-4 space-y-2 border border-dashed">
|
|
<h4 className="text-xs font-bold uppercase tracking-wider text-muted-foreground">Catatan:</h4>
|
|
<p className="text-xs text-muted-foreground leading-relaxed">
|
|
Terima kasih telah berbelanja di {setting?.site_name || 'VN Grup'}.
|
|
Barang yang sudah dibeli tidak dapat ditukar atau dikembalikan kecuali ada perjanjian sebelumnya.
|
|
Simpan invoice ini sebagai bukti pembelian yang sah.
|
|
</p>
|
|
</div>
|
|
<div className="flex items-center gap-2 text-xs text-muted-foreground">
|
|
<Mail className="size-3" />
|
|
<span>Dicatat oleh: <span className="font-medium text-foreground">{order.user?.name || '-'}</span></span>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="w-full md:w-80 space-y-3">
|
|
<div className="flex justify-between text-sm">
|
|
<span className="text-muted-foreground">Subtotal</span>
|
|
<span className="font-medium">{order.subtotal_formatted}</span>
|
|
</div>
|
|
<div className="flex justify-between text-sm">
|
|
<span className="text-muted-foreground">Potongan / Diskon</span>
|
|
<span className="font-medium text-red-500">- {order.discount_formatted}</span>
|
|
</div>
|
|
<Separator />
|
|
<div className="flex justify-between items-center pt-1">
|
|
<span className="text-lg font-bold">Total Tagihan</span>
|
|
<span className="text-2xl font-black text-primary">{order.total_formatted}</span>
|
|
</div>
|
|
<div className="flex justify-between items-center rounded-lg bg-primary/5 px-3 py-2 border border-primary/10 mt-4">
|
|
<span className="text-xs font-bold uppercase text-primary/70">Sudah Dibayar</span>
|
|
<span className="text-sm font-bold text-primary">{order.payment_formatted}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="pt-10 text-center text-sm text-muted-foreground print:pt-20">
|
|
<p className="font-medium">Semoga hari Anda menyenangkan!</p>
|
|
<p className="text-[10px] mt-1 opacity-50">Generated by {setting?.site_name || 'VN Grup'} System</p>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
OrderShow.layout = (page: any) => (
|
|
<div className="min-h-screen bg-muted/20 dark:bg-muted/5">{page}</div>
|
|
);
|