Rework artwork list
This commit is contained in:
120
src/actions/artworks/getArtworksTablePage.ts
Normal file
120
src/actions/artworks/getArtworksTablePage.ts
Normal file
@ -0,0 +1,120 @@
|
||||
"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;
|
||||
}
|
||||
Reference in New Issue
Block a user