Merge pull request 'Add mentor information to form' (#3) from feature_basic_form into master
This commit is contained in:
		
						commit
						94e33f4baa
					
				| @ -6,7 +6,7 @@ | ||||
|     <meta name="theme-color" content="#000000" /> | ||||
|     <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap&subset=latin,latin-ext" /> | ||||
|     <link rel="manifest" href="%PUBLIC_URL%/manifest.json" /> | ||||
|     <title>React App</title> | ||||
|     <title>Zgłoszenie praktyki studenckiej</title> | ||||
|   </head> | ||||
|   <body> | ||||
|     <noscript>You need to enable JavaScript to run this app.</noscript> | ||||
|  | ||||
| @ -3,4 +3,3 @@ export * from './company' | ||||
| export * from './course' | ||||
| export * from './internship' | ||||
| export * from './student' | ||||
| export { emptyInternship } from "@/provider/dummy/internship"; | ||||
|  | ||||
| @ -2,6 +2,7 @@ import { Moment } from "moment"; | ||||
| import { Identifiable } from "./common"; | ||||
| import { countWorkingWeeksInRange } from "@/utils/date"; | ||||
| import { Student } from "@/data/student"; | ||||
| import { Company } from "@/data/company"; | ||||
| 
 | ||||
| export enum InternshipType { | ||||
|     FreeInternship = "FreeInternship", | ||||
| @ -61,4 +62,13 @@ export interface Internship extends Identifiable { | ||||
|     endDate: Moment; | ||||
|     isAccepted: boolean; | ||||
|     lengthInWeeks: number; | ||||
|     mentor: Mentor; | ||||
|     company: Company; | ||||
| } | ||||
| 
 | ||||
| export interface Mentor { | ||||
|     name: string; | ||||
|     surname: string; | ||||
|     email: string; | ||||
|     phone: string | null; | ||||
| } | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| import React, { ChangeEvent, HTMLProps, useMemo, useState } from "react"; | ||||
| import React, { HTMLProps, useMemo, useState } from "react"; | ||||
| import { | ||||
|     FormControl, | ||||
|     Grid, | ||||
| @ -17,12 +17,13 @@ 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, Course, emptyInternship, Internship, InternshipType, internshipTypeLabels } from "@/data"; | ||||
| 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 = {} | ||||
| 
 | ||||
| @ -150,7 +151,7 @@ export const InternshipForm: React.FunctionComponent<InternshipFormProps> = prop | ||||
|             <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/> | ||||
|             <CompanyForm internship={ internship } onChange={ setInternship }/> | ||||
|             <Button variant="contained" color="primary">Wyślij</Button> | ||||
|         </div> | ||||
|     ) | ||||
|  | ||||
| @ -1,11 +1,14 @@ | ||||
| import React, { HTMLProps, useEffect, useMemo, useState } from "react"; | ||||
| import { BranchOffice, Company, emptyAddress, emptyBranchOffice, emptyCompany, formatAddress } from "@/data"; | ||||
| import { BranchOffice, Company, Course, emptyAddress, emptyBranchOffice, emptyCompany, formatAddress, Mentor } from "@/data"; | ||||
| import { sampleCompanies } from "@/provider/dummy"; | ||||
| import { Autocomplete } from "@material-ui/lab"; | ||||
| import { Grid, TextField, Typography } from "@material-ui/core"; | ||||
| import { formFieldProps } from "./helpers"; | ||||
| import { Alert, Autocomplete } from "@material-ui/lab"; | ||||
| import { Button, Grid, TextField, Typography } from "@material-ui/core"; | ||||
| import { BoundProperty, formFieldProps } from "./helpers"; | ||||
| import { InternshipFormSectionProps } from "@/forms/Internship"; | ||||
| import { sampleCourse } from "@/provider/dummy/student"; | ||||
| import { emptyMentor } from "@/provider/dummy/internship"; | ||||
| 
 | ||||
| export type CompanyFormProps = {} | ||||
| export type CompanyFormProps = {} & InternshipFormSectionProps; | ||||
| 
 | ||||
| export type BranchOfficeProps = { | ||||
|     company: Company, | ||||
| @ -95,10 +98,38 @@ export const BranchForm: React.FC<BranchOfficeProps> = ({ company, disabled = fa | ||||
|     ) | ||||
| } | ||||
| 
 | ||||
| export const CompanyForm: React.FunctionComponent<CompanyFormProps> = props => { | ||||
| export const MentorForm = ({ mentor, onMentorChange }: BoundProperty<Mentor, 'onMentorChange', 'mentor'>) => { | ||||
|     const fieldProps = formFieldProps(mentor, onMentorChange) | ||||
| 
 | ||||
|     return ( | ||||
|         <> | ||||
|             <Grid container> | ||||
|                 <Grid item md={6}> | ||||
|                     <TextField label="Imię" fullWidth { ...fieldProps("name") }/> | ||||
|                 </Grid> | ||||
|                 <Grid item md={6}> | ||||
|                     <TextField label="Nazwisko" value={ mentor.surname } fullWidth { ...fieldProps("surname") }/> | ||||
|                 </Grid> | ||||
|                 <Grid item md={8}> | ||||
|                     <TextField label="E-mail" value={ mentor.email } fullWidth { ...fieldProps("email") }/> | ||||
|                 </Grid> | ||||
|                 <Grid item md={4}> | ||||
|                     <TextField label="Nr telefonu" value={ mentor.phone } fullWidth { ...fieldProps("phone") }/> | ||||
|                 </Grid> | ||||
|             </Grid> | ||||
|         </> | ||||
|     ); | ||||
| } | ||||
| 
 | ||||
| export const CompanyForm: React.FunctionComponent<CompanyFormProps> = ({ internship, onChange }) => { | ||||
|     const [company, setCompany] = useState<Company>(emptyCompany); | ||||
|     const [mentor, setMentor] = useState<Mentor>(emptyMentor); | ||||
| 
 | ||||
|     const canEdit = useMemo(() => !company.id, [company.id]); | ||||
| 
 | ||||
|     useEffect(() => onChange({ ...internship, mentor }), [ mentor ]); | ||||
|     useEffect(() => onChange({ ...internship, company }), [ company ]); | ||||
| 
 | ||||
|     const fieldProps = formFieldProps(company, setCompany) | ||||
| 
 | ||||
|     const handleCompanyChange = (event: any, value: Company | string | null) => { | ||||
| @ -133,6 +164,8 @@ export const CompanyForm: React.FunctionComponent<CompanyFormProps> = props => { | ||||
|                 {/*    <TextField label={ "Url" } fullWidth { ...fieldProps("url") } disabled={ !canEdit }/>*/} | ||||
|                 {/*</Grid>*/} | ||||
|             </Grid> | ||||
|             <Typography variant="subtitle1" className="subsection-header">Zakładowy opiekun praktyki</Typography> | ||||
|             <MentorForm mentor={ mentor } onMentorChange={ setMentor }/> | ||||
|             <Typography variant="subtitle1" className="subsection-header">Oddział</Typography> | ||||
|             <BranchForm company={ company }/> | ||||
|         </> | ||||
|  | ||||
| @ -2,22 +2,29 @@ import { DOMEvent } from "@/helpers"; | ||||
| 
 | ||||
| type UpdatingEvent = "onBlur" | "onChange" | "onInput"; | ||||
| type FormFieldHelperOptions<T> = { | ||||
|     event: UpdatingEvent | ||||
|     event: UpdatingEvent, | ||||
|     property: string, | ||||
| } | ||||
| 
 | ||||
| export function formFieldProps<T>(subject: T, update: (value: T) => void, options: Partial<FormFieldHelperOptions<T>> = {}) { | ||||
|     const { | ||||
|         event = "onChange" | ||||
|         event = "onChange", | ||||
|         property = "value", | ||||
|     } = options; | ||||
| 
 | ||||
|     return <P extends keyof T, TArgs extends any[]>( | ||||
|         field: P, | ||||
|         extractor: (...args: TArgs) => T[P] = ((event: DOMEvent<HTMLInputElement>) => event.target.value as unknown as T[P]) as any | ||||
|     ) => ({ | ||||
|         value: subject[field], | ||||
|         [property]: subject[field], | ||||
|         [event]: (...args: TArgs) => update({ | ||||
|             ...subject, | ||||
|             [field]: extractor(...args), | ||||
|         } as T) | ||||
|     }) | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| export type BoundProperty<T, TEvent extends string = 'onChange', TProperty extends string = 'value'> = | ||||
|     { [property in TProperty]: T; } & | ||||
|     { [event in TEvent]: (value: T) => void; } | ||||
|  | ||||
| @ -4,9 +4,8 @@ import { makeIdSequence } from "./helpers"; | ||||
| const companySequence = makeIdSequence(); | ||||
| const officeSequence = makeIdSequence(); | ||||
| 
 | ||||
| export const sampleCompanies: Company[] = [ | ||||
| export const sampleCompanies: Company[] = companySequence.assignIds([ | ||||
|     { | ||||
|         id: companySequence(), | ||||
|         name: "Intel", | ||||
|         url: "https://www.intel.com/content/www/us/en/jobs/locations/poland.html", | ||||
|         nip: "9570752316", | ||||
| @ -22,7 +21,6 @@ export const sampleCompanies: Company[] = [ | ||||
|         }] | ||||
|     }, | ||||
|     { | ||||
|         id: companySequence(), | ||||
|         name: "IHS Markit", | ||||
|         url: "http://ihsgdansk.com/", | ||||
|         nip: "5842068320", | ||||
| @ -38,12 +36,10 @@ export const sampleCompanies: Company[] = [ | ||||
|         }] | ||||
|     }, | ||||
|     { | ||||
|         id: companySequence(), | ||||
|         name: "Asseco Poland", | ||||
|         url: "http://pl.asseco.com/", | ||||
|         nip: "5842068320", | ||||
|         offices: [{ | ||||
|             id: officeSequence(), | ||||
|         offices: officeSequence.assignIds([{ | ||||
|             address: { | ||||
|                 city: "Gdynia", | ||||
|                 street: "ul. Podolska", | ||||
| @ -52,7 +48,6 @@ export const sampleCompanies: Company[] = [ | ||||
|                 country: "Poland" | ||||
|             } | ||||
|         }, { | ||||
|             id: officeSequence(), | ||||
|             address: { | ||||
|                 city: "Łódź", | ||||
|                 street: "al. Marszałka Józefa Piłsudskiego", | ||||
| @ -61,7 +56,6 @@ export const sampleCompanies: Company[] = [ | ||||
|                 country: "Poland" | ||||
|             } | ||||
|         }, { | ||||
|             id: officeSequence(), | ||||
|             address: { | ||||
|                 city: "Wrocław", | ||||
|                 street: "Traugutta", | ||||
| @ -69,6 +63,6 @@ export const sampleCompanies: Company[] = [ | ||||
|                 postalCode: "50-449", | ||||
|                 country: "Poland" | ||||
|             } | ||||
|         }] | ||||
|         }]) | ||||
|     } | ||||
| ] | ||||
| ]) | ||||
|  | ||||
| @ -1,5 +1,12 @@ | ||||
| import { Nullable } from "@/helpers"; | ||||
| import { Internship, InternshipType } from "@/data"; | ||||
| import { emptyCompany, Internship, Mentor } from "@/data"; | ||||
| 
 | ||||
| export const emptyMentor: Mentor = { | ||||
|     phone: null, | ||||
|     email: "", | ||||
|     name: "", | ||||
|     surname: "" | ||||
| } | ||||
| 
 | ||||
| export const emptyInternship: Nullable<Internship> = { | ||||
|     intern: null, | ||||
| @ -9,4 +16,6 @@ export const emptyInternship: Nullable<Internship> = { | ||||
|     program: null, | ||||
|     isAccepted: false, | ||||
|     lengthInWeeks: 0, | ||||
|     mentor: emptyMentor, | ||||
|     company: emptyCompany, | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user