96 lines
4.6 KiB
TypeScript
96 lines
4.6 KiB
TypeScript
import React, { useMemo } from "react";
|
|
import { Page } from "@/pages/base";
|
|
import { Box, Button, Container, Step as StepperStep, StepContent, StepLabel, Stepper, StepProps as StepperStepProps, Typography } from "@material-ui/core";
|
|
import { Link as RouterLink } from "react-router-dom";
|
|
import { route } from "@/routing";
|
|
import { useTranslation } from "react-i18next";
|
|
import moment, { Moment } from "moment";
|
|
import { useSelector } from "react-redux";
|
|
import { AppState } from "@/state/reducer";
|
|
import { getMissingStudentData, Student } from "@/data";
|
|
import { Deadlines, Edition, getEditionDeadlines } from "@/data/edition";
|
|
import { Description as DescriptionIcon } from "@material-ui/icons"
|
|
import { Actions } from "@/components/actions";
|
|
|
|
type StepProps = StepperStepProps & {
|
|
until?: Moment;
|
|
completedOn?: Moment;
|
|
label: string;
|
|
}
|
|
|
|
const now = moment();
|
|
|
|
const Step = ({ until, label, completedOn, children, completed, ...props }: StepProps) => {
|
|
const { t } = useTranslation();
|
|
|
|
const isLate = useMemo(() => until?.isBefore(completedOn || now), [completedOn, until]);
|
|
const left = useMemo(() => moment.duration(now.diff(until)), [until]);
|
|
|
|
return <StepperStep { ...props } completed={ completed || !!completedOn }>
|
|
<StepLabel>
|
|
{ label }
|
|
{ until && <Box>
|
|
<Typography variant="subtitle2" color="textSecondary">
|
|
{ t('until', { date: until }) }
|
|
{ isLate && <Typography color="error" display="inline"
|
|
variant="body2"> - { t('late', { by: moment.duration(now.diff(until)) }) }</Typography> }
|
|
{ !isLate && !completed && <Typography display="inline" variant="body2"> - { t('left', { left: left }) }</Typography> }
|
|
</Typography>
|
|
</Box> }
|
|
</StepLabel>
|
|
{ children && <StepContent>{ children }</StepContent> }
|
|
</StepperStep>
|
|
}
|
|
|
|
export const MainPage = () => {
|
|
const { t } = useTranslation();
|
|
|
|
const student = useSelector<AppState, Student | null>(state => state.student);
|
|
const deadlines = useSelector<AppState, Deadlines>(state => getEditionDeadlines(state.edition as Edition)); // edition cannot be null at this point
|
|
|
|
const missingStudentData = useMemo(() => student ? getMissingStudentData(student) : [], [student]);
|
|
|
|
return <Page my={ 6 }>
|
|
<Container>
|
|
<Typography variant="h2">{ t("sections.my-internship.header") }</Typography>
|
|
<Stepper orientation="vertical" nonLinear>
|
|
<Step label={ t('steps.personal-data.header') } completed={ missingStudentData.length === 0 } until={ deadlines.personalData }>
|
|
{ missingStudentData.length > 0 && <>
|
|
<p>{ t('steps.personal-data.info') }</p>
|
|
|
|
<ul>
|
|
{ missingStudentData.map(field => <li key={ field }>{ t(`student.${ field }`) }</li>) }
|
|
</ul>
|
|
|
|
<Button to={ route("internship_proposal") } variant="contained" color="primary" component={ RouterLink }>
|
|
{ t('steps.personal-data.form') }
|
|
</Button>
|
|
</> }
|
|
</Step>
|
|
<Step label={ t('steps.internship-proposal.header') } active={ missingStudentData.length === 0 } until={ deadlines.proposal }>
|
|
<p>{ t('steps.internship-proposal.info') }</p>
|
|
|
|
<Button to={ route("internship_proposal") } variant="contained" color="primary" component={ RouterLink }>
|
|
{ t('steps.internship-proposal.form') }
|
|
</Button>
|
|
</Step>
|
|
<Step label={ t('steps.plan.header') } active={ missingStudentData.length === 0 } until={ deadlines.proposal }>
|
|
<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.report.header') } until={ deadlines.report }/>
|
|
<Step label={ t('steps.grade.header') }/>
|
|
</Stepper>
|
|
</Container>
|
|
</Page>
|
|
}
|