"use client" import { useState, useEffect } from "react" import { useForm } from "react-hook-form" import { zodResolver } from "@hookform/resolvers/zod" import * as z from "zod" import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog" import { Button } from "@/components/ui/button" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select" import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, FormDescription, } from "@/components/ui/form" import { Input } from "@/components/ui/input" import { Switch } from "@/components/ui/switch" import { Hero } from "@/types/hero" import { heroService } from "@/services/heroService" import { toast } from "sonner" // Zod Schema const formSchema = z.object({ title: z.string().min(2, "Başlık en az 2 karakter olmalıdır"), text1: z.string().optional(), text2: z.string().optional(), text4: z.string().optional(), text5: z.string().optional(), color: z.string().optional(), is_active: z.boolean(), width: z.coerce.number().min(1, "Genişlik 0'dan büyük olmalıdır"), height: z.coerce.number().min(1, "Yükseklik 0'dan büyük olmalıdır"), quality: z.coerce.number().min(1).max(100).default(85), format: z.string().optional().default("avif"), image: z.any().optional(), }) interface HeroDialogProps { open: boolean onOpenChange: (open: boolean) => void hero?: Hero | null onSuccess?: () => void } export function HeroDialog({ open, onOpenChange, hero, onSuccess }: HeroDialogProps) { const [loading, setLoading] = useState(false) const [preview, setPreview] = useState(null) const form = useForm>({ // eslint-disable-next-line @typescript-eslint/no-explicit-any resolver: zodResolver(formSchema) as any, defaultValues: { title: "", text1: "", text2: "", text4: "", text5: "", color: "#000000", is_active: true, width: 0, height: 0, quality: 85, format: "webp", }, }) useEffect(() => { if (hero) { form.reset({ title: hero.title, text1: hero.text1 || "", text2: hero.text2 || "", text4: hero.text4 || "", text5: hero.text5 || "", color: hero.color || "#000000", is_active: !!hero.is_active, width: hero.width || 0, height: hero.height || 0, quality: hero.quality || 85, format: hero.format || "avif", }) // Existing image preview // Backend returns relative path usually, ensure full URL if needed or use as is // Assuming backend/frontend serve static files correctly setPreview(hero.image ? `${process.env.NEXT_PUBLIC_API_URL}${hero.image}` : null) } else { form.reset({ title: "", text1: "", text2: "", text4: "", text5: "", color: "#000000", is_active: true, width: 0, height: 0, quality: 85, format: "avif", }) setPreview(null) } }, [hero, form, open]) const handleImageChange = (e: React.ChangeEvent) => { const file = e.target.files?.[0] if (file) { form.setValue("image", file) const reader = new FileReader() reader.onloadend = () => { setPreview(reader.result as string) } reader.readAsDataURL(file) } } const onSubmit = async (values: z.infer) => { setLoading(true) const formData = new FormData() formData.append("title", values.title) if (values.text1) formData.append("text1", values.text1) if (values.text2) formData.append("text2", values.text2) if (values.text4) formData.append("text4", values.text4) if (values.text5) formData.append("text5", values.text5) if (values.color) formData.append("color", values.color) formData.append("is_active", String(values.is_active)) // New fields formData.append("width", String(values.width)) formData.append("height", String(values.height)) formData.append("quality", String(values.quality)) if (values.format) formData.append("format", values.format) if (values.image instanceof File) { formData.append("image", values.image) } try { if (hero) { await heroService.updateHero(hero.ID, formData) toast.success("Hero başarıyla güncellendi") } else { await heroService.createHero(formData) toast.success("Hero başarıyla oluşturuldu") } onOpenChange(false) if (onSuccess) onSuccess() } catch (error: unknown) { console.error("Hero save error:", error) toast.error((error as Error).message || "Bir hata oluştu") } finally { setLoading(false) } } return ( {hero ? "Hero Düzenle" : "Yeni Hero Ekle"}
( Başlık )} />
( Text 1 )} /> ( Text 2 )} />
( Text 4 )} /> ( Text 5 )} />
( Genişlik (px) )} /> ( Yükseklik (px) )} />
( Kalite (1-100) )} /> ( Format )} />
( Renk (Hex)
)} /> (
Aktif Bu hero banner sitede görüntülensin mi?
)} /> Görsel {preview && (
{/* Note: Using standard img for now to avoid Next.js Image Config issues with localhost */} {/* eslint-disable-next-line @next/next/no-img-element */} Preview
)}
) }