Add image upload and edit functions

This commit is contained in:
2025-12-20 16:34:50 +01:00
parent 96fa12993b
commit dfb6f7042a
72 changed files with 7413 additions and 81 deletions

View File

@ -0,0 +1,99 @@
"use client"
// import { PortfolioImage } from "@/generated/prisma";
import { cn } from "@/lib/utils";
import { ArtworkWithRelations } from "@/types/Artwork";
import Image from "next/image";
import Link from "next/link";
import { useSearchParams } from "next/navigation";
import { useState } from "react";
import { Button } from "../ui/button";
export default function ArtworkGallery({
initialArtworks,
initialCursor,
}: {
initialArtworks: ArtworkWithRelations[];
initialCursor: string | null;
}) {
const searchParams = useSearchParams();
const published = searchParams.get("published") ?? "all";
const [artworks, setArtworks] = useState(initialArtworks);
const [cursor, setCursor] = useState<string | null>(initialCursor);
const [loading, setLoading] = useState(false);
const loadMore = async () => {
if (!cursor || loading) return;
setLoading(true);
try {
const qs = new URLSearchParams();
qs.set("published", published);
qs.set("cursor", cursor);
qs.set("take", "48");
const res = await fetch(`/api/artworks/page?${qs.toString()}`, {
method: "GET",
cache: "no-store",
});
if (!res.ok) throw new Error("Failed to load more artworks");
const data: { items: ArtworkWithRelations[]; nextCursor: string | null } =
await res.json();
setArtworks((prev) => [...prev, ...data.items]);
setCursor(data.nextCursor);
} finally {
setLoading(false);
}
};
return (
<div className="w-full flex flex-col gap-4">
<div
className="flex flex-wrap gap-4"
>
{artworks.map((artwork) => (
<div key={artwork.id} style={{ width: 200, height: 200 }}>
<Link href={`/artworks/${artwork.id}`}>
<div
className={cn(
"overflow-hidden transition-all duration-100",
"w-full h-full",
"hover:border-2 border-transparent"
)}
style={{
'--tw-border-opacity': 1,
} as React.CSSProperties}
>
<div
className={cn(
"relative w-full h-full"
)}
>
<Image
src={`/api/image/thumbnail/${artwork.file.fileKey}.webp`}
alt={artwork.altText ?? artwork.name ?? "Image"}
fill
className={cn("object-cover"
)}
loading="lazy"
/>
</div>
</div>
</Link>
</div>
))}
</div>
{cursor ? (
<div className="flex justify-center">
<Button onClick={loadMore} disabled={loading}>
{loading ? "Loading..." : "Load more"}
</Button>
</div>
) : null}
</div>
);
}