121 lines
3.9 KiB
TypeScript
121 lines
3.9 KiB
TypeScript
"use server";
|
|
|
|
import { prisma } from "@/lib/prisma";
|
|
import { ArtworkTableInput, artworkTableInputSchema, artworkTableOutputSchema } from "@/schemas/artworks/tableSchema";
|
|
|
|
function triToBool(tri: "any" | "true" | "false"): boolean | undefined {
|
|
if (tri === "any") return undefined;
|
|
return tri === "true";
|
|
}
|
|
|
|
function mapSortingToOrderBy(sorting: ArtworkTableInput["sorting"]) {
|
|
const allowed: Record<string, (desc: boolean) => any> = {
|
|
createdAt: (desc) => ({ createdAt: desc ? "desc" : "asc" }),
|
|
updatedAt: (desc) => ({ updatedAt: desc ? "desc" : "asc" }),
|
|
sortIndex: (desc) => ({ sortIndex: desc ? "desc" : "asc" }),
|
|
name: (desc) => ({ name: desc ? "desc" : "asc" }),
|
|
slug: (desc) => ({ slug: desc ? "desc" : "asc" }),
|
|
published: (desc) => ({ published: desc ? "desc" : "asc" }),
|
|
nsfw: (desc) => ({ nsfw: desc ? "desc" : "asc" }),
|
|
needsWork: (desc) => ({ needsWork: desc ? "desc" : "asc" }),
|
|
|
|
// relation counts: Prisma supports ordering by _count
|
|
albumsCount: (desc) => ({ albums: { _count: desc ? "desc" : "asc" } }),
|
|
categoriesCount: (desc) => ({ categories: { _count: desc ? "desc" : "asc" } }),
|
|
tagsCount: (desc) => ({ tags: { _count: desc ? "desc" : "asc" } }),
|
|
};
|
|
|
|
const orderBy = sorting
|
|
.map((s) => allowed[s.id]?.(s.desc))
|
|
.filter(Boolean);
|
|
|
|
orderBy.push({ id: "desc" });
|
|
return orderBy;
|
|
}
|
|
|
|
export async function getArtworksTablePage(input: unknown) {
|
|
const parsed = artworkTableInputSchema.safeParse(input);
|
|
if (!parsed.success) throw new Error(parsed.error.message);
|
|
|
|
const { pagination, sorting, filters } = parsed.data;
|
|
const { pageIndex, pageSize } = pagination;
|
|
|
|
const published = triToBool(filters.published);
|
|
const nsfw = triToBool(filters.nsfw);
|
|
const needsWork = triToBool(filters.needsWork);
|
|
|
|
const where: any = {
|
|
...(typeof published === "boolean" ? { published } : {}),
|
|
...(typeof nsfw === "boolean" ? { nsfw } : {}),
|
|
...(typeof needsWork === "boolean" ? { needsWork } : {}),
|
|
|
|
...(filters.name
|
|
? { name: { contains: filters.name, mode: "insensitive" } }
|
|
: {}),
|
|
...(filters.slug
|
|
? { slug: { contains: filters.slug, mode: "insensitive" } }
|
|
: {}),
|
|
|
|
...(filters.galleryId ? { galleryId: filters.galleryId } : {}),
|
|
|
|
...(filters.albumIds?.length
|
|
? { albums: { some: { id: { in: filters.albumIds } } } }
|
|
: {}),
|
|
...(filters.categoryIds?.length
|
|
? { categories: { some: { id: { in: filters.categoryIds } } } }
|
|
: {}),
|
|
};
|
|
|
|
const orderBy = mapSortingToOrderBy(sorting);
|
|
|
|
const [total, items] = await Promise.all([
|
|
prisma.artwork.count({ where }),
|
|
prisma.artwork.findMany({
|
|
where,
|
|
orderBy,
|
|
skip: pageIndex * pageSize,
|
|
take: pageSize,
|
|
select: {
|
|
id: true,
|
|
name: true,
|
|
slug: true,
|
|
published: true,
|
|
nsfw: true,
|
|
needsWork: true,
|
|
createdAt: true,
|
|
updatedAt: true,
|
|
sortIndex: true,
|
|
file: { select: { fileKey: true } },
|
|
gallery: { select: { id: true, name: true } },
|
|
albums: { select: { id: true, name: true } },
|
|
categories: { select: { id: true, name: true } },
|
|
_count: { select: { albums: true, categories: true, tags: true } },
|
|
},
|
|
}),
|
|
]);
|
|
|
|
const rows = items.map((a) => ({
|
|
id: a.id,
|
|
name: a.name,
|
|
slug: a.slug,
|
|
published: a.published,
|
|
nsfw: a.nsfw,
|
|
needsWork: a.needsWork,
|
|
createdAt: a.createdAt.toISOString(),
|
|
updatedAt: a.updatedAt.toISOString(),
|
|
fileKey: a.file.fileKey,
|
|
gallery: a.gallery ? { id: a.gallery.id, name: a.gallery.name } : null,
|
|
albums: a.albums,
|
|
categories: a.categories,
|
|
albumsCount: a._count.albums,
|
|
categoriesCount: a._count.categories,
|
|
tagsCount: a._count.tags,
|
|
}));
|
|
|
|
const out = { rows, total, pageIndex, pageSize };
|
|
const outParsed = artworkTableOutputSchema.safeParse(out);
|
|
if (!outParsed.success) throw new Error(outParsed.error.message);
|
|
|
|
return outParsed.data;
|
|
}
|