Add auth
This commit is contained in:
53
src/app/(admin)/artworks/[id]/page.tsx
Normal file
53
src/app/(admin)/artworks/[id]/page.tsx
Normal file
@ -0,0 +1,53 @@
|
||||
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 } }) {
|
||||
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 categories = await prisma.artCategory.findMany({ include: { tags: true }, orderBy: { sortIndex: "asc" } });
|
||||
const tags = await prisma.artTag.findMany({ orderBy: { sortIndex: "asc" } });
|
||||
|
||||
if (!item) return <div>Artwork with this id not found</div>
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold mb-4">Edit artwork</h1>
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
||||
<div>
|
||||
{item ? <EditArtworkForm artwork={item} tags={tags} categories={categories} /> : 'Artwork not found...'}
|
||||
<div className="mt-6">
|
||||
{item && <DeleteArtworkButton artworkId={item.id} />}
|
||||
</div>
|
||||
<div>
|
||||
{item && <ArtworkVariants variants={item.variants} />}
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
{item && <ArtworkColors colors={item.colors} artworkId={item.id} />}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
92
src/app/(admin)/artworks/page.tsx
Normal file
92
src/app/(admin)/artworks/page.tsx
Normal file
@ -0,0 +1,92 @@
|
||||
import { ArtworkColorProcessor } from "@/components/artworks/ArtworkColorProcessor";
|
||||
import { ArtworksTable } from "@/components/artworks/ArtworksTable";
|
||||
import { getArtworksPage } from "@/lib/queryArtworks";
|
||||
|
||||
export default async function ArtworksPage({
|
||||
searchParams
|
||||
}: {
|
||||
searchParams?: {
|
||||
// type?: string;
|
||||
published?: string;
|
||||
// groupBy?: string;
|
||||
// year?: string;
|
||||
// album?: string;
|
||||
cursor?: string;
|
||||
}
|
||||
}) {
|
||||
const {
|
||||
// type = "all",
|
||||
published = "all",
|
||||
// groupBy = "year",
|
||||
// year,
|
||||
// album,
|
||||
cursor = undefined
|
||||
} = await searchParams ?? {};
|
||||
// const groupMode = groupBy === "album" ? "album" : "year";
|
||||
// const groupId = groupMode === "album" ? album ?? "all" : year ?? "all";
|
||||
|
||||
// Filter by type
|
||||
// if (type !== "all") {
|
||||
// where.typeId = type === "none" ? null : type;
|
||||
// }
|
||||
|
||||
// Filter by published status
|
||||
// if (published === "published") {
|
||||
// where.published = true;
|
||||
// } else if (published === "unpublished") {
|
||||
// where.published = false;
|
||||
// } else if (published === "needsWork") {
|
||||
// where.needsWork = true;
|
||||
// }
|
||||
|
||||
// Filter by group (year or album)
|
||||
// if (groupMode === "year" && groupId !== "all") {
|
||||
// where.year = parseInt(groupId);
|
||||
// } else if (groupMode === "album" && groupId !== "all") {
|
||||
// where.albumId = groupId;
|
||||
// }
|
||||
|
||||
const { items, nextCursor } = await getArtworksPage(
|
||||
{
|
||||
published,
|
||||
cursor,
|
||||
take: 48
|
||||
}
|
||||
)
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<h1 className="text-2xl font-bold">Artworks</h1>
|
||||
{/* <ProcessArtworkColorsButton /> */}
|
||||
<ArtworkColorProcessor />
|
||||
<ArtworksTable />
|
||||
</div>
|
||||
// <div>
|
||||
// <div className="flex justify-between pb-4 items-end">
|
||||
// <h1 className="text-2xl font-bold mb-4">Artworks</h1>
|
||||
// <Link href="/uploads/single" className="flex gap-2 items-center cursor-pointer bg-primary hover:bg-primary/90 text-primary-foreground px-4 py-2 rounded">
|
||||
// <PlusCircleIcon className="h-[1.2rem] w-[1.2rem] scale-100 rotate-0 transition-all text-primary-foreground" /> Upload new artwork
|
||||
// </Link>
|
||||
// <Link href="/uploads/bulk" className="flex gap-2 items-center cursor-pointer bg-primary hover:bg-primary/90 text-primary-foreground px-4 py-2 rounded">
|
||||
// <PlusCircleIcon className="h-[1.2rem] w-[1.2rem] scale-100 rotate-0 transition-all text-primary-foreground" /> Upload many artwork
|
||||
// </Link>
|
||||
// </div>
|
||||
// <FilterBar
|
||||
// // types={types}
|
||||
// // albums={albums}
|
||||
// // years={years}
|
||||
// // currentType={type}
|
||||
// currentPublished={published}
|
||||
// // groupBy={groupMode}
|
||||
// // groupId={groupId}
|
||||
// />
|
||||
// <div className="mt-6">
|
||||
// {items.length > 0 ? (
|
||||
// <ArtworkGallery initialArtworks={items} initialCursor={nextCursor} />
|
||||
// ) : (
|
||||
// <p className="text-muted-foreground italic">No artworks found.</p>
|
||||
// )}
|
||||
// </div>
|
||||
// </div >
|
||||
);
|
||||
}
|
||||
18
src/app/(admin)/categories/[id]/page.tsx
Normal file
18
src/app/(admin)/categories/[id]/page.tsx
Normal file
@ -0,0 +1,18 @@
|
||||
import EditCategoryForm from "@/components/categories/EditCategoryForm";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export default async function PortfolioCategoriesEditPage({ params }: { params: { id: string } }) {
|
||||
const { id } = await params;
|
||||
const category = await prisma.artCategory.findUnique({
|
||||
where: {
|
||||
id,
|
||||
}
|
||||
})
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold mb-4">Edit Category</h1>
|
||||
{category && <EditCategoryForm category={category} />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
10
src/app/(admin)/categories/new/page.tsx
Normal file
10
src/app/(admin)/categories/new/page.tsx
Normal file
@ -0,0 +1,10 @@
|
||||
import NewCategoryForm from "@/components/categories/NewCategoryForm";
|
||||
|
||||
export default function PortfolioCategoriesNewPage() {
|
||||
return (
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold mb-4">New Category</h1>
|
||||
<NewCategoryForm />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
29
src/app/(admin)/categories/page.tsx
Normal file
29
src/app/(admin)/categories/page.tsx
Normal file
@ -0,0 +1,29 @@
|
||||
import CategoryTable from "@/components/categories/CategoryTable";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { PlusCircleIcon } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
|
||||
export default async function CategoriesPage() {
|
||||
const items = await prisma.artCategory.findMany({
|
||||
include: {
|
||||
_count: { select: { artworks: true, tags: true } },
|
||||
},
|
||||
orderBy: [{ sortIndex: "asc" }, { name: "asc" }],
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="flex gap-4 justify-between pb-8">
|
||||
<h1 className="text-2xl font-bold mb-4">Art Categories</h1>
|
||||
<Link href="/categories/new" className="flex gap-2 items-center cursor-pointer bg-primary hover:bg-primary/90 text-primary-foreground px-4 py-2 rounded">
|
||||
<PlusCircleIcon className="h-[1.2rem] w-[1.2rem] scale-100 rotate-0 transition-all text-primary-foreground" /> Add new category
|
||||
</Link>
|
||||
</div>
|
||||
{items.length > 0 ? (
|
||||
<CategoryTable categories={items} />
|
||||
) : (
|
||||
<p>There are no categories yet. Consider adding some!</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
17
src/app/(admin)/commissions/guidelines/page.tsx
Normal file
17
src/app/(admin)/commissions/guidelines/page.tsx
Normal file
@ -0,0 +1,17 @@
|
||||
import { getActiveGuidelines } from "@/actions/commissions/guidelines/getGuidelines";
|
||||
import GuidelinesEditor from "@/components/commissions/guidelines/Editor";
|
||||
|
||||
export default async function CommissionGuidelinesPage() {
|
||||
const markdown = await getActiveGuidelines();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="flex gap-4 justify-between pb-8">
|
||||
<h1 className="text-2xl font-bold mb-4">Commission Guidelines</h1>
|
||||
</div>
|
||||
<div className="space-y-4 p-1 border rounded-xl bg-muted/20">
|
||||
<GuidelinesEditor markdown={markdown} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
5
src/app/(admin)/commissions/page.tsx
Normal file
5
src/app/(admin)/commissions/page.tsx
Normal file
@ -0,0 +1,5 @@
|
||||
export default function CommissionPage() {
|
||||
return (
|
||||
<div>CommissionPage</div>
|
||||
);
|
||||
}
|
||||
38
src/app/(admin)/commissions/types/[id]/page.tsx
Normal file
38
src/app/(admin)/commissions/types/[id]/page.tsx
Normal file
@ -0,0 +1,38 @@
|
||||
import EditTypeForm from "@/components/commissions/types/EditTypeForm";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export default async function CommissionTypesEditPage({ params }: { params: { id: string } }) {
|
||||
const { id } = await params;
|
||||
const commissionType = await prisma.commissionType.findUnique({
|
||||
where: {
|
||||
id,
|
||||
},
|
||||
include: {
|
||||
options: { include: { option: true }, orderBy: { sortIndex: "asc" } },
|
||||
extras: { include: { extra: true }, orderBy: { sortIndex: "asc" } },
|
||||
customInputs: { include: { customInput: true }, orderBy: { sortIndex: "asc" } },
|
||||
},
|
||||
})
|
||||
const options = await prisma.commissionOption.findMany({
|
||||
orderBy: [{ sortIndex: "asc" }, { name: "asc" }],
|
||||
});
|
||||
const extras = await prisma.commissionExtra.findMany({
|
||||
orderBy: [{ sortIndex: "asc" }, { name: "asc" }],
|
||||
})
|
||||
const customInputs = await prisma.commissionCustomInput.findMany({
|
||||
orderBy: [{ sortIndex: "asc" }, { name: "asc" }],
|
||||
})
|
||||
|
||||
if (!commissionType) {
|
||||
return <div>Type not found</div>
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="flex gap-4 justify-between pb-8">
|
||||
<h1 className="text-2xl font-bold mb-4">Edit Commission Type</h1>
|
||||
</div>
|
||||
<EditTypeForm type={commissionType} allOptions={options} allExtras={extras} allCustomInputs={customInputs} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
24
src/app/(admin)/commissions/types/new/page.tsx
Normal file
24
src/app/(admin)/commissions/types/new/page.tsx
Normal file
@ -0,0 +1,24 @@
|
||||
import NewTypeForm from "@/components/commissions/types/NewTypeForm";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export default async function CommissionTypesNewPage() {
|
||||
const options = await prisma.commissionOption.findMany({
|
||||
orderBy: [{ sortIndex: "asc" }, { name: "asc" }],
|
||||
});
|
||||
const extras = await prisma.commissionExtra.findMany({
|
||||
orderBy: [{ sortIndex: "asc" }, { name: "asc" }],
|
||||
})
|
||||
const customInputs = await prisma.commissionCustomInput.findMany({
|
||||
orderBy: [{ sortIndex: "asc" }, { name: "asc" }],
|
||||
})
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="flex gap-4 justify-between pb-8">
|
||||
<h1 className="text-2xl font-bold mb-4">New Commission Type</h1>
|
||||
</div>
|
||||
<NewTypeForm options={options} extras={extras} customInputs={customInputs} />
|
||||
</div>
|
||||
|
||||
);
|
||||
}
|
||||
27
src/app/(admin)/commissions/types/page.tsx
Normal file
27
src/app/(admin)/commissions/types/page.tsx
Normal file
@ -0,0 +1,27 @@
|
||||
import ListTypes from "@/components/commissions/types/ListTypes";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { PlusCircleIcon } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
|
||||
export default async function CommissionTypesPage() {
|
||||
const types = await prisma.commissionType.findMany({
|
||||
include: {
|
||||
options: { include: { option: true }, orderBy: { sortIndex: "asc" } },
|
||||
extras: { include: { extra: true }, orderBy: { sortIndex: "asc" } },
|
||||
customInputs: { include: { customInput: true }, orderBy: { sortIndex: "asc" } },
|
||||
},
|
||||
orderBy: [{ sortIndex: "asc" }, { name: "asc" }],
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="flex gap-4 justify-between pb-8">
|
||||
<h1 className="text-2xl font-bold mb-4">Commission Types</h1>
|
||||
<Link href="/commissions/types/new" className="flex gap-2 items-center cursor-pointer bg-primary hover:bg-primary/90 text-primary-foreground px-4 py-2 rounded">
|
||||
<PlusCircleIcon className="h-[1.2rem] w-[1.2rem] scale-100 rotate-0 transition-all text-primary-foreground" /> Add new Type
|
||||
</Link>
|
||||
</div>
|
||||
{types && types.length > 0 ? <ListTypes types={types} /> : <p className="text-muted-foreground italic">No types found.</p>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
25
src/app/(admin)/tags/[id]/page.tsx
Normal file
25
src/app/(admin)/tags/[id]/page.tsx
Normal file
@ -0,0 +1,25 @@
|
||||
import EditTagForm from "@/components/tags/EditTagForm";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export default async function PortfolioTagsEditPage({ params }: { params: { id: string } }) {
|
||||
const { id } = await params;
|
||||
const tag = await prisma.artTag.findUnique({
|
||||
where: {
|
||||
id,
|
||||
},
|
||||
include: {
|
||||
categories: true,
|
||||
aliases: true
|
||||
}
|
||||
})
|
||||
|
||||
const categories = await prisma.artCategory.findMany({ include: { tags: true }, orderBy: { sortIndex: "asc" } });
|
||||
const tags = await prisma.artTag.findMany({ where: { isParent: true }, orderBy: { sortIndex: "asc" } });
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold mb-4">Edit Tag</h1>
|
||||
{tag && <EditTagForm tag={tag} categories={categories} allTags={tags} />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
14
src/app/(admin)/tags/new/page.tsx
Normal file
14
src/app/(admin)/tags/new/page.tsx
Normal file
@ -0,0 +1,14 @@
|
||||
import NewTagForm from "@/components/tags/NewTagForm";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export default async function PortfolioTagsNewPage() {
|
||||
const categories = await prisma.artCategory.findMany({ include: { tags: true }, orderBy: { sortIndex: "asc" } });
|
||||
const tags = await prisma.artTag.findMany({ where: { isParent: true }, orderBy: { sortIndex: "asc" } });
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold mb-4">New Tag</h1>
|
||||
<NewTagForm categories={categories} allTags={tags} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
47
src/app/(admin)/tags/page.tsx
Normal file
47
src/app/(admin)/tags/page.tsx
Normal file
@ -0,0 +1,47 @@
|
||||
import TagTabs from "@/components/tags/TagTabs";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { PlusCircleIcon } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
|
||||
export default async function ArtTagsPage() {
|
||||
const items = await prisma.artTag.findMany({
|
||||
include: {
|
||||
parent: { select: { id: true, name: true } },
|
||||
aliases: { select: { alias: true } },
|
||||
categories: { select: { id: true, name: true } },
|
||||
_count: { select: { artworks: true } },
|
||||
},
|
||||
orderBy: [{ sortIndex: "asc" }, { name: "asc" }],
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="mx-auto w-full max-w-7xl px-4 py-6">
|
||||
<header className="mb-6 flex flex-col gap-3 sm:flex-row sm:items-end sm:justify-between">
|
||||
<div className="space-y-1">
|
||||
<h1 className="text-2xl font-semibold tracking-tight sm:text-3xl">
|
||||
Art Tags
|
||||
</h1>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Manage tags, aliases, categories, and usage across artworks.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Button asChild className="h-11 gap-2">
|
||||
<Link href="/tags/new">
|
||||
<PlusCircleIcon className="h-4 w-4" />
|
||||
Add new tag
|
||||
</Link>
|
||||
</Button>
|
||||
</header>
|
||||
|
||||
{items.length > 0 ? (
|
||||
<TagTabs tags={items} />
|
||||
) : (
|
||||
<p className="text-muted-foreground">
|
||||
There are no tags yet. Consider adding some!
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
17
src/app/(admin)/tos/page.tsx
Normal file
17
src/app/(admin)/tos/page.tsx
Normal file
@ -0,0 +1,17 @@
|
||||
import { getLatestTos } from "@/actions/tos/getTos";
|
||||
import TosEditor from "@/components/tos/Editor";
|
||||
|
||||
export default async function TosPage() {
|
||||
const markdown = await getLatestTos();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="flex gap-4 justify-between pb-8">
|
||||
<h1 className="text-2xl font-bold mb-4">Terms of Service</h1>
|
||||
</div>
|
||||
<div className="space-y-4 p-1 border rounded-xl bg-muted/20">
|
||||
<TosEditor markdown={markdown} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
7
src/app/(admin)/uploads/bulk/page.tsx
Normal file
7
src/app/(admin)/uploads/bulk/page.tsx
Normal file
@ -0,0 +1,7 @@
|
||||
import UploadBulkImageForm from "@/components/uploads/UploadBulkImageForm";
|
||||
|
||||
export default function UploadsBulkPage() {
|
||||
return (
|
||||
<div><UploadBulkImageForm /></div>
|
||||
);
|
||||
}
|
||||
7
src/app/(admin)/uploads/single/page.tsx
Normal file
7
src/app/(admin)/uploads/single/page.tsx
Normal file
@ -0,0 +1,7 @@
|
||||
import UploadImageForm from "@/components/uploads/UploadImageForm";
|
||||
|
||||
export default function UploadsSinglePage() {
|
||||
return (
|
||||
<div><UploadImageForm /></div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user