add day-end and change item model

This commit is contained in:
Dhananjaya99
2026-08-20 14:10:39 +05:30
parent 8835ba9500
commit 4cc6a546c7
43 changed files with 8955 additions and 1680 deletions
@@ -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>
)
}