uup
This commit is contained in:
183
app/components/customers/CustomerForm.tsx
Normal file
183
app/components/customers/CustomerForm.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user