"use client"; import { useEffect, useRef, useState } from "react"; import { Alert, Spinner } from "../UI"; import type { Client, ClientFormData, ClientFormErrors } from "../../types/client"; // ── Fixed styles (same token system as UserFormModal) ────────────────────── const S = { input: { width: "100%", height: 40, padding: "0 0.75rem", borderRadius: "var(--radius-md)", border: "1px solid var(--color-border)", background: "var(--color-surface)", fontSize: 13, color: "var(--color-text-primary)", outline: "none", fontFamily: "var(--font-sans)", } as React.CSSProperties, label: { display: "flex", flexDirection: "column" as const, gap: 6, fontSize: 12, fontWeight: 600, color: "var(--color-text-secondary)", } as React.CSSProperties, errorText: { fontSize: 11, color: "var(--color-danger)", fontWeight: 500, } as React.CSSProperties, }; // ── Validation ───────────────────────────────────────────────────────────── const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; const PHONE_RE = /^\+?[0-9]{10,15}$/; function validate(data: ClientFormData): ClientFormErrors { const e: ClientFormErrors = {}; if (!data.name.trim()) e.name = "اسم العميل مطلوب"; if (!data.email.trim()) { e.email = "البريد الإلكتروني مطلوب"; } else if (!EMAIL_RE.test(data.email)) { e.email = "صيغة البريد الإلكتروني غير صحيحة"; } if (!data.phone.trim()) { e.phone = "رقم الهاتف مطلوب"; } else if (!PHONE_RE.test(data.phone.replace(/\s/g, ""))) { e.phone = "رقم هاتف غير صالح (10–15 رقم)"; } return e; } // ── Props ────────────────────────────────────────────────────────────────── interface ClientFormModalProps { editClient: Client | null; // null = create mode, Client = edit mode onClose: () => void; onSubmit: (data: ClientFormData, isNew: boolean) => Promise; } // ── Component ────────────────────────────────────────────────────────────── export function ClientFormModal({ editClient, onClose, onSubmit, }: ClientFormModalProps) { const isNew = editClient === null; const [form, setForm] = useState({ name: editClient?.name ?? "", email: editClient?.email ?? "", phone: editClient?.phone ?? "", taxId: editClient?.taxId ?? "", notes: editClient?.notes ?? "", }); const [errors, setErrors] = useState({}); const [saving, setSaving] = useState(false); const [apiError, setApiError] = useState(""); const firstInputRef = useRef(null); useEffect(() => { firstInputRef.current?.focus(); }, []); useEffect(() => { const handler = (e: KeyboardEvent) => { if (e.key === "Escape") onClose(); }; window.addEventListener("keydown", handler); return () => window.removeEventListener("keydown", handler); }, [onClose]); const set = (field: keyof ClientFormData) => (e: React.ChangeEvent) => { setForm((p) => ({ ...p, [field]: e.target.value })); if (errors[field]) setErrors((p) => ({ ...p, [field]: undefined })); }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); const errs = validate(form); if (Object.keys(errs).length) { setErrors(errs); return; } setSaving(true); setApiError(""); const ok = await onSubmit(form, isNew); setSaving(false); if (ok) onClose(); else setApiError("حدث خطأ غير متوقع. يرجى المحاولة لاحقاً."); }; const inputStyle = (field: keyof ClientFormErrors): React.CSSProperties => ({ ...S.input, ...(errors[field] ? { borderColor: "var(--color-danger)", background: "#FEF2F2" } : {}), }); return (
{ if (e.target === e.currentTarget) onClose(); }} style={{ position: "fixed", inset: 0, zIndex: 50, background: "rgba(15,23,42,0.55)", backdropFilter: "blur(4px)", display: "flex", alignItems: "center", justifyContent: "center", padding: "1rem", }} >
e.stopPropagation()} style={{ width: "100%", maxWidth: 520, background: "var(--color-surface)", borderRadius: "var(--radius-2xl)", border: "1px solid var(--color-border)", boxShadow: "0 24px 64px rgba(0,0,0,.18)", overflow: "hidden", }} > {/* Header */}

{isNew ? "إضافة عميل" : "تعديل عميل"}

{isNew ? "عميل جديد" : editClient?.name}

{/* Body */}
{apiError && ( setApiError("")} /> )} {/* Name */} {/* Email + Phone */}
{/* Tax ID */} {/* Notes */}