META-INF.resources.js.multishipping.AddressSelector.tsx Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of com.liferay.commerce.order.content.web
Show all versions of com.liferay.commerce.order.content.web
Liferay Commerce Order Content Web
/**
* SPDX-FileCopyrightText: (c) 2024 Liferay, Inc. https://liferay.com
* SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06
*/
import ClayForm, {
ClayInput,
ClaySelect,
ClaySelectWithOption,
} from '@clayui/form';
import ClayIcon from '@clayui/icon';
import classnames from 'classnames';
// @ts-ignore
import {CommerceServiceProvider} from 'commerce-frontend-js';
import {sub} from 'frontend-js-web';
import React, {
SetStateAction,
useCallback,
useEffect,
useRef,
useState,
} from 'react';
import ErrorMessage, {showError} from './ErrorMessage';
import {
IAPIResponseError,
ICountry,
ICountryAPIResponse,
IFieldError,
IPostalAddress,
IPostalAddressAPIResponse,
IRegion,
} from './Types';
interface IAddressSelectorProps {
setHandleSubmit(
callback: SetStateAction<(event: Event) => Promise>
): void;
setIsFormValid(value: boolean): void;
accountId: number;
addressId?: number;
addressType?: string;
hasManageAddressesPermission?: boolean;
label?: string;
namespace?: string;
}
const MANDATORY_FIELDS = [
'addressCountry',
'addressLocality',
'addressRegion',
'name',
'postalCode',
'streetAddressLine1',
];
function AddressSelector({
accountId,
addressId = 0,
addressType = 'shipping',
hasManageAddressesPermission = true,
label = Liferay.Language.get('delivery-group'),
namespace = 'AddressSelector',
setHandleSubmit,
setIsFormValid,
}: IAddressSelectorProps) {
const defaultAddressRef: React.MutableRefObject = useRef({
addressType,
id: 0,
primary: false,
});
const [addresses, setAddresses] = useState>([]);
const [countries, setCountries] = useState>([]);
const [errors, setErrors] = useState(
MANDATORY_FIELDS.reduce((map: IFieldError, field: string) => {
map[field] = '';
return map;
}, {})
);
const [regions, setRegions] = useState>([]);
const [currentAddress, setCurrentAddress] = useState(
defaultAddressRef.current
);
const handleAddressIdChange = useCallback(
({target: {value}}) => {
setCurrentAddress(
() =>
addresses.find((address) => address.id === Number(value)) ||
defaultAddressRef.current
);
if (Number(value) === 0) {
setErrors(
MANDATORY_FIELDS.reduce((map: IFieldError, field) => {
map[field] = '';
return map;
}, {})
);
}
else {
setErrors({});
}
},
[addresses]
);
const handleFieldChange = useCallback(
({
target: {name: fieldName, value},
}: {
target: {
name: string;
value: boolean | number | string | undefined;
};
}) => {
setCurrentAddress((prevState) => {
return {
...prevState,
addressRegion:
fieldName === 'addressCountry'
? null
: prevState.addressRegion,
[fieldName]: value,
} as IPostalAddress;
});
if (MANDATORY_FIELDS.includes(fieldName)) {
setErrors((prevState) => {
if (
(!value && fieldName !== 'addressRegion') ||
(!value &&
fieldName === 'addressRegion' &&
!!regions.length)
) {
return {
...prevState,
[fieldName]: Liferay.Language.get(
'this-field-is-required'
),
};
}
else {
delete prevState[fieldName];
return {
...prevState,
};
}
});
}
},
[regions]
);
useEffect(() => {
let data: Array = [];
if (currentAddress.addressCountry) {
data = (
countries.find(
(country) => country.name === currentAddress.addressCountry
)?.regions || []
).reduce((data, region) => {
if (region.active) {
region.label =
region.title_i18n[
Liferay.ThemeDisplay.getLanguageId()
] || region.title_i18n['en_US'];
data.push(region);
}
return data;
}, [] as Array);
setRegions(data);
}
else {
setRegions(data);
}
setErrors((prevState) => {
if (!currentAddress.id && data.length) {
prevState['addressRegion'] = '';
}
else {
delete prevState['addressRegion'];
}
return {
...prevState,
};
});
}, [countries, currentAddress.addressCountry, currentAddress.id]);
useEffect(() => {
CommerceServiceProvider.AdminUserAPI('v1')
.getPostalAddresses(accountId)
.then(({items}: IPostalAddressAPIResponse) => {
const data = items.filter(
(item) =>
item.addressType === 'billing-and-shipping' ||
item.addressType === addressType
);
setAddresses(data);
if (addressId) {
setCurrentAddress(
() =>
data.find(
(address) => address.id === Number(addressId)
) || defaultAddressRef.current
);
setErrors({});
}
})
.catch((error: IAPIResponseError) => {
setAddresses([]);
showError(error);
});
}, [accountId, addressId, addressType]);
useEffect(() => {
CommerceServiceProvider.AdminAddressAPI('v1')
.getCountries({
pageSize: -1,
})
.then((data: ICountryAPIResponse) => {
setCountries(
(data?.items || [])
.reduce((data, country) => {
if (country.active) {
country.name =
country.title_i18n[
Liferay.ThemeDisplay.getLanguageId()
] || country.title_i18n['en_US'];
data.push(country);
}
return data;
}, [] as Array)
.sort((item1, item2) =>
item1.name.localeCompare(item2.name)
)
);
})
.catch((error: IAPIResponseError) => {
setCountries([]);
showError(error);
});
}, []);
useEffect(() => {
setHandleSubmit(() => async (event: Event): Promise => {
event.preventDefault();
if (!currentAddress.id) {
MANDATORY_FIELDS.forEach((field) => {
handleFieldChange({
target: {name: field, value: currentAddress[field]},
});
});
if (Object.keys(errors).length) {
return Promise.resolve({id: 0});
}
return CommerceServiceProvider.AdminUserAPI('v1')
.postPostalAddress(accountId, currentAddress)
.then((response: IPostalAddress) => {
return response;
})
.catch((error: IAPIResponseError) => {
showError(error);
return Promise.resolve({id: 0});
});
}
else {
return Promise.resolve(currentAddress);
}
});
}, [accountId, currentAddress, errors, handleFieldChange, setHandleSubmit]);
useEffect(() => {
setIsFormValid(!Object.keys(errors).length);
}, [errors, setIsFormValid]);
return (
<>
{hasManageAddressesPermission && (
)}
{addresses.map((address) => (
))}
{
return {
'aria-label': country.name,
'label': country.name,
'value': country.name,
};
}),
]}
required={!currentAddress.id}
value={currentAddress?.addressCountry || ''}
/>
{
return {
'aria-label': region.name,
'label': region.label,
'value': region.name,
};
}),
]}
required={!currentAddress.id && !!regions.length}
value={currentAddress?.addressRegion || ''}
/>
>
);
}
export default AddressSelector;