Add request single page
This commit is contained in:
@ -0,0 +1,110 @@
|
||||
"use server";
|
||||
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import {
|
||||
commissionRequestTableRowSchema,
|
||||
commissionStatusSchema,
|
||||
} from "@/schemas/commissions/tableSchema";
|
||||
import { z } from "zod";
|
||||
|
||||
export type CursorPagination = { pageIndex: number; pageSize: number };
|
||||
export type SortDir = "asc" | "desc";
|
||||
|
||||
const triStateSchema = z.enum(["any", "true", "false"]);
|
||||
type TriState = z.infer<typeof triStateSchema>;
|
||||
|
||||
const sortingSchema = z.array(
|
||||
z.object({
|
||||
id: z.string(),
|
||||
desc: z.boolean(),
|
||||
})
|
||||
);
|
||||
|
||||
const filtersSchema = z.object({
|
||||
q: z.string().optional(),
|
||||
email: z.string().optional(),
|
||||
status: z.union([z.literal("any"), commissionStatusSchema]).default("any"),
|
||||
hasFiles: triStateSchema.default("any"),
|
||||
});
|
||||
|
||||
export async function getCommissionRequestsTablePage(input: {
|
||||
pagination: CursorPagination;
|
||||
sorting: z.infer<typeof sortingSchema>;
|
||||
filters: z.infer<typeof filtersSchema>;
|
||||
}) {
|
||||
const { pagination, sorting, filters } = input;
|
||||
|
||||
const where: any = {};
|
||||
|
||||
if (filters.q) {
|
||||
const q = filters.q.trim();
|
||||
if (q) {
|
||||
where.OR = [
|
||||
{ customerName: { contains: q, mode: "insensitive" } },
|
||||
{ customerEmail: { contains: q, mode: "insensitive" } },
|
||||
{ message: { 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: any =
|
||||
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,
|
||||
createdAt: true,
|
||||
status: true,
|
||||
customerName: true,
|
||||
customerEmail: true,
|
||||
customerSocials: true,
|
||||
message: true,
|
||||
_count: { select: { files: true } },
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
const mapped = rows.map((r) => ({
|
||||
id: r.id,
|
||||
createdAt: r.createdAt.toISOString(),
|
||||
status: r.status as any,
|
||||
customerName: r.customerName,
|
||||
customerEmail: r.customerEmail,
|
||||
customerSocials: r.customerSocials ?? null,
|
||||
messagePreview: r.message.slice(0, 140),
|
||||
filesCount: 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 };
|
||||
}
|
||||
Reference in New Issue
Block a user