139 lines
4.9 KiB
TypeScript
139 lines
4.9 KiB
TypeScript
import { Student } from "@/data";
|
|
import { Transformer } from "@/serialization";
|
|
import React, { useMemo } from "react";
|
|
import { Field, Formik, useFormikContext } from "formik";
|
|
import api from "@/api";
|
|
import { Button, Grid, Typography } from "@material-ui/core";
|
|
import { TextField as TextFieldFormik } from "formik-material-ui";
|
|
import { useTranslation } from "react-i18next";
|
|
import { Actions } from "@/components";
|
|
import { Nullable } from "@/helpers";
|
|
import * as Yup from "yup";
|
|
import { StudentActions, useDispatch } from "@/state/actions";
|
|
import { route } from "@/routing";
|
|
import { useHistory } from "react-router-dom";
|
|
|
|
interface StudentFormValues {
|
|
firstName: string;
|
|
lastName: string;
|
|
email: string;
|
|
albumNumber: number | "";
|
|
semester: number | "";
|
|
}
|
|
|
|
type StudentFormProps = {
|
|
student: Student;
|
|
}
|
|
|
|
const studentToFormValuesTransformer: Transformer<Nullable<Student>, StudentFormValues, { current: Student }> = {
|
|
transform(subject: Nullable<Student>, context: { current: Student }): StudentFormValues {
|
|
return {
|
|
firstName: subject.name || "",
|
|
lastName: subject.surname || "",
|
|
albumNumber: subject.albumNumber || "",
|
|
semester: subject.semester || "",
|
|
email: subject.email || "",
|
|
};
|
|
},
|
|
reverseTransform(subject: StudentFormValues, { current }: { current: Student }): Nullable<Student> {
|
|
return {
|
|
...current,
|
|
name: subject.firstName,
|
|
surname: subject.lastName,
|
|
albumNumber: subject.albumNumber ? subject.albumNumber : null,
|
|
semester: subject.semester ? subject.semester : null,
|
|
email: subject.email,
|
|
};
|
|
},
|
|
}
|
|
|
|
export const StudentForm = ({ student }: StudentFormProps) => {
|
|
const { t } = useTranslation();
|
|
const dispatch = useDispatch();
|
|
const history = useHistory();
|
|
|
|
const validationSchema = useMemo(() => Yup.object<StudentFormValues>({
|
|
semester: Yup.number().required().min(1).max(10),
|
|
albumNumber: Yup.number().required(),
|
|
email: Yup.string().required(),
|
|
firstName: Yup.string().required(),
|
|
lastName: Yup.string().required(),
|
|
}), []);
|
|
|
|
const initialValues: StudentFormValues = useMemo(
|
|
() => studentToFormValuesTransformer.transform(student, { current: student }),
|
|
[ student ]
|
|
)
|
|
|
|
|
|
const handleFormSubmit = async (values: StudentFormValues) => {
|
|
const update = studentToFormValuesTransformer.reverseTransform(values, { current: student }) as Student;
|
|
const updated = await api.student.update(update);
|
|
|
|
dispatch({
|
|
type: StudentActions.Set,
|
|
student: updated,
|
|
})
|
|
|
|
history.push(route("home"));
|
|
}
|
|
|
|
|
|
const InnerForm = () => {
|
|
const { handleSubmit } = useFormikContext();
|
|
|
|
return <form onSubmit={ handleSubmit }>
|
|
<Typography variant="subtitle1">{ t("forms.student.sections.personal") }</Typography>
|
|
<Grid container>
|
|
<Grid item md={ 6 }>
|
|
<Field component={ TextFieldFormik }
|
|
name="firstName"
|
|
label={ t("forms.student.fields.first-name") }
|
|
fullWidth
|
|
/>
|
|
</Grid>
|
|
<Grid item md={ 6 }>
|
|
<Field component={ TextFieldFormik }
|
|
name="lastName"
|
|
label={ t("forms.student.fields.last-name") }
|
|
fullWidth
|
|
/>
|
|
</Grid>
|
|
<Grid item>
|
|
<Field component={ TextFieldFormik }
|
|
name="email"
|
|
label={ t("forms.student.fields.email") }
|
|
fullWidth
|
|
/>
|
|
</Grid>
|
|
</Grid>
|
|
<Typography variant="subtitle1">{ t("forms.student.sections.studies")}</Typography>
|
|
<Grid container>
|
|
<Grid item md={ 6 }>
|
|
<Field component={ TextFieldFormik }
|
|
name="albumNumber"
|
|
label={ t("forms.student.fields.album-number") }
|
|
fullWidth
|
|
/>
|
|
</Grid>
|
|
<Grid item md={ 6 }>
|
|
<Field component={ TextFieldFormik }
|
|
name="semester"
|
|
label={ t("forms.student.fields.semester") }
|
|
fullWidth
|
|
/>
|
|
</Grid>
|
|
</Grid>
|
|
<Actions>
|
|
<Button variant="contained" type="submit" color="primary">{ t("save") }</Button>
|
|
</Actions>
|
|
</form>
|
|
}
|
|
|
|
return <Formik initialValues={ initialValues } onSubmit={ handleFormSubmit } validationSchema={ validationSchema }>
|
|
<InnerForm />
|
|
</Formik>
|
|
}
|
|
|
|
export default StudentForm;
|