add day-end and change item model
This commit is contained in:
@@ -1,74 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import { useEffect, useState } from "react"
|
||||
import { useParams } from "next/navigation"
|
||||
import { Printer } from "lucide-react"
|
||||
|
||||
import { bundleApi } from "@/lib/api/bundles"
|
||||
import { errorMessage } from "@/lib/error-map"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
|
||||
import { BundleSale } from "@/types/bundles"
|
||||
|
||||
export default function BundlePrintPage() {
|
||||
const params = useParams<{ id: string }>()
|
||||
const bundleSaleId = Number(params.id)
|
||||
const [bundle, setBundle] = useState<BundleSale | null>(null)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
if (!Number.isFinite(bundleSaleId)) {
|
||||
setError(`Invalid bundle id '${params.id}'.`)
|
||||
return
|
||||
}
|
||||
bundleApi.getBundle(bundleSaleId).then((res) => setBundle(res)).catch((err) => setError(errorMessage(err)))
|
||||
}, [bundleSaleId, params.id])
|
||||
|
||||
if (error && !bundle) return <div className="rounded-lg border border-destructive/30 bg-destructive/5 p-5 text-base text-destructive">{error}</div>
|
||||
if (!bundle) return <div className="rounded-2xl border border-dashed p-8 text-muted-foreground">Loading bundle print...</div>
|
||||
|
||||
return (
|
||||
<div className="mx-auto flex w-full max-w-6xl flex-col gap-6 rounded-3xl border bg-white p-6 shadow-sm print:rounded-none print:border-0 print:p-0 print:shadow-none">
|
||||
<div className="flex items-center justify-end print:hidden">
|
||||
<Button variant="outline" onClick={() => window.print()}>
|
||||
<Printer className="size-4" />
|
||||
Print
|
||||
</Button>
|
||||
</div>
|
||||
<div className="border-b pb-4">
|
||||
<div className="text-xs font-semibold uppercase tracking-[0.3em] text-muted-foreground">Bundle Sales</div>
|
||||
<h1 className="mt-2 text-3xl font-semibold text-foreground">{bundle.bundleNo}</h1>
|
||||
<p className="mt-2 text-sm text-muted-foreground">{bundle.bundleName}</p>
|
||||
</div>
|
||||
<div className="grid gap-3 text-sm md:grid-cols-3">
|
||||
<div><div className="text-muted-foreground">Customer</div><div className="font-medium">{bundle.customerSnapshotName}</div></div>
|
||||
<div><div className="text-muted-foreground">Warehouse</div><div className="font-medium">{bundle.warehouseId}</div></div>
|
||||
<div><div className="text-muted-foreground">Status</div><div className="font-medium">{bundle.status}</div></div>
|
||||
</div>
|
||||
<div className="overflow-hidden rounded-2xl border">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>Item</TableHead>
|
||||
<TableHead>Description</TableHead>
|
||||
<TableHead className="text-right">Qty</TableHead>
|
||||
<TableHead className="text-right">Price</TableHead>
|
||||
<TableHead className="text-right">Total</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{bundle.lines.map((line) => (
|
||||
<TableRow key={line.bundleSaleLineId}>
|
||||
<TableCell>{line.itemId}</TableCell>
|
||||
<TableCell>{line.description}</TableCell>
|
||||
<TableCell className="text-right">{line.qty.toFixed(2)}</TableCell>
|
||||
<TableCell className="text-right">{line.unitPrice.toFixed(2)}</TableCell>
|
||||
<TableCell className="text-right font-medium">{line.lineTotal.toFixed(2)}</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import { Suspense, useEffect, useState } from "react"
|
||||
import { useSearchParams } from "next/navigation"
|
||||
import { Printer } from "lucide-react"
|
||||
|
||||
import { bundleApi } from "@/lib/api/bundles"
|
||||
import { errorMessage } from "@/lib/error-map"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
import { Skeleton } from "@/components/ui/skeleton"
|
||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
|
||||
import { BundleSaleSummary } from "@/types/bundles"
|
||||
|
||||
function statusClass(status: BundleSaleSummary["status"]) {
|
||||
switch (status) {
|
||||
case "Draft":
|
||||
return "border-amber-200 bg-amber-50 text-amber-800"
|
||||
case "Posted":
|
||||
return "border-emerald-200 bg-emerald-50 text-emerald-800"
|
||||
case "Cancelled":
|
||||
return "border-rose-200 bg-rose-50 text-rose-800"
|
||||
}
|
||||
}
|
||||
|
||||
function BundleBatchPrintContent() {
|
||||
const searchParams = useSearchParams()
|
||||
const status = searchParams.get("status") ?? "All"
|
||||
const query = searchParams.get("q") ?? ""
|
||||
const [rows, setRows] = useState<BundleSaleSummary[] | null>(null)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
bundleApi.listBundles({ page: 1, pageSize: 200 }).then((res) => setRows(res.items)).catch((err) => setError(errorMessage(err)))
|
||||
}, [])
|
||||
|
||||
const visibleRows = rows?.filter((row) => {
|
||||
const matchesStatus = status === "All" || row.status === status
|
||||
const matchesQuery = `${row.bundleNo} ${row.customerSnapshotName} ${row.bundleName}`.toLowerCase().includes(query.toLowerCase())
|
||||
return matchesStatus && matchesQuery
|
||||
})
|
||||
|
||||
if (error && !rows) return <div className="rounded-lg border border-destructive/30 bg-destructive/5 p-5 text-base text-destructive">{error}</div>
|
||||
if (!rows) return <div className="rounded-2xl border border-dashed p-8 text-muted-foreground">Loading bundle print data...</div>
|
||||
|
||||
return (
|
||||
<div className="mx-auto flex w-full max-w-6xl flex-col gap-6 rounded-3xl border bg-white p-6 shadow-sm print:rounded-none print:border-0 print:p-0 print:shadow-none">
|
||||
<div className="flex items-center justify-end print:hidden">
|
||||
<Button variant="outline" onClick={() => window.print()}>
|
||||
<Printer className="size-4" />
|
||||
Print
|
||||
</Button>
|
||||
</div>
|
||||
<div className="border-b pb-4">
|
||||
<div className="text-xs font-semibold uppercase tracking-[0.3em] text-muted-foreground">Bundle Sales</div>
|
||||
<h1 className="mt-2 text-3xl font-semibold text-foreground">Bundle Batch Print</h1>
|
||||
<p className="mt-2 text-sm text-muted-foreground">Printed register snapshot of current bundle sales.</p>
|
||||
</div>
|
||||
<div className="overflow-hidden rounded-2xl border">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>Bundle</TableHead>
|
||||
<TableHead>Customer</TableHead>
|
||||
<TableHead>Date</TableHead>
|
||||
<TableHead className="text-right">Price</TableHead>
|
||||
<TableHead className="text-right">Grand</TableHead>
|
||||
<TableHead>Status</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{visibleRows?.map((row) => (
|
||||
<TableRow key={row.bundleSaleId}>
|
||||
<TableCell className="font-medium">{row.bundleNo}</TableCell>
|
||||
<TableCell>{row.customerSnapshotName}</TableCell>
|
||||
<TableCell>{new Date(row.createdAt).toLocaleDateString()}</TableCell>
|
||||
<TableCell className="text-right">{row.bundlePrice.toFixed(2)}</TableCell>
|
||||
<TableCell className="text-right font-medium">{row.grandTotal.toFixed(2)}</TableCell>
|
||||
<TableCell>
|
||||
<Badge variant="outline" className={statusClass(row.status)}>
|
||||
{row.status}
|
||||
</Badge>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default function BundleBatchPrintPage() {
|
||||
return (
|
||||
<Suspense fallback={<Skeleton className="h-48 w-full" />}>
|
||||
<BundleBatchPrintContent />
|
||||
</Suspense>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user