Files
webshop/shop/components/admin/category-dialog.tsx

194 lines
6.6 KiB
TypeScript

'use client'
import { useState } from 'react'
import { useForm } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import * as z from 'zod'
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from '@/components/ui/dialog'
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@/components/ui/form'
import { Input } from '@/components/ui/input'
import { Button } from '@/components/ui/button'
import { createCategory, updateCategory } from '@/lib/actions/products'
import { Category } from '@/lib/types'
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue
} from '@/components/ui/select'
import { ScrollArea } from '@/components/ui/scroll-area'
import { Cloud, Utensils, HardDrive, Package } from 'lucide-react'
const categorySchema = z.object({
name: z.string().min(2, 'Name muss mindestens 2 Zeichen lang sein'),
description: z.string().optional(),
icon: z.string().default('Package'),
sort_order: z.coerce.number().int().min(0).default(0),
})
type CategoryFormValues = z.infer<typeof categorySchema>
export function CategoryDialog({
children,
category
}: {
children?: React.ReactNode,
category?: Category
}) {
const [open, setOpen] = useState(false)
const form = useForm<CategoryFormValues>({
resolver: zodResolver(categorySchema) as any,
defaultValues: {
name: category?.name || '',
description: category?.description || '',
icon: category?.icon || 'Package',
sort_order: category?.sort_order ?? 0,
},
})
async function onSubmit(values: CategoryFormValues) {
try {
if (category) {
await updateCategory(category.id, values)
} else {
await createCategory(values)
}
setOpen(false)
form.reset()
} catch (error) {
console.error('Error saving category:', error)
}
}
const icons = [
{ name: 'Cloud', Icon: Cloud },
{ name: 'Utensils', Icon: Utensils },
{ name: 'HardDrive', Icon: HardDrive },
{ name: 'Package', Icon: Package },
]
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
{children || (
<Button className="bg-primary hover:bg-primary/90">
Kategorie hinzufügen
</Button>
)}
</DialogTrigger>
<DialogContent className="glass-dark border-white/10 text-white shadow-2xl">
<DialogHeader>
<DialogTitle>{category ? 'Kategorie bearbeiten' : 'Neue Kategorie erstellen'}</DialogTitle>
<DialogDescription className="text-slate-300">
Definieren Sie eine Kategorie für Ihre Produkte.
</DialogDescription>
</DialogHeader>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4 flex-1 overflow-hidden flex flex-col min-h-0">
<ScrollArea className="max-h-[60vh] pr-4">
<div className="space-y-4 py-2">
<FormField
control={form.control}
name="name"
render={({ field }) => (
<FormItem>
<FormLabel className="text-white">Name</FormLabel>
<FormControl>
<Input placeholder="z.B. Software" className="bg-white/5 border-white/10 text-white" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="description"
render={({ field }) => (
<FormItem>
<FormLabel className="text-white">Beschreibung</FormLabel>
<FormControl>
<Input placeholder="Kurze Beschreibung" className="bg-white/5 border-white/10 text-white" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="icon"
render={({ field }) => (
<FormItem>
<FormLabel className="text-white">Icon</FormLabel>
<Select onValueChange={field.onChange} defaultValue={field.value}>
<FormControl>
<SelectTrigger className="bg-white/5 border-white/10 text-white">
<SelectValue placeholder="Icon wählen" />
</SelectTrigger>
</FormControl>
<SelectContent className="glass-dark border-white/10 text-white">
{icons.map(({ name, Icon }) => (
<SelectItem key={name} value={name} className="text-white hover:bg-white/10">
<div className="flex items-center gap-2">
<Icon className="w-4 h-4" />
{name}
</div>
</SelectItem>
))}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="sort_order"
render={({ field }) => (
<FormItem>
<FormLabel className="text-white">Reihenfolge im Bestellvorgang</FormLabel>
<FormControl>
<Input
type="number"
min={0}
placeholder="0 = zuerst"
className="bg-white/5 border-white/10 text-white"
{...field}
/>
</FormControl>
<FormMessage />
<p className="text-xs text-slate-400">Kleinere Zahl = weiter oben im Bestellformular angezeigt.</p>
</FormItem>
)}
/>
</div>
</ScrollArea>
<DialogFooter className="pt-4">
<Button type="submit" className="w-full bg-primary hover:bg-primary/90">
{category ? 'Aktualisieren' : 'Erstellen'}
</Button>
</DialogFooter>
</form>
</Form>
</DialogContent>
</Dialog>
)
}