Improve artwork edit form
This commit is contained in:
@ -1,7 +1,6 @@
|
||||
"use client"
|
||||
|
||||
import { updateArtwork } from "@/actions/artworks/updateArtwork";
|
||||
// import { updateImage } from "@/actions/portfolio/images/updateImage";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Calendar } from "@/components/ui/calendar";
|
||||
import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
|
||||
@ -11,10 +10,8 @@ import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
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, CategoryWithTags } from "@/types/Artwork";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { format } from "date-fns";
|
||||
@ -45,15 +42,10 @@ export default function EditArtworkForm({ artwork, categories, tags }:
|
||||
month: artwork.month || undefined,
|
||||
year: artwork.year || undefined,
|
||||
creationDate: artwork.creationDate ? new Date(artwork.creationDate) : undefined,
|
||||
|
||||
// albumId: image.albumId ?? undefined,
|
||||
// typeId: image.typeId ?? undefined,
|
||||
metadataId: artwork.metadata?.id ?? undefined,
|
||||
categoryIds: artwork.categories?.map(cat => cat.id) ?? [],
|
||||
colorIds: artwork.colors?.map(color => color.id) ?? [],
|
||||
// sortContextIds: image.sortContexts?.map(sortContext => sortContext.id) ?? [],
|
||||
tagIds: artwork.tags?.map(tag => tag.id) ?? [],
|
||||
variantIds: artwork.variants?.map(variant => variant.id) ?? [],
|
||||
newCategoryNames: [],
|
||||
newTagNames: []
|
||||
}
|
||||
})
|
||||
|
||||
@ -109,6 +101,19 @@ export default function EditArtworkForm({ artwork, categories, tags }:
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="notes"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Internal notes</FormLabel>
|
||||
<FormControl>
|
||||
<Textarea {...field} placeholder="Any note to the image" />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
{/* Number */}
|
||||
<FormField
|
||||
control={form.control}
|
||||
@ -192,89 +197,62 @@ export default function EditArtworkForm({ artwork, categories, tags }:
|
||||
)}
|
||||
/>
|
||||
{/* Select */}
|
||||
{/* <FormField
|
||||
control={form.control}
|
||||
name="albumId"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Album</FormLabel>
|
||||
<Select
|
||||
onValueChange={(value) => field.onChange(value === "" ? undefined : value)}
|
||||
value={field.value ?? ""}
|
||||
>
|
||||
<FormControl>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Select an album" />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
{albums.map((album) => (
|
||||
<SelectItem key={album.id} value={album.id}>
|
||||
{album.name}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/> */}
|
||||
{/* <FormField
|
||||
control={form.control}
|
||||
name="typeId"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Art Type</FormLabel>
|
||||
<Select
|
||||
onValueChange={(value) => field.onChange(value === "" ? undefined : value)}
|
||||
value={field.value ?? ""}
|
||||
>
|
||||
<FormControl>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Select an art type" />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
{types.map((type) => (
|
||||
<SelectItem key={type.id} value={type.id}>
|
||||
{type.name}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/> */}
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="categoryIds"
|
||||
render={({ field }) => {
|
||||
const existingOptions = categories.map((cat) => ({
|
||||
label: cat.name,
|
||||
value: cat.id,
|
||||
}));
|
||||
|
||||
const selectedCategoryIds = field.value ?? [];
|
||||
const selectedOptions = categories
|
||||
.filter(cat => field.value?.includes(cat.id))
|
||||
.map(cat => ({ label: cat.name, value: cat.id }));
|
||||
.filter((cat) => selectedCategoryIds.includes(cat.id))
|
||||
.map((cat) => ({ label: cat.name, value: cat.id }));
|
||||
|
||||
// Also include any "new" selections so they stay visible after selection
|
||||
const newCategoryNames = form.watch("newCategoryNames") ?? [];
|
||||
const newSelectedOptions = newCategoryNames.map((name) => ({
|
||||
label: `Create: ${name}`,
|
||||
value: `__new__:${name}`,
|
||||
}));
|
||||
|
||||
return (
|
||||
<FormItem>
|
||||
<FormLabel>Categories</FormLabel>
|
||||
<FormControl>
|
||||
<MultipleSelector
|
||||
defaultOptions={categories.map(cat => ({
|
||||
label: cat.name,
|
||||
value: cat.id,
|
||||
}))}
|
||||
placeholder="Select categories"
|
||||
options={existingOptions}
|
||||
placeholder="Select or type to create categories"
|
||||
hidePlaceholderWhenSelected
|
||||
selectFirstItem
|
||||
value={selectedOptions}
|
||||
value={[...selectedOptions, ...newSelectedOptions]}
|
||||
creatable
|
||||
createOption={(raw) => ({
|
||||
value: `__new__:${raw}`,
|
||||
label: `Create: ${raw}`,
|
||||
})}
|
||||
onChange={(options) => {
|
||||
const ids = options.map(option => option.value);
|
||||
field.onChange(ids);
|
||||
const values = options.map((o) => o.value);
|
||||
|
||||
const existingIds = values.filter((v) => !v.startsWith("__new__:"));
|
||||
const newNames = values
|
||||
.filter((v) => v.startsWith("__new__:"))
|
||||
.map((v) => v.replace("__new__:", "").trim())
|
||||
.filter(Boolean);
|
||||
|
||||
field.onChange(existingIds);
|
||||
form.setValue("newCategoryNames", Array.from(new Set(newNames)), {
|
||||
shouldDirty: true,
|
||||
shouldValidate: true,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)
|
||||
);
|
||||
}}
|
||||
/>
|
||||
|
||||
@ -284,6 +262,7 @@ export default function EditArtworkForm({ artwork, categories, tags }:
|
||||
render={({ field }) => {
|
||||
const selectedTagIds = field.value ?? [];
|
||||
const selectedCategoryIds = form.watch("categoryIds") ?? [];
|
||||
const newTagNames = form.watch("newTagNames") ?? [];
|
||||
|
||||
// Tag IDs connected to selected categories
|
||||
const preferredTagIds = new Set<string>();
|
||||
@ -292,27 +271,29 @@ export default function EditArtworkForm({ artwork, categories, tags }:
|
||||
for (const t of cat.tags) preferredTagIds.add(t.id);
|
||||
}
|
||||
|
||||
// Build grouped options: Selected -> Category -> Other
|
||||
// Existing tag options with groups
|
||||
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
|
||||
};
|
||||
return { label: t.name, value: t.id, group };
|
||||
})
|
||||
// Optional: stable ordering within each group
|
||||
.sort((a, b) => a.label.localeCompare(b.label));
|
||||
|
||||
// Selected value objects
|
||||
const selectedOptions = tags
|
||||
// Selected existing tags
|
||||
const selectedExistingOptions = tags
|
||||
.filter((t) => selectedTagIds.includes(t.id))
|
||||
.map((t) => ({ label: t.name, value: t.id }));
|
||||
|
||||
// Selected "new" tags (so they remain visible)
|
||||
const selectedNewOptions = newTagNames.map((name) => ({
|
||||
label: `Create: ${name}`,
|
||||
value: `__new__:${name}`,
|
||||
group: "Selected",
|
||||
}));
|
||||
|
||||
return (
|
||||
<FormItem>
|
||||
<FormLabel>Tags</FormLabel>
|
||||
@ -322,11 +303,31 @@ export default function EditArtworkForm({ artwork, categories, tags }:
|
||||
groupBy="group"
|
||||
groupOrder={["Selected", "From selected categories", "Other tags"]}
|
||||
showSelectedInDropdown
|
||||
placeholder="Select tags"
|
||||
placeholder="Select or type to create tags"
|
||||
hidePlaceholderWhenSelected
|
||||
selectFirstItem
|
||||
value={selectedOptions}
|
||||
onChange={(options) => field.onChange(options.map((o) => o.value))}
|
||||
value={[...selectedExistingOptions, ...selectedNewOptions]}
|
||||
creatable
|
||||
createOption={(raw) => ({
|
||||
value: `__new__:${raw}`,
|
||||
label: `Create: ${raw}`,
|
||||
group: "Selected",
|
||||
})}
|
||||
onChange={(options) => {
|
||||
const values = options.map((o) => o.value);
|
||||
|
||||
const existingIds = values.filter((v) => !v.startsWith("__new__:"));
|
||||
const newNames = values
|
||||
.filter((v) => v.startsWith("__new__:"))
|
||||
.map((v) => v.replace("__new__:", "").trim())
|
||||
.filter(Boolean);
|
||||
|
||||
field.onChange(existingIds);
|
||||
form.setValue("newTagNames", Array.from(new Set(newNames)), {
|
||||
shouldDirty: true,
|
||||
shouldValidate: true,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
|
||||
Reference in New Issue
Block a user