/** * Hook: orders list fetching & pagination state. * Store (origin) comes from shipping in the API response. */ import { useEffect, useState, useCallback, useRef } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; import apiFetch from '@wordpress/api-fetch'; import type { Order, OrdersListResponse } from '../../../types'; import { getApiErrorMessage } from '../../../shared/utils'; import { captureException, addBreadcrumb, withSpan } from '../../../shared/sentry'; export interface UseOrdersReturn { orders: Order[]; total: number; page: number; loading: boolean; error: string | null; fetchOrders: (pageToFetch?: number) => Promise; setPage: (page: number) => void; } export function useOrders(rowsPerPage: number): UseOrdersReturn { const [orders, setOrders] = 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 fetchOrders = useCallback( async (pageToFetch: number = 1) => { try { setLoading(true); setError(null); const params = new URLSearchParams({ page: String(pageToFetch), per_page: String(rowsPerPage), }); const json = (await withSpan( 'orders.list', 'http.client', async () => apiFetch({ path: `/parcel2go-shipping/v1/orders?${params.toString()}`, }) as Promise )) as OrdersListResponse; if (isMountedRef.current) { setOrders(json?.orders ?? []); setTotal(json?.total ?? 0); setPage(pageToFetch); } } catch (e: unknown) { captureException(e instanceof Error ? e : new Error(String(e))); addBreadcrumb('Orders fetch failed', {}, 'api'); if (isMountedRef.current) setError( getApiErrorMessage( e, __('Failed to load orders.', 'parcel2go-shipping') ) ); } finally { if (isMountedRef.current) setLoading(false); } }, [rowsPerPage], ); useEffect(() => { isMountedRef.current = true; fetchOrders(); return () => { isMountedRef.current = false; }; }, [fetchOrders]); return { orders, total, page, loading, error, fetchOrders, setPage }; }