Files
kovakemlak-crm/src/components/customers/customer-form-sheet.tsx
T

144 lines
5.3 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 { useActionState, useEffect } from "react";
import { CircleNotch } from '@/lib/icons';
import { toast } from "sonner";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { ResponsiveSheet, FormWizard } from "@/components/ui/responsive-sheet";
import { createCustomerAction, updateCustomerAction } from "@/lib/appwrite/customer-actions";
import type { Customer } from "@/lib/appwrite/schema";
import { CUSTOMER_STAGE_LABELS, CUSTOMER_SOURCE_LABELS } from "@/lib/appwrite/schema";
type ActionState = { ok: boolean; error?: string; fieldErrors?: Record<string, string[]> };
const INITIAL: ActionState = { ok: false };
interface CustomerFormSheetProps {
open: boolean;
onOpenChange: (v: boolean) => void;
customer?: Customer | null;
onSuccess?: () => void;
}
export function CustomerFormSheet({ open, onOpenChange, customer, onSuccess }: CustomerFormSheetProps) {
const action = customer
? updateCustomerAction.bind(null, customer.$id)
: createCustomerAction;
const [state, formAction, isPending] = useActionState(action, INITIAL);
useEffect(() => {
if (state.ok) {
toast.success(customer ? "Müşteri güncellendi." : "Müşteri oluşturuldu.");
onSuccess?.();
onOpenChange(false);
} else if (state.error) {
toast.error(state.error);
}
}, [state]);
const fe = state.fieldErrors ?? {};
const steps = [
{
label: "Kimlik",
content: (
<>
<div className="grid gap-1.5">
<Label htmlFor="name">Ad Soyad *</Label>
<Input id="name" name="name" defaultValue={customer?.name} placeholder="Ahmet Yılmaz" />
{fe.name && <p className="text-destructive text-xs">{fe.name[0]}</p>}
</div>
<div className="grid grid-cols-2 gap-3">
<div className="grid gap-1.5">
<Label>Müşteri tipi *</Label>
<select name="type" defaultValue={customer?.type ?? "alici"}
className="border-input bg-background h-9 rounded-md border px-3 text-sm">
<option value="alici">Alıcı</option>
<option value="kiraci">Kiracı</option>
<option value="yatirimci">Yatırımcı</option>
</select>
{fe.type && <p className="text-destructive text-xs">{fe.type[0]}</p>}
</div>
<div className="grid gap-1.5">
<Label>Aşama</Label>
<select name="stage" defaultValue={customer?.stage ?? "ilk_temas"}
className="border-input bg-background h-9 rounded-md border px-3 text-sm">
{Object.entries(CUSTOMER_STAGE_LABELS).map(([v, l]) => (
<option key={v} value={v}>{l}</option>
))}
</select>
</div>
</div>
</>
),
},
{
label: "İletişim",
content: (
<>
<div className="grid grid-cols-2 gap-3">
<div className="grid gap-1.5">
<Label htmlFor="phone">Telefon</Label>
<Input id="phone" name="phone" type="tel" defaultValue={customer?.phone ?? ""} placeholder="+90 555 123 45 67" />
</div>
<div className="grid gap-1.5">
<Label htmlFor="email">Email</Label>
<Input id="email" name="email" type="email" defaultValue={customer?.email ?? ""} placeholder="ahmet@example.com" />
{fe.email && <p className="text-destructive text-xs">{fe.email[0]}</p>}
</div>
</div>
<div className="grid grid-cols-2 gap-3">
<div className="grid gap-1.5">
<Label>Kaynak</Label>
<select name="source" defaultValue={customer?.source ?? ""}
className="border-input bg-background h-9 rounded-md border px-3 text-sm">
<option value="">Seçiniz</option>
{Object.entries(CUSTOMER_SOURCE_LABELS).map(([v, l]) => (
<option key={v} value={v}>{l}</option>
))}
</select>
</div>
<div className="grid gap-1.5">
<Label htmlFor="nextFollowUpDate">Takip tarihi</Label>
<Input id="nextFollowUpDate" name="nextFollowUpDate" type="date"
defaultValue={customer?.nextFollowUpDate ? customer.nextFollowUpDate.split("T")[0] : ""} />
</div>
</div>
</>
),
},
{
label: "Not",
content: (
<div className="grid gap-1.5">
<Label htmlFor="notes">Notlar</Label>
<Textarea id="notes" name="notes" rows={4} defaultValue={customer?.notes ?? ""} placeholder="Müşteri hakkında notlar..." />
</div>
),
},
];
return (
<ResponsiveSheet
open={open}
onOpenChange={onOpenChange}
title={customer ? "Müşteriyi Düzenle" : "Yeni Müşteri"}
maxWidth="sm:max-w-lg"
>
<form
action={formAction}
onKeyDown={(e) => {
if (e.key === "Enter" && (e.target as HTMLElement).tagName !== "TEXTAREA") {
e.preventDefault();
}
}}
>
<FormWizard steps={steps} isPending={isPending} submitLabel={customer ? "Güncelle" : "Oluştur"} />
</form>
</ResponsiveSheet>
);
}