"use client"; import { useCallback, useEffect, useState } from "react"; import { getStoredToken } from "../../lib/auth"; import { carService } from "../../services/car.service"; import { get } from "../../services/api"; import { Spinner, Alert } from "../../Components/UI"; import { CarFormModal } from "../../Components/car/CarFormModal"; import { CarDetailPanel } from "../../Components/car/CarDetailPanel"; import { CarDeleteModal } from "../../Components/car/CarDeleteModal"; import type { Car, CreateCarPayload, UpdateCarPayload } from "../../types/car"; // ── API response shape ──────────────────────────────────────────────────────── interface ApiResponse { data: { data: Car[]; pagination: { total: number; page: number; pages: number }; meta?: { total: number; pages: number }; }; } // ── Status badge config ─────────────────────────────────────────────────────── const STATUS_MAP: Record< Car["currentStatus"], { label: string; color: string; bg: string; border: string; dot: string } > = { Active: { label: "نشط", color: "#166534", bg: "#DCFCE7", border: "#BBF7D0", dot: "#16A34A" }, InMaintenance: { label: "صيانة", color: "#854D0E", bg: "#FFFBEB", border: "#FDE68A", dot: "#D97706" }, InTrip: { label: "في رحلة", color: "#1E40AF", bg: "#EFF6FF", border: "#BFDBFE", dot: "#3B82F6" }, Inactive: { label: "غير نشط", color: "#64748B", bg: "#F1F5F9", border: "#E2E8F0", dot: "#94A3B8" }, }; const INS_MAP: Record = { Valid: { label: "سارٍ", color: "#16A34A" }, Expired: { label: "منتهي", color: "#DC2626" }, NotInsured: { label: "غير مؤمَّن", color: "#D97706" }, }; function fmtDate(iso?: string) { if (!iso) return "—"; return new Date(iso).toLocaleDateString("ar-SA", { year: "numeric", month: "short", day: "numeric" }); } function isExpiringSoon(iso?: string) { if (!iso) return false; return (new Date(iso).getTime() - Date.now()) / 86_400_000 <= 90; } // ── Toast (inline — mirrors Components/User/Toast pattern) ─────────────────── interface ToastMsg { type: "success" | "error"; message: string } function CarToast({ notification }: { notification: ToastMsg | null }) { const [vis, setVis] = useState(false); useEffect(() => { if (notification) setVis(true); else { const t = setTimeout(() => setVis(false), 300); return () => clearTimeout(t); } }, [notification]); if (!vis && !notification) return null; const ok = notification?.type === "success"; return (
{ok ? "✓" : "⚠"} {notification?.message}
); } // ── Vehicle Card component ──────────────────────────────────────────────────── 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 as string | undefined); 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 — prominent */}
رقم اللوحة {car.plateLetters} {car.plateNumber}
{/* Key attributes grid */}
{/* Branch */}
الفرع {car.branch?.name ?? "—"}
{/* Insurance */}
التأمين {ins?.label ?? "—"}
{/* Registration expiry */}
انتهاء الاستمارة {regWarn && "⚠ "}{fmtDate(car.registrationExpiryDate as string | undefined)}
{/* Capacity */}
الطاقة {car.capacity != null ? car.capacity : "—"}
{/* Footer CTA hint */}

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

); } // ── Page ────────────────────────────────────────────────────────────────────── export default function CarsPage() { // List state const [cars, setCars] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [search, setSearch] = useState(""); const [page, setPage] = useState(1); const [total, setTotal] = useState(0); const [pages, setPages] = useState(1); // Modal state const [detailId, setDetailId] = useState(null); // CarDetailPanel const [formTarget, setFormTarget] = useState(false); // false=closed const [deleteTarget, setDeleteTarget] = useState(null); const [deleting, setDeleting] = useState(false); // Toast const [toast, setToast] = useState<{ type: "success" | "error"; message: string } | null>(null); const notify = useCallback((t: typeof toast) => { setToast(t); setTimeout(() => setToast(null), 3500); }, []); // ── Fetch list ───────────────────────────────────────────────────────────── const loadCars = useCallback(() => { const token = getStoredToken(); setLoading(true); setError(null); const query = `?page=${page}&limit=12${search ? `&search=${encodeURIComponent(search)}` : ""}`; get(`cars${query}`, token) .then((res) => { const payload = (res as unknown as { data: ApiResponse["data"] }).data ?? res; setCars((payload as ApiResponse["data"]).data ?? []); setTotal((payload as ApiResponse["data"]).meta?.total ?? 0); setPages((payload as ApiResponse["data"]).meta?.pages ?? 1); }) .catch((err: Error) => setError(err.message)) .finally(() => setLoading(false)); }, [page, search]); useEffect(() => { loadCars(); }, [loadCars]); // ── Create / Update ──────────────────────────────────────────────────────── const handleFormSubmit = async ( payload: CreateCarPayload | UpdateCarPayload, isNew: boolean, ): Promise => { const token = getStoredToken(); try { if (isNew) { await carService.create(payload as CreateCarPayload, token); notify({ type: "success", message: "تم إضافة المركبة بنجاح." }); } else { await carService.update((formTarget as Car).id, payload as UpdateCarPayload, token); notify({ type: "success", message: "تم تحديث بيانات المركبة." }); } loadCars(); return true; } catch (err: unknown) { notify({ type: "error", message: err instanceof Error ? err.message : "فشلت العملية." }); return false; } }; // ── Delete ───────────────────────────────────────────────────────────────── const handleDeleteConfirm = async () => { if (!deleteTarget) return; setDeleting(true); const token = getStoredToken(); try { await carService.delete(deleteTarget.id, token); // Optimistic removal — no page refresh needed setCars(prev => prev.filter(c => c.id !== deleteTarget.id)); setTotal(prev => Math.max(0, prev - 1)); setDeleteTarget(null); notify({ type: "success", message: `تم حذف ${deleteTarget.manufacturer} ${deleteTarget.model} بنجاح.` }); } catch (err: unknown) { notify({ type: "error", message: err instanceof Error ? err.message : "فشل الحذف." }); } finally { setDeleting(false); } }; // ── Render ───────────────────────────────────────────────────────────────── return ( <> {/* Toast notification */} {/* Detail panel (slide-in) */} {detailId && ( setDetailId(null)} onEdit={(car) => { setDetailId(null); setFormTarget(car); }} onDelete={(car) => { setDetailId(null); setDeleteTarget(car); }} /> )} {/* Create / Edit modal */} {formTarget !== false && ( setFormTarget(false)} onSubmit={handleFormSubmit} /> )} {/* Delete confirmation */} {deleteTarget && ( setDeleteTarget(null)} onConfirm={handleDeleteConfirm} /> )}
{/* ── 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 ? ( /* Empty state */
🚗

{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) => ( ))}
)}
); }