Fix internship selection
This commit is contained in:
		
							parent
							
								
									d9902702db
								
							
						
					
					
						commit
						52bda87494
					
				@ -20,7 +20,7 @@ export interface EditionTeaserDTO extends Identifiable {
 | 
			
		||||
 | 
			
		||||
export const editionTeaserDtoTransformer: OneWayTransformer<EditionTeaserDTO, Subset<Edition>> = {
 | 
			
		||||
    transform(subject: EditionTeaserDTO, context?: undefined): Subset<Edition> {
 | 
			
		||||
        return {
 | 
			
		||||
        return subject && {
 | 
			
		||||
            id: subject.id,
 | 
			
		||||
            startDate: moment(subject.editionStart),
 | 
			
		||||
            endDate: moment(subject.editionFinish),
 | 
			
		||||
 | 
			
		||||
@ -5,6 +5,7 @@ import { MentorDTO, mentorDtoTransformer } from "@/api/dto/mentor";
 | 
			
		||||
import { InternshipTypeDTO, internshipTypeDtoTransformer } from "@/api/dto/type";
 | 
			
		||||
import { Moment } from "moment";
 | 
			
		||||
import { sampleStudent } from "@/provider/dummy";
 | 
			
		||||
import { UploadType } from "@/api/upload";
 | 
			
		||||
 | 
			
		||||
export enum SubmissionState {
 | 
			
		||||
    Draft = "Draft",
 | 
			
		||||
@ -48,10 +49,17 @@ export interface InternshipRegistrationDTO extends Identifiable {
 | 
			
		||||
    declaredHours: number,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface InternshipDocument extends Identifiable {
 | 
			
		||||
    description: null,
 | 
			
		||||
    type: UploadType,
 | 
			
		||||
    state: SubmissionState,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const reference = (subject: Identifiable | null): Identifiable | null => subject && { id: subject.id };
 | 
			
		||||
 | 
			
		||||
export interface InternshipInfoDTO {
 | 
			
		||||
    internshipRegistration: InternshipRegistrationDTO;
 | 
			
		||||
    documentation: InternshipDocument[],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const internshipRegistrationUpdateTransformer: OneWayTransformer<Nullable<Internship>, Nullable<InternshipRegistrationUpdate>> = {
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,8 @@
 | 
			
		||||
import { axios } from "@/api/index";
 | 
			
		||||
import { Edition } from "@/data/edition";
 | 
			
		||||
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 EDITION_INFO_ENDPOINT = "/editions/:key";
 | 
			
		||||
@ -29,11 +30,15 @@ export async function join(key: string): Promise<boolean> {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export async function get(key: string): Promise<Edition | null> {
 | 
			
		||||
    const response = await axios.get<EditionDTO>(prepare(EDITION_INFO_ENDPOINT, { key }));
 | 
			
		||||
export async function get(key: string): Promise<Subset<Edition> | null> {
 | 
			
		||||
    if (!key) {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const response = await axios.get<EditionTeaserDTO>(prepare(EDITION_INFO_ENDPOINT, { key }));
 | 
			
		||||
    const dto = response.data;
 | 
			
		||||
 | 
			
		||||
    return editionDtoTransformer.transform(dto);
 | 
			
		||||
    return editionTeaserDtoTransformer.transform(dto);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export async function current(): Promise<Edition> {
 | 
			
		||||
 | 
			
		||||
@ -6,15 +6,12 @@ const INTERNSHIP_REGISTRATION_ENDPOINT = '/internshipRegistration';
 | 
			
		||||
const INTERNSHIP_ENDPOINT = '/internship';
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export async function get(): Promise<InternshipInfoDTO> {
 | 
			
		||||
    const response = await axios.get<InternshipInfoDTO>(INTERNSHIP_ENDPOINT);
 | 
			
		||||
 | 
			
		||||
    console.log(response);
 | 
			
		||||
 | 
			
		||||
    return response.data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,6 @@
 | 
			
		||||
import { Identifiable } from "@/data";
 | 
			
		||||
import { axios } from "@/api/index";
 | 
			
		||||
import { InternshipDocument } from "@/api/dto/internship-registration";
 | 
			
		||||
import { prepare } from "@/routing";
 | 
			
		||||
 | 
			
		||||
export enum UploadType {
 | 
			
		||||
    Ipp = "IppScan",
 | 
			
		||||
@ -10,14 +11,15 @@ export enum UploadType {
 | 
			
		||||
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) {
 | 
			
		||||
    const response = await axios.post<InternshipDocument>(CREATE_DOCUMENT_ENDPOINT, { type });
 | 
			
		||||
    return response.data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export async function create(type: UploadType, content: File)
 | 
			
		||||
{
 | 
			
		||||
    const response = await axios.post<Document>(CREATE_DOCUMENT_ENDPOINT, { type });
 | 
			
		||||
export async function upload(document: InternshipDocument, file: File) {
 | 
			
		||||
    const data = new FormData();
 | 
			
		||||
    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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface Plan extends Identifiable {
 | 
			
		||||
    
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface Mentor {
 | 
			
		||||
    name: string;
 | 
			
		||||
    surname: string;
 | 
			
		||||
 | 
			
		||||
@ -5,24 +5,39 @@ import { Actions } from "@/components";
 | 
			
		||||
import { Link as RouterLink, useHistory } from "react-router-dom";
 | 
			
		||||
import { route } from "@/routing";
 | 
			
		||||
import React, { useState } from "react";
 | 
			
		||||
import { Plan } from "@/data";
 | 
			
		||||
import { useTranslation } from "react-i18next";
 | 
			
		||||
import { useDispatch } from "@/state/actions";
 | 
			
		||||
import { InternshipPlanActions, useDispatch } from "@/state/actions";
 | 
			
		||||
import { UploadType } from "@/api/upload";
 | 
			
		||||
import api from "@/api";
 | 
			
		||||
import { useSelector } from "react-redux";
 | 
			
		||||
import { AppState } from "@/state/reducer";
 | 
			
		||||
import { InternshipDocument } from "@/api/dto/internship-registration";
 | 
			
		||||
 | 
			
		||||
export const PlanForm = () => {
 | 
			
		||||
    const { t } = useTranslation();
 | 
			
		||||
 | 
			
		||||
    const [plan, setPlan] = useState<Plan>({});
 | 
			
		||||
    const [file, setFile] = useState<File>();
 | 
			
		||||
 | 
			
		||||
    const dispatch = useDispatch();
 | 
			
		||||
    const history = useHistory();
 | 
			
		||||
 | 
			
		||||
    const handleSubmit = () => {
 | 
			
		||||
        api.upload.create(UploadType.Ipp, null as any);
 | 
			
		||||
        // dispatch({ type: InternshipPlanActions.Send, plan });
 | 
			
		||||
        history.push(route("home"))
 | 
			
		||||
    const document = useSelector<AppState>(state => state.plan.document);
 | 
			
		||||
 | 
			
		||||
    const handleSubmit = async () => {
 | 
			
		||||
        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>
 | 
			
		||||
@ -35,7 +50,7 @@ export const PlanForm = () => {
 | 
			
		||||
            </Button>
 | 
			
		||||
        </Grid>
 | 
			
		||||
        <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>
 | 
			
		||||
        </Grid>
 | 
			
		||||
        <Grid item>
 | 
			
		||||
 | 
			
		||||
@ -12,3 +12,17 @@ export interface DOMEvent<TTarget extends EventTarget> extends Event {
 | 
			
		||||
export function delay(time: number) {
 | 
			
		||||
  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);
 | 
			
		||||
            }
 | 
			
		||||
        }).catch(error => {
 | 
			
		||||
            console.error(error)
 | 
			
		||||
 | 
			
		||||
            if (semaphore.value == myMagicNumber) {
 | 
			
		||||
                setError(error);
 | 
			
		||||
                setLoading(false);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										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 ])
 | 
			
		||||
}
 | 
			
		||||
@ -11,7 +11,27 @@ import api from "@/api";
 | 
			
		||||
import { Section } from "@/components/section";
 | 
			
		||||
import { useVerticalSpacing } from "@/styles";
 | 
			
		||||
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 = () => {
 | 
			
		||||
    const { t } = useTranslation();
 | 
			
		||||
@ -23,24 +43,7 @@ export const PickEditionPage = () => {
 | 
			
		||||
    const classes = useVerticalSpacing(3);
 | 
			
		||||
 | 
			
		||||
    const pickEditionHandler = (id: string) => async () => {
 | 
			
		||||
        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
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        await dispatch(loginToEdition(id));
 | 
			
		||||
        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 { useTranslation } from "react-i18next";
 | 
			
		||||
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 { Label, Section } from "@/components/section";
 | 
			
		||||
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 = () => {
 | 
			
		||||
    const { t } = useTranslation();
 | 
			
		||||
 | 
			
		||||
    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 dispatch = useDispatch();
 | 
			
		||||
    const history = useHistory();
 | 
			
		||||
 | 
			
		||||
    useEffect(() => {
 | 
			
		||||
    useDebouncedEffect(() => {
 | 
			
		||||
        setEdition(api.edition.get(key));
 | 
			
		||||
    }, [ key ])
 | 
			
		||||
 | 
			
		||||
    const handleRegister = () => {
 | 
			
		||||
    const handleRegister = async () => {
 | 
			
		||||
        try {
 | 
			
		||||
            api.edition.join(key);
 | 
			
		||||
            await api.edition.join(key);
 | 
			
		||||
            await dispatch(loginToEdition(key));
 | 
			
		||||
            history.push("/");
 | 
			
		||||
        } catch (error) {
 | 
			
		||||
 | 
			
		||||
            console.log(error);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -37,7 +46,7 @@ export const RegisterEditionPage = () => {
 | 
			
		||||
    const Edition = () => edition
 | 
			
		||||
        ? <Section>
 | 
			
		||||
            <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">
 | 
			
		||||
                { t('internship.date-range', { start: edition.startDate, end: edition.endDate }) }
 | 
			
		||||
            </Typography>
 | 
			
		||||
 | 
			
		||||
@ -15,8 +15,29 @@ import { InsuranceStep } from "@/pages/steps/insurance";
 | 
			
		||||
import { StudentStep } from "@/pages/steps/student";
 | 
			
		||||
import { useDeadlines } from "@/hooks";
 | 
			
		||||
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 { 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 = () => {
 | 
			
		||||
    const { t } = useTranslation();
 | 
			
		||||
@ -28,15 +49,7 @@ export const MainPage = () => {
 | 
			
		||||
    const dispatch = useDispatch();
 | 
			
		||||
 | 
			
		||||
    useEffect(() => {
 | 
			
		||||
        (async () => {
 | 
			
		||||
            const internship = await api.internship.get();
 | 
			
		||||
 | 
			
		||||
            dispatch({
 | 
			
		||||
                type: InternshipProposalActions.Receive,
 | 
			
		||||
                state: internship.internshipRegistration.state,
 | 
			
		||||
                internship: internshipRegistrationDtoTransformer.transform(internship.internshipRegistration),
 | 
			
		||||
            })
 | 
			
		||||
        })()
 | 
			
		||||
        dispatch(updateInternshipInfo);
 | 
			
		||||
    }, [])
 | 
			
		||||
 | 
			
		||||
    if (!student) {
 | 
			
		||||
 | 
			
		||||
@ -37,7 +37,8 @@ export const Actions = {
 | 
			
		||||
    ...StudentActions,
 | 
			
		||||
}
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,3 @@
 | 
			
		||||
import { Plan } from "@/data";
 | 
			
		||||
import {
 | 
			
		||||
    ReceiveSubmissionApproveAction,
 | 
			
		||||
    ReceiveSubmissionDeclineAction,
 | 
			
		||||
@ -7,6 +6,8 @@ import {
 | 
			
		||||
    SendSubmissionAction
 | 
			
		||||
} from "@/state/actions/submission";
 | 
			
		||||
 | 
			
		||||
import { InternshipDocument, SubmissionState } from "@/api/dto/internship-registration";
 | 
			
		||||
 | 
			
		||||
export enum InternshipPlanActions {
 | 
			
		||||
    Send = "SEND_PLAN",
 | 
			
		||||
    Save = "SAVE_PLAN",
 | 
			
		||||
@ -16,7 +17,7 @@ export enum InternshipPlanActions {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface SendPlanAction extends SendSubmissionAction<InternshipPlanActions.Send> {
 | 
			
		||||
    plan: Plan;
 | 
			
		||||
    document: InternshipDocument;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ReceivePlanApproveAction extends ReceiveSubmissionApproveAction<InternshipPlanActions.Approve> {
 | 
			
		||||
@ -26,10 +27,12 @@ export interface ReceivePlanDeclineAction extends ReceiveSubmissionDeclineAction
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ReceivePlanUpdateAction extends ReceiveSubmissionUpdateAction<InternshipPlanActions.Receive> {
 | 
			
		||||
    document: InternshipDocument;
 | 
			
		||||
    state: SubmissionState;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface SavePlanAction extends SaveSubmissionAction<InternshipPlanActions.Save> {
 | 
			
		||||
    plan: Plan;
 | 
			
		||||
    document: InternshipDocument;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type InternshipPlanAction
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,4 @@
 | 
			
		||||
import { InternshipPlanAction, InternshipPlanActions } from "@/state/actions";
 | 
			
		||||
import { Plan } from "@/data";
 | 
			
		||||
import { InternshipPlanAction, InternshipPlanActions, InternshipProposalActions } from "@/state/actions";
 | 
			
		||||
import { Serializable } from "@/serialization/types";
 | 
			
		||||
import {
 | 
			
		||||
    createSubmissionReducer,
 | 
			
		||||
@ -10,19 +9,18 @@ import {
 | 
			
		||||
} from "@/state/reducer/submission";
 | 
			
		||||
import { Reducer } from "react";
 | 
			
		||||
import { SubmissionAction } from "@/state/actions/submission";
 | 
			
		||||
import { InternshipDocument, SubmissionState as ApiSubmissionState } from "@/api/dto/internship-registration";
 | 
			
		||||
 | 
			
		||||
export type InternshipPlanState = SubmissionState & MayRequireDeanApproval & {
 | 
			
		||||
    plan: Serializable<Plan> | null;
 | 
			
		||||
    document: Serializable<InternshipDocument> | null;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const defaultInternshipPlanState: InternshipPlanState = {
 | 
			
		||||
    ...defaultDeanApprovalsState,
 | 
			
		||||
    ...defaultSubmissionState,
 | 
			
		||||
    plan: null,
 | 
			
		||||
    document: null,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const getInternshipPlan = ({ plan }: InternshipPlanState): Plan | null => plan;
 | 
			
		||||
 | 
			
		||||
const internshipPlanSubmissionReducer: Reducer<InternshipPlanState, InternshipPlanAction> = createSubmissionReducer({
 | 
			
		||||
    [InternshipPlanActions.Approve]: SubmissionAction.Approve,
 | 
			
		||||
    [InternshipPlanActions.Decline]: SubmissionAction.Decline,
 | 
			
		||||
@ -39,8 +37,20 @@ const internshipPlanReducer = (state: InternshipPlanState = defaultInternshipPla
 | 
			
		||||
        case InternshipPlanActions.Send:
 | 
			
		||||
            return {
 | 
			
		||||
                ...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:
 | 
			
		||||
            return state;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user