/** * Hook: create a P2G order via the checkout API. * * Provides two ways to create an order: * - createOrder(quote, extras, options) — builds the payload internally. * - createOrderFromPayload(payload) — accepts a pre-built (potentially enriched) payload. */ import { useState, useCallback } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; import apiFetch from '@wordpress/api-fetch'; import type { Quote, Order, CheckoutValidateRequest, CheckoutOrderResponse, CheckoutOrderResult, PluginSettings, } from '../../types'; import { orderToCheckoutValidatePayload, type OrderToCheckoutValidatePayloadOptions, } from '../../features/order-ship/utils/orderToCheckoutValidatePayload'; import { getApiErrorMessage } from '../utils'; import { captureException, addBreadcrumb, withSpan, captureMessage } from '../sentry'; export interface UseCheckoutOrderReturn { /** Build payload internally from quote/extras and POST to /checkout. */ createOrder: ( quote: Quote, extras: string[], options?: OrderToCheckoutValidatePayloadOptions, ) => Promise; /** POST a pre-built (and possibly enriched) payload to /checkout. */ createOrderFromPayload: ( payload: CheckoutValidateRequest, ) => Promise; orderResult: CheckoutOrderResult | null; orderError: string | null; isCreatingOrder: boolean; resetOrder: () => void; } export function useCheckoutOrder( order?: Order, settings?: PluginSettings, ): UseCheckoutOrderReturn { const [isCreatingOrder, setIsCreatingOrder] = useState(false); const [orderResult, setOrderResult] = useState(null); const [orderError, setOrderError] = useState(null); const postCheckout = useCallback( async ( payload: CheckoutValidateRequest, ): Promise => { setOrderError(null); setIsCreatingOrder(true); setOrderResult(null); try { const response = (await withSpan( 'Create checkout order', 'http.client', async () => apiFetch({ path: '/parcel2go-shipping/v1/checkout', method: 'POST', data: payload, }) as Promise, { payload: payload } )) as CheckoutOrderResponse; if (!response.success || !response.result) { const message = response.error?.issues[0].detail ?? __( 'Failed to create order. Please try again.', 'parcel2go-shipping', ); setOrderError(message); captureMessage('checkout_order_failed', 'warning', { payload: payload, response: response, }); return null; } setOrderResult(response.result); return response.result; } catch (err: unknown) { captureException(err instanceof Error ? err : new Error(String(err))); addBreadcrumb('Checkout order failed', {payload: payload}, 'api'); const message = getApiErrorMessage( err, __( 'Order creation failed. Please try again.', 'parcel2go-shipping', ), ); setOrderError(message); return null; } finally { setIsCreatingOrder(false); } }, [], ); const createOrder = useCallback( async ( quote: Quote, extras: string[], options?: OrderToCheckoutValidatePayloadOptions, ): Promise => { const payload = orderToCheckoutValidatePayload( order, settings, quote, extras, options, ); if (!payload) { setOrderError( __( 'Unable to build order request. Please check your addresses.', 'parcel2go-shipping', ), ); return null; } return postCheckout(payload); }, [order, settings, postCheckout], ); const createOrderFromPayload = useCallback( async ( payload: CheckoutValidateRequest, ): Promise => { return postCheckout(payload); }, [postCheckout], ); const resetOrder = useCallback(() => { setOrderResult(null); setOrderError(null); }, []); return { createOrder, createOrderFromPayload, orderResult, orderError, isCreatingOrder, resetOrder, }; }