Initial commit

This commit is contained in:
admin
2026-05-26 22:46:00 +02:00
commit 7e2c2ff89c
256 changed files with 51523 additions and 0 deletions
+87
View File
@@ -0,0 +1,87 @@
import { notFound } from "next/navigation";
import { getActressBySlug, listImages, listActressCategories, libraryLetterCounts, listCoStars } from "@/lib/db/queries";
import { MasonryGrid } from "@/components/grid/MasonryGrid";
import { RegisterVisible } from "@/components/select/RegisterVisible";
import { FilterBar } from "@/components/grid/FilterBar";
import { LetterBar } from "@/components/grid/LetterBar";
import { resolveSort } from "@/lib/sortServer";
import { ActressHero } from "@/components/actress/ActressHero";
import { CoStarsRow } from "@/components/actress/CoStarsRow";
import { parseFilterCriteria, statusToFlags } from "@/lib/filters";
export const dynamic = "force-dynamic";
export default async function ActressPage({
params,
searchParams,
}: {
params: Promise<{ slug: string }>;
searchParams: Promise<Record<string, string | string[] | undefined>>;
}) {
const { slug } = await params;
const sp = await searchParams;
const sort = await resolveSort(typeof sp.sort === "string" ? sp.sort : undefined);
const rawLetter = (typeof sp.letter === "string" ? sp.letter : "").toUpperCase();
const letter = rawLetter === "#" ? "#" : (/^[A-Z]$/.test(rawLetter) ? rawLetter : null);
const search = (typeof sp.q === "string" ? sp.q.trim() : "") || undefined;
const criteria = parseFilterCriteria(sp);
const a = getActressBySlug(decodeURIComponent(slug));
if (!a) notFound();
const items = listImages({
actressId: a.id,
sort,
letter: letter ?? undefined,
search,
...statusToFlags(criteria.status),
marks: criteria.marks,
actressIds: criteria.ids.actresses,
actressMode: criteria.mode.actresses,
studioIds: criteria.ids.studios,
seriesIds: criteria.ids.series,
genreIds: criteria.ids.genres,
genreMode: criteria.mode.genres,
collectionIds: criteria.ids.collections,
collectionMode: criteria.mode.collections,
tagIds: criteria.ids.tags,
tagMode: criteria.mode.tags,
categoryIds: criteria.ids.categories,
categoryMode: criteria.mode.categories,
});
const allCategories = listActressCategories();
const costars = listCoStars(a.id, 24);
const letterCounts = libraryLetterCounts({
actressId: a.id,
search,
...statusToFlags(criteria.status),
marks: criteria.marks,
actressIds: criteria.ids.actresses,
actressMode: criteria.mode.actresses,
studioIds: criteria.ids.studios,
seriesIds: criteria.ids.series,
genreIds: criteria.ids.genres,
genreMode: criteria.mode.genres,
collectionIds: criteria.ids.collections,
collectionMode: criteria.mode.collections,
tagIds: criteria.ids.tags,
tagMode: criteria.mode.tags,
categoryIds: criteria.ids.categories,
categoryMode: criteria.mode.categories,
});
return (
<div className="max-w-[1600px] mx-auto px-6 py-6 fade-in">
<ActressHero actress={a} coverCount={items.length} allCategories={allCategories} />
<CoStarsRow actressName={a.name} costars={costars} />
<FilterBar current={{ kind: "actress", name: a.name }} criteria={criteria} sort={sort} />
<div className="my-6">
<LetterBar active={letter} counts={letterCounts} />
</div>
<RegisterVisible ids={items.map((i) => i.id)} />
<div key={letter ?? "all"} className="fade-in">
<MasonryGrid images={items} />
</div>
</div>
);
}