import { useState, useEffect } from "react"; import { Form, useActionData, useNavigation } from "@remix-run/react"; import { Button, Input, Select, Text, Card, CardHeader, CardBody, MultiSelect } from "~/components/ui"; import { AutocompleteInput } from "~/components/ui/AutocompleteInput"; import { useSettings } from "~/contexts/SettingsContext"; import type { MaintenanceVisitWithRelations, Customer, Vehicle, MaintenanceType, MaintenanceJob } from "~/types/database"; import { PAYMENT_STATUS_NAMES, VISIT_DELAY_OPTIONS } from "~/lib/constants"; interface MaintenanceVisitFormProps { visit?: MaintenanceVisitWithRelations; customers: Customer[]; vehicles: Vehicle[]; maintenanceTypes: { id: number; name: string; }[]; onCancel?: () => void; } export function MaintenanceVisitForm({ visit, customers, vehicles, maintenanceTypes, onCancel }: MaintenanceVisitFormProps) { const actionData = useActionData(); const navigation = useNavigation(); const isSubmitting = navigation.state === "submitting"; const { settings } = useSettings(); // Form state const [plateNumberInput, setPlateNumberInput] = useState( visit?.vehicle?.plateNumber || "" ); const [selectedCustomerId, setSelectedCustomerId] = useState( visit?.customerId?.toString() || "" ); const [selectedVehicleId, setSelectedVehicleId] = useState( visit?.vehicleId?.toString() || "" ); const [filteredVehicles, setFilteredVehicles] = useState(vehicles); // Maintenance jobs state (with costs) const [maintenanceJobs, setMaintenanceJobs] = useState(() => { if (visit?.maintenanceJobs) { try { const jobs = JSON.parse(visit.maintenanceJobs); return jobs; } catch { return []; } } return []; }); // Current maintenance type being added const [currentTypeId, setCurrentTypeId] = useState(""); const [currentCost, setCurrentCost] = useState(""); // Create autocomplete options for plate numbers const plateNumberOptions = vehicles.map(vehicle => { const customer = customers.find(c => c.id === vehicle.ownerId); return { value: vehicle.plateNumber, label: `${vehicle.plateNumber} - ${vehicle.manufacturer} ${vehicle.model} (${customer?.name || 'غير محدد'})`, data: { vehicle, customer } }; }); // Handle plate number selection const handlePlateNumberSelect = (option: any) => { const { vehicle, customer } = option.data; setPlateNumberInput(vehicle.plateNumber); setSelectedCustomerId(customer?.id?.toString() || ""); setSelectedVehicleId(vehicle.id.toString()); }; // Reset form state when visit prop changes (switching between create/edit modes) useEffect(() => { if (visit) { // Editing mode - populate with visit data setPlateNumberInput(visit.vehicle?.plateNumber || ""); setSelectedCustomerId(visit.customerId?.toString() || ""); setSelectedVehicleId(visit.vehicleId?.toString() || ""); // Parse maintenance jobs from JSON try { const jobs = JSON.parse(visit.maintenanceJobs); setMaintenanceJobs(jobs); } catch { setMaintenanceJobs([]); } } else { // Create mode - reset to empty state setPlateNumberInput(""); setSelectedCustomerId(""); setSelectedVehicleId(""); setMaintenanceJobs([]); setCurrentTypeId(""); setCurrentCost(""); } }, [visit]); // Filter vehicles based on selected customer useEffect(() => { if (selectedCustomerId) { const customerId = parseInt(selectedCustomerId); const customerVehicles = vehicles.filter(v => v.ownerId === customerId); setFilteredVehicles(customerVehicles); // Reset vehicle selection if current vehicle doesn't belong to selected customer if (selectedVehicleId) { const vehicleId = parseInt(selectedVehicleId); const vehicleBelongsToCustomer = customerVehicles.some(v => v.id === vehicleId); if (!vehicleBelongsToCustomer) { setSelectedVehicleId(""); } } } else { setFilteredVehicles(vehicles); } }, [selectedCustomerId, vehicles, selectedVehicleId]); // Format date for input const formatDateForInput = (date: Date | string | null) => { if (!date) return ""; const d = new Date(date); return d.toISOString().slice(0, 16); // YYYY-MM-DDTHH:MM format }; // Calculate total cost from maintenance jobs const totalCost = maintenanceJobs.reduce((sum, job) => sum + job.cost, 0); // Add maintenance job const handleAddMaintenanceJob = () => { if (!currentTypeId || !currentCost) return; const typeIdNum = parseInt(currentTypeId); const costNum = parseFloat(currentCost); if (isNaN(typeIdNum) || isNaN(costNum) || costNum <= 0) return; // Check if type already exists if (maintenanceJobs.some(job => job.typeId === typeIdNum)) { alert("هذا النوع من الصيانة موجود بالفعل"); return; } const type = maintenanceTypes.find(t => t.id === typeIdNum); if (!type) return; const newJob: MaintenanceJob = { typeId: typeIdNum, job: type.name, cost: costNum, notes: '' }; setMaintenanceJobs([...maintenanceJobs, newJob]); setCurrentTypeId(""); setCurrentCost(""); }; // Remove maintenance job const handleRemoveMaintenanceJob = (typeId: number) => { setMaintenanceJobs(maintenanceJobs.filter(job => job.typeId !== typeId)); }; return ( {visit ? "تعديل زيارة الصيانة" : "إضافة زيارة صيانة جديدة"}
{visit && ( )} {/* Plate Number Autocomplete - Only show for new visits */} {!visit && (
ابدأ بكتابة رقم اللوحة لاختيار المركبة والعميل تلقائياً
)}
{/* Customer Selection */}
{actionData?.errors?.customerId && ( {actionData.errors.customerId} )} {!visit && plateNumberInput && selectedCustomerId && ( تم اختيار العميل تلقائياً من رقم اللوحة )}
{/* Vehicle Selection */}
{actionData?.errors?.vehicleId && ( {actionData.errors.vehicleId} )} {!selectedCustomerId && !plateNumberInput && ( يرجى اختيار العميل أولاً أو البحث برقم اللوحة )} {!visit && plateNumberInput && selectedVehicleId && ( تم اختيار المركبة تلقائياً من رقم اللوحة )}
{/* Maintenance Types Selection */}
{/* Add Maintenance Type Form */}
setCurrentCost(e.target.value)} placeholder="التكلفة" step="0.01" min="0" className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500" />
{/* List of Added Maintenance Types */} {maintenanceJobs.length > 0 && (
{maintenanceJobs.map((job) => (
{job.job}
{job.cost.toFixed(2)} {settings.currency}
))}
)} {maintenanceJobs.length === 0 && ( لم يتم إضافة أي نوع صيانة بعد )} {/* Hidden input to pass maintenance jobs data */} {actionData?.errors?.maintenanceJobs && ( {actionData.errors.maintenanceJobs} )}
{/* Payment Status */}