From 0ca507c03e23fb24369519ebde4a3e2b395c30e0 Mon Sep 17 00:00:00 2001 From: kris liu Date: Fri, 5 Aug 2022 15:49:29 +0800 Subject: [PATCH] feat: add remote form configuration to app https://bigc-b2b.atlassian.net/browse/BUN-87 --- apps/storefront/package.json | 3 +- apps/storefront/src/App.tsx | 18 + .../src/components/B3CustomForm.tsx | 2 +- .../src/components/RegisteredCloseButton.tsx | 7 +- .../src/components/form/B3FileUpload.tsx | 8 +- apps/storefront/src/components/form/styled.ts | 1 + apps/storefront/src/locales/en-US/users.ts | 1 + apps/storefront/src/locales/zh-CN/users.ts | 1 + .../src/pages/registered/RegisterComplete.tsx | 220 ++++----- .../src/pages/registered/Registered.tsx | 69 ++- .../pages/registered/RegisteredAccount.tsx | 66 ++- .../pages/registered/RegisteredBCToB2B.tsx | 74 +--- .../src/pages/registered/RegisteredDetail.tsx | 71 +-- .../src/pages/registered/RegisteredStep.tsx | 9 +- .../storefront/src/pages/registered/config.ts | 416 ++++++++---------- .../registered/context/RegisteredContext.tsx | 10 +- .../shared/service/b2b/graphql/register.ts | 31 +- .../src/shared/service/b2b/index.ts | 2 + yarn.lock | 30 +- 19 files changed, 520 insertions(+), 519 deletions(-) diff --git a/apps/storefront/package.json b/apps/storefront/package.json index a5927dc4..7c12bcc0 100644 --- a/apps/storefront/package.json +++ b/apps/storefront/package.json @@ -11,8 +11,8 @@ "coverage": "vitest --coverage" }, "dependencies": { - "@b3/lang": "*", "@b3/global-b3": "*", + "@b3/lang": "*", "@emotion/cache": "^11.9.3", "@emotion/react": "^11.9.3", "@emotion/styled": "^11.9.3", @@ -20,6 +20,7 @@ "@mui/material": "^5.8.7", "@mui/styles": "^5.8.7", "@mui/x-date-pickers": "^5.0.0-beta.0", + "@rollup/plugin-graphql": "^1.1.0", "@types/babel__core": "^7.1.19", "date-fns": "^2.28.0", "graphql": "^16.5.0", diff --git a/apps/storefront/src/App.tsx b/apps/storefront/src/App.tsx index 24902091..b7637a25 100644 --- a/apps/storefront/src/App.tsx +++ b/apps/storefront/src/App.tsx @@ -1,3 +1,6 @@ +import { + useEffect, +} from 'react' import { HashRouter, Route, @@ -37,9 +40,24 @@ const HeaderContainer = styled('div')(() => ({ marginBottom: '1rem', })) +const { + height: defaultHeight, + overflow: defaultOverflow, +} = document.body.style + export default function App() { const [isOpen, setIsOpen] = useB3AppOpen(false) + useEffect(() => { + if (isOpen) { + document.body.style.height = '100%' + document.body.style.overflow = 'hidden' + } else { + document.body.style.height = defaultHeight + document.body.style.overflow = defaultOverflow + } + }, [isOpen]) + return (
diff --git a/apps/storefront/src/components/B3CustomForm.tsx b/apps/storefront/src/components/B3CustomForm.tsx index d776ec80..4eb272b8 100644 --- a/apps/storefront/src/components/B3CustomForm.tsx +++ b/apps/storefront/src/components/B3CustomForm.tsx @@ -79,7 +79,7 @@ export function B3CustomForm(props: B3UI.B3CustomFormProps) { ) } { - ['file'].includes(fieldType) && ( + ['files'].includes(fieldType) && ( + ) } diff --git a/apps/storefront/src/components/form/B3FileUpload.tsx b/apps/storefront/src/components/form/B3FileUpload.tsx index d280e477..07445934 100644 --- a/apps/storefront/src/components/form/B3FileUpload.tsx +++ b/apps/storefront/src/components/form/B3FileUpload.tsx @@ -60,12 +60,12 @@ interface FileUploadProps extends B3UI.B3UIProps { const getMaxFileSizeLabel = (maxSize: number) => { if (maxSize / 1048576 > 1) { - return `${(maxSize / 1048576).toFixed(1)}M` + return `${(maxSize / 1048576).toFixed(1)}MB` } if (maxSize / 1024 > 1) { - return `${(maxSize / 1024).toFixed(1)}kb` + return `${(maxSize / 1024).toFixed(1)}KB` } - return `${maxSize}b` + return `${maxSize}B` } export const B3FileUpload = (props: FileUploadProps) => { @@ -128,7 +128,7 @@ export const B3FileUpload = (props: FileUploadProps) => { return ( <> { - ['file'].includes(fieldType) && ( + ['files'].includes(fieldType) && ( ({ display: 'flex', justifyContent: 'center', alignItems: 'center', + cursor: 'default', '& .MuiTypography-root': { fontSize: '1rem', color: '#767676', diff --git a/apps/storefront/src/locales/en-US/users.ts b/apps/storefront/src/locales/en-US/users.ts index b1dfe5a6..5b9b41f8 100644 --- a/apps/storefront/src/locales/en-US/users.ts +++ b/apps/storefront/src/locales/en-US/users.ts @@ -3,6 +3,7 @@ export default { 'intl.user.register.title.accountCreated': 'Your personal account has been created.', 'intl.user.register.title.accountRegister': 'Account Registration', 'intl.user.register.title.attachments': 'Attachments', + 'intl.user.register.title.bcToB2B.businessAccountApplication': 'Business Account Application', 'intl.user.register.title.address': 'Address', 'intl.user.register.title.businessDetails': 'Business Details', diff --git a/apps/storefront/src/locales/zh-CN/users.ts b/apps/storefront/src/locales/zh-CN/users.ts index 5806dad3..ac84f407 100644 --- a/apps/storefront/src/locales/zh-CN/users.ts +++ b/apps/storefront/src/locales/zh-CN/users.ts @@ -2,6 +2,7 @@ export default { 'intl.user.register.title.registerComplete': '注册完成。欢迎!', 'intl.user.register.title.accountCreated': '您的个人帐户已被创建。', 'intl.user.register.title.accountRegister': '账户注册', + 'intl.user.register.title.bcToB2B.businessAccountApplication': '商业账户申请', 'intl.user.register.title.attachments': '附件', 'intl.user.register.title.address': '地址', 'intl.user.register.title.businessDetails': '公司信息', diff --git a/apps/storefront/src/pages/registered/RegisterComplete.tsx b/apps/storefront/src/pages/registered/RegisterComplete.tsx index 46ffb746..7fa718cf 100644 --- a/apps/storefront/src/pages/registered/RegisterComplete.tsx +++ b/apps/storefront/src/pages/registered/RegisterComplete.tsx @@ -35,8 +35,7 @@ import { } from '@/shared/service/b2b' import { - RegisterFields, CustomFieldItems, Base64, - validatorRules, + RegisterFields, CustomFieldItems, deCodeField, toHump, } from './config' import { @@ -54,7 +53,7 @@ interface RegisterCompleteProps { activeStep: number, } -type RegisterCompleteList = Array | undefined +type RegisterCompleteList = Array | undefined export default function RegisterComplete(props: RegisterCompleteProps) { const b3Lang = useB3Lang() @@ -71,6 +70,7 @@ export default function RegisterComplete(props: RegisterCompleteProps) { const { control, handleSubmit, + setError, formState: { errors, }, @@ -84,26 +84,33 @@ export default function RegisterComplete(props: RegisterCompleteProps) { const { contactInformation, - bcContactInformationFields, - passwordInformation, + bcContactInformation, + passwordInformation = [], + bcPasswordInformation = [], accountType, additionalInformation, - addressBasicFields, - addressExtraFields, - companyInformation, + bcAdditionalInformation, + addressBasicFields = [], + bcAddressBasicFields = [], + companyInformation = [], emailMarketingNewsletter, - companyAttachment, - companyExtraFields, } = state - const emailName = accountType === '1' ? 'workEmailAddress' : 'emailAddress' - const list:RegisterCompleteList = accountType === '1' ? contactInformation : bcContactInformationFields + const list:RegisterCompleteList = accountType === '1' ? contactInformation : bcContactInformation + const passwordInfo:RegisterCompleteList = accountType === '1' ? passwordInformation : bcPasswordInformation + + const passwordName = passwordInfo[0]?.groupName || '' + + const additionalInfo:RegisterCompleteList = accountType === '1' ? additionalInformation : bcAdditionalInformation + + const addressBasicList = accountType === '1' ? addressBasicFields : bcAddressBasicFields + useEffect(() => { if (!accountType) return - const newPasswordInformation: Array = [] + let newPasswordInformation: Array = [] let emailItem: CustomFieldItems = {} if (list && list.length) { - const emailFields = list.find((item: RegisterFields) => item.name === emailName) || {} + const emailFields = list.find((item: RegisterFields) => item.name === 'email') || {} emailItem = { ...emailFields, } @@ -113,20 +120,10 @@ export default function RegisterComplete(props: RegisterCompleteProps) { newPasswordInformation.push(emailItem) } - if (passwordInformation?.length) newPasswordInformation.push(passwordInformation[0]) - newPasswordInformation.push({ - default: '', - required: true, - label: b3Lang('intl.user.register.RegisterComplete.confirmPassword'), - name: 'ConfirmPassword', - id: 'Confirm Password', - fieldType: 'password', - xs: 12, - validate: validatorRules(['password']), - }) + newPasswordInformation = [...newPasswordInformation, ...passwordInfo] setPersonalInfo(newPasswordInformation) - }, [contactInformation, bcContactInformationFields, accountType]) + }, [contactInformation, bcContactInformation, accountType]) const getBCFieldsValue = (data: CustomFieldItems) => { const bcFields: CustomFieldItems = {} @@ -140,29 +137,19 @@ export default function RegisterComplete(props: RegisterCompleteProps) { if (list) { list.forEach((item: any) => { - if (item.name === 'lastName') { - bcFields.last_name = item.default - } - if (item.name === 'firstName') { - bcFields.first_name = item.default - } - if (item.name === 'phoneNumber') { - bcFields.phone = item?.default || '' - } - if (item.name === 'companyName') { - bcFields.company = item?.default || '' - } - if (item.name === emailName) { - bcFields.email = item.default + const name = deCodeField(item.name) + if (name === 'accepts_marketing_emails') { + bcFields.accepts_product_review_abandoned_cart_emails = !!item?.default?.length + } else { + bcFields[name] = item?.default || '' } }) bcFields.form_fields = [] - - if (additionalInformation && (additionalInformation as Array).length) { - additionalInformation.forEach((field: CustomFieldItems) => { + if (additionalInfo && (additionalInfo as Array).length) { + additionalInfo.forEach((field: CustomFieldItems) => { bcFields.form_fields.push({ - name: field.label, + name: field.bcLabel, value: field.default, }) }) @@ -174,38 +161,34 @@ export default function RegisterComplete(props: RegisterCompleteProps) { if (accountType === '2') { const addresses: CustomFieldItems = {} - if (addressBasicFields) { + const getBCAddressField = addressBasicList.filter((field: any) => !field.custom) + const getBCExtraAddressField = addressBasicList.filter((field: any) => field.custom) + + if (getBCAddressField) { bcFields.addresses = {} - addressBasicFields.forEach((field: any) => { + getBCAddressField.forEach((field: any) => { if (field.name === 'country') { addresses.country_code = field.default - } - if (field.name === 'address1') { - addresses.address1 = field.default - } - if (field.name === 'address2') { - addresses.address2 = field.default - } - if (field.name === 'city') { - addresses.city = field.default - } - if (field.name === 'state') { + } else if (field.name === 'state') { addresses.state_or_province = field.default - } - if (field.name === 'zipCode') { + } else if (field.name === 'postalCode') { addresses.postal_code = field.default + } else if (field.name === 'firstName') { + addresses.first_name = field.default + } else if (field.name === 'lastName') { + addresses.last_name = field.default + } else { + addresses[field.name] = field.default } }) } - addresses.first_name = bcFields.first_name - addresses.last_name = bcFields.last_name addresses.form_fields = [] // BC Extra field - if (addressExtraFields && addressExtraFields.length) { - addressExtraFields.forEach((field: any) => { + if (getBCExtraAddressField && getBCExtraAddressField.length) { + getBCExtraAddressField.forEach((field: any) => { addresses.form_fields.push({ - name: field.label, + name: field.bcLabel, value: field.default, }) }) @@ -224,22 +207,26 @@ export default function RegisterComplete(props: RegisterCompleteProps) { return createBCCompanyUser(userItem) } - const getB2BFieldsValue = async (data: CustomFieldItems, customerId: Number | String) => { - const b2bFields: any = {} + const getB2BFieldsValue = async (data: CustomFieldItems, customerId: Number | String, fileList: any) => { + const b2bFields: CustomFieldItems = {} b2bFields.customerId = customerId || '' b2bFields.storeHash = storeHash - if (companyInformation) { - companyInformation.forEach((item: any) => { - b2bFields[item.name] = item?.default || '' + const companyInfo = companyInformation.filter((list) => !list.custom && list.fieldType !== 'files') + const companyExtraInfo = companyInformation.filter((list) => !!list.custom) + // company field + if (companyInfo.length) { + companyInfo.forEach((item: any) => { + b2bFields[toHump(deCodeField(item.name))] = item?.default || '' }) } - if (companyExtraFields) { + // Company Additional Field + if (companyExtraInfo.length) { const extraFields:Array = [] - companyExtraFields.forEach((item: any) => { + companyExtraInfo.forEach((item: CustomFieldItems) => { const itemExtraField: CustomFieldItems = {} - itemExtraField.fieldName = Base64.decode(item.name) + itemExtraField.fieldName = deCodeField(item.name) itemExtraField.fieldValue = item?.default || '' extraFields.push(itemExtraField) }) @@ -248,37 +235,47 @@ export default function RegisterComplete(props: RegisterCompleteProps) { b2bFields.companyEmail = data.email - if (addressBasicFields) { - addressBasicFields.forEach((field: any) => { - if (field.name === 'country') { - b2bFields.country = field.default - } - if (field.name === 'address1') { + // address Field + const addressBasicInfo = addressBasicList.filter((list) => !list.custom) + const addressExtraBasicInfo = addressBasicList.filter((list) => !!list.custom) + + if (addressBasicInfo.length) { + addressBasicInfo.forEach((field: CustomFieldItems) => { + const name = deCodeField(field.name) + if (name === 'address1') { b2bFields.addressLine1 = field.default } - if (field.name === 'address2') { + if (name === 'address2') { b2bFields.addressLine2 = field.default } - if (field.name === 'city') { - b2bFields.city = field.default - } - if (field.name === 'state') { - b2bFields.state = field.default - } - if (field.name === 'zipCode') { - b2bFields.zipCode = field.default - } + b2bFields[name] = field.default }) } - let attachments: File[] = [] - if (companyAttachment) { - companyAttachment.forEach((field: any) => { - if (field.name === 'companyAttachments') { - attachments = field.default - } + // address Additional Field + if (addressExtraBasicInfo.length) { + const extraFields:Array = [] + addressExtraBasicInfo.forEach((item: CustomFieldItems) => { + const itemExtraField: CustomFieldItems = {} + itemExtraField.fieldName = deCodeField(item.name) + itemExtraField.fieldValue = item?.default || '' + extraFields.push(itemExtraField) }) + b2bFields.addressExtraFields = extraFields } + b2bFields.fileList = fileList + + return createB2BCompanyUser(b2bFields) + } + + const getFileUrl = async (attachmentsList: RegisterFields[]) => { + let attachments: File[] = [] + + if (!attachmentsList.length) return + + attachmentsList.forEach((field: any) => { + attachments = field.default + }) try { const fileResponse = await Promise.all(attachments.map( @@ -288,24 +285,41 @@ export default function RegisterComplete(props: RegisterCompleteProps) { }), )) - b2bFields.fileList = fileResponse.reduce((fileList: any, res: any) => { + const fileList = fileResponse.reduce((fileList: any, res: any) => { if (res.code === 200) { fileList = [...fileList, res.data] + } else { + throw res.data.errMsg || res.message || b3Lang('intl.global.fileUpload.fileUploadFailure') } return fileList }, []) + + return fileList } catch (error) { - b2bFields.fileList = [] + // eslint-disable-next-line no-console + console.log(error) + throw error } - - return createB2BCompanyUser(b2bFields) } const handleCompleted = (event: MouseEvent) => { if (captchaMessage !== 'success') return handleSubmit(async (completeData: CustomFieldItems) => { - if (completeData.password !== completeData.ConfirmPassword) { - setErrorMessage(b3Lang('intl.user.register.RegisterComplete.passwordMatchPrompt')) + if (completeData.password !== completeData.confirmPassword) { + setError( + 'confirmPassword', + { + type: 'manual', + message: b3Lang('intl.user.register.RegisterComplete.passwordMatchPrompt'), + }, + ) + setError( + 'password', + { + type: 'manual', + message: b3Lang('intl.user.register.RegisterComplete.passwordMatchPrompt'), + }, + ) return } try { @@ -319,11 +333,13 @@ export default function RegisterComplete(props: RegisterCompleteProps) { if (accountType === '2') { await getBCFieldsValue(completeData) } else { + const attachmentsList = companyInformation.filter((list) => list.fieldType === 'files') + const fileList = await getFileUrl(attachmentsList || []) const res = await getBCFieldsValue(completeData) const { data, } = res - const accountInfo = await getB2BFieldsValue(completeData, (data as any)[0].id) + const accountInfo = await getB2BFieldsValue(completeData, (data as any)[0].id, fileList) const { companyCreate: { @@ -383,7 +399,7 @@ export default function RegisterComplete(props: RegisterCompleteProps) { ) } - {b3Lang('intl.user.register.RegisterComplete.title')} + { passwordName } { personalInfo && ( = [1, 2] + interface RegisteredProps { setIsOpen: Dispatch>, } @@ -89,13 +85,13 @@ export default function Registered(props: RegisteredProps) { }) } - const { - customerAccount, - billingAddress, - } = await getBCRegisterCustomFields() - const { - companyExtraFields, - } = await getB2BRegisterCustomFields() + const accountFormAllFields = formType.map((item: number) => getB2BAccountFormFields(item)) + + const accountFormFields = await Promise.all(accountFormAllFields) + + const bcAccountFormFields = getAccountFormFields(accountFormFields[0]?.accountFormFields || []) + const b2bAccountFormFields = getAccountFormFields(accountFormFields[1]?.accountFormFields || []) + const { quoteConfig, } = await getB2BRegisterLogo() @@ -109,24 +105,20 @@ export default function Registered(props: RegisteredProps) { } = await storeB2BBasicInfo() const registerLogo = getRegisterLogo(quoteConfig) - const newCustomerAccount = customerAccount.length ? customerAccount.filter((field: RegisterFields) => field.custom) : [] - const newAdditionalInformation: Array = conversionDataFormat(newCustomerAccount) - - const filterCompanyExtraFields = companyExtraFields.length ? companyExtraFields.filter((field: RegisterFields) => field?.visibleToEnduser) : [] - const newCompanyExtraFields: Array = conversionDataFormat(filterCompanyExtraFields) - - const customAddress = billingAddress.length ? billingAddress.filter((field: RegisterFields) => field.custom) : [] - const addressExtraFields: Array = conversionDataFormat(customAddress) + const newAddressInformationFields = b2bAccountFormFields.address.map((addressFields: Partial):Partial => { + if (addressFields.name === 'country') { + addressFields.options = countries + } + return addressFields + }) - const newAddressInformationFields = addressInformationFields(b3Lang).map((addressFields) => { + const newBCAddressInformationFields = bcAccountFormFields.address.map((addressFields: Partial):Partial => { if (addressFields.name === 'country') { addressFields.options = countries } return addressFields }) - const filterPasswordInformation = customerAccount.length ? customerAccount.filter((field: RegisterFields) => !field.custom && field.fieldType === 'password') : [] - const newPasswordInformation: Array = conversionDataFormat(filterPasswordInformation) if (dispatch) { dispatch({ type: 'all', @@ -134,16 +126,22 @@ export default function Registered(props: RegisteredProps) { accountType: '1', isLoading: false, storeName, - contactInformation: [...contactInformationFields(b3Lang)], - additionalInformation: [...newAdditionalInformation], - bcContactInformationFields: [...bcContactInformationFields(b3Lang)], - companyExtraFields: [...newCompanyExtraFields], - companyInformation: [...companyInformationFields(b3Lang)], + // account + contactInformation: [...b2bAccountFormFields.contactInformation], + bcContactInformation: [...bcAccountFormFields.contactInformation], + additionalInformation: [...b2bAccountFormFields.additionalInformation], + bcAdditionalInformation: [...bcAccountFormFields.additionalInformation], + // detail + companyExtraFields: [], + companyInformation: [...b2bAccountFormFields?.businessDetails || []], companyAttachment: [...companyAttachmentsFields(b3Lang)], addressBasicFields: [...newAddressInformationFields], - addressExtraFields: [...addressExtraFields], + bcAddressBasicFields: [...newBCAddressInformationFields], countryList: [...countries], - passwordInformation: [...newPasswordInformation], + // password + passwordInformation: [...b2bAccountFormFields.password], + bcPasswordInformation: [...bcAccountFormFields.password], + }, }) } @@ -178,7 +176,6 @@ export default function Registered(props: RegisteredProps) { submitSuccess: false, contactInformation: [], additionalInformation: [], - bcContactInformationFields: [], companyExtraFields: [], companyInformation: [], companyAttachment: [], diff --git a/apps/storefront/src/pages/registered/RegisteredAccount.tsx b/apps/storefront/src/pages/registered/RegisteredAccount.tsx index 77a97c77..0c2bb648 100644 --- a/apps/storefront/src/pages/registered/RegisteredAccount.tsx +++ b/apps/storefront/src/pages/registered/RegisteredAccount.tsx @@ -1,7 +1,6 @@ import { useContext, ChangeEvent, - useCallback, useState, MouseEvent, } from 'react' @@ -26,7 +25,6 @@ import { B3CustomForm, } from '@/components' import RegisteredStepButton from './component/RegisteredStepButton' -import RegisteredSigleCheckBox from './component/RegisteredSigleCheckBox' import { RegisteredContext, @@ -69,8 +67,8 @@ export default function RegisteredAccount(props: RegisteredAccountProps) { const { contactInformation, accountType, additionalInformation, - bcContactInformationFields, - emailMarketingNewsletter, + bcContactInformation, + bcAdditionalInformation, } = state const { @@ -85,6 +83,16 @@ export default function RegisteredAccount(props: RegisteredAccountProps) { mode: 'onSubmit', }) + const additionName = accountType === '1' ? 'additionalInformation' : 'bcAdditionalInformation' + const additionalInfo: any = accountType === '1' ? additionalInformation : bcAdditionalInformation + + const contactInfo: any = accountType === '1' ? contactInformation : bcContactInformation + const contactName = accountType === '1' ? 'contactInformation' : 'bcContactInformationFields' + + const contactInformationLabel = contactInfo.length ? contactInfo[0]?.groupName : '' + + const additionalInformationLabel = additionalInfo.length ? additionalInfo[0]?.groupName : '' + const handleChange = (event: ChangeEvent) => { dispatch({ type: 'accountType', @@ -114,22 +122,24 @@ export default function RegisteredAccount(props: RegisteredAccountProps) { isLoading: true, }, }) - const email = accountType === '2' ? data.emailAddress : data.workEmailAddress + + const emailItem: any = contactInformation?.filter((item: any) => item.fieldId === 'field_email') + const email = data[emailItem[0]?.name] + getB2BCompanyUserInfo(email).then(({ companyUserInfo: { userType, }, }: any) => { if (userType === 1) { - const contactInfo: any = accountType === '1' ? contactInformation : bcContactInformationFields - const contactName = accountType === '1' ? 'contactInformation' : 'bcContactInformationFields' const newContactInfo = contactInfo.map((item: RegisterFields) => { item.default = data[item.name] || item.default return item }) + let newAdditionalInformation: Array = [] - if (additionalInformation) { - newAdditionalInformation = (additionalInformation as Array).map((item: RegisterFields) => { + if (additionalInfo) { + newAdditionalInformation = (additionalInfo as Array).map((item: RegisterFields) => { item.default = data[item.name] || item.default return item }) @@ -138,7 +148,7 @@ export default function RegisteredAccount(props: RegisteredAccountProps) { dispatch({ type: 'all', payload: { - additionalInformation: [...newAdditionalInformation], + [additionName]: [...newAdditionalInformation], [contactName]: [...newContactInfo], }, }) @@ -152,9 +162,7 @@ export default function RegisteredAccount(props: RegisteredAccountProps) { isLoading: false, }, }) - }).catch((err: any) => { - // eslint-disable-next-line no-console - console.log(err) + }).catch(() => { dispatch({ type: 'loading', payload: { @@ -169,17 +177,6 @@ export default function RegisteredAccount(props: RegisteredAccountProps) { (window as Window).location.href = '/login.php?action=create_account' } - const handleEmailSletterChange = useCallback((event: ChangeEvent) => { - dispatch({ - type: 'emailSletter', - payload: { - emailMarketingNewsletter: event.target.checked, - }, - }) - }, []) - - const additionalList: any = accountType === '1' ? contactInformation : bcContactInformationFields - return ( - {b3Lang('intl.user.register.registeredAccount.contactInformation')} + {contactInformationLabel} - - - { - (additionalInformation && additionalInformation.length) ? ( + (additionalInfo && additionalInfo.length) ? ( - {b3Lang('intl.user.register.registeredAccount.additionalInformation')} + {additionalInformationLabel} field?.visibleToEnduser) : [] - const newCompanyExtraFields: Array = conversionDataFormat(filterCompanyExtraFields) - - const newAddressInformationFields = addressInformationFields(b3Lang).map((addressFields) => { + const newAddressInformationFields = bcToB2BAccountFormFields.address.map((addressFields: Partial):Partial => { if (addressFields.name === 'country') { addressFields.options = countries } return addressFields }) + const newContactInformation = bcToB2BAccountFormFields.contactInformation.map((contactInformationField: Partial):Partial => { + contactInformationField.disabled = true + + return contactInformationField + }) + if (dispatch) { dispatch({ type: 'all', payload: { isLoading: false, storeName, - contactInformation: [...contactInformationFields(b3Lang)], - companyExtraFields: [...newCompanyExtraFields], - companyInformation: [...companyInformationFields(b3Lang)], - companyAttachment: [...companyAttachmentsFields(b3Lang)], + contactInformation: [...newContactInformation], + companyExtraFields: [], + companyInformation: [...bcToB2BAccountFormFields.businessDetails], addressBasicFields: [...newAddressInformationFields], countryList: [...countries], }, @@ -149,21 +147,11 @@ export default function RegisteredBCToB2B() { getBCAdditionalFields() }, []) - const setAddressFieldsRequire = (accountType: string, addressBasicFields: Array) => { - const fieldRequired = addressFieldsRequired[`account_type_${accountType || '1'}`] || {} - - addressBasicFields.forEach((field: RegisterFields) => { - field.required = fieldRequired[field.name] || false - }) - - return addressBasicFields - } - const { contactInformation, isLoading, companyInformation = [], - companyAttachment = [], + // companyAttachment = [], addressBasicFields = [], countryList = [], companyExtraFields = [], @@ -194,14 +182,6 @@ export default function RegisteredBCToB2B() { }) } - const [addressFields, setAddressFields] = useState>(addressBasicFields) - - useEffect(() => { - if (addressBasicFields && addressBasicFields.length) { - setAddressFields([...setAddressFieldsRequire('1', addressBasicFields)]) - } - }, [addressBasicFields]) - useEffect(() => { const subscription = watch((value, { name, @@ -249,10 +229,10 @@ export default function RegisteredBCToB2B() { ) } - Business Account Application + {b3Lang('intl.user.register.title.bcToB2B.businessAccountApplication')} - {b3Lang('intl.user.register.registeredAccount.contactInformation')} + {contactInformation?.length ? contactInformation[0]?.groupName : ''} - {b3Lang('intl.user.register.title.businessDetails')} + {companyInformation?.length ? companyInformation[0]?.groupName : ''} - - {b3Lang('intl.user.register.title.attachments')} - - - {b3Lang('intl.user.register.title.address')} + {addressBasicFields?.length ? addressBasicFields[0]?.groupName : ''} >(addressBasicFields) - - const setAddressFieldsRequire = (accountType: string, addressBasicFields: Array) => { - const fieldRequired = addressFieldsRequired[`account_type_${accountType || '1'}`] || {} - - addressBasicFields.forEach((field: RegisterFields) => { - field.required = fieldRequired[field.name] || false - }) - - return addressBasicFields - } + const addressBasicName = accountType === '1' ? 'addressBasicFields' : 'bcAddressBasicFields' + const addressBasicList = accountType === '1' ? addressBasicFields : bcAddressBasicFields - useEffect(() => { - if (accountType === '1') { - setAddressFields([...setAddressFieldsRequire(accountType, addressBasicFields)]) - } else { - setAddressFields([...setAddressFieldsRequire( - accountType, - addressBasicFields, - ), ...addressExtraFields]) - } - }, [accountType]) + const addressName = addressBasicList[0]?.groupName || '' const handleCountryChange = (countryCode: string, stateCode: string = '') => { const stateList = countryList.find((country: Country) => country.countryCode === countryCode)?.states || [] - const stateFields = addressBasicFields.find((formFields: RegisterFields) => formFields.name === 'state') + const stateFields = addressBasicList.find((formFields: RegisterFields) => formFields.name === 'state') if (stateFields) { if (stateList.length > 0) { @@ -125,13 +100,13 @@ export default function RegisteredDetail(props: RegisteredDetailProps) { } } - setValue('state', stateCode && countryCode && (stateList.find((state: State) => state.stateCode === stateCode) || stateList.length === 0) ? stateCode : '') + setValue('state', stateCode && countryCode && (stateList.find((state: State) => state.stateName === stateCode) || stateList.length === 0) ? stateCode : '') dispatch({ type: 'stateList', payload: { stateList, - addressBasicFields: [...addressBasicFields], + [addressBasicName]: [...addressBasicList], }, }) } @@ -151,6 +126,7 @@ export default function RegisteredDetail(props: RegisteredDetailProps) { country, state, } = value + if (name === 'country' && type === 'change') { handleCountryChange(country, state) } @@ -197,7 +173,8 @@ export default function RegisteredDetail(props: RegisteredDetailProps) { try { if (accountType === '1') { - const extraFields = companyExtraFields.map((field: RegisterFields) => ({ + const extraCompanyInformation = companyInformation.filter((item: RegisterFields) => !!item.custom) + const extraFields = extraCompanyInformation.map((field: RegisterFields) => ({ fieldName: Base64.decode(field.name), fieldValue: data[field.name] || field.default, })) @@ -216,19 +193,15 @@ export default function RegisteredDetail(props: RegisteredDetailProps) { } const newCompanyInformation = setRegisterFieldsValue(companyInformation, data) - const newCompanyExtraFields = setRegisterFieldsValue(companyExtraFields, data) const newCompanyAttachment = setRegisterFieldsValue(companyAttachment, data) - const newAddressBasicFields = setRegisterFieldsValue(addressBasicFields, data) - const newAddressExtraFields = setRegisterFieldsValue(addressExtraFields, data) + const newAddressBasicFields = setRegisterFieldsValue(addressBasicList, data) dispatch({ type: 'all', payload: { companyInformation: [...newCompanyInformation], - companyExtraFields: [...newCompanyExtraFields], companyAttachment: [...newCompanyAttachment], - addressBasicFields: [...newAddressBasicFields], - addressExtraFields: [...newAddressExtraFields], + [addressBasicName]: [...newAddressBasicFields], }, }) showLading(false) @@ -262,19 +235,9 @@ export default function RegisteredDetail(props: RegisteredDetailProps) { accountType === '1' ? ( <> - {b3Lang('intl.user.register.title.businessDetails')} - - - - {b3Lang('intl.user.register.title.attachments')} + {businessDetailsName} - {b3Lang('intl.user.register.title.address')} + { addressName } Boolean, + activeStep: number +} + +export default function RegisteredStep(props: RegisteredStepProps) { const { children, isStepOptional, diff --git a/apps/storefront/src/pages/registered/config.ts b/apps/storefront/src/pages/registered/config.ts index b2b376f3..7bc164e0 100644 --- a/apps/storefront/src/pages/registered/config.ts +++ b/apps/storefront/src/pages/registered/config.ts @@ -2,10 +2,16 @@ import { B3Lang, } from '@b3/lang' +import { + format, +} from 'date-fns' + import { re, } from '../../constants' +const inputFormat = 'yyyy-MM-dd' + export interface CustomFieldItems { [key: string]: any } @@ -21,8 +27,8 @@ export interface ValidateOptions { export interface RegisterFields { name: string, label?: string, - required: Boolean, - fieldType: string, + required?: Boolean, + fieldType?: string, default?: string | Array | number, [key: string]: any } @@ -35,6 +41,55 @@ interface ValidateOptionItems { export type ContactInformationItems = Array +interface AccountFormFieldsItemsValueConfigs { + defaultValue?: string, + fieldName?: string, + isRequired?: boolean, + labelName?: string, + maximumLength?: string, + maxLength?: string, + name?: string, + required?: string + type?: string, + custom?: boolean + id: string | number + // [key: string]: string +} + +interface AccountFormFieldsItems { + fieldId?: string, + fieldName?: string, + fieldType?: string, + groupId: number | string, + groupName?: string, + id?: string, + isRequired?: boolean, + labelName?: string, + visible?: boolean, + custom?: boolean + valueConfigs?: AccountFormFieldsItemsValueConfigs +} + +type AccountFormFieldsList = Array<[]> | Array + +export interface RegisterFieldsItems { + id?: string | number, + name: string, + label: string + required: boolean, + default: string | number | Array, + fieldType: string | number, + xs: number, + visible: boolean, + custom: boolean, + bcLabel?: string, + fieldId: string, + groupId: string | number, + groupName: string + options?: any, + disabled: boolean, +} + export const steps = [ 'intl.user.register.step.account', 'intl.user.register.step.details', @@ -83,7 +138,7 @@ const fieldsType = { date: ['date'], } -const classificationType = (item: RegisterFields) => { +const classificationType = (item: CustomFieldItems) => { let optionItems: ValidateOptionItems = {} if (fieldsType.text.includes(item.fieldType)) { optionItems = { @@ -102,6 +157,10 @@ const classificationType = (item: RegisterFields) => { if (item.fieldType === 'password') { optionItems.validate = validatorRules(['password']) } + + if (item?.fieldName === 'email' || item?.fieldName === 'phone') { + optionItems.validate = validatorRules([item.fieldName]) + } } if (fieldsType.checkbox.includes(item.fieldType)) { optionItems = { @@ -149,143 +208,148 @@ const classificationType = (item: RegisterFields) => { return optionItems } -export const conversionDataFormat = (registerArr: Array) => { - const newRegisterArr = registerArr.map((item: RegisterFields) => { - const requiredItems = { - id: item.id || item.fieldName, - name: item.name || Base64.encode(item.fieldName), - label: item.label || item.fieldName, - required: item.required || item.isRequired, - default: item.default || item.defaultValue || '', - fieldType: item.fieldType, - xs: 12, +const noEncryptFieldList = ['country', 'state', 'email'] + +const groupItems = { + 1: 'contactInformation', + 2: 'additionalInformation', + 3: 'businessDetails', + 4: 'address', + 5: 'password', +} + +export const deCodeField = (fieldName: string) => { + if (noEncryptFieldList.includes(fieldName)) { + return fieldName + } + return Base64.decode(fieldName) +} + +export const enCodeFieldName = (fieldName: string) => { + if (noEncryptFieldList.includes(fieldName)) { + return fieldName + } + + return Base64.encode(fieldName) +} + +const bcFieldName = (fieldName: string) => { + if (fieldName === 'countryCode') { + return 'country' + } + if (fieldName === 'stateOrProvince') { + return 'state' + } + return fieldName +} + +export const conversionSigleItem = (item: CustomFieldItems): Partial => { + const requiredItems = { + id: item.id || item.fieldName, + name: bcFieldName(item.name) || enCodeFieldName(item.fieldName), + label: item.label || item.labelName, + required: item.required || item.isRequired, + default: item.default || item.defaultValue || '', + fieldType: item.fieldType, + xs: 12, + visible: item?.visible || false, + custom: item?.custom || false, + bcLabel: item.label || '', + } + + if (typeof (item.fieldType) === 'number') { + item.fieldType = companyExtraFieldsType[item.fieldType] + requiredItems.fieldType = item.fieldType + } + + const optionItems = classificationType(item) + + return { + ...requiredItems, + ...optionItems, + } +} + +export const toHump = (name:string) => name.replace(/_(\w)/g, (all, letter) => letter.toUpperCase()) + +export const conversionItemFormat = (FormFields: AccountFormFieldsList) => { + const getFormFields: any = {} + FormFields.forEach((item: CustomFieldItems) => { + const key: string = (groupItems as CustomFieldItems)[item.groupId] + + if (!getFormFields[key]?.length) { + getFormFields[key] = [] + } + + let obj:any = {} + if (item.valueConfigs?.id) { + obj = conversionSigleItem(item.valueConfigs) + } else { + obj = conversionSigleItem(item) + } + + obj.required = item.isRequired + obj.id = item.id + obj.fieldId = item.fieldId + obj.groupId = item.groupId + obj.groupName = item.groupName + obj.visible = item.visible + obj.label = item.labelName + obj.custom = obj.custom || item?.custom + + if (obj.fieldType === 'date' && !obj.default) { + obj.default = format(new Date(), inputFormat) } - if (typeof (item.fieldType) === 'number') { - item.fieldType = companyExtraFieldsType[item.fieldType] - requiredItems.fieldType = item.fieldType + if (obj.name === 'country') { + obj.replaceOptions = { + label: 'countryName', + value: 'countryCode', + } } - const optionItems = classificationType(item) + if (obj.name === 'state') { + obj.replaceOptions = { + label: 'stateName', + value: 'stateName', + } + } - return { - ...requiredItems, - ...optionItems, + if (item.fieldId === 'field_confirm_password') { + obj.name = 'confirmPassword' } + if (obj.fieldType === 'files') { + obj.filesLimit = 3 + obj.maxFileSize = 2097152 + obj.default = [] + } + + if (obj.fieldType === 'checkbox' && !obj.options) { + obj.label = '' + obj.options = [{ + label: item.labelName, + value: item.labelName, + }] + } + + getFormFields[key].push(obj) }) - return newRegisterArr + return getFormFields } -export const bcContactInformationFields = (b3lang: B3Lang) : ContactInformationItems => [ - { - name: 'firstName', - label: b3lang('intl.user.register.registeredAccount.firstName'), - default: '', - fieldType: 'text', - required: true, - xs: 6, - }, - { - name: 'lastName', - label: b3lang('intl.user.register.registeredAccount.lastName'), - default: '', - fieldType: 'text', - required: true, - xs: 6, - }, - { - name: 'emailAddress', - label: b3lang('intl.user.register.registeredAccount.emailAddress'), - default: '', - fieldType: 'text', - required: true, - validate: validatorRules(['email']), - xs: 12, - }, - { - name: 'companyName', - label: b3lang('intl.user.register.registeredAccount.companyName'), - default: '', - fieldType: 'text', - required: false, - xs: 12, - }, - { - name: 'phoneNumber', - label: b3lang('intl.user.register.registeredAccount.phoneNumber'), - default: '', - fieldType: 'text', - required: false, - xs: 12, - }, -] +export const getAccountFormFields = (accountFormFields: AccountFormFieldsList) => { + if (accountFormFields?.length) { + const filterVisibleAccountFormFields: AccountFormFieldsList = accountFormFields ? (accountFormFields as any).filter((item: Partial) => !!item.visible) : [] -export const contactInformationFields = (b3lang: B3Lang) : ContactInformationItems => [ - { - name: 'firstName', - label: b3lang('intl.user.register.registeredAccount.firstName'), - default: '', - fieldType: 'text', - required: true, - xs: 6, - }, - { - name: 'lastName', - label: b3lang('intl.user.register.registeredAccount.lastName'), - default: '', - fieldType: 'text', - required: true, - xs: 6, - }, - { - name: 'workEmailAddress', - label: b3lang('intl.user.register.registeredAccount.workEmailAddress'), - default: '', - fieldType: 'text', - required: true, - validate: validatorRules(['email']), - xs: 12, - }, - { - name: 'phoneNumber', - label: b3lang('intl.user.register.registeredAccount.phoneNumber'), - default: '', - fieldType: 'text', - required: false, - xs: 12, - }, -] + const getAccountFormItems = filterVisibleAccountFormFields ? conversionItemFormat(filterVisibleAccountFormFields) : {} -export const companyInformationFields = (b3lang: B3Lang) : ContactInformationItems => [ - { - name: 'companyName', - label: b3lang('intl.user.register.label.companyName'), - default: '', - fieldType: 'text', - required: true, - maxLength: 255, - xs: 12, - }, - { - name: 'companyEmail', - label: b3lang('intl.user.register.label.companyEmail'), - default: '', - fieldType: 'text', - required: false, - validate: validatorRules(['email']), - xs: 12, - }, - { - name: 'companyPhoneNumber', - label: b3lang('intl.user.register.label.companyPhoneNumber'), - default: '', - fieldType: 'text', - required: false, - validate: validatorRules(['phone']), - xs: 12, - }, -] + return getAccountFormItems + } + return {} +} + +// todo export const companyAttachmentsFields = (b3lang: B3Lang) : ContactInformationItems => [ { @@ -299,98 +363,6 @@ export const companyAttachmentsFields = (b3lang: B3Lang) : ContactInformationIte maxFileSize: 2097152, // 2M }, ] - -export const addressInformationFields = (b3lang: B3Lang) : ContactInformationItems => [ - { - name: 'country', - label: b3lang('intl.user.register.label.country'), - default: '', - fieldType: 'dropdown', - required: false, - maxLength: 255, - xs: 12, - options: [], - replaceOptions: { - label: 'countryName', - value: 'countryCode', - }, - }, - { - name: 'address1', - label: b3lang('intl.user.register.label.address1'), - default: '', - fieldType: 'text', - maxLength: 255, - required: false, - xs: 12, - }, - { - name: 'address2', - label: b3lang('intl.user.register.label.address2'), - default: '', - fieldType: 'text', - maxLength: 255, - required: false, - xs: 12, - }, - { - name: 'city', - label: b3lang('intl.user.register.label.city'), - default: '', - fieldType: 'text', - maxLength: 255, - required: false, - xs: 12, - }, - { - name: 'state', - label: b3lang('intl.user.register.label.state'), - default: '', - fieldType: 'text', - maxLength: 255, - required: false, - xs: 8, - replaceOptions: { - label: 'stateName', - value: 'stateName', - }, - }, - { - name: 'zipCode', - label: b3lang('intl.user.register.label.zipCode'), - default: '', - fieldType: 'text', - maxLength: 255, - required: false, - xs: 4, - }, -] - -type FieldsRequired = { - [k: string]: { - [v: string]: boolean - } -} - -export const addressFieldsRequired: FieldsRequired = { - account_type_1: { - country: false, - address1: false, - address2: false, - city: false, - state: false, - zipCode: false, - }, - account_type_2: { - country: true, - address1: true, - address2: false, - city: true, - state: true, - zipCode: true, - }, -} - export interface Country { countryCode: string, countryName: string, @@ -398,8 +370,8 @@ export interface Country { states: [] } export interface State { - stateCode: string, - stateName: string, + stateCode?: string, + stateName?: string, id?: string, } diff --git a/apps/storefront/src/pages/registered/context/RegisteredContext.tsx b/apps/storefront/src/pages/registered/context/RegisteredContext.tsx index 24faff63..28c04873 100644 --- a/apps/storefront/src/pages/registered/context/RegisteredContext.tsx +++ b/apps/storefront/src/pages/registered/context/RegisteredContext.tsx @@ -16,16 +16,20 @@ interface RegisterState { contactInformation?: Array, accountType?: string, additionalInformation?: Array, - bcContactInformationFields?: Array, + bcAdditionalInformation?: Array, + bcContactInformation?: Array, emailMarketingNewsletter?: Boolean, companyInformation?: Array, + bcCompanyInformation?: Array, companyExtraFields?: Array companyAttachment?: Array, addressBasicFields?: Array, + bcAddressBasicFields?: Array, addressExtraFields?: Array, countryList?: Array, stateList?: Array, passwordInformation?: Array, + bcPasswordInformation?: Array, isLoading?: Boolean, submitSuccess?: Boolean, isAutoApproval?: Boolean, @@ -48,13 +52,17 @@ const initState = { contactInformation: [], bcContactInformation: [], additionalInformation: [], + bcAdditionalInformation: [], passwordInformation: [], + bcPasswordInformation: [], accountType: '', emailMarketingNewsletter: false, companyInformation: [], + bcCompanyInformation: [], companyExtraFields: [], companyAttachment: [], addressBasicFields: [], + bcAddressBasicFields: [], addressExtraFields: [], countryList: [], stateList: [], diff --git a/apps/storefront/src/shared/service/b2b/graphql/register.ts b/apps/storefront/src/shared/service/b2b/graphql/register.ts index 195d90bd..54d942cb 100644 --- a/apps/storefront/src/shared/service/b2b/graphql/register.ts +++ b/apps/storefront/src/shared/service/b2b/graphql/register.ts @@ -11,6 +11,27 @@ interface CustomFieldItems { [key: string]: any } +const getAccountFormFields = (type: number) => `{ + accountFormFields(storeHash: "${storeHash}", formType: ${type}){ + id + formType + fieldFrom + fieldId + fieldIndex + custom + groupId + groupName + isRequired + visible + labelName + fieldName + fieldType + valueConfigs + createdAt + updatedAt + } +}` + const getCompanyExtraFields = () => `{ companyExtraFields(storeHash: "${storeHash}") { fieldName, @@ -67,17 +88,17 @@ const storeBasicInfo = () => `{ const createCompanyUser = (data: any) => `mutation{ companyCreate(companyData: { - customerId: "${data.customerId || 2945}", + customerId: "${data.customerId}", storeHash: "${data.storeHash}", companyName: "${data.companyName}", companyEmail: "${data.companyEmail}", - companyPhoneNumber: "${data.companyPhoneNumber}", + companyPhoneNumber: "${data.companyCompanyPhoneNumber}", country: "${data.country}", addressLine1: "${data.addressLine1}", addressLine2: "${data.addressLine2}", city: "${data.city}", state: "${data.state}", - zipCode: "${data.zipCode}", + zipCode: "${data.zip_code}", extraFields: ${convertArrayToGraphql(data.extraFields)} fileList: ${convertArrayToGraphql(data.fileList)} }) { @@ -88,6 +109,10 @@ const createCompanyUser = (data: any) => `mutation{ } }` +export const getB2BAccountFormFields = (type: number): CustomFieldItems => B3Request.graphqlB2B({ + query: getAccountFormFields(type), +}) + export const getB2BCompanyUserInfo = (email: string): CustomFieldItems => B3Request.graphqlB2B({ query: getCompanyUserInfo(email), }) diff --git a/apps/storefront/src/shared/service/b2b/index.ts b/apps/storefront/src/shared/service/b2b/index.ts index 966d076c..99407be7 100644 --- a/apps/storefront/src/shared/service/b2b/index.ts +++ b/apps/storefront/src/shared/service/b2b/index.ts @@ -5,6 +5,7 @@ import { getB2BCountries, createB2BCompanyUser, storeB2BBasicInfo, + getB2BAccountFormFields, } from './graphql/register' import { @@ -26,4 +27,5 @@ export { createB2BCompanyUser, storeB2BBasicInfo, validateBCCompanyExtraFields, + getB2BAccountFormFields, } diff --git a/yarn.lock b/yarn.lock index fe06ddf6..b37af93b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -907,6 +907,22 @@ resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.5.tgz#db5a11bf66bdab39569719555b0f76e138d7bd64" integrity sha512-9X2obfABZuDVLCgPK9aX0a/x4jaOEweTTWE2+9sr0Qqqevj2Uv5XorvusThmc9XGYpS9yI+fhh8RTafBtGposw== +"@rollup/plugin-graphql@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@rollup/plugin-graphql/-/plugin-graphql-1.1.0.tgz#492f579816f65bc21ce26394f2f140d95192622d" + integrity sha512-X+H6oFlprDlnO3D0UiEytdW97AMphPXO0C7KunS7i/rBXIGQRQVDU5WKTXnBu2tfyYbjCTtfhXMSGI0i885PNg== + dependencies: + "@rollup/pluginutils" "^4.0.0" + graphql-tag "^2.2.2" + +"@rollup/pluginutils@^4.0.0": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-4.2.1.tgz#e6c6c3aba0744edce3fb2074922d3776c0af2a6d" + integrity sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ== + dependencies: + estree-walker "^2.0.1" + picomatch "^2.2.2" + "@testing-library/dom@^8.5.0": version "8.16.0" resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-8.16.0.tgz#d6fc50250aed17b1035ca1bd64655e342db3936a" @@ -2550,6 +2566,11 @@ estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== +estree-walker@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" + integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== + esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" @@ -2863,6 +2884,13 @@ graceful-fs@^4.1.6, graceful-fs@^4.2.0: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== +graphql-tag@^2.2.2: + version "2.12.6" + resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.12.6.tgz#d441a569c1d2537ef10ca3d1633b48725329b5f1" + integrity sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg== + dependencies: + tslib "^2.1.0" + graphql@^16.5.0: version "16.5.0" resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.5.0.tgz#41b5c1182eaac7f3d47164fb247f61e4dfb69c85" @@ -4007,7 +4035,7 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==