160 lines
6.9 KiB
TypeScript
160 lines
6.9 KiB
TypeScript
import React, { HTMLProps, useMemo, useState } from "react";
|
|
import {
|
|
FormControl,
|
|
Grid,
|
|
Input,
|
|
InputLabel,
|
|
Typography,
|
|
FormHelperText,
|
|
TextField,
|
|
FormGroup,
|
|
FormControlLabel,
|
|
Checkbox,
|
|
FormLabel,
|
|
Button
|
|
} 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 { Course, Internship, InternshipType, internshipTypeLabels } from "@/data";
|
|
import { Nullable } from "@/helpers";
|
|
import moment, { Moment } from "moment";
|
|
import { computeWorkingHours } from "@/utils/date";
|
|
import { Autocomplete } from "@material-ui/lab";
|
|
import { formFieldProps } from "@/forms/helpers";
|
|
import { emptyInternship } from "@/provider/dummy/internship";
|
|
|
|
export type InternshipFormProps = {}
|
|
|
|
export type InternshipFormSectionProps = {
|
|
internship: Nullable<Internship>,
|
|
onChange: (internship: Nullable<Internship>) => void,
|
|
}
|
|
|
|
export const InternshipTypeItem = ({ type, ...props }: { type: InternshipType } & HTMLProps<any>) => {
|
|
const info = internshipTypeLabels[type];
|
|
|
|
return (
|
|
<div className="internship=type-item" { ...props }>
|
|
<div>{ info.label }</div>
|
|
{ info.description && <Typography variant="caption">{ info.description }</Typography> }
|
|
</div>
|
|
)
|
|
}
|
|
|
|
const InternshipProgramForm = ({ internship, onChange }: InternshipFormSectionProps) => {
|
|
const fieldProps = formFieldProps(internship, onChange);
|
|
|
|
const course = internship.intern?.course as Course;
|
|
|
|
return (
|
|
<Grid container>
|
|
<Grid item md={4}>
|
|
<Autocomplete renderInput={ props => <TextField { ...props } label="Rodzaj praktyki/umowy" fullWidth/> }
|
|
getOptionLabel={ (option: InternshipType) => internshipTypeLabels[option].label }
|
|
renderOption={ (option: InternshipType) => <InternshipTypeItem type={ option } /> }
|
|
options={ Object.values(InternshipType) as InternshipType[] }
|
|
disableClearable
|
|
{ ...fieldProps("type", (event, value) => value) as any }
|
|
/>
|
|
</Grid>
|
|
<Grid item md={8}>
|
|
{ internship.type === InternshipType.Other && <TextField label={"Inny - Wprowadź"} fullWidth/> }
|
|
</Grid>
|
|
<Grid item>
|
|
<FormGroup>
|
|
<FormLabel component="legend" className="subsection-header">Realizowane punkty programu praktyk (minimum 3)</FormLabel>
|
|
{ course.possibleProgramEntries.map(entry => {
|
|
return (
|
|
<FormControlLabel label={ entry.description } key={ entry.id }
|
|
control={ <Checkbox /> }
|
|
/>
|
|
)
|
|
}) }
|
|
</FormGroup>
|
|
</Grid>
|
|
</Grid>
|
|
)
|
|
}
|
|
|
|
const InternshipDurationForm = ({ internship }: InternshipFormSectionProps) => {
|
|
const [startDate, setStartDate] = useState<Moment | null>(internship.startDate);
|
|
const [endDate, setEndDate] = useState<Moment | null>(internship.endDate);
|
|
const [overrideHours, setHoursOverride] = useState<number | null>(null)
|
|
const [workingHours, setWorkingHours] = useState<number>(40)
|
|
|
|
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 / 40) : null, [ hours ]);
|
|
|
|
return (
|
|
<Grid container>
|
|
<Grid item md={ 6 }>
|
|
<DatePicker value={ startDate } onChange={ setStartDate }
|
|
format="DD MMMM yyyy"
|
|
clearable disableToolbar fullWidth
|
|
variant="inline" label={ "Data rozpoczęcia praktyki" }
|
|
/>
|
|
</Grid>
|
|
<Grid item md={ 6 }>
|
|
<DatePicker value={ endDate } onChange={ setEndDate }
|
|
format="DD MMMM yyyy"
|
|
clearable disableToolbar fullWidth
|
|
variant="inline" label={ "Data zakończenia praktyki" }
|
|
minDate={ startDate || moment() }
|
|
/>
|
|
</Grid>
|
|
<Grid item md={ 4 }>
|
|
<FormControl fullWidth>
|
|
<InputLabel>Wymiar etatu</InputLabel>
|
|
<Input value={ workingHours }
|
|
onChange={ ev => setWorkingHours(parseInt(ev.target.value) || 0) }
|
|
fullWidth
|
|
/>
|
|
<FormHelperText>Liczba godzin w tygodniu roboczym</FormHelperText>
|
|
</FormControl>
|
|
</Grid>
|
|
<Grid item md={ 4 }>
|
|
<FormControl fullWidth>
|
|
<InputLabel>Łączna liczba godzin</InputLabel>
|
|
<Input value={ hours || "" }
|
|
onChange={ ev => setHoursOverride(parseInt(ev.target.value) || 0) }
|
|
fullWidth
|
|
/>
|
|
</FormControl>
|
|
</Grid>
|
|
<Grid item md={ 4 }>
|
|
<FormControl fullWidth>
|
|
<InputLabel>Liczba tygodni</InputLabel>
|
|
<Input value={ weeks || "" }
|
|
disabled
|
|
fullWidth
|
|
/>
|
|
<FormHelperText>Wyliczona automatycznie</FormHelperText>
|
|
</FormControl>
|
|
</Grid>
|
|
</Grid>
|
|
);
|
|
}
|
|
|
|
export const InternshipForm: React.FunctionComponent<InternshipFormProps> = props => {
|
|
const [internship, setInternship] = useState<Nullable<Internship>>({ ...emptyInternship, intern: sampleStudent })
|
|
|
|
return (
|
|
<div className="internship-form">
|
|
<Typography variant="h5" className="section-header">Dane osoby odbywającej praktykę</Typography>
|
|
<StudentForm student={ sampleStudent }/>
|
|
<Typography variant="h5" className="section-header">Rodzaj i program praktyki</Typography>
|
|
<InternshipProgramForm internship={ internship } onChange={ setInternship }/>
|
|
<Typography variant="h5" className="section-header">Czas trwania praktyki</Typography>
|
|
<InternshipDurationForm internship={ internship } onChange={ setInternship }/>
|
|
<Typography variant="h5" className="section-header">Miejsce odbywania praktyki</Typography>
|
|
<CompanyForm internship={ internship } onChange={ setInternship }/>
|
|
<Button variant="contained" color="primary">Wyślij</Button>
|
|
</div>
|
|
)
|
|
}
|
|
|