Files
XBid/src/components/assets/asset-dialog.tsx
T
2026-08-18 12:11:20 +02:00

87 lines
3.9 KiB
TypeScript

"use client";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { assetSchema, type AssetFormValues } from "@/lib/validations";
import type { Resolver } from "react-hook-form";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import { Label } from "@/components/ui/label";
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Loader2 } from "lucide-react";
import { ASSET_TYPES } from "@/lib/constants";
interface Props {
open: boolean;
onOpenChange: (v: boolean) => void;
onSubmit: (data: AssetFormValues) => Promise<void>;
initialData?: Partial<AssetFormValues>;
}
export function AssetDialog({ open, onOpenChange, onSubmit, initialData }: Props) {
const {
register,
handleSubmit,
setValue,
reset,
formState: { errors, isSubmitting },
} = useForm<AssetFormValues>({
resolver: zodResolver(assetSchema) as Resolver<AssetFormValues>,
defaultValues: { complexityMultiplier: 1, ...initialData },
});
const handleClose = () => { reset(); onOpenChange(false); };
const submit = async (data: AssetFormValues) => { await onSubmit(data); reset(); };
return (
<Dialog open={open} onOpenChange={handleClose}>
<DialogContent className="bg-zinc-900 border-zinc-800 max-w-lg">
<DialogHeader>
<DialogTitle>{initialData ? "Edit Asset" : "Add Asset"}</DialogTitle>
</DialogHeader>
<form onSubmit={handleSubmit(submit as Parameters<typeof handleSubmit>[0])} className="space-y-4">
<div className="grid grid-cols-2 gap-4">
<div className="space-y-1.5 col-span-2">
<Label>Asset Name *</Label>
<Input {...register("assetName")} className="bg-zinc-800 border-zinc-700" placeholder="e.g. Hero Character" />
{errors.assetName && <p className="text-red-400 text-xs">{errors.assetName.message}</p>}
</div>
<div className="space-y-1.5">
<Label>Asset Type</Label>
<Select onValueChange={(v) => setValue("assetType", v ?? undefined)} defaultValue={initialData?.assetType ?? undefined}>
<SelectTrigger className="bg-zinc-800 border-zinc-700">
<SelectValue placeholder="Select type" />
</SelectTrigger>
<SelectContent className="bg-zinc-900 border-zinc-700">
{ASSET_TYPES.map((t) => <SelectItem key={t} value={t}>{t}</SelectItem>)}
</SelectContent>
</Select>
</div>
<div className="space-y-1.5">
<Label>Complexity Multiplier</Label>
<Input {...register("complexityMultiplier")} type="number" step="0.1" min="0.1" max="10" className="bg-zinc-800 border-zinc-700" />
</div>
</div>
<div className="space-y-1.5">
<Label>Description</Label>
<Input {...register("description")} className="bg-zinc-800 border-zinc-700" />
</div>
<div className="space-y-1.5">
<Label>Notes</Label>
<Textarea {...register("notes")} className="bg-zinc-800 border-zinc-700" rows={2} />
</div>
<div className="flex gap-3 justify-end pt-2">
<Button type="button" variant="outline" className="border-zinc-700" onClick={handleClose}>Cancel</Button>
<Button type="submit" disabled={isSubmitting} className="bg-amber-500 hover:bg-amber-400 text-black font-semibold">
{isSubmitting && <Loader2 className="h-4 w-4 mr-2 animate-spin" />}
{initialData ? "Save" : "Add Asset"}
</Button>
</div>
</form>
</DialogContent>
</Dialog>
);
}