94 lines
2.7 KiB
TypeScript
94 lines
2.7 KiB
TypeScript
"use server";
|
|
|
|
import type { Prisma } from "@/generated/prisma/client";
|
|
import { prisma } from "@/lib/prisma";
|
|
import { commissionRequestTableRowSchema } from "@/schemas/commissions/requests";
|
|
import type {
|
|
CommissionRequestsTableFilters,
|
|
CommissionRequestsTableSorting,
|
|
} from "@/schemas/commissions/requestsTable";
|
|
import type { CursorPagination } from "@/types/pagination";
|
|
import { z } from "zod/v4";
|
|
|
|
// Builds a paginated, filtered, and sorted commission-requests table payload for the admin UI.
|
|
export async function getCommissionRequestsTablePage(input: {
|
|
pagination: CursorPagination;
|
|
sorting: CommissionRequestsTableSorting;
|
|
filters: CommissionRequestsTableFilters;
|
|
}) {
|
|
const { pagination, sorting, filters } = input;
|
|
|
|
const where: Prisma.CommissionRequestWhereInput = {};
|
|
|
|
if (filters.q) {
|
|
const q = filters.q.trim();
|
|
if (q) {
|
|
where.OR = [
|
|
{ customerName: { contains: q, mode: "insensitive" } },
|
|
{ customerEmail: { contains: q, mode: "insensitive" } },
|
|
];
|
|
}
|
|
}
|
|
|
|
if (filters.email) {
|
|
const e = filters.email.trim();
|
|
if (e) where.customerEmail = { contains: e, mode: "insensitive" };
|
|
}
|
|
|
|
if (filters.status !== "any") {
|
|
where.status = filters.status;
|
|
}
|
|
|
|
if (filters.hasFiles !== "any") {
|
|
where.files = filters.hasFiles === "true" ? { some: {} } : { none: {} };
|
|
}
|
|
|
|
// sorting
|
|
const sort = sorting?.[0] ?? { id: "createdAt", desc: true };
|
|
const orderBy: Prisma.CommissionRequestOrderByWithRelationInput =
|
|
sort.id === "createdAt"
|
|
? { createdAt: sort.desc ? "desc" : "asc" }
|
|
: sort.id === "status"
|
|
? { status: sort.desc ? "desc" : "asc" }
|
|
: { createdAt: "desc" };
|
|
|
|
const [total, rows] = await prisma.$transaction([
|
|
prisma.commissionRequest.count({ where }),
|
|
prisma.commissionRequest.findMany({
|
|
where,
|
|
orderBy,
|
|
skip: pagination.pageIndex * pagination.pageSize,
|
|
take: pagination.pageSize,
|
|
select: {
|
|
id: true,
|
|
index: true,
|
|
createdAt: true,
|
|
status: true,
|
|
customerName: true,
|
|
customerEmail: true,
|
|
customerSocials: true,
|
|
_count: { select: { files: true } },
|
|
},
|
|
}),
|
|
]);
|
|
|
|
const mapped = rows.map((r) => ({
|
|
id: r.id,
|
|
index: r.index,
|
|
createdAt: r.createdAt.toISOString(),
|
|
customerName: r.customerName,
|
|
customerEmail: r.customerEmail,
|
|
customerSocials: r.customerSocials ?? null,
|
|
status: r.status,
|
|
fileCount: r._count.files,
|
|
}));
|
|
|
|
// Validate output once (helps catch schema drift)
|
|
const parsed = z.array(commissionRequestTableRowSchema).safeParse(mapped);
|
|
if (!parsed.success) {
|
|
throw new Error("Commission table row shape mismatch");
|
|
}
|
|
|
|
return { total, rows: parsed.data };
|
|
}
|