Moving the arttags table to tags table part 1

This commit is contained in:
2026-02-02 13:05:52 +01:00
parent 6680ccc023
commit 7605ccb0aa
27 changed files with 604 additions and 107 deletions

View File

@ -171,7 +171,7 @@ export default function ArtworkDetails({
v: (
<div className="flex flex-wrap gap-2 text-xs">
<Badge variant="secondary">{(artwork.categories?.length ?? 0)} categories</Badge>
<Badge variant="secondary">{(artwork.tags?.length ?? 0)} tags</Badge>
<Badge variant="secondary">{(artwork.tagsV2?.length ?? 0)} tags</Badge>
<Badge variant="secondary">{(artwork.colors?.length ?? 0)} colors</Badge>
<Badge variant="secondary">{(artwork.variants?.length ?? 0)} variants</Badge>
</div>

View File

@ -7,7 +7,7 @@ import { Input } from "@/components/ui/input";
import MultipleSelector from "@/components/ui/multiselect";
import { Switch } from "@/components/ui/switch";
import { Textarea } from "@/components/ui/textarea";
import type { ArtTag } from "@/generated/prisma/client";
import type { Tag } from "@/generated/prisma/client";
import { artworkSchema } from "@/schemas/artworks/imageSchema";
import type { ArtworkWithRelations, CategoryWithTags } from "@/types/Artwork";
import { zodResolver } from "@hookform/resolvers/zod";
@ -20,7 +20,7 @@ export default function EditArtworkForm({ artwork, categories, tags }:
{
artwork: ArtworkWithRelations,
categories: CategoryWithTags[]
tags: ArtTag[]
tags: Tag[]
}) {
const router = useRouter();
const form = useForm<z.infer<typeof artworkSchema>>({
@ -39,7 +39,7 @@ export default function EditArtworkForm({ artwork, categories, tags }:
year: artwork.year || undefined,
creationDate: artwork.creationDate ? new Date(artwork.creationDate) : undefined,
categoryIds: artwork.categories?.map(cat => cat.id) ?? [],
tagIds: artwork.tags?.map(tag => tag.id) ?? [],
tagIds: artwork.tagsV2?.map(tag => tag.id) ?? [],
newCategoryNames: [],
newTagNames: []
}
@ -264,7 +264,7 @@ export default function EditArtworkForm({ artwork, categories, tags }:
const preferredTagIds = new Set<string>();
for (const cat of categories) {
if (!selectedCategoryIds.includes(cat.id)) continue;
for (const t of cat.tags) preferredTagIds.add(t.id);
for (const link of cat.tagLinks) preferredTagIds.add(link.tagId);
}
// Existing tag options with groups
@ -402,4 +402,4 @@ export default function EditArtworkForm({ artwork, categories, tags }:
</Form>
</div >
);
}
}

View File

@ -17,7 +17,7 @@ type CatRow = {
id: string;
name: string;
slug: string;
_count: { artworks: number, tags: number };
_count: { artworks: number, tagLinks: number };
};
export default function CategoryTable({ categories }: { categories: CatRow[] }) {
@ -48,7 +48,7 @@ export default function CategoryTable({ categories }: { categories: CatRow[] })
</TableCell>
<TableCell className="text-right tabular-nums">
{c._count.tags}
{c._count.tagLinks}
</TableCell>
<TableCell className="text-right tabular-nums">

View File

@ -19,6 +19,9 @@ const artworkItems = [
title: "Categories",
href: "/categories",
},
]
const topicItems = [
{
title: "Tags",
href: "/tags",
@ -110,6 +113,25 @@ export default function TopNav() {
</NavigationMenuContent>
</NavigationMenuItem>
<NavigationMenuItem>
<NavigationMenuTrigger>Topics</NavigationMenuTrigger>
<NavigationMenuContent>
<ul className="grid w-50 gap-4">
{topicItems.map((item) => (
<li key={item.title}>
<NavigationMenuLink asChild>
<Link href={item.href}>
<div className="text-sm leading-none font-medium">{item.title}</div>
<p className="text-muted-foreground line-clamp-2 text-sm leading-snug">
</p>
</Link>
</NavigationMenuLink>
</li>
))}
</ul>
</NavigationMenuContent>
</NavigationMenuItem>
<NavigationMenuItem>
<NavigationMenuTrigger>Commissions</NavigationMenuTrigger>
<NavigationMenuContent>

View File

@ -34,10 +34,15 @@ export const adminNav: AdminNavGroup[] = [
title: "Artwork Management",
items: [
{ title: "Categories", href: "/categories" },
{ title: "Tags", href: "/tags" },
],
},
{
type: "group",
title: "Topics",
items: [{ title: "Tags", href: "/tags" }],
},
{
type: "group",
title: "Commissions",

View File

@ -5,7 +5,7 @@ import { Button } from "@/components/ui/button";
import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import { ArtCategory, ArtTag, ArtTagAlias } from "@/generated/prisma/client";
import { ArtCategory, Tag, TagAlias } from "@/generated/prisma/client";
import { TagFormInput, tagSchema } from "@/schemas/artworks/tagSchema";
import { zodResolver } from "@hookform/resolvers/zod";
import { useRouter } from "next/navigation";
@ -16,17 +16,32 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from ".
import { Switch } from "../ui/switch";
import AliasEditor from "./AliasEditor";
export default function EditTagForm({ tag, categories, allTags }: { tag: ArtTag & { categories: ArtCategory[], aliases: ArtTagAlias[] }, categories: ArtCategory[], allTags: ArtTag[] }) {
export default function EditTagForm({
tag,
categories,
allTags,
}: {
tag: Tag & {
categoryLinks: { category: ArtCategory }[];
aliases: TagAlias[];
parentId?: string | null;
isParent?: boolean;
showOnAnimalPage?: boolean;
};
categories: ArtCategory[];
allTags: Tag[];
}) {
const router = useRouter();
const form = useForm<TagFormInput>({
resolver: zodResolver(tagSchema),
defaultValues: {
name: tag.name,
description: tag.description || "",
categoryIds: tag.categories?.map(cat => cat.id) ?? [],
parentId: (tag as any).parentId ?? null,
categoryIds: tag.categoryLinks?.map((link) => link.category.id) ?? [],
parentId: tag.parentId ?? null,
isParent: tag.isParent ?? false,
showOnAnimalPage: tag.showOnAnimalPage ?? false,
isVisible: tag.isVisible ?? true,
aliases: tag.aliases?.map(a => a.alias) ?? []
}
})
@ -34,12 +49,12 @@ export default function EditTagForm({ tag, categories, allTags }: { tag: ArtTag
async function onSubmit(values: TagFormInput) {
try {
const updated = await updateTag(tag.id, values)
console.log("Art tag updated:", updated)
toast("Art tag updated.")
console.log("Tag updated:", updated)
toast("Tag updated.")
router.push("/tags")
} catch (err) {
console.error(err)
toast("Failed to update art tag.")
toast("Failed to update tag.")
}
}
@ -184,6 +199,23 @@ export default function EditTagForm({ tag, categories, allTags }: { tag: ArtTag
)}
/>
</div>
<div className="flex">
<FormField
control={form.control}
name="isVisible"
render={({ field }) => (
<FormItem className="flex items-center justify-between rounded-lg border p-4">
<div className="space-y-0.5">
<FormLabel>Visible</FormLabel>
<FormDescription></FormDescription>
</div>
<FormControl>
<Switch checked={field.value} onCheckedChange={field.onChange} />
</FormControl>
</FormItem>
)}
/>
</div>
<div className="flex flex-col gap-4">
<Button type="submit">Submit</Button>
<Button type="reset" variant="secondary" onClick={() => router.back()}>Cancel</Button>
@ -192,4 +224,4 @@ export default function EditTagForm({ tag, categories, allTags }: { tag: ArtTag
</Form>
</div >
);
}
}

View File

@ -5,7 +5,7 @@ import { Button } from "@/components/ui/button";
import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import { ArtCategory, ArtTag } from "@/generated/prisma/client";
import { ArtCategory, Tag } from "@/generated/prisma/client";
import { TagFormInput, tagSchema } from "@/schemas/artworks/tagSchema";
import { zodResolver } from "@hookform/resolvers/zod";
import { useRouter } from "next/navigation";
@ -17,7 +17,7 @@ import { Switch } from "../ui/switch";
import AliasEditor from "./AliasEditor";
export default function NewTagForm({ categories, allTags }: { categories: ArtCategory[], allTags: ArtTag[] }) {
export default function NewTagForm({ categories, allTags }: { categories: ArtCategory[], allTags: Tag[] }) {
const router = useRouter();
const form = useForm<TagFormInput>({
resolver: zodResolver(tagSchema),
@ -28,6 +28,7 @@ export default function NewTagForm({ categories, allTags }: { categories: ArtCat
parentId: null,
isParent: false,
showOnAnimalPage: false,
isVisible: true,
aliases: [],
}
})
@ -35,12 +36,12 @@ export default function NewTagForm({ categories, allTags }: { categories: ArtCat
async function onSubmit(values: TagFormInput) {
try {
const created = await createTag(values)
console.log("Art tag created:", created)
toast("Art tag created.")
console.log("Tag created:", created)
toast("Tag created.")
router.push("/tags")
} catch (err) {
console.error(err)
toast("Failed to create art tag.")
toast("Failed to create tag.")
}
}
@ -185,6 +186,23 @@ export default function NewTagForm({ categories, allTags }: { categories: ArtCat
)}
/>
</div>
<div className="flex">
<FormField
control={form.control}
name="isVisible"
render={({ field }) => (
<FormItem className="flex items-center justify-between rounded-lg border p-4">
<div className="space-y-0.5">
<FormLabel>Visible</FormLabel>
<FormDescription></FormDescription>
</div>
<FormControl>
<Switch checked={field.value} onCheckedChange={field.onChange} />
</FormControl>
</FormItem>
)}
/>
</div>
<div className="flex flex-col gap-4">
<Button type="submit">Submit</Button>
<Button type="reset" variant="secondary" onClick={() => router.back()}>Cancel</Button>
@ -193,4 +211,4 @@ export default function NewTagForm({ categories, allTags }: { categories: ArtCat
</Form>
</div >
);
}
}