Files
parakasa/components/dashboard/user-form.tsx
2026-01-10 20:38:06 +03:00

285 lines
12 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client"
import { useState } from "react"
import { useRouter } from "next/navigation"
import { useForm } from "react-hook-form"
import { zodResolver } from "@hookform/resolvers/zod"
import * as z from "zod"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { PhoneInput } from "@/components/ui/phone-input"
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form"
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
import { Card, CardContent } from "@/components/ui/card"
import { toast } from "sonner"
import { Loader2 } from "lucide-react"
import { createUser, updateUser, updateProfile } from "@/app/(dashboard)/dashboard/users/actions"
const userSchema = z.object({
firstName: z.string().min(2, "Ad en az 2 karakter olmalıdır."),
lastName: z.string().min(2, "Soyad en az 2 karakter olmalıdır."),
email: z.string().email("Geçerli bir e-posta adresi giriniz."),
password: z.string().optional(), // Password is optional on edit
confirmPassword: z.string().optional(),
role: z.enum(["admin", "user"]),
phone: z.string().optional(),
}).refine((data) => {
// 1. Password match check
if (data.password && data.password !== data.confirmPassword) {
return false;
}
// 2. New user password requirement check (simplified here, but strict would check id)
// We handle the "required" part in onSubmit manually for now as per previous logic,
// but the matching check is now here.
return true
}, {
message: "Şifreler eşleşmiyor.",
path: ["confirmPassword"],
})
type UserFormValues = z.infer<typeof userSchema>
interface UserFormProps {
initialData?: {
id?: string
firstName: string
lastName: string
email: string
role: "admin" | "user"
phone?: string
}
mode?: "admin" | "profile"
}
export function UserForm({ initialData, mode = "admin" }: UserFormProps) {
const router = useRouter()
const [loading, setLoading] = useState(false)
const form = useForm<UserFormValues>({
resolver: zodResolver(userSchema),
defaultValues: initialData ? {
firstName: initialData.firstName,
lastName: initialData.lastName,
email: initialData.email,
password: "", // Empty password means no change
confirmPassword: "",
role: initialData.role,
phone: initialData.phone,
} : {
firstName: "",
lastName: "",
email: "",
password: "",
confirmPassword: "",
role: "user",
phone: "",
},
})
const onSubmit = async (data: UserFormValues) => {
setLoading(true)
try {
let result;
if (mode === "profile") {
// Profile update mode (self-service)
result = await updateProfile({
firstName: data.firstName,
lastName: data.lastName,
phone: data.phone
})
} else if (initialData?.id) {
// Admin update mode
result = await updateUser(initialData.id, {
firstName: data.firstName,
lastName: data.lastName,
email: data.email,
password: data.password,
role: data.role,
phone: data.phone
})
} else {
// Admin create mode
if (!data.password || data.password.length < 6) {
toast.error("Yeni kullanıcı için şifre gereklidir (min 6 karakter).")
setLoading(false)
return
}
result = await createUser(data.firstName, data.lastName, data.email, data.password, data.role, data.phone)
}
if (result.error) {
toast.error(result.error)
return
}
toast.success(
mode === "profile"
? "Profil bilgileriniz güncellendi."
: initialData ? "Kullanıcı güncellendi." : "Kullanıcı oluşturuldu."
)
router.refresh()
if (mode === "admin") {
router.push("/dashboard/users")
}
} catch (error) {
toast.error("Bir sorun oluştu.")
} finally {
setLoading(false)
}
}
return (
<Card className="max-w-xl">
<CardContent className="pt-6">
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
<div className="grid grid-cols-2 gap-4">
<FormField
control={form.control}
name="firstName"
render={({ field }) => (
<FormItem>
<FormLabel>Ad</FormLabel>
<FormControl>
<Input placeholder="Ahmet" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="lastName"
render={({ field }) => (
<FormItem>
<FormLabel>Soyad</FormLabel>
<FormControl>
<Input placeholder="Yılmaz" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
<FormField
control={form.control}
name="phone"
render={({ field }) => (
<FormItem>
<FormLabel>Telefon</FormLabel>
<FormControl>
<PhoneInput placeholder="555 123 4567" defaultCountry="TR" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem>
<FormLabel>E-posta</FormLabel>
<FormControl>
<Input
placeholder="ahmet@parakasa.com"
{...field}
disabled={mode === "profile"}
className={mode === "profile" ? "bg-muted" : ""}
/>
</FormControl>
{mode === "profile" && <p className="text-[0.8rem] text-muted-foreground">E-posta adresi değiştirilemez.</p>}
<FormMessage />
</FormItem>
)}
/>
{mode === "admin" && (
<>
<FormField
control={form.control}
name="password"
render={({ field }) => (
<FormItem>
<FormLabel>Şifre</FormLabel>
<FormControl>
<Input type="password" placeholder={initialData ? "Değiştirmek için yeni şifre girin" : "******"} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="confirmPassword"
render={({ field }) => (
<FormItem>
<FormLabel>Şifre Tekrar</FormLabel>
<FormControl>
<Input type="password" placeholder="******" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="role"
render={({ field }) => (
<FormItem>
<FormLabel>Rol</FormLabel>
<Select onValueChange={field.onChange} defaultValue={field.value}>
<FormControl>
<SelectTrigger>
<SelectValue placeholder="Rol seçin" />
</SelectTrigger>
</FormControl>
<SelectContent>
<SelectItem value="user">Kullanıcı</SelectItem>
<SelectItem value="admin">Yönetici</SelectItem>
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
</>
)}
{mode === "profile" && (
<div className="space-y-1">
<FormLabel>Rol</FormLabel>
<Input value={initialData?.role === 'admin' ? 'Yönetici' : 'Kullanıcı'} disabled className="bg-muted" />
</div>
)}
<Button type="submit" disabled={loading} className="w-full">
{loading && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
{mode === "profile" ? "Değişiklikleri Kaydet" : (initialData ? "Kaydet" : "Kullanıcı Oluştur")}
</Button>
</form>
</Form>
</CardContent>
</Card>
)
}