Add mentor validation
This commit is contained in:
parent
c6c6649245
commit
99e12f7681
@ -18,6 +18,7 @@
|
||||
"@types/react-router-dom": "^5.1.5",
|
||||
"@types/redux": "^3.6.0",
|
||||
"@types/redux-persist": "^4.3.1",
|
||||
"@types/yup": "^0.29.4",
|
||||
"@typescript-eslint/eslint-plugin": "^2.10.0",
|
||||
"@typescript-eslint/parser": "^2.10.0",
|
||||
"babel-core": "^6.26.3",
|
||||
@ -30,6 +31,7 @@
|
||||
"date-holidays": "^1.5.3",
|
||||
"file-loader": "4.3.0",
|
||||
"formik": "^2.1.5",
|
||||
"formik-material-ui": "^3.0.0-alpha.0",
|
||||
"html-webpack-plugin": "4.0.0-beta.11",
|
||||
"i18next": "^19.6.0",
|
||||
"i18next-browser-languagedetector": "^5.0.0",
|
||||
@ -63,7 +65,8 @@
|
||||
"webpack-cli": "^3.3.11",
|
||||
"webpack-dev-server": "3.10.3",
|
||||
"workbox-webpack-plugin": "4.3.1",
|
||||
"yaml-loader": "^0.6.0"
|
||||
"yaml-loader": "^0.6.0",
|
||||
"yup": "^0.29.3"
|
||||
},
|
||||
"scripts": {
|
||||
"serve": "webpack-dev-server --mode development",
|
||||
|
@ -1,3 +1,5 @@
|
||||
export type Identifier = string;
|
||||
|
||||
export interface Identifiable {
|
||||
id?: string
|
||||
id?: Identifier
|
||||
}
|
||||
|
@ -8,6 +8,8 @@ import { InternshipFormSectionProps } from "@/forms/internship";
|
||||
import { emptyMentor } from "@/provider/dummy/internship";
|
||||
import { useProxyState } from "@/hooks";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Field } from "formik";
|
||||
import { TextField as TextFieldFormik } from "formik-material-ui"
|
||||
|
||||
export type CompanyFormProps = {} & InternshipFormSectionProps;
|
||||
|
||||
@ -95,27 +97,24 @@ export const BranchForm: React.FC<BranchOfficeProps> = ({ value: office, onChang
|
||||
)
|
||||
}
|
||||
|
||||
export const MentorForm = ({ mentor, onMentorChange }: BoundProperty<Mentor, 'onMentorChange', 'mentor'>) => {
|
||||
const fieldProps = formFieldProps(mentor, onMentorChange)
|
||||
export const MentorForm = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Grid container>
|
||||
<Grid item md={6}>
|
||||
<TextField label={ t("forms.internship.fields.first-name") } fullWidth { ...fieldProps("name") }/>
|
||||
</Grid>
|
||||
<Grid item md={6}>
|
||||
<TextField label={ t("forms.internship.fields.last-name") } value={ mentor.surname } fullWidth { ...fieldProps("surname") }/>
|
||||
</Grid>
|
||||
<Grid item md={8}>
|
||||
<TextField label={ t("forms.internship.fields.e-mail") } value={ mentor.email } fullWidth { ...fieldProps("email") }/>
|
||||
</Grid>
|
||||
<Grid item md={4}>
|
||||
<TextField label={ t("forms.internship.fields.phone" )} value={ mentor.phone } fullWidth { ...fieldProps("phone") }/>
|
||||
</Grid>
|
||||
<Grid container>
|
||||
<Grid item md={6}>
|
||||
<Field name="mentorFirstName" label={ t("forms.internship.fields.first-name") } fullWidth component={ TextFieldFormik } />
|
||||
</Grid>
|
||||
</>
|
||||
<Grid item md={6}>
|
||||
<Field name="mentorLastName" label={ t("forms.internship.fields.last-name") } fullWidth component={ TextFieldFormik } />
|
||||
</Grid>
|
||||
<Grid item md={8}>
|
||||
<Field name="mentorEmail" label={ t("forms.internship.fields.e-mail") } fullWidth component={ TextFieldFormik } />
|
||||
</Grid>
|
||||
<Grid item md={4}>
|
||||
<Field name="mentorPhone" label={ t("forms.internship.fields.phone") } fullWidth component={ TextFieldFormik } />
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
}
|
||||
|
||||
@ -162,7 +161,7 @@ export const CompanyForm: React.FunctionComponent<CompanyFormProps> = ({ interns
|
||||
{/*</Grid>*/}
|
||||
</Grid>
|
||||
<Typography variant="subtitle1" className="subsection-header">{ t("internship.mentor") }</Typography>
|
||||
<MentorForm mentor={ mentor } onMentorChange={ setMentor }/>
|
||||
<MentorForm />
|
||||
<Typography variant="subtitle1" className="subsection-header">{ t("internship.office") }</Typography>
|
||||
<BranchForm value={ office } onChange={ setOffice } offices={ company.offices } />
|
||||
</>
|
||||
|
@ -4,7 +4,7 @@ import { KeyboardDatePicker as DatePicker } from "@material-ui/pickers";
|
||||
import { CompanyForm } from "@/forms/company";
|
||||
import { StudentForm } from "@/forms/student";
|
||||
import { sampleStudent } from "@/provider/dummy/student";
|
||||
import { Internship, InternshipType, internshipTypeLabels } from "@/data";
|
||||
import { BranchOffice, Company, Internship, InternshipType, internshipTypeLabels, Student } from "@/data";
|
||||
import { Nullable } from "@/helpers";
|
||||
import moment, { Moment } from "moment";
|
||||
import { computeWorkingHours } from "@/utils/date";
|
||||
@ -20,6 +20,8 @@ import { route } from "@/routing";
|
||||
import { useProxyState } from "@/hooks";
|
||||
import { getInternshipProposal } from "@/state/reducer/proposal";
|
||||
import { Actions } from "@/components";
|
||||
import { Form, Formik } from "formik";
|
||||
import * as Yup from "yup";
|
||||
|
||||
export type InternshipFormProps = {}
|
||||
|
||||
@ -28,6 +30,50 @@ export type InternshipFormSectionProps = {
|
||||
onChange: (internship: Nullable<Internship>) => void,
|
||||
}
|
||||
|
||||
export type InternshipFormState = {
|
||||
startDate: Moment | null;
|
||||
endDate: Moment | null;
|
||||
hours: number | null;
|
||||
companyName: string;
|
||||
companyNip: string;
|
||||
city: string;
|
||||
postalCode: string;
|
||||
country: string;
|
||||
building: string;
|
||||
mentorFirstName: string;
|
||||
mentorLastName: string;
|
||||
mentorEmail: string;
|
||||
mentorPhone: string;
|
||||
kindOther: string | null;
|
||||
|
||||
// relations
|
||||
kind: InternshipType | null;
|
||||
company: Company | null;
|
||||
office: BranchOffice | null;
|
||||
student: Student | null;
|
||||
}
|
||||
|
||||
const emptyInternshipValues: InternshipFormState = {
|
||||
building: "",
|
||||
city: "",
|
||||
company: null,
|
||||
companyName: "",
|
||||
companyNip: "",
|
||||
country: "",
|
||||
endDate: null,
|
||||
hours: null,
|
||||
kind: null,
|
||||
kindOther: "",
|
||||
mentorEmail: "",
|
||||
mentorFirstName: "",
|
||||
mentorLastName: "",
|
||||
mentorPhone: "",
|
||||
office: null,
|
||||
postalCode: "",
|
||||
startDate: null,
|
||||
student: null
|
||||
}
|
||||
|
||||
export const InternshipTypeItem = ({ type, ...props }: { type: InternshipType } & HTMLProps<any>) => {
|
||||
const info = internshipTypeLabels[type];
|
||||
|
||||
@ -158,34 +204,50 @@ export const InternshipForm: React.FunctionComponent<InternshipFormProps> = prop
|
||||
setConfirmDialogOpen(false);
|
||||
}
|
||||
|
||||
const validationSchema = Yup.object<Partial<InternshipFormState>>({
|
||||
mentorFirstName: Yup.string().required(t("validation.required")),
|
||||
mentorLastName: Yup.string().required(t("validation.required")),
|
||||
mentorEmail: Yup.string()
|
||||
.required(t("validation.required"))
|
||||
.email(t("validation.email")),
|
||||
mentorPhone: Yup.string()
|
||||
.required(t("validation.required"))
|
||||
.matches(/^[+]*[(]{0,1}[0-9]{1,4}[)]{0,1}[-\s\./0-9]*$/, t("validation.phone")),
|
||||
hours: Yup.number()
|
||||
.min(40, t("validation.internship.minimum-hours")) // todo: take it from edition
|
||||
})
|
||||
|
||||
return (
|
||||
<div className="internship-form">
|
||||
<Typography variant="h3" className="section-header">{ t('internship.sections.intern-info') }</Typography>
|
||||
<StudentForm student={ sampleStudent }/>
|
||||
<Typography variant="h3" className="section-header">{ t('internship.sections.kind' )}</Typography>
|
||||
<InternshipProgramForm internship={ internship } onChange={ setInternship }/>
|
||||
<Typography variant="h3" className="section-header">{ t('internship.sections.duration') }</Typography>
|
||||
<InternshipDurationForm internship={ internship } onChange={ setInternship }/>
|
||||
<Typography variant="h3" className="section-header">{ t('internship.sections.place') }</Typography>
|
||||
<CompanyForm internship={ internship } onChange={ setInternship }/>
|
||||
<Actions>
|
||||
<Button variant="contained" color="primary" onClick={ handleSubmitConfirmation }>{ t("confirm") }</Button>
|
||||
<Formik initialValues={ emptyInternshipValues } onSubmit={ values => console.log(values) }
|
||||
validationSchema={ validationSchema } validateOnChange={ false } validateOnBlur={ true }>
|
||||
{ formik => <Form>
|
||||
<Typography variant="h3" className="section-header">{ t('internship.sections.intern-info') }</Typography>
|
||||
<StudentForm student={ sampleStudent }/>
|
||||
<Typography variant="h3" className="section-header">{ t('internship.sections.kind' )}</Typography>
|
||||
<InternshipProgramForm internship={ internship } onChange={ setInternship }/>
|
||||
<Typography variant="h3" className="section-header">{ t('internship.sections.duration') }</Typography>
|
||||
<InternshipDurationForm internship={ internship } onChange={ setInternship }/>
|
||||
<Typography variant="h3" className="section-header">{ t('internship.sections.place') }</Typography>
|
||||
<CompanyForm internship={ internship } onChange={ setInternship }/>
|
||||
<Actions>
|
||||
<Button variant="contained" color="primary" onClick={ () => formik.validateForm(formik.values) }>{ t("confirm") }</Button>
|
||||
|
||||
<Button component={ RouterLink } to={ route("home") }>
|
||||
{ t('go-back') }
|
||||
</Button>
|
||||
</Actions>
|
||||
<Button component={ RouterLink } to={ route("home") }>
|
||||
{ t('go-back') }
|
||||
</Button>
|
||||
</Actions>
|
||||
|
||||
<Dialog open={ confirmDialogOpen } onClose={ handleCancel }>
|
||||
<DialogContent>
|
||||
<DialogContentText>{ t('forms.internship.send-confirmation') }</DialogContentText>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={ handleCancel }>{ t('cancel') }</Button>
|
||||
<Button color="primary" autoFocus onClick={ handleSubmit }>{ t('confirm') }</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
</div>
|
||||
<Dialog open={ confirmDialogOpen } onClose={ handleCancel }>
|
||||
<DialogContent>
|
||||
<DialogContentText>{ t('forms.internship.send-confirmation') }</DialogContentText>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={ handleCancel }>{ t('cancel') }</Button>
|
||||
<Button color="primary" autoFocus onClick={ formik.submitForm }>{ t('confirm') }</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
</Form> }
|
||||
</Formik>
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -159,4 +159,9 @@ steps:
|
||||
instructions: >
|
||||
papierki do podpisania...
|
||||
|
||||
validation:
|
||||
required: "To pole jest wymagane"
|
||||
email: "Wprowadź poprawny adres e-mail"
|
||||
phone: "Wprowadź poprawny numer telefonu"
|
||||
|
||||
contact-coordinator: "Skontaktuj się z koordynatorem"
|
||||
|
52
yarn.lock
52
yarn.lock
@ -933,6 +933,13 @@
|
||||
dependencies:
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
"@babel/runtime@^7.10.5":
|
||||
version "7.11.2"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.11.2.tgz#f549c13c754cc40b87644b9fa9f09a6a95fe0736"
|
||||
integrity sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
"@babel/template@^7.10.1", "@babel/template@^7.8.6":
|
||||
version "7.10.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.1.tgz#e167154a94cb5f14b28dc58f5356d2162f539811"
|
||||
@ -1311,6 +1318,11 @@
|
||||
"@types/webpack-sources" "*"
|
||||
source-map "^0.6.0"
|
||||
|
||||
"@types/yup@^0.29.4":
|
||||
version "0.29.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/yup/-/yup-0.29.4.tgz#f7b1f9978180d5155663c1cd0ecdc41a72c23d81"
|
||||
integrity sha512-OQ7gZRQb7eSbGu5h57tbK67sgX8UH5wbuqPORTFBG7qiBtOkEf1dXAr0QULyHIeRwaGLPYxPXiQru+40ClR6ng==
|
||||
|
||||
"@typescript-eslint/eslint-plugin@^2.10.0":
|
||||
version "2.34.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.34.0.tgz#6f8ce8a46c7dea4a6f1d171d2bb8fbae6dac2be9"
|
||||
@ -3919,6 +3931,11 @@ flush-write-stream@^1.0.0:
|
||||
inherits "^2.0.3"
|
||||
readable-stream "^2.3.6"
|
||||
|
||||
fn-name@~3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fn-name/-/fn-name-3.0.0.tgz#0596707f635929634d791f452309ab41558e3c5c"
|
||||
integrity sha512-eNMNr5exLoavuAMhIUVsOKF79SWd/zG104ef6sxBTSw+cZc6BXdQXDvYcGvp0VbxVVSp1XDUNoz7mg1xMtSznA==
|
||||
|
||||
follow-redirects@^1.0.0:
|
||||
version "1.11.0"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.11.0.tgz#afa14f08ba12a52963140fe43212658897bc0ecb"
|
||||
@ -3959,6 +3976,11 @@ form-data@~2.3.2:
|
||||
combined-stream "^1.0.6"
|
||||
mime-types "^2.1.12"
|
||||
|
||||
formik-material-ui@^3.0.0-alpha.0:
|
||||
version "3.0.0-alpha.0"
|
||||
resolved "https://registry.yarnpkg.com/formik-material-ui/-/formik-material-ui-3.0.0-alpha.0.tgz#4020b5cbd9e431406fb275a317cdce95ad398545"
|
||||
integrity sha512-N9JcSngi4nWaKN67sN1M3ILXgz0fLCdoMhHHecrZC3NeR+C5lWWAUuAcjGZWNj+z87Qt7NW8VXlxSnGxGus8Uw==
|
||||
|
||||
formik@^2.1.5:
|
||||
version "2.1.5"
|
||||
resolved "https://registry.yarnpkg.com/formik/-/formik-2.1.5.tgz#de5bbbe35543fa6d049fe96b8ee329d6cd6892b8"
|
||||
@ -5383,7 +5405,7 @@ locate-path@^5.0.0:
|
||||
dependencies:
|
||||
p-locate "^4.1.0"
|
||||
|
||||
lodash-es@^4.17.14:
|
||||
lodash-es@^4.17.11, lodash-es@^4.17.14:
|
||||
version "4.17.15"
|
||||
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.15.tgz#21bd96839354412f23d7a10340e5eac6ee455d78"
|
||||
integrity sha512-rlrc3yU3+JNOpZ9zj5pQtxnx2THmvRykwL4Xlxoa8I9lHBlVbbyPhgyPMioxVZ4NqyxaVVtaJnzsyOidQIhyyQ==
|
||||
@ -7216,6 +7238,11 @@ prop-types@^15.6.2, prop-types@^15.7.2:
|
||||
object-assign "^4.1.1"
|
||||
react-is "^16.8.1"
|
||||
|
||||
property-expr@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-2.0.2.tgz#fff2a43919135553a3bc2fdd94bdb841965b2330"
|
||||
integrity sha512-bc/5ggaYZxNkFKj374aLbEDqVADdYaLcFo8XBkishUWbaAdjlphaBFns9TvRA2pUseVL/wMFmui9X3IdNDU37g==
|
||||
|
||||
proxy-addr@~2.0.5:
|
||||
version "2.0.6"
|
||||
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf"
|
||||
@ -8591,6 +8618,11 @@ symbol-observable@^1.2.0:
|
||||
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
|
||||
integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==
|
||||
|
||||
synchronous-promise@^2.0.13:
|
||||
version "2.0.13"
|
||||
resolved "https://registry.yarnpkg.com/synchronous-promise/-/synchronous-promise-2.0.13.tgz#9d8c165ddee69c5a6542862b405bc50095926702"
|
||||
integrity sha512-R9N6uDkVsghHePKh1TEqbnLddO2IY25OcsksyFp/qBe7XYd0PVbKEWxhcdMhpLzE1I6skj5l4aEZ3CRxcbArlA==
|
||||
|
||||
tapable@^1.0.0, tapable@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2"
|
||||
@ -8733,6 +8765,11 @@ toidentifier@1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
|
||||
integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
|
||||
|
||||
toposort@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/toposort/-/toposort-2.0.2.tgz#ae21768175d1559d48bef35420b2f4962f09c330"
|
||||
integrity sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=
|
||||
|
||||
tough-cookie@~2.5.0:
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
|
||||
@ -9506,3 +9543,16 @@ yargs@^13.3.2:
|
||||
which-module "^2.0.0"
|
||||
y18n "^4.0.0"
|
||||
yargs-parser "^13.1.2"
|
||||
|
||||
yup@^0.29.3:
|
||||
version "0.29.3"
|
||||
resolved "https://registry.yarnpkg.com/yup/-/yup-0.29.3.tgz#69a30fd3f1c19f5d9e31b1cf1c2b851ce8045fea"
|
||||
integrity sha512-RNUGiZ/sQ37CkhzKFoedkeMfJM0vNQyaz+wRZJzxdKE7VfDeVKH8bb4rr7XhRLbHJz5hSjoDNwMEIaKhuMZ8gQ==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.10.5"
|
||||
fn-name "~3.0.0"
|
||||
lodash "^4.17.15"
|
||||
lodash-es "^4.17.11"
|
||||
property-expr "^2.0.2"
|
||||
synchronous-promise "^2.0.13"
|
||||
toposort "^2.0.2"
|
||||
|
Loading…
Reference in New Issue
Block a user