Add kanban board to page
This commit is contained in:
122
src/app/(normal)/commissions/status/page.tsx
Normal file
122
src/app/(normal)/commissions/status/page.tsx
Normal file
@ -0,0 +1,122 @@
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
const statusStyles: Record<string, string> = {
|
||||
ACCEPTED: "bg-sky-500/15 text-sky-300 border-sky-500/30",
|
||||
INPROGRESS: "bg-amber-500/15 text-amber-300 border-amber-500/30",
|
||||
COMPLETED: "bg-emerald-500/15 text-emerald-300 border-emerald-500/30",
|
||||
};
|
||||
|
||||
const statusLabels: Record<string, string> = {
|
||||
ACCEPTED: "Accepted",
|
||||
INPROGRESS: "In progress",
|
||||
COMPLETED: "Completed",
|
||||
};
|
||||
|
||||
export default async function CommissionStatusPage() {
|
||||
const [queueItems, doneItems] = await Promise.all([
|
||||
prisma.commissionRequest.findMany({
|
||||
where: { status: { in: ["ACCEPTED", "INPROGRESS"] } },
|
||||
include: { type: true, option: true, extras: true, customCard: true },
|
||||
orderBy: { createdAt: "desc" },
|
||||
}),
|
||||
prisma.commissionRequest.findMany({
|
||||
where: { status: "COMPLETED" },
|
||||
include: { type: true, option: true, extras: true, customCard: true },
|
||||
orderBy: { createdAt: "desc" },
|
||||
}),
|
||||
]);
|
||||
|
||||
return (
|
||||
<div className="mx-auto w-full max-w-6xl px-4 py-8 flex flex-col gap-8">
|
||||
<div className="flex flex-col gap-2">
|
||||
<h1 className="text-3xl font-bold">Commission Status</h1>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 gap-6 md:grid-cols-2">
|
||||
<section className="rounded-2xl border border-border/60 bg-muted/20 p-4 sm:p-6">
|
||||
<div className="mb-4">
|
||||
<h2 className="text-xl font-semibold">Commissions Queue</h2>
|
||||
<p className="text-sm text-muted-foreground">Accepted and in progress</p>
|
||||
</div>
|
||||
<div className="flex flex-col gap-3">
|
||||
{queueItems.length > 0 ? (
|
||||
queueItems.map((item) => (
|
||||
<div
|
||||
key={item.id}
|
||||
className="rounded-xl border border-border/60 bg-background p-4 shadow-sm"
|
||||
>
|
||||
<div className="font-semibold text-lg">{item.customerName}</div>
|
||||
<div className="mt-2 flex flex-wrap gap-2">
|
||||
<Badge variant="outline">
|
||||
{item.customCard?.name ?? item.type?.name ?? "Custom"}
|
||||
</Badge>
|
||||
<Badge variant="outline">
|
||||
{item.option?.name ?? "Base option"}
|
||||
</Badge>
|
||||
{item.extras.map((extra) => (
|
||||
<Badge key={extra.id} variant="secondary">
|
||||
{extra.name}
|
||||
</Badge>
|
||||
))}
|
||||
{item.extras.length === 0 ? (
|
||||
<Badge variant="secondary">No extras</Badge>
|
||||
) : null}
|
||||
<Badge className={statusStyles[item.status] ?? ""}>
|
||||
{statusLabels[item.status] ?? item.status}
|
||||
</Badge>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<div className="rounded-xl border border-dashed border-border/60 bg-background p-4 text-sm text-muted-foreground">
|
||||
No public items yet.
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="rounded-2xl border border-border/60 bg-muted/20 p-4 sm:p-6">
|
||||
<div className="mb-4">
|
||||
<h2 className="text-xl font-semibold">Done</h2>
|
||||
</div>
|
||||
<div className="flex flex-col gap-3">
|
||||
{doneItems.length > 0 ? (
|
||||
doneItems.map((item) => (
|
||||
<div
|
||||
key={item.id}
|
||||
className="rounded-xl border border-border/60 bg-background p-4 shadow-sm"
|
||||
>
|
||||
<div className="font-semibold text-lg">{item.customerName}</div>
|
||||
<div className="mt-2 flex flex-wrap gap-2">
|
||||
<Badge variant="outline">
|
||||
{item.customCard?.name ?? item.type?.name ?? "Custom"}
|
||||
</Badge>
|
||||
<Badge variant="outline">
|
||||
{item.option?.name ?? "Base option"}
|
||||
</Badge>
|
||||
{item.extras.map((extra) => (
|
||||
<Badge key={extra.id} variant="secondary">
|
||||
{extra.name}
|
||||
</Badge>
|
||||
))}
|
||||
{item.extras.length === 0 ? (
|
||||
<Badge variant="secondary">No extras</Badge>
|
||||
) : null}
|
||||
<Badge className={statusStyles[item.status] ?? ""}>
|
||||
{statusLabels[item.status] ?? item.status}
|
||||
</Badge>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<div className="rounded-xl border border-dashed border-border/60 bg-background p-4 text-sm text-muted-foreground">
|
||||
No completed items yet.
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -12,6 +12,7 @@ const links = [
|
||||
{ href: "/artworks", label: "Portfolio" },
|
||||
{ href: "/artworks/animalstudies", label: "Animal Studies" },
|
||||
{ href: "/commissions", label: "Commissions" },
|
||||
{ href: "/commissions/status", label: "Commission Status" },
|
||||
{ href: "/tos", label: "Terms of Service" },
|
||||
// { href: "/portfolio/artfight", label: "Artfight" },
|
||||
// { href: "/portfolio/minis", label: "Miniatures" },
|
||||
@ -72,4 +73,4 @@ export default function TopNav() {
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user