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" />
 | 
					    <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="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" />
 | 
					    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
 | 
				
			||||||
    <title>React App</title>
 | 
					    <title>Zgłoszenie praktyki studenckiej</title>
 | 
				
			||||||
  </head>
 | 
					  </head>
 | 
				
			||||||
  <body>
 | 
					  <body>
 | 
				
			||||||
    <noscript>You need to enable JavaScript to run this app.</noscript>
 | 
					    <noscript>You need to enable JavaScript to run this app.</noscript>
 | 
				
			||||||
 | 
				
			|||||||
@ -3,4 +3,3 @@ export * from './company'
 | 
				
			|||||||
export * from './course'
 | 
					export * from './course'
 | 
				
			||||||
export * from './internship'
 | 
					export * from './internship'
 | 
				
			||||||
export * from './student'
 | 
					export * from './student'
 | 
				
			||||||
export { emptyInternship } from "@/provider/dummy/internship";
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -2,6 +2,7 @@ import { Moment } from "moment";
 | 
				
			|||||||
import { Identifiable } from "./common";
 | 
					import { Identifiable } from "./common";
 | 
				
			||||||
import { countWorkingWeeksInRange } from "@/utils/date";
 | 
					import { countWorkingWeeksInRange } from "@/utils/date";
 | 
				
			||||||
import { Student } from "@/data/student";
 | 
					import { Student } from "@/data/student";
 | 
				
			||||||
 | 
					import { Company } from "@/data/company";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export enum InternshipType {
 | 
					export enum InternshipType {
 | 
				
			||||||
    FreeInternship = "FreeInternship",
 | 
					    FreeInternship = "FreeInternship",
 | 
				
			||||||
@ -61,4 +62,13 @@ export interface Internship extends Identifiable {
 | 
				
			|||||||
    endDate: Moment;
 | 
					    endDate: Moment;
 | 
				
			||||||
    isAccepted: boolean;
 | 
					    isAccepted: boolean;
 | 
				
			||||||
    lengthInWeeks: number;
 | 
					    lengthInWeeks: number;
 | 
				
			||||||
 | 
					    mentor: Mentor;
 | 
				
			||||||
 | 
					    company: Company;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface Mentor {
 | 
				
			||||||
 | 
					    name: string;
 | 
				
			||||||
 | 
					    surname: string;
 | 
				
			||||||
 | 
					    email: string;
 | 
				
			||||||
 | 
					    phone: string | null;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,7 @@ import { Identifiable } from "./common";
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export type Semester = number;
 | 
					export type Semester = number;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface Student extends Identifiable{
 | 
					export interface Student extends Identifiable {
 | 
				
			||||||
    name: string;
 | 
					    name: string;
 | 
				
			||||||
    surname: string;
 | 
					    surname: string;
 | 
				
			||||||
    email: string;
 | 
					    email: string;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
import React, { ChangeEvent, HTMLProps, useMemo, useState } from "react";
 | 
					import React, { HTMLProps, useMemo, useState } from "react";
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
    FormControl,
 | 
					    FormControl,
 | 
				
			||||||
    Grid,
 | 
					    Grid,
 | 
				
			||||||
@ -17,12 +17,13 @@ import { KeyboardDatePicker as DatePicker } from "@material-ui/pickers";
 | 
				
			|||||||
import { CompanyForm } from "@/forms/company";
 | 
					import { CompanyForm } from "@/forms/company";
 | 
				
			||||||
import { StudentForm } from "@/forms/student";
 | 
					import { StudentForm } from "@/forms/student";
 | 
				
			||||||
import { sampleStudent } from "@/provider/dummy/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 { Nullable } from "@/helpers";
 | 
				
			||||||
import moment, { Moment } from "moment";
 | 
					import moment, { Moment } from "moment";
 | 
				
			||||||
import { computeWorkingHours } from "@/utils/date";
 | 
					import { computeWorkingHours } from "@/utils/date";
 | 
				
			||||||
import { Autocomplete } from "@material-ui/lab";
 | 
					import { Autocomplete } from "@material-ui/lab";
 | 
				
			||||||
import { formFieldProps } from "@/forms/helpers";
 | 
					import { formFieldProps } from "@/forms/helpers";
 | 
				
			||||||
 | 
					import { emptyInternship } from "@/provider/dummy/internship";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type InternshipFormProps = {}
 | 
					export type InternshipFormProps = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -150,7 +151,7 @@ export const InternshipForm: React.FunctionComponent<InternshipFormProps> = prop
 | 
				
			|||||||
            <Typography variant="h5" className="section-header">Czas trwania praktyki</Typography>
 | 
					            <Typography variant="h5" className="section-header">Czas trwania praktyki</Typography>
 | 
				
			||||||
            <InternshipDurationForm internship={ internship } onChange={ setInternship }/>
 | 
					            <InternshipDurationForm internship={ internship } onChange={ setInternship }/>
 | 
				
			||||||
            <Typography variant="h5" className="section-header">Miejsce odbywania praktyki</Typography>
 | 
					            <Typography variant="h5" className="section-header">Miejsce odbywania praktyki</Typography>
 | 
				
			||||||
            <CompanyForm/>
 | 
					            <CompanyForm internship={ internship } onChange={ setInternship }/>
 | 
				
			||||||
            <Button variant="contained" color="primary">Wyślij</Button>
 | 
					            <Button variant="contained" color="primary">Wyślij</Button>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
				
			|||||||
@ -1,11 +1,14 @@
 | 
				
			|||||||
import React, { HTMLProps, useEffect, useMemo, useState } from "react";
 | 
					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 { sampleCompanies } from "@/provider/dummy";
 | 
				
			||||||
import { Autocomplete } from "@material-ui/lab";
 | 
					import { Alert, Autocomplete } from "@material-ui/lab";
 | 
				
			||||||
import { Grid, TextField, Typography } from "@material-ui/core";
 | 
					import { Button, Grid, TextField, Typography } from "@material-ui/core";
 | 
				
			||||||
import { formFieldProps } from "./helpers";
 | 
					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 = {
 | 
					export type BranchOfficeProps = {
 | 
				
			||||||
    company: Company,
 | 
					    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 [company, setCompany] = useState<Company>(emptyCompany);
 | 
				
			||||||
 | 
					    const [mentor, setMentor] = useState<Mentor>(emptyMentor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const canEdit = useMemo(() => !company.id, [company.id]);
 | 
					    const canEdit = useMemo(() => !company.id, [company.id]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    useEffect(() => onChange({ ...internship, mentor }), [ mentor ]);
 | 
				
			||||||
 | 
					    useEffect(() => onChange({ ...internship, company }), [ company ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const fieldProps = formFieldProps(company, setCompany)
 | 
					    const fieldProps = formFieldProps(company, setCompany)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const handleCompanyChange = (event: any, value: Company | string | null) => {
 | 
					    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 }/>*/}
 | 
					                {/*    <TextField label={ "Url" } fullWidth { ...fieldProps("url") } disabled={ !canEdit }/>*/}
 | 
				
			||||||
                {/*</Grid>*/}
 | 
					                {/*</Grid>*/}
 | 
				
			||||||
            </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>
 | 
					            <Typography variant="subtitle1" className="subsection-header">Oddział</Typography>
 | 
				
			||||||
            <BranchForm company={ company }/>
 | 
					            <BranchForm company={ company }/>
 | 
				
			||||||
        </>
 | 
					        </>
 | 
				
			||||||
 | 
				
			|||||||
@ -2,22 +2,29 @@ import { DOMEvent } from "@/helpers";
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
type UpdatingEvent = "onBlur" | "onChange" | "onInput";
 | 
					type UpdatingEvent = "onBlur" | "onChange" | "onInput";
 | 
				
			||||||
type FormFieldHelperOptions<T> = {
 | 
					type FormFieldHelperOptions<T> = {
 | 
				
			||||||
    event: UpdatingEvent
 | 
					    event: UpdatingEvent,
 | 
				
			||||||
 | 
					    property: string,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function formFieldProps<T>(subject: T, update: (value: T) => void, options: Partial<FormFieldHelperOptions<T>> = {}) {
 | 
					export function formFieldProps<T>(subject: T, update: (value: T) => void, options: Partial<FormFieldHelperOptions<T>> = {}) {
 | 
				
			||||||
    const {
 | 
					    const {
 | 
				
			||||||
        event = "onChange"
 | 
					        event = "onChange",
 | 
				
			||||||
 | 
					        property = "value",
 | 
				
			||||||
    } = options;
 | 
					    } = options;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return <P extends keyof T, TArgs extends any[]>(
 | 
					    return <P extends keyof T, TArgs extends any[]>(
 | 
				
			||||||
        field: P,
 | 
					        field: P,
 | 
				
			||||||
        extractor: (...args: TArgs) => T[P] = ((event: DOMEvent<HTMLInputElement>) => event.target.value as unknown as T[P]) as any
 | 
					        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({
 | 
					        [event]: (...args: TArgs) => update({
 | 
				
			||||||
            ...subject,
 | 
					            ...subject,
 | 
				
			||||||
            [field]: extractor(...args),
 | 
					            [field]: extractor(...args),
 | 
				
			||||||
        } as T)
 | 
					        } 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 companySequence = makeIdSequence();
 | 
				
			||||||
const officeSequence = makeIdSequence();
 | 
					const officeSequence = makeIdSequence();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const sampleCompanies: Company[] = [
 | 
					export const sampleCompanies: Company[] = companySequence.assignIds([
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        id: companySequence(),
 | 
					 | 
				
			||||||
        name: "Intel",
 | 
					        name: "Intel",
 | 
				
			||||||
        url: "https://www.intel.com/content/www/us/en/jobs/locations/poland.html",
 | 
					        url: "https://www.intel.com/content/www/us/en/jobs/locations/poland.html",
 | 
				
			||||||
        nip: "9570752316",
 | 
					        nip: "9570752316",
 | 
				
			||||||
@ -22,7 +21,6 @@ export const sampleCompanies: Company[] = [
 | 
				
			|||||||
        }]
 | 
					        }]
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        id: companySequence(),
 | 
					 | 
				
			||||||
        name: "IHS Markit",
 | 
					        name: "IHS Markit",
 | 
				
			||||||
        url: "http://ihsgdansk.com/",
 | 
					        url: "http://ihsgdansk.com/",
 | 
				
			||||||
        nip: "5842068320",
 | 
					        nip: "5842068320",
 | 
				
			||||||
@ -38,12 +36,10 @@ export const sampleCompanies: Company[] = [
 | 
				
			|||||||
        }]
 | 
					        }]
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        id: companySequence(),
 | 
					 | 
				
			||||||
        name: "Asseco Poland",
 | 
					        name: "Asseco Poland",
 | 
				
			||||||
        url: "http://pl.asseco.com/",
 | 
					        url: "http://pl.asseco.com/",
 | 
				
			||||||
        nip: "5842068320",
 | 
					        nip: "5842068320",
 | 
				
			||||||
        offices: [{
 | 
					        offices: officeSequence.assignIds([{
 | 
				
			||||||
            id: officeSequence(),
 | 
					 | 
				
			||||||
            address: {
 | 
					            address: {
 | 
				
			||||||
                city: "Gdynia",
 | 
					                city: "Gdynia",
 | 
				
			||||||
                street: "ul. Podolska",
 | 
					                street: "ul. Podolska",
 | 
				
			||||||
@ -52,7 +48,6 @@ export const sampleCompanies: Company[] = [
 | 
				
			|||||||
                country: "Poland"
 | 
					                country: "Poland"
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }, {
 | 
					        }, {
 | 
				
			||||||
            id: officeSequence(),
 | 
					 | 
				
			||||||
            address: {
 | 
					            address: {
 | 
				
			||||||
                city: "Łódź",
 | 
					                city: "Łódź",
 | 
				
			||||||
                street: "al. Marszałka Józefa Piłsudskiego",
 | 
					                street: "al. Marszałka Józefa Piłsudskiego",
 | 
				
			||||||
@ -61,7 +56,6 @@ export const sampleCompanies: Company[] = [
 | 
				
			|||||||
                country: "Poland"
 | 
					                country: "Poland"
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }, {
 | 
					        }, {
 | 
				
			||||||
            id: officeSequence(),
 | 
					 | 
				
			||||||
            address: {
 | 
					            address: {
 | 
				
			||||||
                city: "Wrocław",
 | 
					                city: "Wrocław",
 | 
				
			||||||
                street: "Traugutta",
 | 
					                street: "Traugutta",
 | 
				
			||||||
@ -69,6 +63,6 @@ export const sampleCompanies: Company[] = [
 | 
				
			|||||||
                postalCode: "50-449",
 | 
					                postalCode: "50-449",
 | 
				
			||||||
                country: "Poland"
 | 
					                country: "Poland"
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }]
 | 
					        }])
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
]
 | 
					])
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,12 @@
 | 
				
			|||||||
import { Nullable } from "@/helpers";
 | 
					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> = {
 | 
					export const emptyInternship: Nullable<Internship> = {
 | 
				
			||||||
    intern: null,
 | 
					    intern: null,
 | 
				
			||||||
@ -9,4 +16,6 @@ export const emptyInternship: Nullable<Internship> = {
 | 
				
			|||||||
    program: null,
 | 
					    program: null,
 | 
				
			||||||
    isAccepted: false,
 | 
					    isAccepted: false,
 | 
				
			||||||
    lengthInWeeks: 0,
 | 
					    lengthInWeeks: 0,
 | 
				
			||||||
 | 
					    mentor: emptyMentor,
 | 
				
			||||||
 | 
					    company: emptyCompany,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user