/** * Hook: shipments list – fetches GET /shipments (orders with _p2g_ship_status = Fulfilled only). */ import { useEffect, useState, useCallback, useRef } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; import apiFetch from '@wordpress/api-fetch'; import type { Shipment, ShipmentsListResponse } from '../../../types'; import { getApiErrorMessage } from '../../../shared/utils'; import { captureException, addBreadcrumb } from '../../../shared/sentry'; export interface UseShipmentsReturn { shipments: Shipment[]; total: number; page: number; loading: boolean; error: string | null; fetchShipments: (pageToFetch?: number) => Promise; setPage: (page: number) => void; } export function useShipments(rowsPerPage: number): UseShipmentsReturn { const [shipments, setShipments] = useState([]); const [total, setTotal] = useState(0); const [page, setPage] = useState(1); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const isMountedRef = useRef(true); const fetchShipments = useCallback( async (pageToFetch: number = 1) => { try { setLoading(true); setError(null); const params = new URLSearchParams({ page: String(pageToFetch), per_page: String(rowsPerPage), }); const json = (await apiFetch({ path: `/parcel2go-shipping/v1/shipments?${params.toString()}`, })) as ShipmentsListResponse; const list: Shipment[] = json?.shipments ?? []; if (isMountedRef.current) { const filteredList = list.filter(shipment => shipment.p2g.orderId !== '').sort((a, b) => new Date(b.p2g.bookedAt).getTime() - new Date(a.p2g.bookedAt).getTime()); setShipments(filteredList); setTotal(filteredList.length); setPage(pageToFetch); } } catch (e: unknown) { captureException(e instanceof Error ? e : new Error(String(e))); addBreadcrumb('Shipments fetch failed', {}, 'api'); if (isMountedRef.current) setError( getApiErrorMessage( e, __( 'Failed to load shipments.', 'parcel2go-shipping', ), ), ); } finally { if (isMountedRef.current) { setLoading(false); } } }, [rowsPerPage], ); useEffect(() => { isMountedRef.current = true; fetchShipments(); return () => { isMountedRef.current = false; }; }, [fetchShipments]); return { shipments, total, page, loading, error, fetchShipments, setPage }; }