import React, { useEffect, useMemo } from 'react'; import { useForm } from 'react-hook-form'; import { yupResolver } from '@hookform/resolvers/yup'; import * as yup from 'yup'; import clsx from 'clsx'; import { AddressType, AddressFormType } from '@akinon/next/types'; import { Button, Checkbox, Icon, Input, Radio, Select } from '@theme/components'; import { useGetCountriesQuery, useGetCitiesQuery, useGetTownshipsQuery, useGetDistrictsQuery } from '@akinon/next/data/client/address'; import { useAppSelector } from '@akinon/next/redux/hooks'; import { useLocalization } from '@akinon/next/hooks'; type SelectOptionType = { label: string; value: string | number; }; interface Props { data?: any; onSubmit: (data: any) => void; } const makeAddressFormSchema = (t, { phoneNumberLength, postCodeLength }) => yup.object().shape({ title: yup.string().required(t('account.address_book.form.error.required')), first_name: yup .string() .required(t('account.address_book.form.error.required')), last_name: yup .string() .required(t('account.address_book.form.error.required')), phone_number: yup .string() .transform((value: string) => value.replace(/_/g, '').replace(/ /g, '')) .length( phoneNumberLength, t('account.address_book.form.error.phone_length') ) .required(t('account.address_book.form.error.required')), country: yup .string() .required(t('account.address_book.form.error.required')), city: yup.string().required(t('account.address_book.form.error.required')), township: yup .string() .required(t('account.address_book.form.error.required')), district: yup .string() .required(t('account.address_book.form.error.required')), line: yup .string() .required(t('account.address_book.form.error.required')) .min(10, t('account.address_book.form.error.line_min')) .max(255, t('account.address_book.form.error.line_max')), postcode: yup .string() .transform((value: string) => value.replace(/_/g, '').replace(/ /g, '')) .min(postCodeLength, t('account.address_book.form.error.postcode_min')) .max(postCodeLength, t('account.address_book.form.error.postcode_max')) .required(t('account.address_book.form.error.required')), company_name: yup.string().nullable(), tax_no: yup.string().nullable(), tax_office: yup.string().nullable(), e_bill_taxpayer: yup.boolean().nullable() }); export const AddressForm = (props: Props) => { const { t } = useLocalization(); const { data, onSubmit } = props; const config = useAppSelector((state) => state.config); const addressFormSchema = makeAddressFormSchema(t, { phoneNumberLength: config.user_phone_format.length, postCodeLength: config.user_post_code_format.length }); const { register, handleSubmit, watch, control, reset, formState: { errors } } = useForm({ resolver: yupResolver(addressFormSchema), defaultValues: { is_corporate: AddressType.individual, type: 'customer' } }); const selectedFormType = watch('is_corporate'); const selectedCountry = watch('country'); const selectedCity = watch('city'); const selectedTownship = watch('township'); const { data: country } = useGetCountriesQuery(); const { data: city } = useGetCitiesQuery(selectedCountry, { skip: !selectedCountry }); const { data: township } = useGetTownshipsQuery(selectedCity, { skip: !selectedCity }); const { data: district } = useGetDistrictsQuery(selectedTownship, { skip: !selectedTownship }); const countryOptions = useMemo(() => { if (country) { const options: SelectOptionType[] = [ { label: t('account.address_book.form.country.placeholder'), value: '' } ]; options.push( ...country.results.map((item) => ({ label: item.name, value: item.pk })) ); return options; } return []; }, [country]); // eslint-disable-line react-hooks/exhaustive-deps const cityOptions = useMemo(() => { if (city) { const options: SelectOptionType[] = [ { label: t('account.address_book.form.province.placeholder'), value: '' } ]; options.push( ...city.results.map((item) => ({ label: item.name, value: item.pk })) ); return options; } return []; }, [city]); // eslint-disable-line react-hooks/exhaustive-deps const townshipOptions = useMemo(() => { if (township) { const options: SelectOptionType[] = [ { label: t('account.address_book.form.township.placeholder'), value: '' } ]; options.push( ...township.results.map((item) => ({ label: item.name, value: item.pk })) ); return options; } return []; }, [township]); // eslint-disable-line react-hooks/exhaustive-deps const districtOptions = useMemo(() => { if (district) { const options: SelectOptionType[] = [ { label: t('account.address_book.form.district.placeholder'), value: '' } ]; options.push( ...district.results.map((item) => ({ label: item.name, value: item.pk })) ); return options; } return []; }, [district]); // eslint-disable-line react-hooks/exhaustive-deps useEffect(() => { if (data && country) { reset({ ...data, is_corporate: String(data.is_corporate) }); } }, [data, country, reset]); useEffect(() => { if (selectedFormType !== AddressType.company) { reset({ ...watch(), company_name: '', tax_office: '', tax_no: '' }); } }, [selectedFormType, reset, watch]); return (
{t('account.address_book.form.type.personal')} {t('account.address_book.form.type.corporate')}
{/* TODO: Fix select and textarea components */} )} {township && (
)}
)}