Unverified Commit e2815b8e authored by Zhou (Link)  Fang's avatar Zhou (Link) Fang Committed by GitHub
Browse files

Added the new form fields (#98)

* Added the new form fields

* integrated with new API call

* Added the API call for purchasing, VAT and signing authority

* fixed a typo and cleaned a few comments

* solved the conflicts

* fixed data did not sync up issue
parent 8d44f0dc
...@@ -50,8 +50,15 @@ export const CONTACT_TYPE = { ...@@ -50,8 +50,15 @@ export const CONTACT_TYPE = {
MARKETING: 'MARKETING', MARKETING: 'MARKETING',
ACCOUNTING: 'ACCOUNTING', ACCOUNTING: 'ACCOUNTING',
WORKING_GROUP: 'WORKING_GROUP', WORKING_GROUP: 'WORKING_GROUP',
SIGNING: 'SIGNING',
}; };
export const OPTIONS_FOR_PURCHASING_PROCES = [
{ label: 'Yes', value: 'yes' },
{ label: 'No', value: 'no' },
{ label: 'Not Applicable', value: 'na' },
];
export const END_POINT = { export const END_POINT = {
organizations: 'organizations', organizations: 'organizations',
contacts: 'contacts', contacts: 'contacts',
...@@ -74,7 +81,7 @@ export function getCurrentMode() { ...@@ -74,7 +81,7 @@ export function getCurrentMode() {
'//membership-staging.eclipse.org', '//membership-staging.eclipse.org',
'//membership.eclipse.org/', '//membership.eclipse.org/',
'//www.rem.docker/', '//www.rem.docker/',
].some(value => { ].some((value) => {
return window.location.href.indexOf(value) !== -1; return window.location.href.indexOf(value) !== -1;
}); });
......
...@@ -7,6 +7,7 @@ import { ...@@ -7,6 +7,7 @@ import {
getCurrentMode, getCurrentMode,
MODE_REACT_ONLY, MODE_REACT_ONLY,
MODE_REACT_API, MODE_REACT_API,
OPTIONS_FOR_PURCHASING_PROCES,
} from '../Constants/Constants'; } from '../Constants/Constants';
/** /**
...@@ -88,6 +89,27 @@ export function matchCompanyFields(existingOrganizationData) { ...@@ -88,6 +89,27 @@ export function matchCompanyFields(existingOrganizationData) {
}; };
} }
/**
* @param existingPurchasingAndVATData -
* Existing purchasing process and VAT data, fetched from server
*/
export function mapPurchasingAndVAT(existingPurchasingAndVATData) {
const currentOption = OPTIONS_FOR_PURCHASING_PROCES.find(
(item) =>
item.value === existingPurchasingAndVATData.purchase_order_required
);
return {
// Step1: purchasing process and VAT Info
id: existingPurchasingAndVATData?.id || '',
legalName: existingPurchasingAndVATData?.legal_name || '',
purchasingProcess: existingPurchasingAndVATData.purchase_order_required,
'purchasingProcess-label': currentOption,
vatNumber: existingPurchasingAndVATData.vat_number,
countryOfRegistration: existingPurchasingAndVATData.registration_country,
};
}
/** /**
* @param membershipLevel - * @param membershipLevel -
* Existing membershipLevel data, fetched from server * Existing membershipLevel data, fetched from server
...@@ -118,38 +140,51 @@ export function matchContactFields(existingContactData) { ...@@ -118,38 +140,51 @@ export function matchContactFields(existingContactData) {
let existingAccoutingContact = existingContactData.find( let existingAccoutingContact = existingContactData.find(
(el) => el.type === CONTACT_TYPE.ACCOUNTING (el) => el.type === CONTACT_TYPE.ACCOUNTING
); );
let existingSigningContact = existingContactData.find(
(el) => el.type === CONTACT_TYPE.SIGNING
);
return { return {
member: { organizationContacts: {
id: existingCompanyContact?.id || '', member: {
firstName: existingCompanyContact?.first_name || '', id: existingCompanyContact?.id || '',
lastName: existingCompanyContact?.last_name || '', firstName: existingCompanyContact?.first_name || '',
jobtitle: existingCompanyContact?.job_title || '', lastName: existingCompanyContact?.last_name || '',
email: existingCompanyContact?.email || '', jobtitle: existingCompanyContact?.job_title || '',
}, email: existingCompanyContact?.email || '',
},
marketing: { marketing: {
id: existingMarketingContact?.id || '', id: existingMarketingContact?.id || '',
firstName: existingMarketingContact?.first_name || '', firstName: existingMarketingContact?.first_name || '',
lastName: existingMarketingContact?.last_name || '', lastName: existingMarketingContact?.last_name || '',
jobtitle: existingMarketingContact?.job_title || '', jobtitle: existingMarketingContact?.job_title || '',
email: existingMarketingContact?.email || '', email: existingMarketingContact?.email || '',
sameAsCompany: checkSameContact( sameAsCompany: checkSameContact(
existingCompanyContact, existingCompanyContact,
existingMarketingContact existingMarketingContact
), ),
},
accounting: {
id: existingAccoutingContact?.id || '',
firstName: existingAccoutingContact?.first_name || '',
lastName: existingAccoutingContact?.last_name || '',
jobtitle: existingAccoutingContact?.job_title || '',
email: existingAccoutingContact?.email || '',
sameAsCompany: checkSameContact(
existingCompanyContact,
existingAccoutingContact
),
},
}, },
accounting: { signingAuthorityRepresentative: {
id: existingAccoutingContact?.id || '', id: existingSigningContact?.id || '',
firstName: existingAccoutingContact?.first_name || '', firstName: existingSigningContact?.first_name || '',
lastName: existingAccoutingContact?.last_name || '', lastName: existingSigningContact?.last_name || '',
jobtitle: existingAccoutingContact?.job_title || '', jobtitle: existingSigningContact?.job_title || '',
email: existingAccoutingContact?.email || '', email: existingSigningContact?.email || '',
sameAsCompany: checkSameContact(
existingCompanyContact,
existingAccoutingContact
),
}, },
}; };
} }
...@@ -229,15 +264,20 @@ export function matchCompanyFieldsToBackend(organizationData, formId) { ...@@ -229,15 +264,20 @@ export function matchCompanyFieldsToBackend(organizationData, formId) {
* @param userId - User Id fetched from the server when sign in, sotored in membership context, used for calling APIs * @param userId - User Id fetched from the server when sign in, sotored in membership context, used for calling APIs
*/ */
export function matchMembershipLevelFieldsToBackend( export function matchMembershipLevelFieldsToBackend(
membershipLevel, membershipLevelFormData,
formId, formId,
userId userId
) { ) {
return { return {
id: formId, id: formId,
user_id: userId, user_id: userId,
membership_level: membershipLevel, membership_level: membershipLevelFormData.membershipLevel,
signing_authority: true, signing_authority: true, //what does this do?
purchase_order_required:
membershipLevelFormData.purchasingAndVAT.purchasingProcess,
vat_number: membershipLevelFormData.purchasingAndVAT.vatNumber,
registration_country:
membershipLevelFormData.purchasingAndVAT.countryOfRegistration,
}; };
} }
...@@ -338,17 +378,18 @@ export async function executeSendDataByStep(step, formData, formId, userId) { ...@@ -338,17 +378,18 @@ export async function executeSendDataByStep(step, formData, formId, userId) {
formId formId
) )
); );
callSendData(
formId,
'',
matchMembershipLevelFieldsToBackend(formData, formId, userId)
);
break; break;
case 2: case 2:
callSendData( callSendData(
formId, formId,
'', '',
matchMembershipLevelFieldsToBackend( matchMembershipLevelFieldsToBackend(formData, formId, userId)
formData.membershipLevel,
formId,
userId
)
); );
break; break;
...@@ -363,6 +404,15 @@ export async function executeSendDataByStep(step, formData, formId, userId) { ...@@ -363,6 +404,15 @@ export async function executeSendDataByStep(step, formData, formId, userId) {
break; break;
case 4: case 4:
callSendData(
formId,
END_POINT.contacts,
matchContactFieldsToBackend(
formData.signingAuthorityRepresentative,
CONTACT_TYPE.SIGNING,
formId
)
);
return; return;
default: default:
......
import { useContext, useEffect, useState } from 'react'; import { useContext, useEffect, useState } from 'react';
import MembershipContext from '../../../Context/MembershipContext'; import MembershipContext from '../../../Context/MembershipContext';
import { import {
mapMembershipLevel,
mapPurchasingAndVAT,
matchCompanyFields, matchCompanyFields,
matchContactFields, matchContactFields,
} from '../../../Utils/formFunctionHelpers'; } from '../../../Utils/formFunctionHelpers';
...@@ -14,8 +16,11 @@ import { ...@@ -14,8 +16,11 @@ import {
getCurrentMode, getCurrentMode,
MODE_REACT_ONLY, MODE_REACT_ONLY,
MODE_REACT_API, MODE_REACT_API,
MEMBERSHIP_LEVELS,
} from '../../../Constants/Constants'; } from '../../../Constants/Constants';
import CustomStepButton from '../../UIComponents/Button/CustomStepButton'; import CustomStepButton from '../../UIComponents/Button/CustomStepButton';
import CompanyInformationVAT from './CompanyInformationVAT';
import { makeStyles } from '@material-ui/core';
/** /**
* Wrapper for Contacts and Company components * Wrapper for Contacts and Company components
...@@ -29,6 +34,15 @@ import CustomStepButton from '../../UIComponents/Button/CustomStepButton'; ...@@ -29,6 +34,15 @@ import CustomStepButton from '../../UIComponents/Button/CustomStepButton';
* library (such as "formik.values", "formik.setFieldValue"); * library (such as "formik.values", "formik.setFieldValue");
* - formField: the form field in formModels/formFieldModel.js * - formField: the form field in formModels/formFieldModel.js
*/ */
const useStyles = makeStyles(() => ({
textField: {
marginBottom: 14,
marginTop: 6,
backgroundColor: 'white',
},
}));
const CompanyInformation = ({ formik, isStartNewForm }) => { const CompanyInformation = ({ formik, isStartNewForm }) => {
const { currentFormId, furthestPage } = useContext(MembershipContext); // current chosen form id const { currentFormId, furthestPage } = useContext(MembershipContext); // current chosen form id
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
...@@ -103,7 +117,62 @@ const CompanyInformation = ({ formik, isStartNewForm }) => { ...@@ -103,7 +117,62 @@ const CompanyInformation = ({ formik, isStartNewForm }) => {
// Prefill Data --> Call the setFieldValue of Formik, // Prefill Data --> Call the setFieldValue of Formik,
// to set representative field with the mapped data, // to set representative field with the mapped data,
// if nested, it will automatically map the properties and values // if nested, it will automatically map the properties and values
formik.setFieldValue('representative', tempContacts); formik.setFieldValue(
'representative',
tempContacts.organizationContacts
);
formik.setFieldValue(
'signingAuthorityRepresentative',
tempContacts.signingAuthorityRepresentative
);
}
setLoading(false);
});
} else {
setLoading(false);
}
};
const detectModeAndFetchMembershipLevel = () => {
let url_prefix_local;
let url_suffix_local = '';
if (getCurrentMode() === MODE_REACT_ONLY) {
url_prefix_local = 'membership_data';
url_suffix_local = '/form.json';
}
if (getCurrentMode() === MODE_REACT_API) {
url_prefix_local = API_PREFIX_FORM;
}
// If the current form exsits, and it is not creating a new form
if (currentFormId) {
fetch(url_prefix_local + `/${currentFormId}` + url_suffix_local, {
headers: FETCH_HEADER,
})
.then((resp) => resp.json())
.then((data) => {
if (data) {
// mapMembershipLevel(): Call the the function to map
// the retrived membership level backend data to fit frontend, and
// setFieldValue(): Prefill Data --> Call the setFieldValue of
// Formik, to set membershipLevel field with the mapped data
const tempMembershipLevel = mapMembershipLevel(
data[0]?.membership_level,
MEMBERSHIP_LEVELS
);
formik.setFieldValue(
'membershipLevel',
tempMembershipLevel.value
);
formik.setFieldValue(
'membershipLevel-label',
tempMembershipLevel
);
const tempPurchasingAndVAT = mapPurchasingAndVAT(data[0]);
formik.setFieldValue('purchasingAndVAT', tempPurchasingAndVAT);
} }
setLoading(false); setLoading(false);
}); });
...@@ -130,6 +199,7 @@ const CompanyInformation = ({ formik, isStartNewForm }) => { ...@@ -130,6 +199,7 @@ const CompanyInformation = ({ formik, isStartNewForm }) => {
// then it means this is the 1st time the user see this page // then it means this is the 1st time the user see this page
// need to GET the data // need to GET the data
detectModeAndFetch(); detectModeAndFetch();
detectModeAndFetchMembershipLevel();
} else { } else {
// user already has the data, no need to do any API call // user already has the data, no need to do any API call
setLoading(false); setLoading(false);
...@@ -151,8 +221,9 @@ const CompanyInformation = ({ formik, isStartNewForm }) => { ...@@ -151,8 +221,9 @@ const CompanyInformation = ({ formik, isStartNewForm }) => {
name and address of your organization. name and address of your organization.
</p> </p>
<div className="align-center"> <div className="align-center">
<CompanyInformationCompany formik={formik} /> <CompanyInformationCompany formik={formik} useStyles={useStyles} />
<CompanyInformationContacts formik={formik} /> <CompanyInformationContacts formik={formik} />
<CompanyInformationVAT formik={formik} useStyles={useStyles} />
</div> </div>
<CustomStepButton <CustomStepButton
......
import Input from '../../UIComponents/Inputs/Input'; import Input from '../../UIComponents/Inputs/Input';
import { formField } from '../../UIComponents/FormComponents/formFieldModel'; import { formField } from '../../UIComponents/FormComponents/formFieldModel';
import Autocomplete from '@material-ui/lab/Autocomplete'; import Autocomplete from '@material-ui/lab/Autocomplete';
import { makeStyles, TextField } from '@material-ui/core'; import { TextField } from '@material-ui/core';
/** /**
* Render Oraganization selector (used React-Select) * Render Oraganization selector (used React-Select)
...@@ -12,15 +12,7 @@ import { makeStyles, TextField } from '@material-ui/core'; ...@@ -12,15 +12,7 @@ import { makeStyles, TextField } from '@material-ui/core';
* correct country list names) * correct country list names)
*/ */
const useStyles = makeStyles(() => ({ const CompanyInformationCompany = ({ formik, useStyles }) => {
textField: {
marginBottom: 14,
marginTop: 6,
backgroundColor: 'white',
},
}));
const CompanyInformationCompany = ({ formik }) => {
const classes = useStyles(); const classes = useStyles();
const { organizationName, organizationTwitter, organizationAddress } = const { organizationName, organizationTwitter, organizationAddress } =
formField; formField;
......
...@@ -156,7 +156,7 @@ const Contacts = ({ formik }) => { ...@@ -156,7 +156,7 @@ const Contacts = ({ formik }) => {
label="Same as member rep." label="Same as member rep."
/> />
<div className="row"> <div className="row margin-bottom-40">
{generateContacts( {generateContacts(
companyRep, companyRep,
'accounting-rep', 'accounting-rep',
......
import Input from '../../UIComponents/Inputs/Input';
import { formField } from '../../UIComponents/FormComponents/formFieldModel';
import { TextField } from '@material-ui/core';
import Autocomplete from '@material-ui/lab/Autocomplete';
import { OPTIONS_FOR_PURCHASING_PROCES } from '../../../Constants/Constants';
const { purchasingProcess, vatRegistration } = formField;
export default function CompanyInformationVAT({ formik, useStyles }) {
const classes = useStyles();
return (
<>
<h4
className="fw-600 section-header"
id={`${purchasingProcess.name}-ctn`}
>
Purchasing Process
<span className="orange-star margin-left-5">*</span>
</h4>
<p>
Does your organization require a Purchase Order to facilitate payment of
your membership dues?
</p>
<div className="row">
<div className="col-md-12 margin-bottom-40">
<Autocomplete
id={purchasingProcess.name}
options={OPTIONS_FOR_PURCHASING_PROCES}
getOptionLabel={(option) => (option?.label ? option.label : '')}
getOptionSelected={(option, value) => option.value === value.value}
fullWidth={true}
onChange={(ev, value) => {
// this is only for display
formik.setFieldValue(
`${purchasingProcess.name}-label`,
value ? value : null
);
// this is the data will be actually used
formik.setFieldValue(
purchasingProcess.name,
value ? value.value : null
);
}}
value={
formik.values.purchasingAndVAT['purchasingProcess-label']
? formik.values.purchasingAndVAT['purchasingProcess-label']
: null
}
renderInput={(params) => {
params.inputProps = {
...params.inputProps,
'aria-labelledby': `${purchasingProcess.name}-ctn`,
};
return (
<TextField
{...params}
label={purchasingProcess.label}
placeholder={purchasingProcess.placeholder}
variant="outlined"
size="small"
required={true}
className={classes.textField}
/>
);
}}
/>
</div>
</div>
<h4 className="fw-600" id="vatRegistration">
VAT Registration
</h4>
<p>
If your organization is registered for VAT in the European Union, please
provide the following:
</p>
<div className="row">
<div className="col-md-12">
<Input
name={vatRegistration.vatNumber.name}
labelName={vatRegistration.vatNumber.label}
placeholder={vatRegistration.vatNumber.placeholder}
requiredMark={false}
value={formik.values.purchasingAndVAT.vatNumber}
onChange={formik.handleChange}
ariaLabel={`vatRegistration`}
/>
</div>
<div className="col-md-12">
<Input
name={vatRegistration.countryOfRegistration.name}
labelName={vatRegistration.countryOfRegistration.label}
placeholder={vatRegistration.countryOfRegistration.placeholder}
requiredMark={false}
value={formik.values.purchasingAndVAT.countryOfRegistration}
onChange={formik.handleChange}
ariaLabel={`vatRegistration`}
/>
</div>
</div>
</>
);
}
...@@ -2,10 +2,7 @@ import { useContext, useState } from 'react'; ...@@ -2,10 +2,7 @@ import { useContext, useState } from 'react';
import { Switch, Route, Redirect } from 'react-router-dom'; import { Switch, Route, Redirect } from 'react-router-dom';
import { useFormik } from 'formik'; import { useFormik } from 'formik';
import SignIn from './SignIn/SignIn'; import SignIn from './SignIn/SignIn';
import { import { COMPANY_INFORMATION, PAGE_STEP } from '../../Constants/Constants';
COMPANY_INFORMATION,
PAGE_STEP,
} from '../../Constants/Constants';
import { import {
formField, formField,
initialValues, initialValues,
...@@ -36,11 +33,16 @@ export default function Main() { ...@@ -36,11 +33,16 @@ export default function Main() {
history.push(nextPage); history.push(nextPage);
}; };
const submitForm = (pageIndex, nextPage) => { const updateMembershipLevelForm = (values) => {
// do something for submiting values.forEach((item) => {
// ... formikMembershipLevel.setFieldValue(item.field, item.value);