All Downloads are FREE. Search and download functionalities are using the official Maven repository.

META-INF.resources.js.multishipping.AddressSelector.tsx Maven / Gradle / Ivy

There is a newer version: 4.0.127
Show newest version
/**
 * 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;




© 2015 - 2024 Weber Informatics LLC | Privacy Policy