add archive layout pages to user car driver trip order

This commit is contained in:
m7amedez5511
2026-06-30 17:35:18 +03:00
parent f5882f3791
commit c33778012a
33 changed files with 2669 additions and 30 deletions

View File

@@ -0,0 +1,65 @@
"use client";
import { useEffect, useMemo, useState } from "react";
import { getStoredToken } from "@/src/lib/auth";
import { carService } from "@/src/services/car.service";
import type { Car } from "@/src/types/car";
const PAGE_SIZE = 12;
// ── useArchivedCars ───────────────────────────────────────────────────────────
// GET /cars/archived returns the full archived list at once (no page/search
// params on the backend), so pagination + search are done client-side here —
// mirrors the page/search/pages contract of useCars for a consistent UI.
export function useArchivedCars() {
const [allCars, setAllCars] = useState<Car[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const [page, setPage] = useState(1);
const [search, setSearch] = useState("");
const load = () => {
const token = getStoredToken();
setLoading(true);
setError(null);
carService
.getArchived(token)
.then((res) => {
const payload = (res as unknown as { data: { data: Car[] } }).data ?? res;
setAllCars((payload as { data: Car[] }).data ?? []);
})
.catch((err: Error) => setError(err.message))
.finally(() => setLoading(false));
};
useEffect(() => { load(); }, []);
const filtered = useMemo(() => {
if (!search.trim()) return allCars;
const q = search.trim().toLowerCase();
return allCars.filter(c =>
c.manufacturer.toLowerCase().includes(q) ||
c.model.toLowerCase().includes(q) ||
c.plateNumber.toLowerCase().includes(q) ||
c.plateLetters.toLowerCase().includes(q),
);
}, [allCars, search]);
const total = filtered.length;
const pages = Math.max(1, Math.ceil(total / PAGE_SIZE));
const cars = useMemo(
() => filtered.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE),
[filtered, page],
);
const handleSearch = (value: string) => {
setSearch(value);
setPage(1);
};
return {
cars, loading, error, total, pages, page, search,
setPage, handleSearch, refresh: load, setError,
};
}

View File

@@ -0,0 +1,49 @@
import { useCallback, useEffect, useState } from "react";
import { getStoredToken } from "@/src/lib/auth";
import { archivedDriverService } from "@/src/services/archive/archivedDriver.service";
import type { ArchivedDriver } from "@/src/types/driver";
/**
* Loads and paginates the archived drivers list, mirroring useArchivedUsers.
* Re-fetches whenever `page` or `search` changes.
*/
export function useArchivedDrivers() {
const [drivers, setDrivers] = useState<ArchivedDriver[]>([]);
const [loading, setLoading] = useState(true);
const [total, setTotal] = useState(0);
const [pages, setPages] = useState(1);
const [page, setPage] = useState(1);
const [search, setSearch] = useState("");
const [error, setError] = useState<string | null>(null);
/** Fetches the current page/search slice of archived drivers from the API. */
const load = useCallback(async () => {
setLoading(true);
try {
const token = getStoredToken();
const res = await archivedDriverService.getAll(page, search, token);
setDrivers(res.data.data);
setTotal(res.data.meta.total);
setPages(res.data.meta.totalPages);
setError(null);
} catch {
setError("تعذّر تحميل قائمة السائقين المؤرشفين. يرجى المحاولة لاحقاً.");
} finally {
setLoading(false);
}
}, [page, search]);
useEffect(() => { load(); }, [load]);
/** Updates the search term and resets to page 1. */
const handleSearch = (value: string) => {
setSearch(value);
setPage(1);
};
return {
drivers, loading, total, pages, page, search, error,
setPage, handleSearch, clearError: () => setError(null),
refresh: load,
};
}

View File

@@ -0,0 +1,58 @@
import { useCallback, useEffect, useMemo, useState } from "react";
import { getStoredToken } from "@/src/lib/auth";
import { archivedOrderService } from "@/src/services/archive/archivedOrder.service";
import type { ArchivedOrder } from "@/src/types/order";
const PAGE_SIZE = 10;
export function useArchivedOrders() {
const [orders, setOrders] = useState<ArchivedOrder[]>([]);
const [loading, setLoading] = useState(true);
const [page, setPage] = useState(1);
const [search, setSearch] = useState("");
const [error, setError] = useState<string | null>(null);
const load = useCallback(async () => {
setLoading(true);
try {
const token = getStoredToken();
const res = await archivedOrderService.getAll(token);
setOrders(res.data);
setError(null);
} catch {
setError("تعذّر تحميل الطلبات المؤرشفة. يرجى المحاولة لاحقاً.");
} finally {
setLoading(false);
}
}, []);
useEffect(() => { load(); }, [load]);
// Client-side search — endpoint has no `?search=` param in the sample payload
const filtered = useMemo(() => {
if (!search.trim()) return orders;
const q = search.trim().toLowerCase();
return orders.filter(
o =>
o.shipmentNumber.toLowerCase().includes(q) ||
o.recipientName.toLowerCase().includes(q) ||
o.recipientPhone.includes(q),
);
}, [orders, search]);
const pages = Math.max(1, Math.ceil(filtered.length / PAGE_SIZE));
const paginated = filtered.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE);
const handleSearch = (value: string) => {
setSearch(value);
setPage(1);
};
return {
orders: paginated,
total: filtered.length,
loading, pages, page, search, error,
setPage, handleSearch, clearError: () => setError(null),
refresh: load,
};
}

View File

@@ -0,0 +1,45 @@
import { useCallback, useEffect, useState } from "react";
import { getStoredToken } from "@/src/lib/auth";
import { archivedTripService } from "@/src/services/archive/archivedTrip.service";
import type { Trip } from "@/src/types/trip";
export function useArchivedTrips() {
const [trips, setTrips] = useState<Trip[]>([]);
const [loading, setLoading] = useState(true);
const [total, setTotal] = useState(0);
const [pages, setPages] = useState(1);
const [page, setPage] = useState(1);
const [search, setSearch] = useState("");
const [error, setError] = useState<string | null>(null);
// ── Load archived trips for the current page/search ───────────────────────
const load = useCallback(async () => {
setLoading(true);
try {
const token = getStoredToken();
const res = await archivedTripService.getAll(page, search, token);
setTrips(res.data.data);
setTotal(res.data.meta.total);
setPages(res.data.meta.totalPages);
setError(null);
} catch {
// Network/API failure — surface a friendly Arabic message, matching useArchivedUsers
setError("تعذّر تحميل قائمة الرحلات المؤرشفة. يرجى المحاولة لاحقاً.");
} finally {
setLoading(false);
}
}, [page, search]);
useEffect(() => { load(); }, [load]);
const handleSearch = (value: string) => {
setSearch(value);
setPage(1);
};
return {
trips, loading, total, pages, page, search, error,
setPage, handleSearch, clearError: () => setError(null),
refresh: load,
};
}

View File

@@ -0,0 +1,43 @@
import { useCallback, useEffect, useState } from "react";
import { getStoredToken } from "@/src/lib/auth";
import { archivedUserService } from "@/src/services/archive/archivedUser.service";
import type { ArchivedUser } from "@/src/types/user";
export function useArchivedUsers() {
const [users, setUsers] = useState<ArchivedUser[]>([]);
const [loading, setLoading] = useState(true);
const [total, setTotal] = useState(0);
const [pages, setPages] = useState(1);
const [page, setPage] = useState(1);
const [search, setSearch] = useState("");
const [error, setError] = useState<string | null>(null);
const load = useCallback(async () => {
setLoading(true);
try {
const token = getStoredToken();
const res = await archivedUserService.getAll(page, search, token);
setUsers(res.data.data);
setTotal(res.data.meta.total);
setPages(res.data.meta.totalPages);
setError(null);
} catch {
setError("تعذّر تحميل قائمة الأرشيف. يرجى المحاولة لاحقاً.");
} finally {
setLoading(false);
}
}, [page, search]);
useEffect(() => { load(); }, [load]);
const handleSearch = (value: string) => {
setSearch(value);
setPage(1);
};
return {
users, loading, total, pages, page, search, error,
setPage, handleSearch, clearError: () => setError(null),
refresh: load,
};
}