system-praktyk-front/src/pages/steps/report.tsx
2021-01-18 01:24:18 +01:00

158 lines
6.0 KiB
TypeScript

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, Dialog, DialogContent, DialogProps, DialogTitle, StepProps, Typography } from "@material-ui/core";
import { FileFind, FileUploadOutline } 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, useState } from "react";
import { Alert, AlertTitle } from "@material-ui/lab";
import { ContactButton, Status } from "@/pages/steps/common";
import { useCurrentEdition, useDeadlines } from "@/hooks";
import { useSpacing } from "@/styles";
import { MultiChoiceValue, Report, ReportSchema, SingleChoiceValue, TextFieldValue } from "@/data/report";
import { createPortal } from "react-dom";
import { getInternshipReport } from "@/state/reducer/report";
import { Edition } from "@/data/edition";
import { FileInfo } from "@/components/fileinfo";
import { InternshipDocument } from "@/api/dto/internship-registration";
export type ReportPreviewProps = {
schema: ReportSchema,
report: Report,
}
export const ReportPreview = ({ schema, report }: ReportPreviewProps) => {
return <>{ schema.map(field => {
const value = report.fields[`field_${ field.id }`];
const { t } = useTranslation();
const Value = () => {
switch (field.type) {
case "checkbox":
return <ul>{ ((value as MultiChoiceValue).map(selection => <li>{ selection.pl }</li>)) }</ul>
case "radio":
case "select":
return <div>{ (value as SingleChoiceValue).pl }</div>
case "long-text":
case "short-text":
return <p style={ { marginTop: "0" } }>{ value as TextFieldValue }</p>
}
}
return <>
<Typography variant="subtitle2">{ field.label.pl }</Typography>
{ value ? <Value/> : t("no-value") }
</>
}) }</>
}
export type ReportPreviewDialogProps = {
report: Report;
} & DialogProps;
export const ReportPreviewDialog = ({ report, ...props }: ReportPreviewDialogProps) => {
const edition = useCurrentEdition() as Edition;
const schema = edition.schema || [];
const { t } = useTranslation();
return <Dialog { ...props } maxWidth="md" fullWidth>
<DialogTitle>{ t("steps.report.header") }</DialogTitle>
<DialogContent><ReportPreview schema={ schema } report={ report }/></DialogContent>
</Dialog>
}
const ReportActions = () => {
const status = useSelector<AppState, SubmissionStatus>(state => getSubmissionStatus(state.report));
const { t } = useTranslation();
const FormAction = ({ children = t('steps.report.submit'), ...props }: ButtonProps) =>
<Button to={ route("internship_report") } variant="contained" color="primary" component={ RouterLink }
startIcon={ <FileUploadOutline/> } { ...props as any }>
{ children }
</Button>
const ReviewAction = (props: ButtonProps) => {
const [open, setOpen,] = useState<boolean>(false);
const report = useSelector<AppState, Report>(state => getInternshipReport(state.report) as Report);
return <>
<Button startIcon={ <FileFind/> }
onClick={ () => setOpen(true) }
{ ...props as any }>
{ t('review') }
</Button>
{ createPortal(
<ReportPreviewDialog report={ report } open={ open } onClose={ () => setOpen(false) }/>,
document.getElementById("modals") as Element,
) }
</>
}
switch (status) {
case "awaiting":
return <Actions>
<ReviewAction/>
<FormAction>{ t('send-again') }</FormAction>
</Actions>
case "accepted":
return <Actions>
<FormAction variant="outlined" color="secondary">{ t('send-again') }</FormAction>
</Actions>
case "declined":
return <Actions>
<FormAction>{ t('send-again') }</FormAction>
<ContactButton/>
</Actions>
case "draft":
return <Actions>
<FormAction/>
</Actions>
default:
return <Actions/>
}
}
export const ReportComment = (props: HTMLProps<HTMLDivElement>) => {
const { comment, declined } = useSelector<AppState, SubmissionState>(state => state.report);
const { t } = useTranslation();
return comment ? <Alert severity={ declined ? "error" : "warning" } { ...props as any }>
<AlertTitle>{ t('comments') }</AlertTitle>
<div dangerouslySetInnerHTML={{ __html: comment }}/>
</Alert> : null
}
export const ReportStep = (props: StepProps) => {
const { t } = useTranslation();
const submission = useSelector<AppState, SubmissionState>(state => state.report);
const evaluation = useSelector<AppState, InternshipDocument | null>(state => state.report.evaluation);
const spacing = useSpacing(2);
const edition = useCurrentEdition();
const status = getSubmissionStatus(submission);
const deadlines = useDeadlines();
const { sent, declined, comment } = submission;
return <Step { ...props }
label={ t('steps.report.header') }
active={ true } completed={ sent } declined={ declined } waiting={ status == "awaiting" }
until={ deadlines.report }
notBefore={ edition?.reportingStart }
state={ <Status submission={ submission }/> }>
<div className={ spacing.vertical }>
<p>{ t(`steps.report.info.${ status }`) }</p>
<ReportComment />
{ evaluation && <FileInfo document={ evaluation } /> }
<ReportActions/>
</div>
</Step>;
}