Feat: Implement Customer Edit page and functionality

This commit is contained in:
2025-12-03 22:55:26 +03:00
parent efeff06432
commit e61abe0189
3 changed files with 250 additions and 4 deletions

View File

@@ -0,0 +1,211 @@
'use client'
import { zodResolver } from "@hookform/resolvers/zod"
import { useForm } from "react-hook-form"
import * as z from "zod"
import { Button } from "@/components/ui/button"
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form"
import { Input } from "@/components/ui/input"
import { Textarea } from "@/components/ui/textarea"
import { updateCustomer, deleteCustomer } from "./actions"
import { useRouter } from "next/navigation"
import { useState } from "react"
import { toast } from "sonner"
import { Trash2 } from "lucide-react"
const formSchema = z.object({
full_name: z.string().min(2, "İsim en az 2 karakter olmalıdır."),
phone: z.string().optional(),
email: z.string().email("Geçerli bir e-posta adresi giriniz.").optional().or(z.literal("")),
city: z.string().optional(),
district: z.string().optional(),
address: z.string().optional(),
notes: z.string().optional(),
})
interface EditCustomerFormProps {
customer: {
id: string
full_name: string
phone?: string | null
email?: string | null
city?: string | null
district?: string | null
address?: string | null
notes?: string | null
}
}
export function EditCustomerForm({ customer }: EditCustomerFormProps) {
const router = useRouter()
const [loading, setLoading] = useState(false)
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
full_name: customer.full_name,
phone: customer.phone || "",
email: customer.email || "",
city: customer.city || "",
district: customer.district || "",
address: customer.address || "",
notes: customer.notes || "",
},
})
async function onSubmit(values: z.infer<typeof formSchema>) {
setLoading(true)
try {
await updateCustomer(customer.id, values)
toast.success("Müşteri başarıyla güncellendi")
router.push('/dashboard/customers')
router.refresh()
} catch (error) {
toast.error("Bir hata oluştu")
} finally {
setLoading(false)
}
}
async function handleDelete() {
if (!confirm("Bu müşteriyi silmek istediğinize emin misiniz?")) return
setLoading(true)
try {
await deleteCustomer(customer.id)
toast.success("Müşteri silindi")
router.push('/dashboard/customers')
router.refresh()
} catch (error) {
toast.error("Silme işlemi başarısız")
setLoading(false)
}
}
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<FormField
control={form.control}
name="full_name"
render={({ field }) => (
<FormItem>
<FormLabel>İsim Soyisim</FormLabel>
<FormControl>
<Input placeholder="Ahmet Yılmaz" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="phone"
render={({ field }) => (
<FormItem>
<FormLabel>Telefon</FormLabel>
<FormControl>
<Input placeholder="0555 555 55 55" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
<FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem>
<FormLabel>E-posta</FormLabel>
<FormControl>
<Input type="email" placeholder="ornek@email.com" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<FormField
control={form.control}
name="city"
render={({ field }) => (
<FormItem>
<FormLabel>İl</FormLabel>
<FormControl>
<Input placeholder="İstanbul" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="district"
render={({ field }) => (
<FormItem>
<FormLabel>İlçe</FormLabel>
<FormControl>
<Input placeholder="Kadıköy" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
<FormField
control={form.control}
name="address"
render={({ field }) => (
<FormItem>
<FormLabel>Adres</FormLabel>
<FormControl>
<Textarea placeholder="Tam adres..." {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="notes"
render={({ field }) => (
<FormItem>
<FormLabel>Notlar</FormLabel>
<FormControl>
<Textarea placeholder="Müşteri hakkında notlar..." {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<div className="flex justify-between gap-4">
<Button type="button" variant="destructive" onClick={handleDelete} disabled={loading}>
<Trash2 className="mr-2 h-4 w-4" /> Sil
</Button>
<div className="flex gap-2">
<Button type="button" variant="outline" onClick={() => router.back()} disabled={loading}>
İptal
</Button>
<Button type="submit" disabled={loading}>
{loading ? "Güncelleniyor..." : "Güncelle"}
</Button>
</div>
</div>
</form>
</Form>
)
}

View File

@@ -0,0 +1,31 @@
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { EditCustomerForm } from "./edit-customer-form"
import { createClient } from "@/lib/supabase/server"
import { notFound } from "next/navigation"
export default async function EditCustomerPage({ params }: { params: { id: string } }) {
const supabase = await createClient()
const { data: customer } = await supabase
.from('customers')
.select('*')
.eq('id', params.id)
.single()
if (!customer) {
notFound()
}
return (
<div className="max-w-2xl mx-auto">
<Card>
<CardHeader>
<CardTitle>Müşteri Düzenle</CardTitle>
</CardHeader>
<CardContent>
<EditCustomerForm customer={customer} />
</CardContent>
</Card>
</div>
)
}

View File

@@ -80,7 +80,9 @@ export default async function CustomersPage({
<TableCell>{customer.email}</TableCell>
<TableCell className="max-w-xs truncate">{customer.notes}</TableCell>
<TableCell className="text-right">
<Link href={`/dashboard/customers/${customer.id}`}>
<Button variant="ghost" size="sm">Düzenle</Button>
</Link>
</TableCell>
</TableRow>
))
@@ -100,9 +102,11 @@ export default async function CustomersPage({
<Card key={customer.id} className="overflow-hidden">
<CardHeader className="bg-muted/20 p-4 flex flex-row items-center justify-between space-y-0">
<span className="font-semibold text-lg">{customer.full_name}</span>
<Link href={`/dashboard/customers/${customer.id}`}>
<Button variant="ghost" size="icon" className="h-8 w-8">
<Edit className="h-4 w-4 text-muted-foreground" />
</Button>
</Link>
</CardHeader>
<CardContent className="p-4 space-y-3">
<div className="flex items-center text-sm">