This commit is contained in:
2026-01-23 20:35:40 +03:00
parent cf3b0e48ec
commit 66c151653e
137 changed files with 41495 additions and 0 deletions

View File

@@ -0,0 +1,183 @@
import { Form } from "@remix-run/react";
import { useState, useEffect } from "react";
import { Input } from "~/components/ui/Input";
import { Button } from "~/components/ui/Button";
import { Flex } from "~/components/layout/Flex";
import type { Customer } from "~/types/database";
interface CustomerFormProps {
customer?: Customer;
onCancel: () => void;
errors?: Record<string, string>;
isLoading: boolean;
}
export function CustomerForm({
customer,
onCancel,
errors = {},
isLoading,
}: CustomerFormProps) {
const [formData, setFormData] = useState({
name: customer?.name || "",
phone: customer?.phone || "",
email: customer?.email || "",
address: customer?.address || "",
});
// Reset form data when customer changes
useEffect(() => {
if (customer) {
setFormData({
name: customer.name || "",
phone: customer.phone || "",
email: customer.email || "",
address: customer.address || "",
});
} else {
setFormData({
name: "",
phone: "",
email: "",
address: "",
});
}
}, [customer]);
const handleInputChange = (field: string, value: string) => {
setFormData(prev => ({
...prev,
[field]: value,
}));
};
const isEditing = !!customer;
return (
<Form method="post" className="space-y-6">
<input
type="hidden"
name="_action"
value={isEditing ? "update" : "create"}
/>
{isEditing && (
<input type="hidden" name="id" value={customer.id} />
)}
{/* Customer Name */}
<div>
<label htmlFor="name" className="block text-sm font-medium text-gray-700 mb-2">
اسم العميل *
</label>
<Input
id="name"
name="name"
type="text"
value={formData.name}
onChange={(e) => handleInputChange("name", e.target.value)}
placeholder="أدخل اسم العميل"
error={errors.name}
required
disabled={isLoading}
/>
{errors.name && (
<p className="mt-1 text-sm text-red-600">{errors.name}</p>
)}
</div>
{/* Phone Number */}
<div>
<label htmlFor="phone" className="block text-sm font-medium text-gray-700 mb-2">
رقم الهاتف
</label>
<Input
id="phone"
name="phone"
type="tel"
value={formData.phone}
onChange={(e) => handleInputChange("phone", e.target.value)}
placeholder="أدخل رقم الهاتف"
error={errors.phone}
disabled={isLoading}
dir="ltr"
/>
{errors.phone && (
<p className="mt-1 text-sm text-red-600">{errors.phone}</p>
)}
</div>
{/* Email */}
<div>
<label htmlFor="email" className="block text-sm font-medium text-gray-700 mb-2">
البريد الإلكتروني
</label>
<Input
id="email"
name="email"
type="email"
value={formData.email}
onChange={(e) => handleInputChange("email", e.target.value)}
placeholder="أدخل البريد الإلكتروني"
error={errors.email}
disabled={isLoading}
dir="ltr"
/>
{errors.email && (
<p className="mt-1 text-sm text-red-600">{errors.email}</p>
)}
</div>
{/* Address */}
<div>
<label htmlFor="address" className="block text-sm font-medium text-gray-700 mb-2">
العنوان
</label>
<textarea
id="address"
name="address"
value={formData.address}
onChange={(e) => handleInputChange("address", e.target.value)}
placeholder="أدخل عنوان العميل"
rows={3}
disabled={isLoading}
className={`
w-full px-3 py-2 border rounded-lg shadow-sm
focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500
disabled:bg-gray-50 disabled:text-gray-500
${errors.address
? 'border-red-300 focus:ring-red-500 focus:border-red-500'
: 'border-gray-300'
}
`}
/>
{errors.address && (
<p className="mt-1 text-sm text-red-600">{errors.address}</p>
)}
</div>
{/* Form Actions */}
<Flex justify="end" className="pt-4 gap-2 border-t">
<Button
type="button"
variant="outline"
onClick={onCancel}
disabled={isLoading}
className="w-20"
>
إلغاء
</Button>
<Button
type="submit"
disabled={isLoading || !formData.name.trim()}
className="bg-blue-600 hover:bg-blue-700"
>
{isLoading
? (isEditing ? "جاري التحديث..." : "جاري الإنشاء...")
: (isEditing ? "تحديث العميل" : "إنشاء العميل")
}
</Button>
</Flex>
</Form>
);
}