Merge pull request 'feature/student_data_form' (#18) from feature/student_data_form into master
This commit is contained in:
commit
3b90fb7c61
@ -20,7 +20,7 @@ export interface EditionTeaserDTO extends Identifiable {
|
|||||||
|
|
||||||
export const editionTeaserDtoTransformer: OneWayTransformer<EditionTeaserDTO, Subset<Edition>> = {
|
export const editionTeaserDtoTransformer: OneWayTransformer<EditionTeaserDTO, Subset<Edition>> = {
|
||||||
transform(subject: EditionTeaserDTO, context?: undefined): Subset<Edition> {
|
transform(subject: EditionTeaserDTO, context?: undefined): Subset<Edition> {
|
||||||
return {
|
return subject && {
|
||||||
id: subject.id,
|
id: subject.id,
|
||||||
startDate: moment(subject.editionStart),
|
startDate: moment(subject.editionStart),
|
||||||
endDate: moment(subject.editionFinish),
|
endDate: moment(subject.editionFinish),
|
||||||
|
@ -5,6 +5,7 @@ import { MentorDTO, mentorDtoTransformer } from "@/api/dto/mentor";
|
|||||||
import { InternshipTypeDTO, internshipTypeDtoTransformer } from "@/api/dto/type";
|
import { InternshipTypeDTO, internshipTypeDtoTransformer } from "@/api/dto/type";
|
||||||
import { Moment } from "moment";
|
import { Moment } from "moment";
|
||||||
import { sampleStudent } from "@/provider/dummy";
|
import { sampleStudent } from "@/provider/dummy";
|
||||||
|
import { UploadType } from "@/api/upload";
|
||||||
|
|
||||||
export enum SubmissionState {
|
export enum SubmissionState {
|
||||||
Draft = "Draft",
|
Draft = "Draft",
|
||||||
@ -48,10 +49,17 @@ export interface InternshipRegistrationDTO extends Identifiable {
|
|||||||
declaredHours: number,
|
declaredHours: number,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface InternshipDocument extends Identifiable {
|
||||||
|
description: null,
|
||||||
|
type: UploadType,
|
||||||
|
state: SubmissionState,
|
||||||
|
}
|
||||||
|
|
||||||
const reference = (subject: Identifiable | null): Identifiable | null => subject && { id: subject.id };
|
const reference = (subject: Identifiable | null): Identifiable | null => subject && { id: subject.id };
|
||||||
|
|
||||||
export interface InternshipInfoDTO {
|
export interface InternshipInfoDTO {
|
||||||
internshipRegistration: InternshipRegistrationDTO;
|
internshipRegistration: InternshipRegistrationDTO;
|
||||||
|
documentation: InternshipDocument[],
|
||||||
}
|
}
|
||||||
|
|
||||||
export const internshipRegistrationUpdateTransformer: OneWayTransformer<Nullable<Internship>, Nullable<InternshipRegistrationUpdate>> = {
|
export const internshipRegistrationUpdateTransformer: OneWayTransformer<Nullable<Internship>, Nullable<InternshipRegistrationUpdate>> = {
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { axios } from "@/api/index";
|
import { axios } from "@/api/index";
|
||||||
import { Edition } from "@/data/edition";
|
import { Edition } from "@/data/edition";
|
||||||
import { prepare } from "@/routing";
|
import { prepare } from "@/routing";
|
||||||
import { EditionDTO, editionDtoTransformer, editionTeaserDtoTransformer } from "@/api/dto/edition";
|
import { EditionDTO, editionDtoTransformer, EditionTeaserDTO, editionTeaserDtoTransformer } from "@/api/dto/edition";
|
||||||
|
import { Subset } from "@/helpers";
|
||||||
|
|
||||||
const EDITIONS_ENDPOINT = "/editions";
|
const EDITIONS_ENDPOINT = "/editions";
|
||||||
const EDITION_INFO_ENDPOINT = "/editions/:key";
|
const EDITION_INFO_ENDPOINT = "/editions/:key";
|
||||||
@ -10,9 +11,13 @@ const EDITION_REGISTER_ENDPOINT = "/register";
|
|||||||
const EDITION_LOGIN_ENDPOINT = "/access/loginEdition";
|
const EDITION_LOGIN_ENDPOINT = "/access/loginEdition";
|
||||||
|
|
||||||
export async function available() {
|
export async function available() {
|
||||||
const response = await axios.get(EDITIONS_ENDPOINT);
|
try {
|
||||||
|
const response = await axios.get(EDITIONS_ENDPOINT);
|
||||||
|
|
||||||
return (response.data || []).map(editionTeaserDtoTransformer.transform);
|
return (response.data || []).map(editionTeaserDtoTransformer.transform);
|
||||||
|
} catch (e) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function join(key: string): Promise<boolean> {
|
export async function join(key: string): Promise<boolean> {
|
||||||
@ -25,11 +30,15 @@ export async function join(key: string): Promise<boolean> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function get(key: string): Promise<Edition | null> {
|
export async function get(key: string): Promise<Subset<Edition> | null> {
|
||||||
const response = await axios.get<EditionDTO>(prepare(EDITION_INFO_ENDPOINT, { key }));
|
if (!key) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await axios.get<EditionTeaserDTO>(prepare(EDITION_INFO_ENDPOINT, { key }));
|
||||||
const dto = response.data;
|
const dto = response.data;
|
||||||
|
|
||||||
return editionDtoTransformer.transform(dto);
|
return editionTeaserDtoTransformer.transform(dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function current(): Promise<Edition> {
|
export async function current(): Promise<Edition> {
|
||||||
|
@ -6,15 +6,12 @@ const INTERNSHIP_REGISTRATION_ENDPOINT = '/internshipRegistration';
|
|||||||
const INTERNSHIP_ENDPOINT = '/internship';
|
const INTERNSHIP_ENDPOINT = '/internship';
|
||||||
|
|
||||||
export async function update(internship: Nullable<InternshipRegistrationUpdate>): Promise<boolean> {
|
export async function update(internship: Nullable<InternshipRegistrationUpdate>): Promise<boolean> {
|
||||||
const response = await axios.put(INTERNSHIP_REGISTRATION_ENDPOINT, internship);
|
await axios.put(INTERNSHIP_REGISTRATION_ENDPOINT, internship);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function get(): Promise<InternshipInfoDTO> {
|
export async function get(): Promise<InternshipInfoDTO> {
|
||||||
const response = await axios.get<InternshipInfoDTO>(INTERNSHIP_ENDPOINT);
|
const response = await axios.get<InternshipInfoDTO>(INTERNSHIP_ENDPOINT);
|
||||||
|
|
||||||
console.log(response);
|
|
||||||
|
|
||||||
return response.data;
|
return response.data;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { Identifiable } from "@/data";
|
|
||||||
import { axios } from "@/api/index";
|
import { axios } from "@/api/index";
|
||||||
|
import { InternshipDocument } from "@/api/dto/internship-registration";
|
||||||
|
import { prepare } from "@/routing";
|
||||||
|
|
||||||
export enum UploadType {
|
export enum UploadType {
|
||||||
Ipp = "IppScan",
|
Ipp = "IppScan",
|
||||||
@ -10,14 +11,15 @@ export enum UploadType {
|
|||||||
const CREATE_DOCUMENT_ENDPOINT = '/document';
|
const CREATE_DOCUMENT_ENDPOINT = '/document';
|
||||||
const DOCUMENT_UPLOAD_ENDPOINT = '/document/:id/scan';
|
const DOCUMENT_UPLOAD_ENDPOINT = '/document/:id/scan';
|
||||||
|
|
||||||
interface Document extends Identifiable {
|
export async function create(type: UploadType) {
|
||||||
description?: string;
|
const response = await axios.post<InternshipDocument>(CREATE_DOCUMENT_ENDPOINT, { type });
|
||||||
type: UploadType;
|
return response.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function create(type: UploadType, content: File)
|
export async function upload(document: InternshipDocument, file: File) {
|
||||||
{
|
const data = new FormData();
|
||||||
const response = await axios.post<Document>(CREATE_DOCUMENT_ENDPOINT, { type });
|
data.append('documentScan', file)
|
||||||
|
|
||||||
console.log(response.data);
|
const response = await axios.put(prepare(DOCUMENT_UPLOAD_ENDPOINT, { id: document.id as string }), data);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -26,10 +26,6 @@ export interface Internship extends Identifiable {
|
|||||||
office: Office;
|
office: Office;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Plan extends Identifiable {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Mentor {
|
export interface Mentor {
|
||||||
name: string;
|
name: string;
|
||||||
surname: string;
|
surname: string;
|
||||||
|
@ -5,24 +5,39 @@ import { Actions } from "@/components";
|
|||||||
import { Link as RouterLink, useHistory } from "react-router-dom";
|
import { Link as RouterLink, useHistory } from "react-router-dom";
|
||||||
import { route } from "@/routing";
|
import { route } from "@/routing";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { Plan } from "@/data";
|
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useDispatch } from "@/state/actions";
|
import { InternshipPlanActions, useDispatch } from "@/state/actions";
|
||||||
import { UploadType } from "@/api/upload";
|
import { UploadType } from "@/api/upload";
|
||||||
import api from "@/api";
|
import api from "@/api";
|
||||||
|
import { useSelector } from "react-redux";
|
||||||
|
import { AppState } from "@/state/reducer";
|
||||||
|
import { InternshipDocument } from "@/api/dto/internship-registration";
|
||||||
|
|
||||||
export const PlanForm = () => {
|
export const PlanForm = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const [plan, setPlan] = useState<Plan>({});
|
const [file, setFile] = useState<File>();
|
||||||
|
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
|
||||||
const handleSubmit = () => {
|
const document = useSelector<AppState>(state => state.plan.document);
|
||||||
api.upload.create(UploadType.Ipp, null as any);
|
|
||||||
// dispatch({ type: InternshipPlanActions.Send, plan });
|
const handleSubmit = async () => {
|
||||||
history.push(route("home"))
|
if (!file) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let destination: InternshipDocument = document as any;
|
||||||
|
|
||||||
|
if (!destination) {
|
||||||
|
destination = await api.upload.create(UploadType.Ipp);
|
||||||
|
dispatch({ type: InternshipPlanActions.Send, document: destination });
|
||||||
|
}
|
||||||
|
|
||||||
|
await api.upload.upload(destination, file);
|
||||||
|
|
||||||
|
history.push("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
return <Grid container>
|
return <Grid container>
|
||||||
@ -35,7 +50,7 @@ export const PlanForm = () => {
|
|||||||
</Button>
|
</Button>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item>
|
<Grid item>
|
||||||
<DropzoneArea acceptedFiles={["image/*", "application/pdf"]} filesLimit={ 1 } dropzoneText={ t("dropzone") }/>
|
<DropzoneArea acceptedFiles={["image/*", "application/pdf"]} filesLimit={ 1 } dropzoneText={ t("dropzone") } onChange={ files => setFile(files[0]) }/>
|
||||||
<FormHelperText>{ t('forms.plan.dropzone-help') }</FormHelperText>
|
<FormHelperText>{ t('forms.plan.dropzone-help') }</FormHelperText>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item>
|
<Grid item>
|
||||||
|
@ -12,3 +12,17 @@ export interface DOMEvent<TTarget extends EventTarget> extends Event {
|
|||||||
export function delay(time: number) {
|
export function delay(time: number) {
|
||||||
return new Promise(resolve => setTimeout(resolve, time));
|
return new Promise(resolve => setTimeout(resolve, time));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function throttle<TArgs extends any[]>(decorated: (...args: TArgs) => void, time: number = 150) {
|
||||||
|
let timeout: number | undefined;
|
||||||
|
return function (this: any, ...args: TArgs): void {
|
||||||
|
if (typeof timeout !== 'undefined') {
|
||||||
|
window.clearTimeout(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
timeout = window.setTimeout(() => {
|
||||||
|
timeout = undefined;
|
||||||
|
decorated.call(this, ...args);
|
||||||
|
}, time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -30,6 +30,8 @@ export function useAsync<T, TError = any>(supplier: Promise<T> | (() => Promise<
|
|||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
|
console.error(error)
|
||||||
|
|
||||||
if (semaphore.value == myMagicNumber) {
|
if (semaphore.value == myMagicNumber) {
|
||||||
setError(error);
|
setError(error);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
@ -40,8 +42,10 @@ export function useAsync<T, TError = any>(supplier: Promise<T> | (() => Promise<
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (typeof supplier === "function") {
|
if (typeof supplier === "function") {
|
||||||
setPromise(supplier());
|
setPromise(supplier());
|
||||||
|
} else {
|
||||||
|
setPromise(supplier);
|
||||||
}
|
}
|
||||||
}, [])
|
}, [ supplier ])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isLoading,
|
isLoading,
|
||||||
|
10
src/hooks/useDebouncedEffect.ts
Normal file
10
src/hooks/useDebouncedEffect.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { DependencyList, EffectCallback, useCallback, useEffect } from "react";
|
||||||
|
|
||||||
|
export function useDebouncedEffect(effect: EffectCallback, deps: DependencyList, time: number = 150) {
|
||||||
|
const callback = useCallback(effect, deps);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const timeout = window.setTimeout(() => callback(), time);
|
||||||
|
return () => window.clearTimeout(timeout);
|
||||||
|
}, [ callback, time ])
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
import { Page } from "@/pages/base";
|
import { Page } from "@/pages/base";
|
||||||
import React from "react";
|
import React, { useCallback } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Box, Button, CircularProgress, Container, Typography } from "@material-ui/core";
|
import { Box, Button, CircularProgress, Container, Typography } from "@material-ui/core";
|
||||||
import { Actions } from "@/components";
|
import { Actions } from "@/components";
|
||||||
@ -11,11 +11,31 @@ import api from "@/api";
|
|||||||
import { Section } from "@/components/section";
|
import { Section } from "@/components/section";
|
||||||
import { useVerticalSpacing } from "@/styles";
|
import { useVerticalSpacing } from "@/styles";
|
||||||
import { Alert } from "@material-ui/lab";
|
import { Alert } from "@material-ui/lab";
|
||||||
import { EditionActions, useDispatch, UserActions } from "@/state/actions";
|
import { AppDispatch, EditionActions, useDispatch, UserActions } from "@/state/actions";
|
||||||
|
|
||||||
|
export const loginToEdition = (id: string) => async (dispatch: AppDispatch) => {
|
||||||
|
const token = await api.edition.login(id);
|
||||||
|
|
||||||
|
if (!token) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await dispatch({
|
||||||
|
type: UserActions.Login,
|
||||||
|
token,
|
||||||
|
})
|
||||||
|
|
||||||
|
const edition = await api.edition.current();
|
||||||
|
|
||||||
|
dispatch({
|
||||||
|
type: EditionActions.Set,
|
||||||
|
edition
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
export const PickEditionPage = () => {
|
export const PickEditionPage = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { value: editions, isLoading } = useAsync(() => api.edition.available());
|
const { value: editions, isLoading } = useAsync(useCallback(() => api.edition.available(), []));
|
||||||
|
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
@ -23,24 +43,7 @@ export const PickEditionPage = () => {
|
|||||||
const classes = useVerticalSpacing(3);
|
const classes = useVerticalSpacing(3);
|
||||||
|
|
||||||
const pickEditionHandler = (id: string) => async () => {
|
const pickEditionHandler = (id: string) => async () => {
|
||||||
const token = await api.edition.login(id);
|
await dispatch(loginToEdition(id));
|
||||||
|
|
||||||
if (!token) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await dispatch({
|
|
||||||
type: UserActions.Login,
|
|
||||||
token,
|
|
||||||
})
|
|
||||||
|
|
||||||
const edition = await api.edition.current();
|
|
||||||
|
|
||||||
dispatch({
|
|
||||||
type: EditionActions.Set,
|
|
||||||
edition
|
|
||||||
})
|
|
||||||
|
|
||||||
history.push("/");
|
history.push("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useCallback, useEffect, useState } from "react";
|
||||||
import { Page } from "@/pages/base";
|
import { Page } from "@/pages/base";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Box, Button, CircularProgress, Container, TextField, Typography } from "@material-ui/core";
|
import { Box, Button, CircularProgress, Container, TextField, Typography } from "@material-ui/core";
|
||||||
@ -9,24 +9,33 @@ import { Edition } from "@/data/edition";
|
|||||||
import { useAsyncState } from "@/hooks";
|
import { useAsyncState } from "@/hooks";
|
||||||
import { Label, Section } from "@/components/section";
|
import { Label, Section } from "@/components/section";
|
||||||
import { Alert } from "@material-ui/lab";
|
import { Alert } from "@material-ui/lab";
|
||||||
|
import { Subset } from "@/helpers";
|
||||||
|
import { useDispatch } from "@/state/actions";
|
||||||
|
import { loginToEdition } from "@/pages/edition/pick";
|
||||||
|
import { useHistory } from "react-router-dom";
|
||||||
|
import { useDebouncedEffect } from "@/hooks/useDebouncedEffect";
|
||||||
|
|
||||||
export const RegisterEditionPage = () => {
|
export const RegisterEditionPage = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const [key, setKey] = useState<string>("");
|
const [key, setKey] = useState<string>("");
|
||||||
const [{ value: edition, isLoading }, setEdition] = useAsyncState<Edition | null>(undefined);
|
const [{ value: edition, isLoading }, setEdition] = useAsyncState<Subset<Edition> | null>(undefined);
|
||||||
|
|
||||||
const classes = useVerticalSpacing(3);
|
const classes = useVerticalSpacing(3);
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const history = useHistory();
|
||||||
|
|
||||||
useEffect(() => {
|
useDebouncedEffect(() => {
|
||||||
setEdition(api.edition.get(key));
|
setEdition(api.edition.get(key));
|
||||||
}, [ key ])
|
}, [ key ])
|
||||||
|
|
||||||
const handleRegister = () => {
|
const handleRegister = async () => {
|
||||||
try {
|
try {
|
||||||
api.edition.join(key);
|
await api.edition.join(key);
|
||||||
|
await dispatch(loginToEdition(key));
|
||||||
|
history.push("/");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,7 +46,7 @@ export const RegisterEditionPage = () => {
|
|||||||
const Edition = () => edition
|
const Edition = () => edition
|
||||||
? <Section>
|
? <Section>
|
||||||
<Label>{ t("forms.edition-register.edition" ) }</Label>
|
<Label>{ t("forms.edition-register.edition" ) }</Label>
|
||||||
<Typography className="proposal__primary">{ edition.course.name }</Typography>
|
<Typography className="proposal__primary">{ edition.course?.name }</Typography>
|
||||||
<Typography className="proposal__secondary">
|
<Typography className="proposal__secondary">
|
||||||
{ t('internship.date-range', { start: edition.startDate, end: edition.endDate }) }
|
{ t('internship.date-range', { start: edition.startDate, end: edition.endDate }) }
|
||||||
</Typography>
|
</Typography>
|
||||||
|
@ -15,8 +15,29 @@ import { InsuranceStep } from "@/pages/steps/insurance";
|
|||||||
import { StudentStep } from "@/pages/steps/student";
|
import { StudentStep } from "@/pages/steps/student";
|
||||||
import { useDeadlines } from "@/hooks";
|
import { useDeadlines } from "@/hooks";
|
||||||
import api from "@/api";
|
import api from "@/api";
|
||||||
import { InternshipProposalActions, useDispatch } from "@/state/actions";
|
import { AppDispatch, InternshipPlanActions, InternshipProposalActions, useDispatch } from "@/state/actions";
|
||||||
import { internshipRegistrationDtoTransformer } from "@/api/dto/internship-registration";
|
import { internshipRegistrationDtoTransformer } from "@/api/dto/internship-registration";
|
||||||
|
import { UploadType } from "@/api/upload";
|
||||||
|
|
||||||
|
export const updateInternshipInfo = async (dispatch: AppDispatch) => {
|
||||||
|
const internship = await api.internship.get();
|
||||||
|
|
||||||
|
dispatch({
|
||||||
|
type: InternshipProposalActions.Receive,
|
||||||
|
state: internship.internshipRegistration.state,
|
||||||
|
internship: internshipRegistrationDtoTransformer.transform(internship.internshipRegistration),
|
||||||
|
})
|
||||||
|
|
||||||
|
const plan = internship.documentation.find(doc => doc.type === UploadType.Ipp);
|
||||||
|
|
||||||
|
if (plan) {
|
||||||
|
dispatch({
|
||||||
|
type: InternshipPlanActions.Receive,
|
||||||
|
document: plan,
|
||||||
|
state: plan.state,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const MainPage = () => {
|
export const MainPage = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@ -28,15 +49,7 @@ export const MainPage = () => {
|
|||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
(async () => {
|
dispatch(updateInternshipInfo);
|
||||||
const internship = await api.internship.get();
|
|
||||||
|
|
||||||
dispatch({
|
|
||||||
type: InternshipProposalActions.Receive,
|
|
||||||
state: internship.internshipRegistration.state,
|
|
||||||
internship: internshipRegistrationDtoTransformer.transform(internship.internshipRegistration),
|
|
||||||
})
|
|
||||||
})()
|
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
if (!student) {
|
if (!student) {
|
||||||
|
@ -37,7 +37,8 @@ export const Actions = {
|
|||||||
...StudentActions,
|
...StudentActions,
|
||||||
}
|
}
|
||||||
export type Actions = typeof Actions;
|
export type Actions = typeof Actions;
|
||||||
|
export type AppDispatch = ThunkDispatch<AppState, any, Action>;
|
||||||
|
|
||||||
export const useDispatch = () => useReduxDispatch<ThunkDispatch<AppState, any, Action>>()
|
export const useDispatch = () => useReduxDispatch<AppDispatch>()
|
||||||
|
|
||||||
export default Actions;
|
export default Actions;
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { Plan } from "@/data";
|
|
||||||
import {
|
import {
|
||||||
ReceiveSubmissionApproveAction,
|
ReceiveSubmissionApproveAction,
|
||||||
ReceiveSubmissionDeclineAction,
|
ReceiveSubmissionDeclineAction,
|
||||||
@ -7,6 +6,8 @@ import {
|
|||||||
SendSubmissionAction
|
SendSubmissionAction
|
||||||
} from "@/state/actions/submission";
|
} from "@/state/actions/submission";
|
||||||
|
|
||||||
|
import { InternshipDocument, SubmissionState } from "@/api/dto/internship-registration";
|
||||||
|
|
||||||
export enum InternshipPlanActions {
|
export enum InternshipPlanActions {
|
||||||
Send = "SEND_PLAN",
|
Send = "SEND_PLAN",
|
||||||
Save = "SAVE_PLAN",
|
Save = "SAVE_PLAN",
|
||||||
@ -16,7 +17,7 @@ export enum InternshipPlanActions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface SendPlanAction extends SendSubmissionAction<InternshipPlanActions.Send> {
|
export interface SendPlanAction extends SendSubmissionAction<InternshipPlanActions.Send> {
|
||||||
plan: Plan;
|
document: InternshipDocument;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ReceivePlanApproveAction extends ReceiveSubmissionApproveAction<InternshipPlanActions.Approve> {
|
export interface ReceivePlanApproveAction extends ReceiveSubmissionApproveAction<InternshipPlanActions.Approve> {
|
||||||
@ -26,10 +27,12 @@ export interface ReceivePlanDeclineAction extends ReceiveSubmissionDeclineAction
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ReceivePlanUpdateAction extends ReceiveSubmissionUpdateAction<InternshipPlanActions.Receive> {
|
export interface ReceivePlanUpdateAction extends ReceiveSubmissionUpdateAction<InternshipPlanActions.Receive> {
|
||||||
|
document: InternshipDocument;
|
||||||
|
state: SubmissionState;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SavePlanAction extends SaveSubmissionAction<InternshipPlanActions.Save> {
|
export interface SavePlanAction extends SaveSubmissionAction<InternshipPlanActions.Save> {
|
||||||
plan: Plan;
|
document: InternshipDocument;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type InternshipPlanAction
|
export type InternshipPlanAction
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { InternshipPlanAction, InternshipPlanActions } from "@/state/actions";
|
import { InternshipPlanAction, InternshipPlanActions, InternshipProposalActions } from "@/state/actions";
|
||||||
import { Plan } from "@/data";
|
|
||||||
import { Serializable } from "@/serialization/types";
|
import { Serializable } from "@/serialization/types";
|
||||||
import {
|
import {
|
||||||
createSubmissionReducer,
|
createSubmissionReducer,
|
||||||
@ -10,19 +9,18 @@ import {
|
|||||||
} from "@/state/reducer/submission";
|
} from "@/state/reducer/submission";
|
||||||
import { Reducer } from "react";
|
import { Reducer } from "react";
|
||||||
import { SubmissionAction } from "@/state/actions/submission";
|
import { SubmissionAction } from "@/state/actions/submission";
|
||||||
|
import { InternshipDocument, SubmissionState as ApiSubmissionState } from "@/api/dto/internship-registration";
|
||||||
|
|
||||||
export type InternshipPlanState = SubmissionState & MayRequireDeanApproval & {
|
export type InternshipPlanState = SubmissionState & MayRequireDeanApproval & {
|
||||||
plan: Serializable<Plan> | null;
|
document: Serializable<InternshipDocument> | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultInternshipPlanState: InternshipPlanState = {
|
const defaultInternshipPlanState: InternshipPlanState = {
|
||||||
...defaultDeanApprovalsState,
|
...defaultDeanApprovalsState,
|
||||||
...defaultSubmissionState,
|
...defaultSubmissionState,
|
||||||
plan: null,
|
document: null,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getInternshipPlan = ({ plan }: InternshipPlanState): Plan | null => plan;
|
|
||||||
|
|
||||||
const internshipPlanSubmissionReducer: Reducer<InternshipPlanState, InternshipPlanAction> = createSubmissionReducer({
|
const internshipPlanSubmissionReducer: Reducer<InternshipPlanState, InternshipPlanAction> = createSubmissionReducer({
|
||||||
[InternshipPlanActions.Approve]: SubmissionAction.Approve,
|
[InternshipPlanActions.Approve]: SubmissionAction.Approve,
|
||||||
[InternshipPlanActions.Decline]: SubmissionAction.Decline,
|
[InternshipPlanActions.Decline]: SubmissionAction.Decline,
|
||||||
@ -39,8 +37,20 @@ const internshipPlanReducer = (state: InternshipPlanState = defaultInternshipPla
|
|||||||
case InternshipPlanActions.Send:
|
case InternshipPlanActions.Send:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
plan: action.plan,
|
document: action.document,
|
||||||
}
|
}
|
||||||
|
case InternshipPlanActions.Receive:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
accepted: action.state === ApiSubmissionState.Accepted,
|
||||||
|
sent: [
|
||||||
|
ApiSubmissionState.Accepted,
|
||||||
|
ApiSubmissionState.Rejected,
|
||||||
|
ApiSubmissionState.Submitted
|
||||||
|
].includes(action.state),
|
||||||
|
document: action.document,
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,7 @@ pages:
|
|||||||
my-editions: "Moje praktyki"
|
my-editions: "Moje praktyki"
|
||||||
pick: "wybierz"
|
pick: "wybierz"
|
||||||
register: "Zapisz się do edycji praktyk"
|
register: "Zapisz się do edycji praktyk"
|
||||||
|
no-editions: "Brak edycji do wyboru, zarejestruj się do edycji praktyk przyciskiem poniżej."
|
||||||
user-fill:
|
user-fill:
|
||||||
title: "Uzupełnij swoje dane"
|
title: "Uzupełnij swoje dane"
|
||||||
user-profile:
|
user-profile:
|
||||||
|
Loading…
Reference in New Issue
Block a user