Add tags and categories

This commit is contained in:
2025-12-20 17:37:52 +01:00
parent dfb6f7042a
commit e90578c98a
23 changed files with 913 additions and 45 deletions

View File

@ -10,12 +10,12 @@ import MultipleSelector from "@/components/ui/multiselect";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { Switch } from "@/components/ui/switch";
import { Textarea } from "@/components/ui/textarea";
import { ArtCategory, ArtTag } from "@/generated/prisma/client";
import { ArtTag } from "@/generated/prisma/client";
// import { Color, ImageColor, ImageMetadata, ImageVariant, PortfolioAlbum, PortfolioCategory, PortfolioImage, PortfolioSortContext, PortfolioTag, PortfolioType } from "@/generated/prisma";
import { cn } from "@/lib/utils";
import { artworkSchema } from "@/schemas/artworks/imageSchema";
// import { imageSchema } from "@/schemas/portfolio/imageSchema";
import { ArtworkWithRelations } from "@/types/Artwork";
import { ArtworkWithRelations, CategoryWithTags } from "@/types/Artwork";
import { zodResolver } from "@hookform/resolvers/zod";
import { format } from "date-fns";
import { useRouter } from "next/navigation";
@ -26,7 +26,7 @@ import { z } from "zod/v4";
export default function EditArtworkForm({ artwork, categories, tags }:
{
artwork: ArtworkWithRelations,
categories: ArtCategory[]
categories: CategoryWithTags[]
tags: ArtTag[]
}) {
const router = useRouter();
@ -246,37 +246,6 @@ export default function EditArtworkForm({ artwork, categories, tags }:
</FormItem>
)}
/> */}
<FormField
control={form.control}
name="tagIds"
render={({ field }) => {
const selectedOptions = tags
.filter(tag => field.value?.includes(tag.id))
.map(tag => ({ label: tag.name, value: tag.id }));
return (
<FormItem>
<FormLabel>Tags</FormLabel>
<FormControl>
<MultipleSelector
defaultOptions={tags.map(tag => ({
label: tag.name,
value: tag.id,
}))}
placeholder="Select tags"
hidePlaceholderWhenSelected
selectFirstItem
value={selectedOptions}
onChange={(options) => {
const ids = options.map(option => option.value);
field.onChange(ids);
}}
/>
</FormControl>
<FormMessage />
</FormItem>
)
}}
/>
<FormField
control={form.control}
name="categoryIds"
@ -308,6 +277,64 @@ export default function EditArtworkForm({ artwork, categories, tags }:
)
}}
/>
<FormField
control={form.control}
name="tagIds"
render={({ field }) => {
const selectedTagIds = field.value ?? [];
const selectedCategoryIds = form.watch("categoryIds") ?? [];
// Tag IDs connected to selected categories
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);
}
// Build grouped options: Selected -> Category -> Other
const tagOptions = tags
.map((t) => {
let group = "Other tags";
if (selectedTagIds.includes(t.id)) group = "Selected";
else if (preferredTagIds.has(t.id)) group = "From selected categories";
return {
label: t.name,
value: t.id,
group, // IMPORTANT: groupBy will use this
};
})
// Optional: stable ordering within each group
.sort((a, b) => a.label.localeCompare(b.label));
// Selected value objects
const selectedOptions = tags
.filter((t) => selectedTagIds.includes(t.id))
.map((t) => ({ label: t.name, value: t.id }));
return (
<FormItem>
<FormLabel>Tags</FormLabel>
<FormControl>
<MultipleSelector
options={tagOptions}
groupBy="group"
groupOrder={["Selected", "From selected categories", "Other tags"]}
showSelectedInDropdown
placeholder="Select tags"
hidePlaceholderWhenSelected
selectFirstItem
value={selectedOptions}
onChange={(options) => field.onChange(options.map((o) => o.value))}
/>
</FormControl>
<FormMessage />
</FormItem>
);
}}
/>
{/* Boolean */}
<FormField
control={form.control}