daphnis/components/avatarcustomization/page.tsx

168 lines
5.6 KiB
TypeScript
Raw Normal View History

2024-07-21 16:19:30 +00:00
"use client";
import { zodResolver } from "@hookform/resolvers/zod";
import { Check, ChevronsUpDown } from "lucide-react";
import { useForm } from "react-hook-form";
import { z } from "zod";
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
} from "@/components/ui/command";
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import { toast } from "@/components/ui/use-toast";
2024-07-21 17:26:18 +00:00
import { chuni_static_avatar } from "@/prisma/schemas/artemis/generated/artemis";
type chunithm = chuni_static_avatar;
2024-07-21 16:19:30 +00:00
const AvatarParts = [
2024-07-21 17:24:31 +00:00
{ label: "Head", value: "avatarHead", src: "/path/to/head.png" },
{ label: "Body", value: "avatarBody", src: "/path/to/body.png" },
{ label: "Face", value: "avatarFace", src: "/path/to/face.png" },
{ label: "Back", value: "avatarBack", src: "/path/to/back.png" },
2024-07-21 16:19:30 +00:00
] as const;
const FormSchema = z.object({
AvatarHead: z.string({
required_error: "Please select a head item.",
}),
AvatarBody: z.string({
required_error: "Please select a body item.",
}),
AvatarFace: z.string({
required_error: "Please select a face item.",
}),
AvatarBack: z.string({
required_error: "Please select a back item.",
}),
});
export function AvatarCustomization() {
const form = useForm<z.infer<typeof FormSchema>>({
resolver: zodResolver(FormSchema),
});
function onSubmit(data: z.infer<typeof FormSchema>) {
toast({
title: "You submitted the following values:",
description: (
<pre className="mt-2 w-[340px] rounded-md bg-slate-950 p-4">
<code className="text-white">{JSON.stringify(data, null, 2)}</code>
</pre>
),
});
}
return (
2024-07-21 17:24:31 +00:00
<div className="bg-red-500 rounded-sm mx-auto">
<div className="flex flex-col md:flex-row justify-center items-center">
<div className="avatar_group w-full md:w-1/2 flex justify-center items-center">
<div className="avatar_base">
{AvatarParts.map(({ value, src }) => (
<div className={value} key={value}>
<img src={src} alt={value} />
</div>
))}
</div>
</div>
</div>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
{AvatarParts.map((part) => (
<FormField
key={part.value}
control={form.control}
name={part.value as keyof z.infer<typeof FormSchema>}
render={({ field }) => (
<FormItem className="flex flex-col">
<FormLabel>{`Avatar ${part.label} Item`}</FormLabel>
<Popover>
<PopoverTrigger asChild>
<FormControl>
<Button
variant="outline"
role="combobox"
className={cn(
"w-[200px] justify-between",
!field.value && "text-muted-foreground"
)}
>
{field.value
? AvatarParts.find(
(item) => item.value === field.value
)?.label
: `Select ${part.label.toLowerCase()} item`}
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent className="w-[200px] p-0">
<Command>
<CommandInput
placeholder={`Search ${part.label.toLowerCase()} item...`}
/>
<CommandList>
<CommandEmpty>
No {part.label.toLowerCase()} item found.
</CommandEmpty>
<CommandGroup>
{AvatarParts.map((item) => (
<CommandItem
value={item.value}
key={item.value}
onSelect={() => {
form.setValue(
part.value as keyof z.infer<
typeof FormSchema
>,
item.value
);
}}
>
<Check
className={cn(
"mr-2 h-4 w-4",
item.value === field.value
? "opacity-100"
: "opacity-0"
)}
/>
{item.label}
</CommandItem>
))}
</CommandGroup>
</CommandList>
</Command>
</PopoverContent>
</Popover>
<FormMessage />
</FormItem>
)}
/>
))}
<Button type="submit">Submit</Button>
</form>
</Form>
</div>
2024-07-21 16:19:30 +00:00
);
}