Fix multiple issues with forms

This commit is contained in:
Kacper Donat 2020-10-18 13:48:05 +02:00
parent 263be22901
commit 5879efc978
12 changed files with 96 additions and 35 deletions

View File

@ -1,4 +1,4 @@
import { Company, Identifiable, Internship, Mentor, Office } from "@/data";
import { Address, Company, Identifiable, Internship, Mentor, Office } from "@/data";
import { momentSerializationTransformer, OneWayTransformer } from "@/serialization";
import { Nullable } from "@/helpers";
import { MentorDTO, mentorDtoTransformer } from "@/api/dto/mentor";
@ -7,24 +7,34 @@ import { Moment } from "moment";
import { sampleStudent } from "@/provider/dummy";
export enum SubmissionState {
Draft,
Submitted,
Accepted,
Rejected,
Archival,
Draft = "Draft",
Submitted = "Submitted",
Accepted = "Accepted",
Rejected = "Rejected",
Archival = "Archival",
}
export interface NewBranchOffice extends Address {
}
export interface InternshipRegistrationUpdateCompany {
id: string,
branchOffice: Identifiable,
branchOffice: Identifiable | NewBranchOffice,
}
export interface NewCompany {
nip: string;
name: string;
branchOffice: NewBranchOffice | null;
}
export interface InternshipRegistrationUpdate {
company: InternshipRegistrationUpdateCompany,
company: InternshipRegistrationUpdateCompany | NewCompany,
start: string,
end: string,
type: number,
mentor: MentorDTO,
hours: number,
}
export interface InternshipRegistrationDTO extends Identifiable {
@ -35,8 +45,11 @@ export interface InternshipRegistrationDTO extends Identifiable {
mentor: MentorDTO,
company: Company,
branchAddress: Office,
declaredHours: number,
}
const reference = (subject: Identifiable | null): Identifiable | null => subject && { id: subject.id };
export interface InternshipInfoDTO {
internshipRegistration: InternshipRegistrationDTO;
}
@ -48,12 +61,17 @@ export const internshipRegistrationUpdateTransformer: OneWayTransformer<Nullable
end: subject?.endDate?.toISOString() || null,
type: parseInt(subject?.type?.id || "0"),
mentor: mentorDtoTransformer.reverseTransform(subject.mentor as Mentor),
company: {
company: subject?.company?.id ? {
id: subject?.company?.id as string,
branchOffice: {
id: subject?.office?.id
},
}
branchOffice: subject?.office?.id
? reference(subject?.office) as Identifiable
: subject?.office?.address as NewBranchOffice,
} : {
name: subject?.company?.name as string,
nip: subject?.company?.nip as string,
branchOffice: subject?.office?.address as NewBranchOffice
},
hours: subject?.hours,
}
}
}
@ -68,7 +86,7 @@ export const internshipRegistrationDtoTransformer: OneWayTransformer<InternshipR
startDate: momentSerializationTransformer.reverseTransform(dto.start) as Moment,
endDate: momentSerializationTransformer.reverseTransform(dto.end) as Moment,
type: internshipTypeDtoTransformer.transform(dto.type),
hours: 0,
hours: dto.declaredHours,
isAccepted: dto.state === SubmissionState.Accepted,
lengthInWeeks: 0,
program: [],

View File

@ -10,6 +10,7 @@ import * as student from "./student";
import * as type from "./type";
import * as companies from "./companies";
import * as internship from "./internship";
import * as upload from "./upload";
export const axios = Axios.create({
baseURL: process.env.API_BASE_URL || "https://system-praktyk.stg.kadet.net/api/",
@ -40,6 +41,7 @@ const api = {
type,
companies,
internship,
upload
}
export default api;

View File

@ -2,10 +2,11 @@ import { InternshipInfoDTO, InternshipRegistrationUpdate } from "@/api/dto/inter
import { axios } from "@/api/index";
import { Nullable } from "@/helpers";
const INTERNSHIP_ENDPOINT = '/internshipRegistration';
const INTERNSHIP_REGISTRATION_ENDPOINT = '/internshipRegistration';
const INTERNSHIP_ENDPOINT = '/internship';
export async function update(internship: Nullable<InternshipRegistrationUpdate>): Promise<boolean> {
const response = await axios.put(INTERNSHIP_ENDPOINT, internship);
const response = await axios.put(INTERNSHIP_REGISTRATION_ENDPOINT, internship);
return true;
}

23
src/api/upload.ts Normal file
View File

@ -0,0 +1,23 @@
import { Identifiable } from "@/data";
import { axios } from "@/api/index";
export enum UploadType {
Ipp = "IppScan",
DeanConsent = "DeanConsent",
Insurance = "NnwInsurance",
}
const CREATE_DOCUMENT_ENDPOINT = '/document';
const DOCUMENT_UPLOAD_ENDPOINT = '/document/:id/scan';
interface Document extends Identifiable {
description?: string;
type: UploadType;
}
export async function create(type: UploadType, content: File)
{
const response = await axios.post<Document>(CREATE_DOCUMENT_ENDPOINT, { type });
console.log(response.data);
}

View File

@ -103,7 +103,7 @@ export const BranchForm: React.FC = () => {
onInputChange={ handleCityInput }
onBlur={ ev => setFieldTouched("city", true) }
inputValue={ values.city }
value={ values.office ? values.office : null }
value={ values.office ? values.office : values.city }
freeSolo
/>
</Grid>
@ -155,9 +155,15 @@ export const CompanyForm: React.FunctionComponent = () => {
const canEdit = useMemo(() => !values.company, [values.company]);
useEffect(() => {
if (!input || values.companyName == input) {
return;
}
(async () => {
setCompanies(await api.companies.search(input));
})()
setValues({ ...values, company: null, companyName: input }, true)
}, [ input ]);
const handleCompanyChange = (event: any, value: Company | string | null) => {
@ -194,7 +200,9 @@ export const CompanyForm: React.FunctionComponent = () => {
renderOption={ company => <CompanyItem company={ company }/> }
renderInput={ props => <TextField { ...props } label={ t("forms.internship.fields.company-name") } fullWidth
error={ touched.companyName && !!errors.companyName } helperText={ touched.companyName && errors.companyName }/> }
onChange={ handleCompanyChange } value={ values.company || values.companyName }
onChange={ handleCompanyChange }
value={ values.company || values.companyName }
inputValue={ input }
freeSolo
onInputChange={ (_, value) => setInput(value) }
/>

View File

@ -97,7 +97,7 @@ const InternshipProgramForm = () => {
renderOption={ (option: InternshipType) => <InternshipTypeItem internshipType={ option }/> }
options={ types }
disableClearable
value={ values.kind || undefined }
value={ values.kind || null as any }
onChange={ (_, value) => setFieldValue("kind", value) }
onBlur={ handleBlur }
/>
@ -234,7 +234,7 @@ const converter: Transformer<Nullable<Internship>, InternshipFormValues, Interns
nip: form.companyNip,
offices: [],
},
hours: form.hours as number,
hours: form.hours ? form.hours : 0,
type: form.kind as InternshipType,
}
}
@ -299,6 +299,8 @@ export const InternshipForm: React.FunctionComponent = () => {
const internship = converter.reverseTransform(values, { internship: initialInternship as Internship });
const update = internshipRegistrationUpdateTransformer.transform(internship);
console.log(update);
api.internship.update(update);
// history.push(route("home"))
@ -308,8 +310,8 @@ export const InternshipForm: React.FunctionComponent = () => {
const { submitForm, validateForm } = useFormikContext();
const handleSubmitConfirmation = async () => {
const errors = await validateForm();
// const errors = await validateForm();
const errors = {};
if (Object.keys(errors).length == 0) {
setConfirmDialogOpen(true);
} else {

View File

@ -7,7 +7,9 @@ import { route } from "@/routing";
import React, { useState } from "react";
import { Plan } from "@/data";
import { useTranslation } from "react-i18next";
import { InternshipPlanActions, useDispatch } from "@/state/actions";
import { useDispatch } from "@/state/actions";
import { UploadType } from "@/api/upload";
import api from "@/api";
export const PlanForm = () => {
const { t } = useTranslation();
@ -18,7 +20,8 @@ export const PlanForm = () => {
const history = useHistory();
const handleSubmit = () => {
dispatch({ type: InternshipPlanActions.Send, plan });
api.upload.create(UploadType.Ipp, null as any);
// dispatch({ type: InternshipPlanActions.Send, plan });
history.push(route("home"))
}

View File

@ -33,7 +33,7 @@ export const StudentForm = () => {
/>
</Grid>
<Grid item md={3}>
<TextField label={ t("forms.internship.fields.semester") } value={ student.semester } disabled fullWidth/>
<TextField label={ t("forms.internship.fields.semester") } value={ student.semester || "" } disabled fullWidth/>
</Grid>
<Grid item>
<Alert severity="warning" action={ <Button color="inherit" size="small">skontaktuj się z opiekunem</Button> }>

View File

@ -5,21 +5,21 @@ import { Redirect } from "react-router-dom";
import React from "react";
import { UserState } from "@/state/reducer/user";
export const isReadyMiddleware: Middleware<any, any> = next => isLoggedInMiddleware(() => {
export const isReadyMiddleware: Middleware<any, any> = Next => isLoggedInMiddleware(() => {
const ready = useSelector(isReady);
if (ready) {
return <>{ next() }</>;
return <Next />;
}
return <Redirect to={ route("edition_pick") } />;
})
export const isLoggedInMiddleware: Middleware<any, any> = next => {
export const isLoggedInMiddleware: Middleware<any, any> = Next => {
const user = useSelector<AppState>(state => state.user) as UserState;
if (user.loggedIn) {
return <>{ next() }</>;
return <Next />;
}
return <Redirect to={ route("user_login") } />;

View File

@ -115,10 +115,6 @@ export const InternshipProposalPreviewPage = () => {
{ proposal && <ProposalPreview proposal={ proposal } /> }
<Actions>
<Button component={ RouterLink } to={ route("home") } variant="contained" color="primary">
{ t('go-back') }
</Button>
<ButtonGroup color="primary" variant="contained">
<Button onClick={ handleAcceptWithoutComment } startIcon={ <StickerCheckOutline /> }>
{ t('accept-without-comments') }
@ -134,6 +130,10 @@ export const InternshipProposalPreviewPage = () => {
<Button onClick={ handleDiscardAction } color="secondary" startIcon={ <StickerRemoveOutline /> }>
{ t('discard') }
</Button>
<Button component={ RouterLink } to={ route("home") }>
{ t('go-back') }
</Button>
</Actions>
</Container>
<Dialog open={ isDiscardModalOpen } onClose={ handleDiscardModalClose } maxWidth="md">

View File

@ -47,7 +47,7 @@ export const UserProfilePage = () => {
</Box>
</Paper>
<Actions>
<Button variant="contained" component={ RouterLink } to={ route("home") }>
<Button component={ RouterLink } to={ route("home") }>
{ t('go-back') }
</Button>
</Actions>

View File

@ -1,15 +1,19 @@
import { Edition } from "@/data/edition";
import { EditionAction, EditionActions } from "@/state/actions/edition";
import { editionSerializationTransformer, Serializable } from "@/serialization";
import { LoginAction, LogoutAction, UserActions } from "@/state/actions";
export type EditionState = Serializable<Edition> | null;
const initialEditionState: EditionState = null;
const editionReducer = (state: EditionState = initialEditionState, action: EditionAction): EditionState => {
const editionReducer = (state: EditionState = initialEditionState, action: EditionAction | LogoutAction | LoginAction): EditionState => {
switch (action.type) {
case EditionActions.Set:
return editionSerializationTransformer.transform(action.edition);
case UserActions.Login:
case UserActions.Logout:
return initialEditionState;
}
return state;