import React, { HTMLProps, useMemo, useState } from "react"; import { Button, Dialog, DialogActions, DialogContent, DialogContentText, Grid, TextField, Typography } from "@material-ui/core"; 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 { Company, Internship, InternshipType, internshipTypeLabels, Office, Student } from "@/data"; import { Nullable } from "@/helpers"; import moment, { Moment } from "moment"; import { computeWorkingHours } from "@/utils/date"; import { Autocomplete } from "@material-ui/lab"; import { emptyInternship } from "@/provider/dummy/internship"; import { InternshipProposalActions, useDispatch } from "@/state/actions"; import { useTranslation } from "react-i18next"; import { useSelector } from "react-redux"; import { AppState } from "@/state/reducer"; import { Link as RouterLink, useHistory } from "react-router-dom"; import { route } from "@/routing"; import { getInternshipProposal } from "@/state/reducer/proposal"; import { Actions } from "@/components"; import { Field, Form, Formik, useFormikContext } from "formik"; import * as Yup from "yup"; import { Transformer } from "@/serialization"; import { TextField as TextFieldFormik } from "formik-material-ui" import { Edition } from "@/data/edition"; import { useUpdateEffect } from "@/hooks"; export type InternshipFormValues = { startDate: Moment | null; endDate: Moment | null; hours: number | ""; workingHours: number; companyName: string; companyNip: string; city: string; postalCode: string; country: string; street: string; building: string; mentorFirstName: string; mentorLastName: string; mentorEmail: string; mentorPhone: string; kindOther: string | null; // relations kind: InternshipType | null; company: Company | null; office: Office | null; student: Student; } const emptyInternshipValues: InternshipFormValues = { building: "", city: "", company: null, companyName: "", companyNip: "", country: "", street: "", endDate: null, hours: "", kind: null, kindOther: "", mentorEmail: "", mentorFirstName: "", mentorLastName: "", mentorPhone: "", office: null, postalCode: "", startDate: null, student: sampleStudent, workingHours: 40, } export const InternshipTypeItem = ({ type, ...props }: { type: InternshipType } & HTMLProps) => { const info = internshipTypeLabels[type]; return (
{ info.label }
{ info.description && { info.description } }
) } const InternshipProgramForm = () => { const { t } = useTranslation(); const { values, handleBlur, setFieldValue, errors } = useFormikContext(); return ( } getOptionLabel={ (option: InternshipType) => internshipTypeLabels[option].label } renderOption={ (option: InternshipType) => } options={ Object.values(InternshipType) as InternshipType[] } disableClearable value={ values.kind || undefined } onChange={ (_, value) => setFieldValue("kind", value) } onBlur={ handleBlur } /> { values.kind === InternshipType.Other && } ) } const InternshipDurationForm = () => { const { t } = useTranslation(); const { values: { startDate, endDate, workingHours }, errors, touched, setFieldTouched, setFieldValue } = useFormikContext(); const [overrideHours, setHoursOverride] = useState(null) const computedHours = useMemo(() => startDate && endDate && computeWorkingHours(startDate, endDate, workingHours / 5), [startDate, endDate, workingHours]); const hours = useMemo(() => overrideHours !== null ? overrideHours : computedHours || null, [overrideHours, computedHours]); const weeks = useMemo(() => hours !== null ? Math.floor(hours / workingHours) : null, [ hours ]); useUpdateEffect(() => { setFieldTouched("hours", true); setFieldValue("hours", hours, true); }, [ hours ]); return ( setFieldValue("startDate", value) } format="DD MMMM yyyy" disableToolbar fullWidth variant="inline" label={ t("forms.internship.fields.start-date") } minDate={ moment() } /> setFieldValue("endDate", value) } format="DD MMMM yyyy" disableToolbar fullWidth variant="inline" label={ t("forms.internship.fields.end-date") } minDate={ startDate || moment() } /> setHoursOverride(parseInt(ev.target.value) || 0) } /> ); } type InternshipConverterContext = { internship: Internship, } const converter: Transformer, InternshipFormValues, InternshipConverterContext> = { transform(internship: Nullable): InternshipFormValues { return { student: internship.intern as Student, kind: internship.type, kindOther: "", startDate: internship.startDate, endDate: internship.endDate, hours: internship.hours || "", building: internship.office?.address?.building || "", office: internship.office, city: internship.office?.address?.city || "", postalCode: internship.office?.address?.postalCode || "", street: internship.office?.address?.street || "", country: internship.office?.address?.country || "", company: internship.company, companyName: internship.company?.name || "", companyNip: internship.company?.nip || "", mentorEmail: internship.mentor?.email || "", mentorFirstName: internship.mentor?.name || "", mentorLastName: internship.mentor?.surname || "", mentorPhone: internship.mentor?.phone || "", workingHours: 40, } }, reverseTransform(form: InternshipFormValues, context: InternshipConverterContext): Nullable { return { ...context.internship, startDate: form.startDate as Moment, endDate: form.endDate as Moment, office: form.office || { address: { street: form.street, postalCode: form.postalCode, country: form.country, city: form.city, building: form.building, } }, mentor: { surname: form.mentorLastName, name: form.mentorFirstName, email: form.mentorEmail, phone: form.mentorPhone, }, company: form.company || { name: form.companyName, nip: form.companyNip, offices: [], }, hours: form.hours as number, type: form.kind as InternshipType, } } } export const InternshipForm: React.FunctionComponent = () => { const initialInternship = useSelector>(state => getInternshipProposal(state.proposal) || { ...emptyInternship, office: null, company: null, mentor: null, intern: sampleStudent }); const edition = useSelector(state => state.edition as Edition); const { t } = useTranslation(); const dispatch = useDispatch(); const history = useHistory(); const [confirmDialogOpen, setConfirmDialogOpen] = useState(false); const validationSchema = Yup.object>({ 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(edition.minimumInternshipHours, t("validation.internship.minimum-hours", { hours: edition.minimumInternshipHours })), companyName: Yup.string().when("company", { is: null, then: Yup.string().required(t("validation.required")) }), companyNip: Yup.string().when("company", { is: null, then: Yup.string() .required(t("validation.required")) }), street: Yup.string().required(t("validation.required")), country: Yup.string().required(t("validation.required")), city: Yup.string().required(t("validation.required")), postalCode: Yup.string().required(t("validation.required")), building: Yup.string().required(t("validation.required")), kindOther: Yup.string().when("kind", { is: (values: InternshipFormValues) => values?.kind === InternshipType.Other, then: Yup.string().required(t("validation.required")) }) }) const values = converter.transform(initialInternship); const handleSubmit = (values: InternshipFormValues) => { setConfirmDialogOpen(false); dispatch({ type: InternshipProposalActions.Send, internship: converter.reverseTransform(values, { internship: initialInternship as Internship, }) as Internship }); history.push(route("home")) } const InnerForm = () => { const { submitForm, validateForm } = useFormikContext(); const handleSubmitConfirmation = async () => { const errors = await validateForm(); if (Object.keys(errors).length == 0) { setConfirmDialogOpen(true); } else { console.warn(errors); } } const handleCancel = () => { setConfirmDialogOpen(false); } return
{ t('internship.sections.intern-info') } { t('internship.sections.kind' )} { t('internship.sections.duration') } { t('internship.sections.place') } { t('forms.internship.send-confirmation') } } return ( ) }