@@ -246,6 +246,7 @@ export default function CheckoutPage() {
246246 const [ isPreparingCheckout , setIsPreparingCheckout ] = useState ( false ) ;
247247 const [ isFinalizingPayment , setIsFinalizingPayment ] = useState ( false ) ;
248248 const [ isOrderPaymentConfirmed , setIsOrderPaymentConfirmed ] = useState ( false ) ;
249+ const [ continueWithoutHelperSignals , setContinueWithoutHelperSignals ] = useState ( false ) ;
249250
250251 const hasCompletedCheckoutRef = useRef ( false ) ;
251252 const reservationIdsRef = useRef < string [ ] > ( [ ] ) ;
@@ -322,6 +323,13 @@ export default function CheckoutPage() {
322323 const hasReservationQueries = reservationOutcomeQueries . length > 0 ;
323324 const areReservationSignalsLoading = reservationOutcomeQueries . some ( ( query ) => query . isLoading ) ;
324325 const areReservationSignalsFetching = reservationOutcomeQueries . some ( ( query ) => query . isFetching ) ;
326+ const hasHelperSignalsError = isInventoryHealthError || Boolean ( reservationSignalsError ) ;
327+
328+ useEffect ( ( ) => {
329+ if ( ! hasHelperSignalsError ) {
330+ setContinueWithoutHelperSignals ( false ) ;
331+ }
332+ } , [ hasHelperSignalsError ] ) ;
325333
326334 const retryInventoryHealth = ( ) => {
327335 void refetchInventoryHealth ( ) ;
@@ -331,6 +339,18 @@ export default function CheckoutPage() {
331339 void Promise . allSettled ( reservationOutcomeQueries . map ( ( query ) => query . refetch ( ) ) ) ;
332340 } ;
333341
342+ const retryHelperSignals = ( ) => {
343+ if ( isInventoryHealthError ) {
344+ retryInventoryHealth ( ) ;
345+ }
346+
347+ if ( reservationSignalsError ) {
348+ retryReservationOutcomes ( ) ;
349+ }
350+
351+ setContinueWithoutHelperSignals ( false ) ;
352+ } ;
353+
334354 const updateShippingField = ( field : ShippingFieldKey , value : string ) => {
335355 setShippingData ( ( previous ) => ( { ...previous , [ field ] : value } ) ) ;
336356 setShippingFieldErrors ( ( previous ) => {
@@ -988,13 +1008,46 @@ export default function CheckoutPage() {
9881008 </ p >
9891009 ) : null }
9901010
1011+ { hasHelperSignalsError ? (
1012+ < div className = "space-y-2" role = "alert" aria-live = "assertive" >
1013+ < p className = "text-sm text-red-600 dark:text-red-400" >
1014+ Live inventory assistant signals are temporarily unavailable.
1015+ </ p >
1016+ < div className = "flex flex-wrap gap-2" >
1017+ < Button
1018+ type = "button"
1019+ variant = "outline"
1020+ size = "sm"
1021+ onClick = { retryHelperSignals }
1022+ disabled = { isInventoryHealthFetching || areReservationSignalsFetching }
1023+ >
1024+ Retry signal checks
1025+ </ Button >
1026+ < Button
1027+ type = "button"
1028+ variant = "ghost"
1029+ size = "sm"
1030+ onClick = { ( ) => setContinueWithoutHelperSignals ( true ) }
1031+ >
1032+ Continue without live signals
1033+ </ Button >
1034+ </ div >
1035+ </ div >
1036+ ) : null }
1037+
1038+ { continueWithoutHelperSignals ? (
1039+ < p className = "text-sm text-gray-700 dark:text-gray-300" role = "status" aria-live = "polite" >
1040+ Continuing without live assistant signals. Checkout remains available.
1041+ </ p >
1042+ ) : null }
1043+
9911044 { isInventoryHealthLoading ? (
9921045 < p className = "text-sm text-gray-600 dark:text-gray-400" role = "status" aria-live = "polite" >
9931046 Checking inventory health signals…
9941047 </ p >
9951048 ) : null }
9961049
997- { isInventoryHealthError ? (
1050+ { isInventoryHealthError && ! continueWithoutHelperSignals ? (
9981051 < div className = "space-y-2" role = "alert" aria-live = "assertive" >
9991052 < p className = "text-sm text-red-600 dark:text-red-400" >
10001053 Inventory health signals are temporarily unavailable. Retry to refresh current stock risk.
@@ -1013,7 +1066,7 @@ export default function CheckoutPage() {
10131066 </ div >
10141067 ) : null }
10151068
1016- { reservationSignalsError ? (
1069+ { reservationSignalsError && ! continueWithoutHelperSignals ? (
10171070 < div className = "space-y-2" role = "alert" aria-live = "assertive" >
10181071 < p className = "text-sm text-red-600 dark:text-red-400" >
10191072 Reservation outcomes are temporarily unavailable. Retry to confirm hold status before payment.
0 commit comments