316 lines
9.8 KiB
TypeScript
316 lines
9.8 KiB
TypeScript
import { ChannelShippingData } from "@dashboard/channels/utils";
|
|
import {
|
|
CountryFragment,
|
|
CreateShippingRateMutationVariables,
|
|
PostalCodeRuleInclusionTypeEnum,
|
|
ShippingMethodChannelListingUpdateMutationVariables,
|
|
ShippingMethodTypeEnum,
|
|
ShippingMethodTypeFragment,
|
|
ShippingPostalCodeRulesCreateInputRange,
|
|
UpdateShippingRateMutationVariables,
|
|
useCreateShippingRateMutation,
|
|
useDeleteShippingRateMutation,
|
|
useShippingMethodChannelListingUpdateMutation,
|
|
} from "@dashboard/graphql";
|
|
import useNavigator from "@dashboard/hooks/useNavigator";
|
|
import useNotifier from "@dashboard/hooks/useNotifier";
|
|
import { commonMessages } from "@dashboard/intl";
|
|
import { extractMutationErrors, getMutationState } from "@dashboard/misc";
|
|
import { getParsedDataForJsonStringField } from "@dashboard/utils/richText/misc";
|
|
import differenceBy from "lodash/differenceBy";
|
|
import { useIntl } from "react-intl";
|
|
|
|
import { ShippingZoneRateCommonFormData } from "./components/ShippingZoneRatesPage/types";
|
|
import { shippingRateEditUrl } from "./urls";
|
|
|
|
export const createChannelsChangeHandler = (
|
|
selectedChannels: ChannelShippingData[],
|
|
setSelectedChannels: (channels: ChannelShippingData[]) => void,
|
|
triggerChange: () => void,
|
|
) => (
|
|
channelId: string,
|
|
value: { maxValue: string; minValue: string; price: string },
|
|
) => {
|
|
const itemIndex = selectedChannels.findIndex(item => item.id === channelId);
|
|
const channel = selectedChannels[itemIndex];
|
|
setSelectedChannels([
|
|
...selectedChannels.slice(0, itemIndex),
|
|
{
|
|
...channel,
|
|
maxValue: value.maxValue,
|
|
minValue: value.minValue,
|
|
price: value.price,
|
|
},
|
|
...selectedChannels.slice(itemIndex + 1),
|
|
]);
|
|
triggerChange();
|
|
};
|
|
|
|
const getPostalCodeRulesToAdd = (
|
|
rules: ShippingMethodTypeFragment["postalCodeRules"],
|
|
) =>
|
|
rules
|
|
.filter(code => !code.id || code.id === "0")
|
|
.map(
|
|
code =>
|
|
({
|
|
end: code.end,
|
|
start: code.start,
|
|
} as ShippingPostalCodeRulesCreateInputRange),
|
|
);
|
|
|
|
export function getCreateShippingPriceRateVariables(
|
|
data: ShippingZoneRateCommonFormData,
|
|
id: string,
|
|
addPostalCodeRules: ShippingMethodTypeFragment["postalCodeRules"],
|
|
inclusionType: PostalCodeRuleInclusionTypeEnum,
|
|
): CreateShippingRateMutationVariables {
|
|
const parsedMinDays = parseInt(data.minDays, 10);
|
|
const parsedMaxDays = parseInt(data.maxDays, 10);
|
|
const postalCodeRules = getPostalCodeRulesToAdd(addPostalCodeRules);
|
|
return {
|
|
input: {
|
|
addPostalCodeRules: postalCodeRules,
|
|
inclusionType,
|
|
maximumDeliveryDays: parsedMaxDays,
|
|
minimumDeliveryDays: parsedMinDays,
|
|
name: data.name,
|
|
shippingZone: id,
|
|
type: ShippingMethodTypeEnum.PRICE,
|
|
description: getParsedDataForJsonStringField(data.description),
|
|
},
|
|
};
|
|
}
|
|
|
|
export function getCreateShippingWeightRateVariables(
|
|
data: ShippingZoneRateCommonFormData,
|
|
id: string,
|
|
addPostalCodeRules: ShippingMethodTypeFragment["postalCodeRules"],
|
|
inclusionType: PostalCodeRuleInclusionTypeEnum,
|
|
): CreateShippingRateMutationVariables {
|
|
const parsedMinValue = parseFloat(data.minValue);
|
|
const parsedMaxValue = parseFloat(data.maxValue);
|
|
const parsedMinDays = parseInt(data.minDays, 10);
|
|
const parsedMaxDays = parseInt(data.maxDays, 10);
|
|
const isWeightSet = data.orderValueRestricted;
|
|
const postalCodeRules = getPostalCodeRulesToAdd(addPostalCodeRules);
|
|
return {
|
|
input: {
|
|
addPostalCodeRules: postalCodeRules,
|
|
inclusionType,
|
|
maximumDeliveryDays: parsedMaxDays,
|
|
maximumOrderWeight: isWeightSet ? parsedMaxValue : null,
|
|
minimumDeliveryDays: parsedMinDays,
|
|
minimumOrderWeight: isWeightSet ? parsedMinValue : null,
|
|
name: data.name,
|
|
shippingZone: id,
|
|
type: ShippingMethodTypeEnum.WEIGHT,
|
|
description: getParsedDataForJsonStringField(data.description),
|
|
},
|
|
};
|
|
}
|
|
|
|
export function getUpdateShippingPriceRateVariables(
|
|
data: ShippingZoneRateCommonFormData,
|
|
id: string,
|
|
rateId: string,
|
|
addPostalCodeRules: ShippingMethodTypeFragment["postalCodeRules"],
|
|
deletePostalCodeRules: string[],
|
|
): UpdateShippingRateMutationVariables {
|
|
const parsedMinDays = parseInt(data.minDays, 10);
|
|
const parsedMaxDays = parseInt(data.maxDays, 10);
|
|
const postalCodeRules = getPostalCodeRulesToAdd(addPostalCodeRules);
|
|
return {
|
|
id: rateId,
|
|
input: {
|
|
addPostalCodeRules: postalCodeRules,
|
|
deletePostalCodeRules,
|
|
inclusionType:
|
|
addPostalCodeRules[0]?.inclusionType ||
|
|
PostalCodeRuleInclusionTypeEnum.EXCLUDE,
|
|
maximumDeliveryDays: parsedMaxDays,
|
|
minimumDeliveryDays: parsedMinDays,
|
|
name: data.name,
|
|
shippingZone: id,
|
|
type: ShippingMethodTypeEnum.PRICE,
|
|
description: getParsedDataForJsonStringField(data.description),
|
|
taxClass: data.taxClassId,
|
|
},
|
|
};
|
|
}
|
|
|
|
export function getUpdateShippingWeightRateVariables(
|
|
data: ShippingZoneRateCommonFormData,
|
|
id: string,
|
|
rateId: string,
|
|
addPostalCodeRules: ShippingMethodTypeFragment["postalCodeRules"],
|
|
deletePostalCodeRules: string[],
|
|
): UpdateShippingRateMutationVariables {
|
|
const parsedMinValue = parseFloat(data.minValue);
|
|
const parsedMaxValue = parseFloat(data.maxValue);
|
|
const parsedMinDays = parseInt(data.minDays, 10);
|
|
const parsedMaxDays = parseInt(data.maxDays, 10);
|
|
const isWeightSet = data.orderValueRestricted;
|
|
const postalCodeRules = getPostalCodeRulesToAdd(addPostalCodeRules);
|
|
return {
|
|
id: rateId,
|
|
input: {
|
|
addPostalCodeRules: postalCodeRules,
|
|
deletePostalCodeRules,
|
|
inclusionType:
|
|
addPostalCodeRules[0]?.inclusionType ||
|
|
PostalCodeRuleInclusionTypeEnum.EXCLUDE,
|
|
maximumDeliveryDays: parsedMaxDays,
|
|
maximumOrderWeight: isWeightSet ? parsedMaxValue : null,
|
|
minimumDeliveryDays: parsedMinDays,
|
|
minimumOrderWeight: isWeightSet ? parsedMinValue : null,
|
|
name: data.name,
|
|
shippingZone: id,
|
|
type: ShippingMethodTypeEnum.WEIGHT,
|
|
description: getParsedDataForJsonStringField(data.description),
|
|
taxClass: data.taxClassId,
|
|
},
|
|
};
|
|
}
|
|
export function getShippingMethodChannelVariables(
|
|
id: string,
|
|
orderValueRestricted: boolean,
|
|
formChannels: ChannelShippingData[],
|
|
prevChannels?: ChannelShippingData[],
|
|
): ShippingMethodChannelListingUpdateMutationVariables {
|
|
const removeChannels = prevChannels
|
|
? differenceBy(prevChannels, formChannels, "id").map(({ id }) => id)
|
|
: [];
|
|
|
|
return {
|
|
id,
|
|
input: {
|
|
addChannels:
|
|
formChannels?.map(channel => ({
|
|
channelId: channel.id,
|
|
maximumOrderPrice:
|
|
channel.maxValue && orderValueRestricted ? channel.maxValue : null,
|
|
minimumOrderPrice:
|
|
channel.minValue && orderValueRestricted ? channel.minValue : null,
|
|
price: channel.price,
|
|
})) || [],
|
|
removeChannels,
|
|
},
|
|
};
|
|
}
|
|
|
|
export function useShippingRateCreator(
|
|
shippingZoneId: string,
|
|
type: ShippingMethodTypeEnum,
|
|
postalCodes: ShippingMethodTypeFragment["postalCodeRules"],
|
|
inclusionType: PostalCodeRuleInclusionTypeEnum,
|
|
) {
|
|
const intl = useIntl();
|
|
const notify = useNotifier();
|
|
const navigate = useNavigator();
|
|
const [
|
|
createBaseShippingRate,
|
|
createBaseShippingRateOpts,
|
|
] = useCreateShippingRateMutation({});
|
|
const [
|
|
updateShippingMethodChannelListing,
|
|
updateShippingMethodChannelListingOpts,
|
|
] = useShippingMethodChannelListingUpdateMutation({});
|
|
const [deleteShippingRate] = useDeleteShippingRateMutation({});
|
|
|
|
const getVariables =
|
|
type === ShippingMethodTypeEnum.PRICE
|
|
? getCreateShippingPriceRateVariables
|
|
: getCreateShippingWeightRateVariables;
|
|
|
|
const createShippingRate = async (data: ShippingZoneRateCommonFormData) => {
|
|
const response = await createBaseShippingRate({
|
|
variables: getVariables(data, shippingZoneId, postalCodes, inclusionType),
|
|
});
|
|
|
|
const createErrors = response.data.shippingPriceCreate.errors;
|
|
|
|
if (createErrors.length > 0) {
|
|
return createErrors;
|
|
}
|
|
|
|
const rateId = response.data.shippingPriceCreate.shippingMethod.id;
|
|
|
|
const errors = await extractMutationErrors(
|
|
updateShippingMethodChannelListing({
|
|
variables: getShippingMethodChannelVariables(
|
|
rateId,
|
|
data.orderValueRestricted,
|
|
data.channelListings,
|
|
),
|
|
}),
|
|
);
|
|
|
|
if (errors.length > 0) {
|
|
deleteShippingRate({
|
|
variables: {
|
|
id: rateId,
|
|
},
|
|
});
|
|
|
|
notify({
|
|
status: "error",
|
|
text: intl.formatMessage(commonMessages.somethingWentWrong),
|
|
});
|
|
|
|
return errors;
|
|
} else {
|
|
notify({
|
|
status: "success",
|
|
text: intl.formatMessage(commonMessages.savedChanges),
|
|
});
|
|
navigate(shippingRateEditUrl(shippingZoneId, rateId));
|
|
return [];
|
|
}
|
|
};
|
|
|
|
const called =
|
|
createBaseShippingRateOpts.called ||
|
|
updateShippingMethodChannelListingOpts.called;
|
|
const loading =
|
|
createBaseShippingRateOpts.loading ||
|
|
updateShippingMethodChannelListingOpts.loading;
|
|
const errors = [
|
|
...(createBaseShippingRateOpts.data?.shippingPriceCreate.errors || []),
|
|
];
|
|
const channelErrors =
|
|
updateShippingMethodChannelListingOpts.data
|
|
?.shippingMethodChannelListingUpdate.errors || [];
|
|
|
|
return {
|
|
channelErrors,
|
|
createShippingRate,
|
|
errors,
|
|
status: getMutationState(called, loading, [...errors, ...channelErrors]),
|
|
};
|
|
}
|
|
|
|
export function getCountrySelectionMap(
|
|
countries?: CountryFragment[],
|
|
countriesSelected?: string[],
|
|
) {
|
|
return (
|
|
countriesSelected &&
|
|
countries?.reduce((acc, country) => {
|
|
acc[country.code] = !!countriesSelected.find(
|
|
selectedCountries => selectedCountries === country.code,
|
|
);
|
|
return acc;
|
|
}, {} as Map<string, boolean>)
|
|
);
|
|
}
|
|
|
|
export function isRestWorldCountriesSelected(
|
|
restWorldCountries?: string[],
|
|
countrySelectionMap?: Map<string, boolean>,
|
|
) {
|
|
return (
|
|
countrySelectionMap &&
|
|
restWorldCountries?.every(countryCode => countrySelectionMap[countryCode])
|
|
);
|
|
}
|