import React, { useCallback, useEffect, useRef, useState } from 'react'; import { useAppDispatch, useAppSelector } from '@akinon/next/redux/hooks'; import { setCurrentStep, setSelectedShippingOptions } from '@akinon/next/redux/reducers/checkout'; import { RootState } from '@theme/redux/store'; import { useSetShippingOptionMutation, useSetAttributeBasedShippingOptionsMutation, useSetDataSourceShippingOptionsMutation } from '@akinon/next/data/client/checkout'; import { Price, Button, Radio } from '@theme/components'; import { partAttrs } from '@akinon/pz-theme/src/utils/part-styles'; import { CheckoutStep } from '@akinon/next/types'; import { useLocalization } from '@akinon/next/hooks'; const ShippingOptions: React.FC = () => { const { t } = useLocalization(); const dispatch = useAppDispatch(); const { steps, shippingOptions, attributeBasedShippingOptions, dataSourceShippingOptions, preOrder, addressList, selectedShippingOptions } = useAppSelector((state: RootState) => state.checkout); const { shipping_option, shipping_address, attribute_based_shipping_options, data_source_shipping_options } = preOrder ?? {}; const [setShippingOption] = useSetShippingOptionMutation(); const [setAttributeBasedShippingOptions] = useSetAttributeBasedShippingOptionsMutation(); const [setDataSourceShippingOption] = useSetDataSourceShippingOptionsMutation(); const prevAttributeBasedOptionsRef = useRef(attributeBasedShippingOptions); const [selectedPks, setSelectedPks] = useState< { dataSourcePk: number; optionPk: number }[] | null >(null); const initializeSelectedOptions = useCallback(() => { if (attribute_based_shipping_options) { const newSelected = { ...selectedShippingOptions }; let hasChanges = false; Object.entries(attributeBasedShippingOptions).forEach( ([color, options]) => { if ( !newSelected[color] || !options.some((opt) => opt.pk === newSelected[color]) ) { newSelected[color] = options[0].pk; hasChanges = true; } } ); if (hasChanges) { dispatch(setSelectedShippingOptions(newSelected)); setAttributeBasedShippingOptions(newSelected); } } else if (shippingOptions.length > 0 && !shipping_option) { setShippingOption(shippingOptions[0].pk); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [ attributeBasedShippingOptions, selectedShippingOptions, setAttributeBasedShippingOptions, attribute_based_shipping_options, shippingOptions, shipping_option, setShippingOption ]); useEffect(() => { if (!data_source_shipping_options) return; const initialSelectedPks = data_source_shipping_options.map((option) => ({ dataSourcePk: option.data_source.pk, optionPk: option.pk })); setSelectedPks(initialSelectedPks); }, [data_source_shipping_options]); useEffect(() => { if ( JSON.stringify(prevAttributeBasedOptionsRef.current) !== JSON.stringify(attributeBasedShippingOptions) || Object.keys(selectedShippingOptions).length === 0 || (!shipping_option && shippingOptions.length > 0) ) { initializeSelectedOptions(); prevAttributeBasedOptionsRef.current = attributeBasedShippingOptions; } }, [ attributeBasedShippingOptions, selectedShippingOptions, initializeSelectedOptions, shipping_option, shippingOptions ]); const handleAttributeBasedOptionChange = useCallback( (color: string, newPk: number) => { const updatedOptions = { ...selectedShippingOptions, [color]: newPk }; dispatch(setSelectedShippingOptions(updatedOptions)); setAttributeBasedShippingOptions(updatedOptions); }, // eslint-disable-next-line react-hooks/exhaustive-deps [selectedShippingOptions, setAttributeBasedShippingOptions] ); if (addressList.length < 1) { return (

{t('checkout.address.shipping.title')}

{t('checkout.address.shipping.select_address_to_continue')}

); } const updateData = (dataSourcePk: number, newPk: number) => { const updatedSelectedPks = selectedPks?.map((item) => item.dataSourcePk === dataSourcePk ? { ...item, optionPk: newPk } : item ); if (!updatedSelectedPks) return; setSelectedPks(updatedSelectedPks); const pks = updatedSelectedPks.map((item) => item.optionPk); setDataSourceShippingOption(pks); }; const handleRadioChange = ( e: React.ChangeEvent, dataSourcePk: number ) => { const newPk = parseInt(e.currentTarget.value); updateData(dataSourcePk, newPk); }; return (

{t('checkout.address.shipping.title')}

{addressList.length < 1 ? (

{t('checkout.address.shipping.select_address_to_continue')}

) : (

{t('checkout.address.shipping.chosen_address')}:{' '} {shipping_address?.city.name}

{shippingOptions && shippingOptions.length > 0 && ( <> {shippingOptions.map((option) => (
{ setShippingOption(option.pk); }} onClick={() => { setShippingOption(option?.pk); }} data-testid={`checkout-shipping-option-${option.pk}`} > {option.name}
))} )} {attributeBasedShippingOptions && Object.keys(attributeBasedShippingOptions).length > 0 && Object.entries(attributeBasedShippingOptions).map( ([color, options]) => (

{color}

{options.map((option) => (
handleAttributeBasedOptionChange(color, option.pk) } data-testid={`checkout-attribute-based-shipping-${option.pk}`} > {`${option.shipping_option_name}`}
))}
) )} {dataSourceShippingOptions && dataSourceShippingOptions.length > 0 && dataSourceShippingOptions.map((option) => (

{option?.name}

{option.data_source_shipping_options.map((opt) => (
item.optionPk === opt.pk) || false } onChange={(e: React.ChangeEvent) => handleRadioChange(e, option.pk) } value={opt.pk} data-testid={`checkout-data-source-shipping-${opt.pk}`} > {opt?.shipping_option_name}
))}
))}
)}
); }; export default ShippingOptions;