diff --git a/Dockerfile b/Dockerfile index eee3ce2..d25d639 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,10 +18,6 @@ RUN bunx prisma generate # Uncomment the following line in case you want to disable telemetry during the build. ENV NEXT_TELEMETRY_DISABLED=1 -ARG DATABASE_URL -ENV DATABASE_URL=$DATABASE_URL -ARG BETTER_AUTH_SECRET -ENV BETTER_AUTH_SECRET=$BETTER_AUTH_SECRET # Copy the rest of the code RUN bun run build -d diff --git a/src/actions/artworks/getArtworks.ts b/src/actions/artworks/getArtworks.ts new file mode 100644 index 0000000..5fda70a --- /dev/null +++ b/src/actions/artworks/getArtworks.ts @@ -0,0 +1,22 @@ +"use server" + +import { prisma } from "@/lib/prisma" + +export async function getSingleArtwork(id: string) { + return await prisma.artwork.findUnique({ + where: { id }, + include: { + // album: true, + // type: true, + file: true, + gallery: true, + metadata: true, + albums: true, + categories: true, + colors: { include: { color: true } }, + // sortContexts: true, + tags: true, + variants: true + } + }) +} \ No newline at end of file diff --git a/src/actions/categories/getCategories.ts b/src/actions/categories/getCategories.ts new file mode 100644 index 0000000..643e20e --- /dev/null +++ b/src/actions/categories/getCategories.ts @@ -0,0 +1,16 @@ +"use server" + +import { prisma } from "@/lib/prisma" + +export async function getCategoriesWithTags() { + return await prisma.artCategory.findMany({ include: { tags: true }, orderBy: { sortIndex: "asc" } }) +} + +export async function getCategoriesWithCount() { + return await prisma.artCategory.findMany({ + include: { + _count: { select: { artworks: true, tags: true } }, + }, + orderBy: [{ sortIndex: "asc" }, { name: "asc" }], + }) +} \ No newline at end of file diff --git a/src/actions/tags/getTags.ts b/src/actions/tags/getTags.ts new file mode 100644 index 0000000..743bc59 --- /dev/null +++ b/src/actions/tags/getTags.ts @@ -0,0 +1,7 @@ +"use server" + +import { prisma } from "@/lib/prisma" + +export async function getTags() { + return await prisma.artTag.findMany({ orderBy: { sortIndex: "asc" } }) +} \ No newline at end of file diff --git a/src/app/(admin)/artworks/[id]/page.tsx b/src/app/(admin)/artworks/[id]/page.tsx index df484ed..10b685d 100644 --- a/src/app/(admin)/artworks/[id]/page.tsx +++ b/src/app/(admin)/artworks/[id]/page.tsx @@ -1,31 +1,18 @@ +import { getSingleArtwork } from "@/actions/artworks/getArtworks"; +import { getCategoriesWithTags } from "@/actions/categories/getCategories"; +import { getTags } from "@/actions/tags/getTags"; import ArtworkColors from "@/components/artworks/single/ArtworkColors"; import ArtworkVariants from "@/components/artworks/single/ArtworkVariants"; import DeleteArtworkButton from "@/components/artworks/single/DeleteArtworkButton"; import EditArtworkForm from "@/components/artworks/single/EditArtworkForm"; -import { prisma } from "@/lib/prisma"; -export default async function ArtworkSinglePage({ params }: { params: { id: string } }) { +export default async function ArtworkSinglePage({ params }: { params: Promise<{ id: string }> }) { const { id } = await params; - const item = await prisma.artwork.findUnique({ - where: { id }, - include: { - // album: true, - // type: true, - file: true, - gallery: true, - metadata: true, - albums: true, - categories: true, - colors: { include: { color: true } }, - // sortContexts: true, - tags: true, - variants: true - } - }) + const item = await getSingleArtwork(id); - const categories = await prisma.artCategory.findMany({ include: { tags: true }, orderBy: { sortIndex: "asc" } }); - const tags = await prisma.artTag.findMany({ orderBy: { sortIndex: "asc" } }); + const categories = await getCategoriesWithTags(); + const tags = await getTags(); if (!item) return
Artwork with this id not found
diff --git a/src/app/(admin)/categories/page.tsx b/src/app/(admin)/categories/page.tsx index eda2b86..d532137 100644 --- a/src/app/(admin)/categories/page.tsx +++ b/src/app/(admin)/categories/page.tsx @@ -1,15 +1,11 @@ +import { getCategoriesWithCount } from "@/actions/categories/getCategories"; import CategoryTable from "@/components/categories/CategoryTable"; -import { prisma } from "@/lib/prisma"; import { PlusCircleIcon } from "lucide-react"; import Link from "next/link"; +import { Suspense } from "react"; export default async function CategoriesPage() { - const items = await prisma.artCategory.findMany({ - include: { - _count: { select: { artworks: true, tags: true } }, - }, - orderBy: [{ sortIndex: "asc" }, { name: "asc" }], - }); + const items = await getCategoriesWithCount(); return (
@@ -19,11 +15,13 @@ export default async function CategoriesPage() { Add new category
- {items.length > 0 ? ( - - ) : ( -

There are no categories yet. Consider adding some!

- )} + Loading...

}> + {items.length > 0 ? ( + + ) : ( +

There are no categories yet. Consider adding some!

+ )} +
); } \ No newline at end of file diff --git a/src/app/error.tsx b/src/app/error.tsx new file mode 100644 index 0000000..63efb97 --- /dev/null +++ b/src/app/error.tsx @@ -0,0 +1,51 @@ +"use client"; + +import { useEffect } from "react"; + +export default function Error({ + error, + reset, +}: { + error: Error & { digest?: string }; + reset: () => void; +}) { + useEffect(() => { + console.error(error); + }, [error]); + + return ( +
+
+

+ Something went wrong +

+ +

+ An unexpected error occurred while loading this section. +

+ +
+ + + + Go home + +
+ + {process.env.NODE_ENV === "development" && ( +
+            {error.message}
+          
+ )} +
+
+ ); +} diff --git a/src/app/global-error.tsx b/src/app/global-error.tsx new file mode 100644 index 0000000..e974c78 --- /dev/null +++ b/src/app/global-error.tsx @@ -0,0 +1,38 @@ +"use client"; + +export default function GlobalError({ + error, + reset, +}: { + error: Error & { digest?: string }; + reset: () => void; +}) { + return ( + + +
+

+ Application error +

+ +

+ A critical error occurred. Please reload the application. +

+ + + + {process.env.NODE_ENV === "development" && ( +
+              {error.message}
+            
+ )} +
+ + + ); +} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 0a520ee..358ae45 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,3 +1,6 @@ +export const dynamic = "force-dynamic"; +export const revalidate = 0; + import { ThemeProvider } from "@/components/global/ThemeProvider"; import type { Metadata } from "next"; import { Geist, Geist_Mono } from "next/font/google"; diff --git a/src/app/loading.tsx b/src/app/loading.tsx new file mode 100644 index 0000000..b37fd52 --- /dev/null +++ b/src/app/loading.tsx @@ -0,0 +1,17 @@ +export default function Loading() { + return ( +
+
+ {/* Spinner */} +
+
+
+
+ +

+ Loading content... +

+
+
+ ); +} diff --git a/src/app/not-found.tsx b/src/app/not-found.tsx new file mode 100644 index 0000000..d8050c1 --- /dev/null +++ b/src/app/not-found.tsx @@ -0,0 +1,31 @@ +import Link from "next/link"; + +export default function NotFound() { + return ( +
+
+ {/* Placeholder artwork */} +
+ 404 +
+ +

+ This page does not exist +

+ +

+ The item you are looking for may have been moved, renamed, or never existed. +

+ +
+ + Go home + +
+
+
+ ); +}