Add IPP state management
This commit is contained in:
		
							parent
							
								
									886153afb5
								
							
						
					
					
						commit
						5cc9f51584
					
				
							
								
								
									
										50
									
								
								src/forms/plan.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								src/forms/plan.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,50 @@
 | 
				
			|||||||
 | 
					import { Button, FormHelperText, Grid, Typography } from "@material-ui/core";
 | 
				
			||||||
 | 
					import { Description as DescriptionIcon } from "@material-ui/icons";
 | 
				
			||||||
 | 
					import { DropzoneArea } from "material-ui-dropzone";
 | 
				
			||||||
 | 
					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 { InternshipPlanActions, useDispatch } from "@/state/actions";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const PlanForm = () => {
 | 
				
			||||||
 | 
					    const { t } = useTranslation();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const [plan, setPlan] = useState<Plan>({});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const dispatch = useDispatch();
 | 
				
			||||||
 | 
					    const history = useHistory();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const handleSubmit = () => {
 | 
				
			||||||
 | 
					        dispatch({ type: InternshipPlanActions.Send, plan });
 | 
				
			||||||
 | 
					        history.push(route("home"))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return <Grid container>
 | 
				
			||||||
 | 
					        <Grid item>
 | 
				
			||||||
 | 
					            <Typography variant="body1" component="p">{ t('forms.plan.instructions') }</Typography>
 | 
				
			||||||
 | 
					        </Grid>
 | 
				
			||||||
 | 
					        <Grid item>
 | 
				
			||||||
 | 
					            <Button href="https://eti.pg.edu.pl/documents/611675/100028367/indywidualny%20program%20praktyk" startIcon={ <DescriptionIcon /> }>
 | 
				
			||||||
 | 
					                { t('steps.plan.template') }
 | 
				
			||||||
 | 
					            </Button>
 | 
				
			||||||
 | 
					        </Grid>
 | 
				
			||||||
 | 
					        <Grid item>
 | 
				
			||||||
 | 
					            <DropzoneArea acceptedFiles={["image/*", "application/x-pdf"]} filesLimit={ 1 } dropzoneText={ t("dropzone") }/>
 | 
				
			||||||
 | 
					            <FormHelperText>{ t('forms.plan.dropzone-help') }</FormHelperText>
 | 
				
			||||||
 | 
					        </Grid>
 | 
				
			||||||
 | 
					        <Grid item>
 | 
				
			||||||
 | 
					            <Actions>
 | 
				
			||||||
 | 
					                <Button variant="contained" color="primary" onClick={ handleSubmit }>
 | 
				
			||||||
 | 
					                    { t('confirm') }
 | 
				
			||||||
 | 
					                </Button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                <Button component={ RouterLink } to={ route("home") }>
 | 
				
			||||||
 | 
					                    { t('go-back') }
 | 
				
			||||||
 | 
					                </Button>
 | 
				
			||||||
 | 
					            </Actions>
 | 
				
			||||||
 | 
					        </Grid>
 | 
				
			||||||
 | 
					    </Grid>
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,3 +1,7 @@
 | 
				
			|||||||
export * from "./internship/proposal";
 | 
					export * from "./internship/proposal";
 | 
				
			||||||
export * from "./errors/not-found"
 | 
					export * from "./errors/not-found"
 | 
				
			||||||
export * from "./main"
 | 
					export * from "./main"
 | 
				
			||||||
 | 
					export { ProposalStep } from "@/pages/steps/proposal";
 | 
				
			||||||
 | 
					export { ProposalComment } from "@/pages/steps/proposal";
 | 
				
			||||||
 | 
					export { ProposalActions } from "@/pages/steps/proposal";
 | 
				
			||||||
 | 
					export { ProposalStatus } from "@/pages/steps/proposal";
 | 
				
			||||||
 | 
				
			|||||||
@ -1,12 +1,10 @@
 | 
				
			|||||||
import { Page } from "@/pages/base";
 | 
					import { Page } from "@/pages/base";
 | 
				
			||||||
import { Button, Container, FormHelperText, Grid, Link, Typography } from "@material-ui/core";
 | 
					import { Container, Link, Typography } from "@material-ui/core";
 | 
				
			||||||
import { Link as RouterLink } from "react-router-dom";
 | 
					import { Link as RouterLink } from "react-router-dom";
 | 
				
			||||||
import { route } from "@/routing";
 | 
					import { route } from "@/routing";
 | 
				
			||||||
import React from "react";
 | 
					import React from "react";
 | 
				
			||||||
import { useTranslation } from "react-i18next";
 | 
					import { useTranslation } from "react-i18next";
 | 
				
			||||||
import { DropzoneArea } from "material-ui-dropzone";
 | 
					import { PlanForm } from "@/forms/plan";
 | 
				
			||||||
import { Description as DescriptionIcon } from "@material-ui/icons";
 | 
					 | 
				
			||||||
import { Actions } from "@/components/actions";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const SubmitPlanPage = () => {
 | 
					export const SubmitPlanPage = () => {
 | 
				
			||||||
    const { t } = useTranslation();
 | 
					    const { t } = useTranslation();
 | 
				
			||||||
@ -20,31 +18,7 @@ export const SubmitPlanPage = () => {
 | 
				
			|||||||
            <Page.Title>{ t("steps.plan.submit") }</Page.Title>
 | 
					            <Page.Title>{ t("steps.plan.submit") }</Page.Title>
 | 
				
			||||||
        </Page.Header>
 | 
					        </Page.Header>
 | 
				
			||||||
        <Container maxWidth={ "md" }>
 | 
					        <Container maxWidth={ "md" }>
 | 
				
			||||||
            <Grid container>
 | 
					            <PlanForm />
 | 
				
			||||||
                <Grid item>
 | 
					 | 
				
			||||||
                    <Typography variant="body1" component="p">{ t('forms.plan.instructions') }</Typography>
 | 
					 | 
				
			||||||
                </Grid>
 | 
					 | 
				
			||||||
                <Grid item>
 | 
					 | 
				
			||||||
                    <Button href="https://eti.pg.edu.pl/documents/611675/100028367/indywidualny%20program%20praktyk" startIcon={ <DescriptionIcon /> }>
 | 
					 | 
				
			||||||
                        { t('steps.plan.template') }
 | 
					 | 
				
			||||||
                    </Button>
 | 
					 | 
				
			||||||
                </Grid>
 | 
					 | 
				
			||||||
                <Grid item>
 | 
					 | 
				
			||||||
                    <DropzoneArea acceptedFiles={["image/*", "application/x-pdf"]} filesLimit={ 1 } dropzoneText={ t("dropzone") }/>
 | 
					 | 
				
			||||||
                    <FormHelperText>{ t('forms.plan.dropzone-help') }</FormHelperText>
 | 
					 | 
				
			||||||
                </Grid>
 | 
					 | 
				
			||||||
                <Grid item>
 | 
					 | 
				
			||||||
                    <Actions>
 | 
					 | 
				
			||||||
                        <Button variant="contained" color="primary">
 | 
					 | 
				
			||||||
                            { t('confirm') }
 | 
					 | 
				
			||||||
                        </Button>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        <Button component={ RouterLink } to={ route("home") }>
 | 
					 | 
				
			||||||
                            { t('go-back') }
 | 
					 | 
				
			||||||
                        </Button>
 | 
					 | 
				
			||||||
                    </Actions>
 | 
					 | 
				
			||||||
                </Grid>
 | 
					 | 
				
			||||||
            </Grid>
 | 
					 | 
				
			||||||
        </Container>
 | 
					        </Container>
 | 
				
			||||||
    </Page>
 | 
					    </Page>
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
import React, { HTMLProps, useMemo } from "react";
 | 
					import React, { useMemo } from "react";
 | 
				
			||||||
import { Page } from "@/pages/base";
 | 
					import { Page } from "@/pages/base";
 | 
				
			||||||
import { Box, Button, ButtonProps, Container, Stepper, StepProps, Theme, Typography } from "@material-ui/core";
 | 
					import { Button, Container, Stepper, Typography } from "@material-ui/core";
 | 
				
			||||||
import { Link as RouterLink } from "react-router-dom";
 | 
					import { Link as RouterLink } from "react-router-dom";
 | 
				
			||||||
import { route } from "@/routing";
 | 
					import { route } from "@/routing";
 | 
				
			||||||
import { useTranslation } from "react-i18next";
 | 
					import { useTranslation } from "react-i18next";
 | 
				
			||||||
@ -8,118 +8,9 @@ import { useSelector } from "react-redux";
 | 
				
			|||||||
import { AppState } from "@/state/reducer";
 | 
					import { AppState } from "@/state/reducer";
 | 
				
			||||||
import { getMissingStudentData, Student } from "@/data";
 | 
					import { getMissingStudentData, Student } from "@/data";
 | 
				
			||||||
import { Deadlines, Edition, getEditionDeadlines } from "@/data/edition";
 | 
					import { Deadlines, Edition, getEditionDeadlines } from "@/data/edition";
 | 
				
			||||||
import { Description as DescriptionIcon } from "@material-ui/icons"
 | 
					import { Step } from "@/components";
 | 
				
			||||||
import { Actions, Step } from "@/components";
 | 
					import { ProposalStep } from "@/pages/steps/proposal";
 | 
				
			||||||
import { InternshipProposalState } from "@/state/reducer/proposal";
 | 
					import { PlanStep } from "@/pages/steps/plan";
 | 
				
			||||||
import { createStyles, makeStyles } from "@material-ui/core/styles";
 | 
					 | 
				
			||||||
import { ClipboardEditOutline, CommentQuestion, FileFind } from "mdi-material-ui";
 | 
					 | 
				
			||||||
import { Alert, AlertTitle } from "@material-ui/lab";
 | 
					 | 
				
			||||||
import { getSubmissionStatus, SubmissionStatus } from "@/state/reducer/submission";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const getColorByStatus = (status: SubmissionStatus, theme: Theme) => {
 | 
					 | 
				
			||||||
    switch (status) {
 | 
					 | 
				
			||||||
        case "awaiting":
 | 
					 | 
				
			||||||
            return theme.palette.info.dark;
 | 
					 | 
				
			||||||
        case "accepted":
 | 
					 | 
				
			||||||
            return theme.palette.success.dark;
 | 
					 | 
				
			||||||
        case "declined":
 | 
					 | 
				
			||||||
            return theme.palette.error.dark;
 | 
					 | 
				
			||||||
        case "draft":
 | 
					 | 
				
			||||||
            return theme.palette.grey["800"];
 | 
					 | 
				
			||||||
        default:
 | 
					 | 
				
			||||||
            return "textPrimary";
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const useStatusStyles = makeStyles((theme: Theme) => {
 | 
					 | 
				
			||||||
    const colorByStatusGetter = ({ status }: any) => getColorByStatus(status, theme);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return createStyles({
 | 
					 | 
				
			||||||
        foreground: {
 | 
					 | 
				
			||||||
            color: colorByStatusGetter
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        background: {
 | 
					 | 
				
			||||||
            backgroundColor: colorByStatusGetter
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    })
 | 
					 | 
				
			||||||
})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const ProposalStatus = () => {
 | 
					 | 
				
			||||||
    const status = useSelector<AppState, SubmissionStatus>(state => getSubmissionStatus(state.proposal))
 | 
					 | 
				
			||||||
    const classes = useStatusStyles({ status });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const { t } = useTranslation();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return <span className={ classes.foreground }>{ t(`proposal.status.${status}`) }</span>;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const ProposalActions = () => {
 | 
					 | 
				
			||||||
    const status = useSelector<AppState, SubmissionStatus>(state => getSubmissionStatus(state.proposal));
 | 
					 | 
				
			||||||
    const { t } = useTranslation();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const ReviewAction = (props: ButtonProps) =>
 | 
					 | 
				
			||||||
        <Button startIcon={ <FileFind /> } { ...props }>{ t('review') }</Button>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const FormAction   = ({ children = t('steps.internship-proposal.form'), ...props }: ButtonProps) =>
 | 
					 | 
				
			||||||
        <Button to={ route("internship_proposal") } variant="contained" color="primary" component={ RouterLink } startIcon={ <ClipboardEditOutline /> } { ...props as any }>
 | 
					 | 
				
			||||||
            { children }
 | 
					 | 
				
			||||||
        </Button>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const ContactAction = (props: ButtonProps) =>
 | 
					 | 
				
			||||||
        <Button startIcon={ <CommentQuestion /> } variant="outlined" color="primary" { ...props }>{ t('contact') }</Button>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    switch (status) {
 | 
					 | 
				
			||||||
        case "awaiting":
 | 
					 | 
				
			||||||
            return <Actions>
 | 
					 | 
				
			||||||
                <ReviewAction />
 | 
					 | 
				
			||||||
            </Actions>
 | 
					 | 
				
			||||||
        case "accepted":
 | 
					 | 
				
			||||||
            return <Actions>
 | 
					 | 
				
			||||||
                <ReviewAction />
 | 
					 | 
				
			||||||
                <FormAction variant="outlined" color="secondary">{ t('make-changes') }</FormAction>
 | 
					 | 
				
			||||||
            </Actions>
 | 
					 | 
				
			||||||
        case "declined":
 | 
					 | 
				
			||||||
            return <Actions>
 | 
					 | 
				
			||||||
                <FormAction>{ t('fix-errors') }</FormAction>
 | 
					 | 
				
			||||||
                <ContactAction/>
 | 
					 | 
				
			||||||
            </Actions>
 | 
					 | 
				
			||||||
        case "draft":
 | 
					 | 
				
			||||||
            return <Actions>
 | 
					 | 
				
			||||||
                <FormAction color="primary">{ t('steps.internship-proposal.action') }</FormAction>
 | 
					 | 
				
			||||||
            </Actions>
 | 
					 | 
				
			||||||
        default:
 | 
					 | 
				
			||||||
            return <Actions />
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const ProposalComment = (props: HTMLProps<HTMLDivElement>) => {
 | 
					 | 
				
			||||||
    const { comment, declined } = useSelector<AppState, InternshipProposalState>(state => state.proposal);
 | 
					 | 
				
			||||||
    const { t } = useTranslation();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return comment ? <Alert severity={declined ? "error" : "warning"} {...props as any}>
 | 
					 | 
				
			||||||
        <AlertTitle>{ t('comments') }</AlertTitle>
 | 
					 | 
				
			||||||
        { comment }
 | 
					 | 
				
			||||||
    </Alert> : null
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const ProposalStep = (props: StepProps) => {
 | 
					 | 
				
			||||||
    const { t } = useTranslation();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const { sent, comment, declined } = useSelector<AppState, InternshipProposalState>(state => state.proposal);
 | 
					 | 
				
			||||||
    const status = useSelector<AppState, SubmissionStatus>(state => getSubmissionStatus(state.proposal));
 | 
					 | 
				
			||||||
    const deadlines = useSelector<AppState, Deadlines>(state => getEditionDeadlines(state.edition as Edition)); // edition cannot be null at this point
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return <Step { ...props }
 | 
					 | 
				
			||||||
                 label={ t('steps.internship-proposal.header') }
 | 
					 | 
				
			||||||
                 active={ true } completed={ sent } declined={ declined } waiting={ status == "awaiting" }
 | 
					 | 
				
			||||||
                 until={ deadlines.proposal }
 | 
					 | 
				
			||||||
                 state={ <ProposalStatus /> }>
 | 
					 | 
				
			||||||
        <p>{ t(`steps.internship-proposal.info.${status}`) }</p>
 | 
					 | 
				
			||||||
        { comment && <Box pb={2}><ProposalComment /></Box> }
 | 
					 | 
				
			||||||
        <ProposalActions />
 | 
					 | 
				
			||||||
    </Step>;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const MainPage = () => {
 | 
					export const MainPage = () => {
 | 
				
			||||||
    const { t } = useTranslation();
 | 
					    const { t } = useTranslation();
 | 
				
			||||||
@ -147,18 +38,7 @@ export const MainPage = () => {
 | 
				
			|||||||
                    </> }
 | 
					                    </> }
 | 
				
			||||||
                </Step>
 | 
					                </Step>
 | 
				
			||||||
                <ProposalStep />
 | 
					                <ProposalStep />
 | 
				
			||||||
                <Step label={ t('steps.plan.header') } active={ missingStudentData.length === 0 } until={ deadlines.proposal }>
 | 
					                <PlanStep />
 | 
				
			||||||
                    <p>{ t('steps.plan.info') }</p>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    <Actions>
 | 
					 | 
				
			||||||
                        <Button to={ route("internship_plan") } variant="contained" color="primary" component={ RouterLink }>
 | 
					 | 
				
			||||||
                            { t('steps.plan.submit') }
 | 
					 | 
				
			||||||
                        </Button>
 | 
					 | 
				
			||||||
                        <Button href="https://eti.pg.edu.pl/documents/611675/100028367/indywidualny%20program%20praktyk" startIcon={ <DescriptionIcon/> }>
 | 
					 | 
				
			||||||
                            { t('steps.plan.template') }
 | 
					 | 
				
			||||||
                        </Button>
 | 
					 | 
				
			||||||
                    </Actions>
 | 
					 | 
				
			||||||
                </Step>
 | 
					 | 
				
			||||||
                <Step label={ t('steps.insurance.header') }/>
 | 
					                <Step label={ t('steps.insurance.header') }/>
 | 
				
			||||||
                <Step label={ t('steps.report.header') } until={ deadlines.report }/>
 | 
					                <Step label={ t('steps.report.header') } until={ deadlines.report }/>
 | 
				
			||||||
                <Step label={ t('steps.grade.header') }/>
 | 
					                <Step label={ t('steps.grade.header') }/>
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										46
									
								
								src/pages/steps/common.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/pages/steps/common.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,46 @@
 | 
				
			|||||||
 | 
					import { getSubmissionStatus, SubmissionState, SubmissionStatus } from "@/state/reducer/submission";
 | 
				
			||||||
 | 
					import { Theme } from "@material-ui/core";
 | 
				
			||||||
 | 
					import { createStyles, makeStyles } from "@material-ui/core/styles";
 | 
				
			||||||
 | 
					import { useTranslation } from "react-i18next";
 | 
				
			||||||
 | 
					import React from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const getColorByStatus = (status: SubmissionStatus, theme: Theme) => {
 | 
				
			||||||
 | 
					    switch (status) {
 | 
				
			||||||
 | 
					        case "awaiting":
 | 
				
			||||||
 | 
					            return theme.palette.info.dark;
 | 
				
			||||||
 | 
					        case "accepted":
 | 
				
			||||||
 | 
					            return theme.palette.success.dark;
 | 
				
			||||||
 | 
					        case "declined":
 | 
				
			||||||
 | 
					            return theme.palette.error.dark;
 | 
				
			||||||
 | 
					        case "draft":
 | 
				
			||||||
 | 
					            return theme.palette.grey["800"];
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            return "textPrimary";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const useStatusStyles = makeStyles((theme: Theme) => {
 | 
				
			||||||
 | 
					    const colorByStatusGetter = ({ status }: any) => getColorByStatus(status, theme);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return createStyles({
 | 
				
			||||||
 | 
					        foreground: {
 | 
				
			||||||
 | 
					            color: colorByStatusGetter
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        background: {
 | 
				
			||||||
 | 
					            backgroundColor: colorByStatusGetter
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type SubmissionStatusProps = {
 | 
				
			||||||
 | 
					    submission: SubmissionState,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const Status = ({ submission } : SubmissionStatusProps) => {
 | 
				
			||||||
 | 
					    const status = getSubmissionStatus(submission);
 | 
				
			||||||
 | 
					    const classes = useStatusStyles({ status });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const { t } = useTranslation();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return <span className={ classes.foreground }>{ t(`submission.status.${ status }`) }</span>;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										92
									
								
								src/pages/steps/plan.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								src/pages/steps/plan.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,92 @@
 | 
				
			|||||||
 | 
					import { useSelector } from "react-redux";
 | 
				
			||||||
 | 
					import { AppState } from "@/state/reducer";
 | 
				
			||||||
 | 
					import { getSubmissionStatus, SubmissionState, SubmissionStatus } from "@/state/reducer/submission";
 | 
				
			||||||
 | 
					import { useTranslation } from "react-i18next";
 | 
				
			||||||
 | 
					import { Box, Button, ButtonProps, StepProps } from "@material-ui/core";
 | 
				
			||||||
 | 
					import { CommentQuestion, FileFind } from "mdi-material-ui/index";
 | 
				
			||||||
 | 
					import { route } from "@/routing";
 | 
				
			||||||
 | 
					import { Link as RouterLink } from "react-router-dom";
 | 
				
			||||||
 | 
					import { Actions, Step } from "@/components";
 | 
				
			||||||
 | 
					import React, { HTMLProps } from "react";
 | 
				
			||||||
 | 
					import { Alert, AlertTitle } from "@material-ui/lab";
 | 
				
			||||||
 | 
					import { Deadlines, Edition, getEditionDeadlines } from "@/data/edition";
 | 
				
			||||||
 | 
					import { Status } from "@/pages/steps/common";
 | 
				
			||||||
 | 
					import { Description as DescriptionIcon } from "@material-ui/icons";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const PlanActions = () => {
 | 
				
			||||||
 | 
					    const status = useSelector<AppState, SubmissionStatus>(state => getSubmissionStatus(state.plan));
 | 
				
			||||||
 | 
					    const { t } = useTranslation();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const ReviewAction = (props: ButtonProps) =>
 | 
				
			||||||
 | 
					        <Button startIcon={ <FileFind/> } { ...props }>{ t('review') }</Button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const FormAction = ({ children = t('steps.plan.form'), ...props }: ButtonProps) =>
 | 
				
			||||||
 | 
					        <Button to={ route("plan") } variant="contained" color="primary" component={ RouterLink } { ...props as any }>
 | 
				
			||||||
 | 
					            { children }
 | 
				
			||||||
 | 
					        </Button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const ContactAction = (props: ButtonProps) =>
 | 
				
			||||||
 | 
					        <Button startIcon={ <CommentQuestion/> } variant="outlined" color="primary" { ...props }>{ t('contact') }</Button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (status) {
 | 
				
			||||||
 | 
					        case "awaiting":
 | 
				
			||||||
 | 
					            return <Actions>
 | 
				
			||||||
 | 
					                <ReviewAction/>
 | 
				
			||||||
 | 
					            </Actions>
 | 
				
			||||||
 | 
					        case "accepted":
 | 
				
			||||||
 | 
					            return <Actions>
 | 
				
			||||||
 | 
					                <ReviewAction/>
 | 
				
			||||||
 | 
					                <FormAction variant="outlined" color="secondary">{ t('send-again') }</FormAction>
 | 
				
			||||||
 | 
					            </Actions>
 | 
				
			||||||
 | 
					        case "declined":
 | 
				
			||||||
 | 
					            return <Actions>
 | 
				
			||||||
 | 
					                <FormAction>{ t('fix-errors') }</FormAction>
 | 
				
			||||||
 | 
					                <ContactAction/>
 | 
				
			||||||
 | 
					            </Actions>
 | 
				
			||||||
 | 
					        case "draft":
 | 
				
			||||||
 | 
					            return <Actions>
 | 
				
			||||||
 | 
					                <Button to={ route("internship_plan") } variant="contained" color="primary" component={ RouterLink }>
 | 
				
			||||||
 | 
					                    { t('steps.plan.submit') }
 | 
				
			||||||
 | 
					                </Button>
 | 
				
			||||||
 | 
					                <Button href="https://eti.pg.edu.pl/documents/611675/100028367/indywidualny%20program%20praktyk" startIcon={ <DescriptionIcon/> }>
 | 
				
			||||||
 | 
					                    { t('steps.plan.template') }
 | 
				
			||||||
 | 
					                </Button>
 | 
				
			||||||
 | 
					            </Actions>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            return <Actions/>
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const PlanComment = (props: HTMLProps<HTMLDivElement>) => {
 | 
				
			||||||
 | 
					    const { comment, declined } = useSelector<AppState, SubmissionState>(state => state.plan);
 | 
				
			||||||
 | 
					    const { t } = useTranslation();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return comment ? <Alert severity={ declined ? "error" : "warning" } { ...props as any }>
 | 
				
			||||||
 | 
					        <AlertTitle>{ t('comments') }</AlertTitle>
 | 
				
			||||||
 | 
					        { comment }
 | 
				
			||||||
 | 
					    </Alert> : null
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const PlanStep = (props: StepProps) => {
 | 
				
			||||||
 | 
					    const { t } = useTranslation();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const submission = useSelector<AppState, SubmissionState>(state => state.plan);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const status = getSubmissionStatus(submission);
 | 
				
			||||||
 | 
					    const deadlines = useSelector<AppState, Deadlines>(state => getEditionDeadlines(state.edition as Edition)); // edition cannot be null at this point
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const { sent, declined, comment } = submission;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return <Step { ...props }
 | 
				
			||||||
 | 
					                 label={ t('steps.plan.header') }
 | 
				
			||||||
 | 
					                 active={ true } completed={ sent } declined={ declined } waiting={ status == "awaiting" }
 | 
				
			||||||
 | 
					                 until={ deadlines.proposal }
 | 
				
			||||||
 | 
					                 state={ <Status submission={ submission } /> }>
 | 
				
			||||||
 | 
					        <p>{ t(`steps.plan.info.${ status }`) }</p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        { comment && <Box pb={ 2 }><PlanComment/></Box> }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <PlanActions/>
 | 
				
			||||||
 | 
					    </Step>;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										84
									
								
								src/pages/steps/proposal.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								src/pages/steps/proposal.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,84 @@
 | 
				
			|||||||
 | 
					import { useSelector } from "react-redux";
 | 
				
			||||||
 | 
					import { AppState } from "@/state/reducer";
 | 
				
			||||||
 | 
					import { getSubmissionStatus, SubmissionState, SubmissionStatus } from "@/state/reducer/submission";
 | 
				
			||||||
 | 
					import { useTranslation } from "react-i18next";
 | 
				
			||||||
 | 
					import React, { HTMLProps } from "react";
 | 
				
			||||||
 | 
					import { InternshipProposalState } from "@/state/reducer/proposal";
 | 
				
			||||||
 | 
					import { Alert, AlertTitle } from "@material-ui/lab";
 | 
				
			||||||
 | 
					import { Box, Button, ButtonProps, StepProps } from "@material-ui/core";
 | 
				
			||||||
 | 
					import { Deadlines, Edition, getEditionDeadlines } from "@/data/edition";
 | 
				
			||||||
 | 
					import { Actions, Step } from "@/components";
 | 
				
			||||||
 | 
					import { route } from "@/routing";
 | 
				
			||||||
 | 
					import { Link as RouterLink } from "react-router-dom";
 | 
				
			||||||
 | 
					import { ClipboardEditOutline, CommentQuestion, FileFind } from "mdi-material-ui/index";
 | 
				
			||||||
 | 
					import { Status } from "@/pages/steps/common";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ProposalActions = () => {
 | 
				
			||||||
 | 
					    const status = useSelector<AppState, SubmissionStatus>(state => getSubmissionStatus(state.proposal));
 | 
				
			||||||
 | 
					    const { t } = useTranslation();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const ReviewAction = (props: ButtonProps) =>
 | 
				
			||||||
 | 
					        <Button startIcon={ <FileFind/> } { ...props }>{ t('review') }</Button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const FormAction = ({ children = t('steps.internship-proposal.form'), ...props }: ButtonProps) =>
 | 
				
			||||||
 | 
					        <Button to={ route("internship_proposal") } variant="contained" color="primary" component={ RouterLink }
 | 
				
			||||||
 | 
					                startIcon={ <ClipboardEditOutline/> } { ...props as any }>
 | 
				
			||||||
 | 
					            { children }
 | 
				
			||||||
 | 
					        </Button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const ContactAction = (props: ButtonProps) =>
 | 
				
			||||||
 | 
					        <Button startIcon={ <CommentQuestion/> } variant="outlined" color="primary" { ...props }>{ t('contact') }</Button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (status) {
 | 
				
			||||||
 | 
					        case "awaiting":
 | 
				
			||||||
 | 
					            return <Actions>
 | 
				
			||||||
 | 
					                <ReviewAction/>
 | 
				
			||||||
 | 
					            </Actions>
 | 
				
			||||||
 | 
					        case "accepted":
 | 
				
			||||||
 | 
					            return <Actions>
 | 
				
			||||||
 | 
					                <ReviewAction/>
 | 
				
			||||||
 | 
					                <FormAction variant="outlined" color="secondary">{ t('make-changes') }</FormAction>
 | 
				
			||||||
 | 
					            </Actions>
 | 
				
			||||||
 | 
					        case "declined":
 | 
				
			||||||
 | 
					            return <Actions>
 | 
				
			||||||
 | 
					                <FormAction>{ t('fix-errors') }</FormAction>
 | 
				
			||||||
 | 
					                <ContactAction/>
 | 
				
			||||||
 | 
					            </Actions>
 | 
				
			||||||
 | 
					        case "draft":
 | 
				
			||||||
 | 
					            return <Actions>
 | 
				
			||||||
 | 
					                <FormAction color="primary">{ t('steps.internship-proposal.action') }</FormAction>
 | 
				
			||||||
 | 
					            </Actions>
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            return <Actions/>
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const ProposalComment = (props: HTMLProps<HTMLDivElement>) => {
 | 
				
			||||||
 | 
					    const { comment, declined } = useSelector<AppState, InternshipProposalState>(state => state.proposal);
 | 
				
			||||||
 | 
					    const { t } = useTranslation();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return comment ? <Alert severity={ declined ? "error" : "warning" } { ...props as any }>
 | 
				
			||||||
 | 
					        <AlertTitle>{ t('comments') }</AlertTitle>
 | 
				
			||||||
 | 
					        { comment }
 | 
				
			||||||
 | 
					    </Alert> : null
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const ProposalStep = (props: StepProps) => {
 | 
				
			||||||
 | 
					    const { t } = useTranslation();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const submission = useSelector<AppState, SubmissionState>(state => state.proposal);
 | 
				
			||||||
 | 
					    const status = useSelector<AppState, SubmissionStatus>(state => getSubmissionStatus(state.proposal));
 | 
				
			||||||
 | 
					    const deadlines = useSelector<AppState, Deadlines>(state => getEditionDeadlines(state.edition as Edition)); // edition cannot be null at this point
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const { sent, declined, comment } = submission;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return <Step { ...props }
 | 
				
			||||||
 | 
					                 label={ t('steps.internship-proposal.header') }
 | 
				
			||||||
 | 
					                 active={ true } completed={ sent } declined={ declined } waiting={ status == "awaiting" }
 | 
				
			||||||
 | 
					                 until={ deadlines.proposal }
 | 
				
			||||||
 | 
					                 state={ <Status submission={ submission } /> }>
 | 
				
			||||||
 | 
					        <p>{ t(`steps.internship-proposal.info.${ status }`) }</p>
 | 
				
			||||||
 | 
					        { comment && <Box pb={ 2 }><ProposalComment/></Box> }
 | 
				
			||||||
 | 
					        <ProposalActions/>
 | 
				
			||||||
 | 
					    </Step>;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -5,16 +5,18 @@ import { InternshipProposalAction, InternshipProposalActions } from "@/state/act
 | 
				
			|||||||
import { Dispatch } from "react";
 | 
					import { Dispatch } from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { useDispatch as useReduxDispatch } from "react-redux";
 | 
					import { useDispatch as useReduxDispatch } from "react-redux";
 | 
				
			||||||
 | 
					import { InternshipPlanAction, InternshipPlanActions } from "@/state/actions/plan";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export * from "./base"
 | 
					export * from "./base"
 | 
				
			||||||
export * from "./edition"
 | 
					export * from "./edition"
 | 
				
			||||||
export * from "./settings"
 | 
					export * from "./settings"
 | 
				
			||||||
export * from "./student"
 | 
					export * from "./student"
 | 
				
			||||||
export * from "./proposal"
 | 
					export * from "./proposal"
 | 
				
			||||||
 | 
					export * from "./plan"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type Action = StudentAction | EditionAction | SettingsAction | InternshipProposalAction;
 | 
					export type Action = StudentAction | EditionAction | SettingsAction | InternshipProposalAction | InternshipPlanAction;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const Actions = { ...StudentActions, ...EditionActions, ...SettingActions, ...InternshipProposalActions }
 | 
					export const Actions = { ...StudentActions, ...EditionActions, ...SettingActions, ...InternshipProposalActions, ...InternshipPlanActions }
 | 
				
			||||||
export type Actions = typeof Actions;
 | 
					export type Actions = typeof Actions;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const useDispatch = () => useReduxDispatch<Dispatch<Action>>()
 | 
					export const useDispatch = () => useReduxDispatch<Dispatch<Action>>()
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										40
									
								
								src/state/actions/plan.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/state/actions/plan.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					import { Plan } from "@/data";
 | 
				
			||||||
 | 
					import {
 | 
				
			||||||
 | 
					    ReceiveSubmissionApproveAction,
 | 
				
			||||||
 | 
					    ReceiveSubmissionDeclineAction,
 | 
				
			||||||
 | 
					    ReceiveSubmissionUpdateAction,
 | 
				
			||||||
 | 
					    SaveSubmissionAction,
 | 
				
			||||||
 | 
					    SendSubmissionAction
 | 
				
			||||||
 | 
					} from "@/state/actions/submission";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export enum InternshipPlanActions {
 | 
				
			||||||
 | 
					    Send = "SEND_PLAN",
 | 
				
			||||||
 | 
					    Save = "SAVE_PLAN",
 | 
				
			||||||
 | 
					    Approve = "RECEIVE_PLAN_APPROVE",
 | 
				
			||||||
 | 
					    Decline = "RECEIVE_PLAN_DECLINE",
 | 
				
			||||||
 | 
					    Receive = "RECEIVE_PLAN_STATE",
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface SendPlanAction extends SendSubmissionAction<InternshipPlanActions.Send> {
 | 
				
			||||||
 | 
					    plan: Plan;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface ReceivePlanApproveAction extends ReceiveSubmissionApproveAction<InternshipPlanActions.Approve> {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface ReceivePlanDeclineAction extends ReceiveSubmissionDeclineAction<InternshipPlanActions.Decline> {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface ReceivePlanUpdateAction extends ReceiveSubmissionUpdateAction<InternshipPlanActions.Receive> {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface SavePlanAction extends SaveSubmissionAction<InternshipPlanActions.Save> {
 | 
				
			||||||
 | 
					    plan: Plan;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type InternshipPlanAction
 | 
				
			||||||
 | 
					    = SendPlanAction
 | 
				
			||||||
 | 
					    | SavePlanAction
 | 
				
			||||||
 | 
					    | ReceivePlanApproveAction
 | 
				
			||||||
 | 
					    | ReceivePlanDeclineAction
 | 
				
			||||||
 | 
					    | ReceivePlanUpdateAction;
 | 
				
			||||||
@ -20,15 +20,12 @@ export interface SendProposalAction extends SendSubmissionAction<InternshipPropo
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface ReceiveProposalApproveAction extends ReceiveSubmissionApproveAction<InternshipProposalActions.Approve> {
 | 
					export interface ReceiveProposalApproveAction extends ReceiveSubmissionApproveAction<InternshipProposalActions.Approve> {
 | 
				
			||||||
    comment: string | null;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface ReceiveProposalDeclineAction extends ReceiveSubmissionDeclineAction<InternshipProposalActions.Decline> {
 | 
					export interface ReceiveProposalDeclineAction extends ReceiveSubmissionDeclineAction<InternshipProposalActions.Decline> {
 | 
				
			||||||
    comment: string;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface ReceiveProposalUpdateAction extends ReceiveSubmissionUpdateAction<InternshipProposalActions.Receive> {
 | 
					export interface ReceiveProposalUpdateAction extends ReceiveSubmissionUpdateAction<InternshipProposalActions.Receive> {
 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface SaveProposalAction extends SaveSubmissionAction<InternshipProposalActions.Save> {
 | 
					export interface SaveProposalAction extends SaveSubmissionAction<InternshipProposalActions.Save> {
 | 
				
			||||||
 | 
				
			|||||||
@ -4,12 +4,14 @@ import studentReducer from "@/state/reducer/student"
 | 
				
			|||||||
import editionReducer from "@/state/reducer/edition";
 | 
					import editionReducer from "@/state/reducer/edition";
 | 
				
			||||||
import settingsReducer from "@/state/reducer/settings";
 | 
					import settingsReducer from "@/state/reducer/settings";
 | 
				
			||||||
import internshipProposalReducer from "@/state/reducer/proposal";
 | 
					import internshipProposalReducer from "@/state/reducer/proposal";
 | 
				
			||||||
 | 
					import internshipPlanReducer from "@/state/reducer/plan";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const rootReducer = combineReducers({
 | 
					const rootReducer = combineReducers({
 | 
				
			||||||
    student: studentReducer,
 | 
					    student: studentReducer,
 | 
				
			||||||
    edition: editionReducer,
 | 
					    edition: editionReducer,
 | 
				
			||||||
    settings: settingsReducer,
 | 
					    settings: settingsReducer,
 | 
				
			||||||
    proposal: internshipProposalReducer,
 | 
					    proposal: internshipProposalReducer,
 | 
				
			||||||
 | 
					    plan: internshipPlanReducer,
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type AppState = ReturnType<typeof rootReducer>;
 | 
					export type AppState = ReturnType<typeof rootReducer>;
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										49
									
								
								src/state/reducer/plan.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								src/state/reducer/plan.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,49 @@
 | 
				
			|||||||
 | 
					import { InternshipPlanAction, InternshipPlanActions } from "@/state/actions";
 | 
				
			||||||
 | 
					import { Plan } from "@/data";
 | 
				
			||||||
 | 
					import { Serializable } from "@/serialization/types";
 | 
				
			||||||
 | 
					import {
 | 
				
			||||||
 | 
					    createSubmissionReducer,
 | 
				
			||||||
 | 
					    defaultDeanApprovalsState,
 | 
				
			||||||
 | 
					    defaultSubmissionState,
 | 
				
			||||||
 | 
					    MayRequireDeanApproval,
 | 
				
			||||||
 | 
					    SubmissionState
 | 
				
			||||||
 | 
					} from "@/state/reducer/submission";
 | 
				
			||||||
 | 
					import { Reducer } from "react";
 | 
				
			||||||
 | 
					import { SubmissionAction } from "@/state/actions/submission";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type InternshipPlanState = SubmissionState & MayRequireDeanApproval & {
 | 
				
			||||||
 | 
					    plan: Serializable<Plan> | null;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const defaultInternshipPlanState: InternshipPlanState = {
 | 
				
			||||||
 | 
					    ...defaultDeanApprovalsState,
 | 
				
			||||||
 | 
					    ...defaultSubmissionState,
 | 
				
			||||||
 | 
					    plan: null,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const getInternshipPlan = ({ plan }: InternshipPlanState): Plan | null => plan;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const internshipPlanSubmissionReducer: Reducer<InternshipPlanState, InternshipPlanAction> = createSubmissionReducer({
 | 
				
			||||||
 | 
					    [InternshipPlanActions.Approve]: SubmissionAction.Approve,
 | 
				
			||||||
 | 
					    [InternshipPlanActions.Decline]: SubmissionAction.Decline,
 | 
				
			||||||
 | 
					    [InternshipPlanActions.Receive]: SubmissionAction.Receive,
 | 
				
			||||||
 | 
					    [InternshipPlanActions.Save]: SubmissionAction.Save,
 | 
				
			||||||
 | 
					    [InternshipPlanActions.Send]: SubmissionAction.Send,
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const internshipPlanReducer = (state: InternshipPlanState = defaultInternshipPlanState, action: InternshipPlanAction): InternshipPlanState => {
 | 
				
			||||||
 | 
					    state = internshipPlanSubmissionReducer(state, action);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (action.type) {
 | 
				
			||||||
 | 
					        case InternshipPlanActions.Save:
 | 
				
			||||||
 | 
					        case InternshipPlanActions.Send:
 | 
				
			||||||
 | 
					            return {
 | 
				
			||||||
 | 
					                ...state,
 | 
				
			||||||
 | 
					                plan: action.plan,
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            return state;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default internshipPlanReducer;
 | 
				
			||||||
@ -17,6 +17,7 @@ review: podgląd
 | 
				
			|||||||
fix-errors: popraw uwagi
 | 
					fix-errors: popraw uwagi
 | 
				
			||||||
contact: skontaktuj się z pełnomocnikiem
 | 
					contact: skontaktuj się z pełnomocnikiem
 | 
				
			||||||
comments: Zgłoszone uwagi
 | 
					comments: Zgłoszone uwagi
 | 
				
			||||||
 | 
					send-again: wyślij ponownie
 | 
				
			||||||
 | 
					
 | 
				
			||||||
dropzone: "Przeciągnij i upuść plik bądź kliknij, aby wybrać"
 | 
					dropzone: "Przeciągnij i upuść plik bądź kliknij, aby wybrać"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -38,7 +39,7 @@ student:
 | 
				
			|||||||
  email: adres e-mail
 | 
					  email: adres e-mail
 | 
				
			||||||
  albumNumber: numer albumu
 | 
					  albumNumber: numer albumu
 | 
				
			||||||
 | 
					
 | 
				
			||||||
proposal:
 | 
					submission:
 | 
				
			||||||
  status:
 | 
					  status:
 | 
				
			||||||
    awaiting: "wysłano, oczekuje na weryfikacje"
 | 
					    awaiting: "wysłano, oczekuje na weryfikacje"
 | 
				
			||||||
    accepted: "zaakceptowano"
 | 
					    accepted: "zaakceptowano"
 | 
				
			||||||
@ -69,7 +70,15 @@ steps:
 | 
				
			|||||||
    action: "zgłoś praktykę"
 | 
					    action: "zgłoś praktykę"
 | 
				
			||||||
  plan:
 | 
					  plan:
 | 
				
			||||||
    header: "Indywidualny Program Praktyki"
 | 
					    header: "Indywidualny Program Praktyki"
 | 
				
			||||||
    info: ""
 | 
					    info:
 | 
				
			||||||
 | 
					      draft: >
 | 
				
			||||||
 | 
					        TODO
 | 
				
			||||||
 | 
					      awaiting: >
 | 
				
			||||||
 | 
					        TODO
 | 
				
			||||||
 | 
					      accepted: >
 | 
				
			||||||
 | 
					        TODO
 | 
				
			||||||
 | 
					      declined: >
 | 
				
			||||||
 | 
					        TODO
 | 
				
			||||||
    template: "Pobierz szablon"
 | 
					    template: "Pobierz szablon"
 | 
				
			||||||
    submit: "Wyślij Indywidualny Plan Praktyki"
 | 
					    submit: "Wyślij Indywidualny Plan Praktyki"
 | 
				
			||||||
  report:
 | 
					  report:
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user