diff --git a/app/(ui)/donate/admin/client.tsx b/app/(ui)/donate/admin/client.tsx index 7c847ce..ab3e975 100644 --- a/app/(ui)/donate/admin/client.tsx +++ b/app/(ui)/donate/admin/client.tsx @@ -35,6 +35,8 @@ import { lePalette } from "../../rubgram/admin/[id]/client"; import { th } from "date-fns/locale"; import TruemoneyIcon from "#/assets/tmn.webp"; import Image from "@/components/image"; +import { Checkbox } from "@/components/ui/checkbox"; +import { toggleCheck } from "@/lib/api"; // directly adapted for date instead of UUID function colorFor(date: Date) { @@ -46,7 +48,12 @@ function colorFor(date: Date) { return lePalette[seed % lePalette.length]; } -const columns: ColumnDef[] = [ +const columns: ColumnDef< + typeof donations.$inferSelect & { + checked: boolean | null; + artifactSubmissionId: string | null; + } +>[] = [ { accessorKey: "created", header: "", @@ -63,6 +70,21 @@ const columns: ColumnDef[] = [ meta: { className: "w-1 p-0 relative" }, }, { accessorKey: "name", header: "ชื่อ", meta: { className: "w-50 truncate" } }, + { + accessorKey: "art_check", + header: "", + meta: { className: "w-6 truncate" }, + cell(row) { + const { artifactSubmissionId, checked } = row.row.original; + if (checked === null || !artifactSubmissionId) return; + return ( + toggleCheck(artifactSubmissionId)} + /> + ); + }, + }, { accessorFn: (row) => `${row.amount}฿`, header: "จำนวน", @@ -274,7 +296,10 @@ export function DonateAdminPage({ data, stats, }: { - data: (typeof donations.$inferSelect)[]; + data: (typeof donations.$inferSelect & { + checked: boolean | null; + artifactSubmissionId: string | null; + })[]; stats: { total: number; today: number; diff --git a/app/(ui)/donate/admin/page.tsx b/app/(ui)/donate/admin/page.tsx index 245eb65..9288f2e 100644 --- a/app/(ui)/donate/admin/page.tsx +++ b/app/(ui)/donate/admin/page.tsx @@ -1,5 +1,6 @@ import { endOfMonth, startOfMonth } from "date-fns"; import { between, desc, getTableColumns, sql, sum } from "drizzle-orm"; +import { alias } from "drizzle-orm/pg-core"; import type { Metadata } from "next"; import { redirect } from "next/navigation"; import { adminCheck } from "@/lib/auth"; @@ -12,15 +13,26 @@ export default async function () { redirect(`/login?next=${encodeURIComponent("/donate/admin")}`); const now = new Date(); + const donation = alias(donations, "donation"); const [data, [stats]] = await Promise.all([ db .select({ - ...getTableColumns(donations), - image: sql`${donations.image} IS NOT NULL`, + ...getTableColumns(donation), + image: sql`${donation.image} IS NOT NULL`, + checked: sql` + (SELECT "artifact"."submissions"."checked" + FROM "artifact"."submissions" + WHERE "artifact"."submissions"."uid" = "donation"."uid") + `, + artifactSubmissionId: sql` + (SELECT "artifact"."submissions"."id" + FROM "artifact"."submissions" + WHERE "artifact"."submissions"."uid" = "donation"."uid") + `, }) - .from(donations) + .from(donation) .limit(100) - .orderBy(desc(donations.id)), + .orderBy(desc(donation.id)), db .select({ total: sum(donations.amount).mapWith(Number), diff --git a/lib/api.ts b/lib/api.ts index fe4530b..d4701c1 100755 --- a/lib/api.ts +++ b/lib/api.ts @@ -180,8 +180,10 @@ export async function toggleCheck(submissionId: string) { .where(eq(submissions.id, submissionId)); revalidatePath("/artifact/admin"); revalidatePath("/artifact"); + revalidatePath("/donate/admin"); sse.artifact.pub("update", { type: "toggleCheck" }); + sse.donate.pub("update", null); await actionLog(`Toggled an artifact submission check mark`); }