2022-11-11 16:17:49 +00:00
|
|
|
/**
|
|
|
|
* External dependencies
|
|
|
|
*/
|
|
|
|
import {
|
|
|
|
createContext,
|
|
|
|
useContext,
|
|
|
|
useCallback,
|
|
|
|
useState,
|
|
|
|
} from '@wordpress/element';
|
|
|
|
import { cleanForSlug } from '@wordpress/url';
|
|
|
|
import type { UniqueIdentifier } from '@dnd-kit/core';
|
|
|
|
import apiFetch from '@wordpress/api-fetch';
|
|
|
|
import { dispatch } from '@wordpress/data';
|
|
|
|
import { __ } from '@wordpress/i18n';
|
2023-04-28 10:29:45 +00:00
|
|
|
import fastDeepEqual from 'fast-deep-equal/es6';
|
2022-11-11 16:17:49 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Internal dependencies
|
|
|
|
*/
|
|
|
|
import type {
|
|
|
|
SortablePickupLocation,
|
|
|
|
SettingsContextType,
|
|
|
|
ShippingMethodSettings,
|
|
|
|
} from './types';
|
|
|
|
import {
|
|
|
|
defaultSettings,
|
|
|
|
getInitialSettings,
|
2022-12-07 15:52:02 +00:00
|
|
|
defaultReadyOnlySettings,
|
|
|
|
readOnlySettings,
|
2022-11-11 16:17:49 +00:00
|
|
|
getInitialPickupLocations,
|
|
|
|
} from './utils';
|
|
|
|
|
|
|
|
const SettingsContext = createContext< SettingsContextType >( {
|
|
|
|
settings: defaultSettings,
|
2022-12-07 15:52:02 +00:00
|
|
|
readOnlySettings: defaultReadyOnlySettings,
|
2022-11-11 16:17:49 +00:00
|
|
|
setSettingField: () => () => void null,
|
|
|
|
pickupLocations: [],
|
|
|
|
setPickupLocations: () => void null,
|
|
|
|
toggleLocation: () => void null,
|
|
|
|
updateLocation: () => void null,
|
|
|
|
isSaving: false,
|
|
|
|
save: () => void null,
|
2024-06-25 01:12:14 +00:00
|
|
|
isDirty: false,
|
2022-11-11 16:17:49 +00:00
|
|
|
} );
|
|
|
|
|
|
|
|
export const useSettingsContext = (): SettingsContextType => {
|
|
|
|
return useContext( SettingsContext );
|
|
|
|
};
|
|
|
|
|
|
|
|
export const SettingsProvider = ( {
|
|
|
|
children,
|
|
|
|
}: {
|
|
|
|
children: JSX.Element[] | JSX.Element;
|
|
|
|
} ): JSX.Element => {
|
|
|
|
const [ isSaving, setIsSaving ] = useState( false );
|
2024-06-25 01:12:14 +00:00
|
|
|
const [ isDirty, setIsDirty ] = useState( false );
|
2022-11-11 16:17:49 +00:00
|
|
|
const [ pickupLocations, setPickupLocations ] = useState<
|
|
|
|
SortablePickupLocation[]
|
|
|
|
>( getInitialPickupLocations );
|
|
|
|
const [ settings, setSettings ] =
|
|
|
|
useState< ShippingMethodSettings >( getInitialSettings );
|
|
|
|
|
|
|
|
const setSettingField = useCallback(
|
|
|
|
( field: keyof ShippingMethodSettings ) => ( newValue: unknown ) => {
|
2024-06-25 01:12:14 +00:00
|
|
|
setIsDirty( true );
|
2022-11-11 16:17:49 +00:00
|
|
|
setSettings( ( prevValue ) => ( {
|
|
|
|
...prevValue,
|
|
|
|
[ field ]: newValue,
|
|
|
|
} ) );
|
|
|
|
},
|
|
|
|
[]
|
|
|
|
);
|
|
|
|
|
|
|
|
const toggleLocation = useCallback( ( rowId: UniqueIdentifier ) => {
|
2024-06-25 01:12:14 +00:00
|
|
|
setIsDirty( true );
|
2022-11-11 16:17:49 +00:00
|
|
|
setPickupLocations( ( previousLocations: SortablePickupLocation[] ) => {
|
|
|
|
const locationIndex = previousLocations.findIndex(
|
|
|
|
( { id } ) => id === rowId
|
|
|
|
);
|
|
|
|
const updated = [ ...previousLocations ];
|
|
|
|
updated[ locationIndex ].enabled =
|
|
|
|
! previousLocations[ locationIndex ].enabled;
|
|
|
|
return updated;
|
|
|
|
} );
|
|
|
|
}, [] );
|
|
|
|
|
|
|
|
const updateLocation = (
|
|
|
|
rowId: UniqueIdentifier | 'new',
|
|
|
|
locationData: SortablePickupLocation
|
|
|
|
) => {
|
|
|
|
setPickupLocations( ( prevData ) => {
|
2024-06-25 01:12:14 +00:00
|
|
|
setIsDirty( true );
|
2022-11-11 16:17:49 +00:00
|
|
|
if ( rowId === 'new' ) {
|
|
|
|
return [
|
|
|
|
...prevData,
|
|
|
|
{
|
|
|
|
...locationData,
|
|
|
|
id:
|
|
|
|
cleanForSlug( locationData.name ) +
|
|
|
|
'-' +
|
|
|
|
prevData.length,
|
|
|
|
},
|
|
|
|
];
|
|
|
|
}
|
|
|
|
return prevData
|
|
|
|
.map( ( location ): SortablePickupLocation => {
|
|
|
|
if ( location.id === rowId ) {
|
|
|
|
return locationData;
|
|
|
|
}
|
|
|
|
return location;
|
|
|
|
} )
|
|
|
|
.filter( Boolean );
|
|
|
|
} );
|
|
|
|
};
|
|
|
|
|
|
|
|
const save = useCallback( () => {
|
|
|
|
const data = {
|
|
|
|
pickup_location_settings: {
|
|
|
|
enabled: settings.enabled ? 'yes' : 'no',
|
|
|
|
title: settings.title,
|
|
|
|
tax_status: [ 'taxable', 'none' ].includes(
|
|
|
|
settings.tax_status
|
|
|
|
)
|
|
|
|
? settings.tax_status
|
|
|
|
: 'taxable',
|
|
|
|
cost: settings.cost,
|
|
|
|
},
|
|
|
|
pickup_locations: pickupLocations.map( ( location ) => ( {
|
|
|
|
name: location.name,
|
|
|
|
address: location.address,
|
|
|
|
details: location.details,
|
|
|
|
enabled: location.enabled,
|
|
|
|
} ) ),
|
|
|
|
};
|
|
|
|
|
|
|
|
setIsSaving( true );
|
2024-06-25 01:12:14 +00:00
|
|
|
setIsDirty( false );
|
2022-11-11 16:17:49 +00:00
|
|
|
|
|
|
|
// @todo This should be improved to include error handling in case of API failure, or invalid data being sent that
|
|
|
|
// does not match the schema. This would fail silently on the API side.
|
|
|
|
apiFetch( {
|
|
|
|
path: '/wp/v2/settings',
|
|
|
|
method: 'POST',
|
|
|
|
data,
|
|
|
|
} ).then( ( response ) => {
|
|
|
|
setIsSaving( false );
|
|
|
|
if (
|
2023-04-28 10:29:45 +00:00
|
|
|
fastDeepEqual(
|
2022-11-11 16:17:49 +00:00
|
|
|
response.pickup_location_settings,
|
|
|
|
data.pickup_location_settings
|
|
|
|
) &&
|
2023-04-28 10:29:45 +00:00
|
|
|
fastDeepEqual(
|
|
|
|
response.pickup_locations,
|
|
|
|
data.pickup_locations
|
|
|
|
)
|
2022-11-11 16:17:49 +00:00
|
|
|
) {
|
|
|
|
dispatch( 'core/notices' ).createSuccessNotice(
|
|
|
|
__(
|
|
|
|
'Local Pickup settings have been saved.',
|
2023-12-12 22:12:36 +00:00
|
|
|
'woocommerce'
|
2022-11-11 16:17:49 +00:00
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
}, [ settings, pickupLocations ] );
|
|
|
|
|
|
|
|
const settingsData = {
|
|
|
|
settings,
|
|
|
|
setSettingField,
|
2022-12-07 15:52:02 +00:00
|
|
|
readOnlySettings,
|
2022-11-11 16:17:49 +00:00
|
|
|
pickupLocations,
|
|
|
|
setPickupLocations,
|
|
|
|
toggleLocation,
|
|
|
|
updateLocation,
|
|
|
|
isSaving,
|
|
|
|
save,
|
2024-06-25 01:12:14 +00:00
|
|
|
isDirty,
|
2022-11-11 16:17:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
return (
|
|
|
|
<SettingsContext.Provider value={ settingsData }>
|
|
|
|
{ children }
|
|
|
|
</SettingsContext.Provider>
|
|
|
|
);
|
|
|
|
};
|