"use client"; import { useCallback, useState } from "react"; import { Spinner, Alert, ArchiveButton } from "@/src/Components/UI"; import { CarFormModal } from "@/src/Components/car/CarFormModal"; import { CarDetailPanel } from "@/src/Components/car/CarDetailPanel"; import { CarDeleteModal } from "@/src/Components/car/CarDeleteModal"; import { ArchivedCarsModal } from "@/src/Components/car/archive/Archivedcarsmodal"; import { useCars, useCarMutations, useToast } from "@/src/hooks/useCars"; import { fmtDateShort, isExpiringSoon, STATUS_MAP, INS_MAP } from "@/src/types/car"; import type { Car, CreateCarPayload, ToastMsg, UpdateCarPayload } from "@/src/types/car"; // ── Toast ───────────────────────────────────────────────────────────────────── function CarToast({ notification }: { notification: ToastMsg | null }) { if (!notification) return null; const ok = notification.type === "success"; return (
{ok ? "✓" : "⚠"} {notification.message}
); } // ── CarCard ─────────────────────────────────────────────────────────────────── function CarCard({ car, onClick }: { car: Car; onClick: () => void }) { const status = STATUS_MAP[car.currentStatus]; const ins = car.insuranceStatus ? INS_MAP[car.insuranceStatus] : null; const regWarn = isExpiringSoon(car.registrationExpiryDate); return (
{ if (e.key === "Enter" || e.key === " ") onClick(); }} aria-label={`${car.manufacturer} ${car.model} — ${car.plateLetters} ${car.plateNumber}`} style={{ borderRadius: "var(--radius-xl)", border: "1px solid var(--color-border)", background: "var(--color-surface)", overflow: "hidden", boxShadow: "var(--shadow-card)", cursor: "pointer", transition: "box-shadow 200ms, transform 200ms", }} onMouseEnter={e => { (e.currentTarget as HTMLElement).style.boxShadow = "0 8px 24px rgba(37,99,235,.12)"; (e.currentTarget as HTMLElement).style.transform = "translateY(-2px)"; }} onMouseLeave={e => { (e.currentTarget as HTMLElement).style.boxShadow = "var(--shadow-card)"; (e.currentTarget as HTMLElement).style.transform = "translateY(0)"; }} > {/* Colour accent bar by status */}
{/* Manufacturer + model */}

{car.manufacturer} {car.model}

{car.year}{car.color ? ` · ${car.color}` : ""}

{/* Status badge */} {status.label}
{/* Plate number */}
رقم اللوحة {car.plateLetters} {car.plateNumber}
{/* Key attributes grid */}
الفرع {car.branch?.name ?? "—"}
التأمين {ins?.label ?? "—"}
انتهاء الاستمارة {regWarn && "⚠ "}{fmtDateShort(car.registrationExpiryDate)}
الطاقة {car.capacity != null ? car.capacity : "—"}
{/* Footer CTA hint */}

اضغط لعرض التفاصيل ←

); } // ── Page ────────────────────────────────────────────────────────────────────── export default function CarsPage() { const [search, setSearch] = useState(""); const [page, setPage] = useState(1); // Modal state const [detailId, setDetailId] = useState(null); const [formTarget, setFormTarget] = useState(false); // false = closed const [deleteTarget, setDeleteTarget] = useState(null); const [archiveOpen, setArchiveOpen] = useState(false); const { toast, notify } = useToast(); const { cars, loading, error, total, pages, loadCars, removeCar, setError } = useCars(page, search); // Need a stable ref to the current edit target for the mutation hook const getEditTarget = useCallback(() => formTarget instanceof Object && formTarget !== null ? formTarget as Car : null, [formTarget]); const { deleting, handleFormSubmit, handleDeleteConfirm } = useCarMutations({ onSuccess: (msg) => { notify({ type: "success", message: msg }); loadCars(); }, onError: (msg) => notify({ type: "error", message: msg }), onDeleted: (id) => { removeCar(id); setDeleteTarget(null); }, getEditTarget, }); const handleDelete = async () => { if (!deleteTarget) return; await handleDeleteConfirm(deleteTarget); }; // ── Render ────────────────────────────────────────────────────────────────── return ( <> {detailId && ( setDetailId(null)} onEdit={(car) => { setDetailId(null); setFormTarget(car); }} onDelete={(car) => { setDetailId(null); setDeleteTarget(car); }} /> )} {formTarget !== false && ( setFormTarget(false)} onSubmit={(payload: CreateCarPayload | UpdateCarPayload, isNew: boolean) => handleFormSubmit(payload, isNew).then((ok) => { if (ok) setFormTarget(false); return ok; }) } /> )} {deleteTarget && ( setDeleteTarget(null)} onConfirm={handleDelete} /> )} {archiveOpen && ( setArchiveOpen(false)} /> )}
{/* ── Header ── */}

إدارة الأسطول

المركبات

إجمالي {total} مركبة في الأسطول

{/* Search */}
{ setSearch(e.target.value); setPage(1); }} dir="rtl" style={{ width: "100%", height: 40, paddingRight: 36, paddingLeft: 12, borderRadius: "var(--radius-lg)", border: "1px solid var(--color-border)", background: "var(--color-surface)", fontSize: 13, color: "var(--color-text-primary)", outline: "none", fontFamily: "var(--font-sans)", }} />
{/* Add button */}
{/* Error alert */} {error && setError(null)} />} {/* ── Loading ── */} {loading ? (
جارٍ تحميل المركبات…
) : cars.length === 0 ? (
🚗

{search ? `لا توجد مركبات تطابق "${search}"` : "لا توجد مركبات بعد"}

اضغط على "إضافة مركبة" لإضافة أول مركبة في الأسطول.

{!search && ( )}
) : ( /* ── Card grid ── */
{cars.map((car) => ( setDetailId(car.id)} /> ))}
)} {/* ── Pagination ── */} {pages > 1 && (
صفحة {page} من{" "} {pages} {" · "} {total} مركبة
{[ { label: "← السابق", action: () => setPage(p => Math.max(1, p - 1)), disabled: page === 1 }, { label: "التالي →", action: () => setPage(p => Math.min(pages, p + 1)), disabled: page === pages }, ].map((btn) => ( ))}
)}
{/* Floating button to open the archive browser */} setArchiveOpen(true)} /> ); }