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

Multiple improvements (#164)

* Added twitter handle validation

* improved validation and sameAs checkbox logic

* Made the page scroll to top when it shows up

* updated the twitter handle validation

* fixed can't go to next step issue in React Only mode
parent 5e78fd9b
......@@ -515,6 +515,9 @@ function callSendData(
if (getCurrentMode() === MODE_REACT_ONLY) {
console.log(`You called ${url} with Method ${method} and data body is:`);
console.log(JSON.stringify(dataBody));
if (goToNextStepObj) {
goToNextStepObj.method(goToNextStepObj.stepNum, goToNextStepObj.pathName);
}
}
if (getCurrentMode() === MODE_REACT_API) {
......@@ -708,3 +711,7 @@ export function requestErrorHandler(
break;
}
}
export function scrollToTop() {
window.scrollTo({ top: 0, behavior: 'smooth' });
}
......@@ -6,6 +6,7 @@ import {
matchCompanyFields,
matchContactFields,
requestErrorHandler,
scrollToTop,
} from '../../../Utils/formFunctionHelpers';
import CompanyInformationCompany from './CompanyInformationCompany';
import CompanyInformationContacts from './CompanyInformationContacts';
......@@ -57,6 +58,10 @@ const CompanyInformation = ({
const [loading, setLoading] = useState(true);
const { setFieldValue } = formik;
useEffect(() => {
scrollToTop();
}, []);
useEffect(() => {
const detectModeAndFetch = () => {
// Once we have API set up ready, we don't need the
......
......@@ -47,6 +47,8 @@ const CompanyInformationCompany = ({ formik, useStyles }) => {
requiredMark={true}
value={formik.values.organization.twitterHandle}
onChange={formik.handleChange}
error={Boolean(formik.errors.organization?.twitterHandle)}
helperText={formik.errors.organization?.twitterHandle}
/>
</div>
</div>
......
......@@ -49,31 +49,44 @@ const Contacts = ({ formik }) => {
};
const handleMemberInputChange = (value, name) => {
const representativeValue = formik.values.representative;
const memberRepInfo = {
...formik.values.representative.member,
...representativeValue.member,
[name]: value,
};
formik.setFieldValue('representative.member', memberRepInfo);
let newRepresentativeValue = {
...representativeValue,
member: memberRepInfo,
};
// update representative.marketing values based on related checkbox
if (isMarketingSameAsCompany) {
const newValues = {
const newMarketingRepValues = {
...memberRepInfo,
id: formik.values.representative.marketing.id || '',
id: representativeValue.marketing.id || '',
sameAsCompany: isMarketingSameAsCompany,
};
formik.setFieldValue('representative.marketing', newValues);
newRepresentativeValue = {
...newRepresentativeValue,
marketing: newMarketingRepValues,
};
}
// update representative.accounting values based on related checkbox
if (isAccountingSameAsCompany) {
const newValues = {
const newAccountingRepValues = {
...memberRepInfo,
id: formik.values.representative.accounting.id || '',
id: representativeValue.accounting.id || '',
sameAsCompany: isAccountingSameAsCompany,
};
formik.setFieldValue('representative.accounting', newValues);
newRepresentativeValue = {
...newRepresentativeValue,
accounting: newAccountingRepValues,
};
}
formik.setFieldValue('representative', newRepresentativeValue);
};
const generateContacts = (
......@@ -98,14 +111,8 @@ const Contacts = ({ formik }) => {
: formik.handleChange
}
value={formik.values.representative?.[type]?.[el.name]}
error={
formik.touched.representative?.[type]?.[el.name] &&
Boolean(formik.errors.representative?.[type]?.[el.name])
}
helperText={
formik.touched.representative?.[type]?.[el.name] &&
formik.errors.representative?.[type]?.[el.name]
}
error={Boolean(formik.errors.representative?.[type]?.[el.name])}
helperText={formik.errors.representative?.[type]?.[el.name]}
/>
</div>
))}
......
......@@ -4,6 +4,8 @@ import Autocomplete from '@material-ui/lab/Autocomplete';
import CustomStepButton from '../../UIComponents/Button/CustomStepButton';
import { formField } from '../../UIComponents/FormComponents/formFieldModel';
import { MEMBERSHIP_LEVELS } from '../../../Constants/Constants';
import { useEffect } from 'react';
import { scrollToTop } from '../../../Utils/formFunctionHelpers';
/**
* Render membership select component (use React-Select), with fetch and prefill data operation
......@@ -25,6 +27,10 @@ const MembershipLevel = ({ formik }) => {
const { membershipLevel } = formField;
const classes = useStyles();
useEffect(() => {
scrollToTop();
}, []);
return (
<form onSubmit={formik.handleSubmit}>
<div className="align-center">
......
import React from 'react';
import React, { useEffect } from 'react';
import CustomStepButton from '../../UIComponents/Button/CustomStepButton';
import { FormValue } from '../../../Interfaces/form_interface';
import { scrollToTop } from '../../../Utils/formFunctionHelpers';
interface ReviewProps {
values: FormValue;
......@@ -8,6 +9,10 @@ interface ReviewProps {
}
const Review: React.FC<ReviewProps> = ({ values, submitForm }) => {
useEffect(() => {
scrollToTop();
}, []);
return (
<form onSubmit={() => submitForm(5, '/submitted')}>
<h1 className="fw-600 h2">
......
import CustomStepButton from '../../UIComponents/Button/CustomStepButton';
import Input from '../../UIComponents/Inputs/Input';
import { formField } from '../../UIComponents/FormComponents/formFieldModel';
import { useEffect } from 'react';
import { scrollToTop } from '../../../Utils/formFunctionHelpers';
/**
* Have not added any API calls here,
......@@ -12,6 +14,10 @@ const sectionName = 'signing-authority';
const SigningAuthority = ({ formik }) => {
const { signingAuthorityRepresentative } = formField;
useEffect(() => {
scrollToTop();
}, []);
return (
<form onSubmit={formik.handleSubmit}>
<h1 className="fw-600 h2" id={sectionName}>
......
import { useEffect } from 'react';
import { scrollToTop } from '../../../Utils/formFunctionHelpers';
/**
* This is just a pure html component to
* display after all steps finished and
* final submitted after preview
*/
const SubmitSuccess = () => {
useEffect(() => {
scrollToTop();
}, []);
return (
<>
<h2>Confirmation message on submission: </h2>
......
......@@ -4,6 +4,7 @@ import WorkingGroup from './WorkingGroup';
import {
matchWorkingGroupFields,
requestErrorHandler,
scrollToTop,
} from '../../../Utils/formFunctionHelpers';
import Loading from '../../UIComponents/Loading/Loading';
import {
......@@ -49,6 +50,10 @@ const WorkingGroupsWrapper = ({
const [workingGroupsUserJoined, setWorkingGroupsUserJoined] = useState([]);
const [fullWorkingGroupList, setFullWorkingGroupList] = useState([]);
useEffect(() => {
scrollToTop();
}, []);
// Fetch data only once and prefill data, as long as
// fetchWorkingGroupsData Function does not change,
// will not cause re-render again
......
......@@ -34,15 +34,22 @@ export const validationSchema = [
// First step - company Info
yup.object().shape({
// First step - representative contacts
organization: yup.object().shape({
twitterHandle: yup
.string()
.min(2, 'Twitter handle is too short')
.max(16, 'Twitter handle is too long')
.matches(/^@([A-Za-z0-9_])*$/, 'Please enter a valid Twitter handle'),
}),
representative: yup.object().shape({
member: yup.object().shape({
email: yup.string('Enter your email').email('Enter a valid email'),
email: yup.string().email('Please enter a valid email'),
}),
marketing: yup.object().shape({
email: yup.string('Enter your email').email('Enter a valid email'),
email: yup.string().email('Please enter a valid email'),
}),
accounting: yup.object().shape({
email: yup.string('Enter your email').email('Enter a valid email'),
email: yup.string().email('Please enter a valid email'),
}),
}),
}),
......@@ -57,7 +64,7 @@ export const validationSchema = [
workingGroups: yup.array().of(
yup.object().shape({
workingGroupRepresentative: yup.object().shape({
email: yup.string('Enter your email').email('Enter a valid email'),
email: yup.string().email('Please enter a valid email'),
}),
})
),
......@@ -69,7 +76,7 @@ export const validationSchema = [
firstName: yup.string().required(`${requiredErrorMsg}`),
lastName: yup.string().required(`${requiredErrorMsg}`),
jobtitle: yup.string().required(`${requiredErrorMsg}`),
email: yup.string('Enter your email').email('Enter a valid email'),
email: yup.string().email('Please enter a valid email'),
}),
}),
];
......@@ -20,6 +20,8 @@ const useStyles = makeStyles(() => ({
root: {
marginBottom: 14,
marginTop: 6,
},
input: {
backgroundColor: 'white',
},
}));
......@@ -55,6 +57,7 @@ export default function Input(props) {
fullWidth={true}
placeholder={placeholder}
InputProps={{
className: classes.input,
inputProps: {
'aria-labelledby': ariaLabel,
},
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment