Add ability to accept or decline ipp
This commit is contained in:
parent
c13d880baa
commit
9d762f4ed2
@ -1,15 +1,16 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8"/>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||||
<meta name="theme-color" content="#000000" />
|
<meta name="theme-color" content="#000000"/>
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap&subset=latin,latin-ext" />
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap&subset=latin,latin-ext"/>
|
||||||
<title>Zgłoszenie praktyki studenckiej</title>
|
<title>Zgłoszenie praktyki studenckiej</title>
|
||||||
<base href="/">
|
<base href="/">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
</body>
|
<div id="modals"></div>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
115
src/components/acceptance-action.tsx
Normal file
115
src/components/acceptance-action.tsx
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import { Button, ButtonGroup, Dialog, DialogActions, DialogContent, DialogTitle, Menu, MenuItem, TextField, Typography } from "@material-ui/core";
|
||||||
|
import { MenuDown, StickerCheckOutline, StickerRemoveOutline } from "mdi-material-ui";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { useVerticalSpacing } from "@/styles";
|
||||||
|
import { createPortal } from "react-dom";
|
||||||
|
|
||||||
|
type AcceptanceActionsProps = {
|
||||||
|
onAccept: (comment?: string) => void;
|
||||||
|
onDiscard: (comment: string) => void;
|
||||||
|
label: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function AcceptanceActions({ onAccept, onDiscard, label }: AcceptanceActionsProps) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const [isDiscardModalOpen, setDiscardModelOpen] = useState<boolean>(false);
|
||||||
|
const [isAcceptModalOpen, setAcceptModelOpen] = useState<boolean>(false);
|
||||||
|
|
||||||
|
const [comment, setComment] = useState<string>("");
|
||||||
|
const [menuAnchor, setMenuAnchor] = useState<null | HTMLElement>(null);
|
||||||
|
|
||||||
|
const classes = useVerticalSpacing(3);
|
||||||
|
|
||||||
|
const handleAccept = () => {
|
||||||
|
onAccept(comment);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDiscard = () => {
|
||||||
|
onDiscard(comment);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleAcceptModalClose = () => {
|
||||||
|
setAcceptModelOpen(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDiscardModalClose = () => {
|
||||||
|
setDiscardModelOpen(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDiscardAction = () => {
|
||||||
|
setDiscardModelOpen(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleAcceptMenuOpen = (ev: React.MouseEvent<HTMLElement>) => {
|
||||||
|
setMenuAnchor(ev.currentTarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleAcceptMenuClose = () => {
|
||||||
|
setMenuAnchor(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleAcceptWithComment = () => {
|
||||||
|
setAcceptModelOpen(true);
|
||||||
|
setMenuAnchor(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleAcceptWithoutComment = () => {
|
||||||
|
onAccept();
|
||||||
|
}
|
||||||
|
|
||||||
|
return <>
|
||||||
|
<ButtonGroup color="primary" variant="contained">
|
||||||
|
<Button onClick={ handleAcceptWithoutComment } startIcon={ <StickerCheckOutline /> }>
|
||||||
|
{ t('accept-without-comments') }
|
||||||
|
</Button>
|
||||||
|
<Button size="small" onClick={ handleAcceptMenuOpen }><MenuDown /></Button>
|
||||||
|
</ButtonGroup>
|
||||||
|
|
||||||
|
<Menu open={ !!menuAnchor } anchorEl={ menuAnchor } onClose={ handleAcceptMenuClose }>
|
||||||
|
<MenuItem onClick={ handleAcceptWithoutComment }>{ t("accept-without-comments") }</MenuItem>
|
||||||
|
<MenuItem onClick={ handleAcceptWithComment }>{ t("accept-with-comments") }</MenuItem>
|
||||||
|
</Menu>
|
||||||
|
|
||||||
|
<Button onClick={ handleDiscardAction } color="secondary" startIcon={ <StickerRemoveOutline /> }>
|
||||||
|
{ t('discard') }
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
{ createPortal(<>
|
||||||
|
<Dialog open={ isDiscardModalOpen } onClose={ handleDiscardModalClose } maxWidth="md">
|
||||||
|
<DialogTitle>{ t(label + ".discard.title") }</DialogTitle>
|
||||||
|
<DialogContent className={ classes.root }>
|
||||||
|
<Typography variant="body1">{ t(label + ".discard.info") }</Typography>
|
||||||
|
<TextField multiline value={ comment } onChange={ ev => setComment(ev.target.value) } fullWidth label={ t("comments") } rows={3}/>
|
||||||
|
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={ handleDiscardModalClose }>
|
||||||
|
{ t('cancel') }
|
||||||
|
</Button>
|
||||||
|
<Button onClick={ handleDiscard } color="primary" variant="contained">
|
||||||
|
{ t('confirm') }
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
|
||||||
|
<Dialog open={ isAcceptModalOpen } onClose={ handleAcceptModalClose } maxWidth="md">
|
||||||
|
<DialogTitle>{ t(label + ".accept.title") }</DialogTitle>
|
||||||
|
<DialogContent className={ classes.root }>
|
||||||
|
<Typography variant="body1">{ t(label + ".accept.info") }</Typography>
|
||||||
|
<TextField multiline value={ comment } onChange={ ev => setComment(ev.target.value) } fullWidth label={ t("comments") } rows={3}/>
|
||||||
|
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={ handleAcceptModalClose }>
|
||||||
|
{ t('cancel') }
|
||||||
|
</Button>
|
||||||
|
<Button onClick={ handleAccept } color="primary" variant="contained">
|
||||||
|
{ t('confirm') }
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
</>, document.getElementById("modals") as Element) }
|
||||||
|
</>
|
||||||
|
}
|
@ -28,6 +28,7 @@ import { Actions } from "@/components";
|
|||||||
import { InternshipProposalActions, useDispatch } from "@/state/actions";
|
import { InternshipProposalActions, useDispatch } from "@/state/actions";
|
||||||
import { MenuDown, StickerCheckOutline, StickerRemoveOutline } from "mdi-material-ui/index";
|
import { MenuDown, StickerCheckOutline, StickerRemoveOutline } from "mdi-material-ui/index";
|
||||||
import { useVerticalSpacing } from "@/styles";
|
import { useVerticalSpacing } from "@/styles";
|
||||||
|
import { AcceptanceActions } from "@/components/acceptance-action";
|
||||||
|
|
||||||
export const InternshipProposalFormPage = () => {
|
export const InternshipProposalFormPage = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@ -54,49 +55,13 @@ export const InternshipProposalPreviewPage = () => {
|
|||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
|
||||||
const [isDiscardModalOpen, setDiscardModelOpen] = useState<boolean>(false);
|
const handleAccept = (comment?: string) => {
|
||||||
const [isAcceptModalOpen, setAcceptModelOpen] = useState<boolean>(false);
|
dispatch({ type: InternshipProposalActions.Approve, comment: comment || null });
|
||||||
|
|
||||||
const [comment, setComment] = useState<string>("");
|
|
||||||
const [menuAnchor, setMenuAnchor] = useState<null | HTMLElement>(null);
|
|
||||||
|
|
||||||
const handleAccept = () => {
|
|
||||||
dispatch({ type: InternshipProposalActions.Approve, comment });
|
|
||||||
history.push(route("home"));
|
history.push(route("home"));
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleDiscard = () => {
|
const handleDiscard = (comment: string) => {
|
||||||
dispatch({ type: InternshipProposalActions.Decline, comment });
|
dispatch({ type: InternshipProposalActions.Decline, comment: comment });
|
||||||
history.push(route("home"));
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleAcceptModalClose = () => {
|
|
||||||
setAcceptModelOpen(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleDiscardModalClose = () => {
|
|
||||||
setDiscardModelOpen(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleDiscardAction = () => {
|
|
||||||
setDiscardModelOpen(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleAcceptMenuOpen = (ev: React.MouseEvent<HTMLElement>) => {
|
|
||||||
setMenuAnchor(ev.currentTarget);
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleAcceptMenuClose = () => {
|
|
||||||
setMenuAnchor(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleAcceptWithComment = () => {
|
|
||||||
setAcceptModelOpen(true);
|
|
||||||
setMenuAnchor(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleAcceptWithoutComment = () => {
|
|
||||||
dispatch({ type: InternshipProposalActions.Approve, comment: null });
|
|
||||||
history.push(route("home"));
|
history.push(route("home"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,59 +80,13 @@ export const InternshipProposalPreviewPage = () => {
|
|||||||
{ proposal && <ProposalPreview proposal={ proposal } /> }
|
{ proposal && <ProposalPreview proposal={ proposal } /> }
|
||||||
|
|
||||||
<Actions>
|
<Actions>
|
||||||
<ButtonGroup color="primary" variant="contained">
|
<AcceptanceActions onAccept={ handleAccept } onDiscard={ handleDiscard } label="internship" />
|
||||||
<Button onClick={ handleAcceptWithoutComment } startIcon={ <StickerCheckOutline /> }>
|
|
||||||
{ t('accept-without-comments') }
|
|
||||||
</Button>
|
|
||||||
<Button size="small" onClick={ handleAcceptMenuOpen }><MenuDown /></Button>
|
|
||||||
</ButtonGroup>
|
|
||||||
|
|
||||||
<Menu open={ !!menuAnchor } anchorEl={ menuAnchor } onClose={ handleAcceptMenuClose }>
|
|
||||||
<MenuItem onClick={ handleAcceptWithoutComment }>{ t("accept-without-comments") }</MenuItem>
|
|
||||||
<MenuItem onClick={ handleAcceptWithComment }>{ t("accept-with-comments") }</MenuItem>
|
|
||||||
</Menu>
|
|
||||||
|
|
||||||
<Button onClick={ handleDiscardAction } color="secondary" startIcon={ <StickerRemoveOutline /> }>
|
|
||||||
{ t('discard') }
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Button component={ RouterLink } to={ route("home") }>
|
<Button component={ RouterLink } to={ route("home") }>
|
||||||
{ t('go-back') }
|
{ t('go-back') }
|
||||||
</Button>
|
</Button>
|
||||||
</Actions>
|
</Actions>
|
||||||
</Container>
|
</Container>
|
||||||
<Dialog open={ isDiscardModalOpen } onClose={ handleDiscardModalClose } maxWidth="md">
|
|
||||||
<DialogTitle>{ t("internship.discard.title") }</DialogTitle>
|
|
||||||
<DialogContent className={ classes.root }>
|
|
||||||
<Typography variant="body1">{ t("internship.discard.info") }</Typography>
|
|
||||||
<TextField multiline value={ comment } onChange={ ev => setComment(ev.target.value) } fullWidth label={ t("comments") } rows={3}/>
|
|
||||||
|
|
||||||
<DialogActions>
|
|
||||||
<Button onClick={ handleDiscardModalClose }>
|
|
||||||
{ t('cancel') }
|
|
||||||
</Button>
|
|
||||||
<Button onClick={ handleDiscard } color="primary" variant="contained">
|
|
||||||
{ t('confirm') }
|
|
||||||
</Button>
|
|
||||||
</DialogActions>
|
|
||||||
</DialogContent>
|
|
||||||
</Dialog>
|
|
||||||
<Dialog open={ isAcceptModalOpen } onClose={ handleAcceptModalClose } maxWidth="md">
|
|
||||||
<DialogTitle>{ t("internship.accept.title") }</DialogTitle>
|
|
||||||
<DialogContent className={ classes.root }>
|
|
||||||
<Typography variant="body1">{ t("internship.accept.info") }</Typography>
|
|
||||||
<TextField multiline value={ comment } onChange={ ev => setComment(ev.target.value) } fullWidth label={ t("comments") } rows={3}/>
|
|
||||||
|
|
||||||
<DialogActions>
|
|
||||||
<Button onClick={ handleAcceptModalClose }>
|
|
||||||
{ t('cancel') }
|
|
||||||
</Button>
|
|
||||||
<Button onClick={ handleAccept } color="primary" variant="contained">
|
|
||||||
{ t('confirm') }
|
|
||||||
</Button>
|
|
||||||
</DialogActions>
|
|
||||||
</DialogContent>
|
|
||||||
</Dialog>
|
|
||||||
</Page>
|
</Page>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import { useTranslation } from "react-i18next";
|
|||||||
import { Box, Button, ButtonProps, StepProps } from "@material-ui/core";
|
import { Box, Button, ButtonProps, StepProps } from "@material-ui/core";
|
||||||
import { FileDownloadOutline, FileUploadOutline } from "mdi-material-ui/index";
|
import { FileDownloadOutline, FileUploadOutline } from "mdi-material-ui/index";
|
||||||
import { route } from "@/routing";
|
import { route } from "@/routing";
|
||||||
import { Link as RouterLink } from "react-router-dom";
|
import { Link as RouterLink, useHistory } from "react-router-dom";
|
||||||
import { Actions, Step } from "@/components";
|
import { Actions, Step } from "@/components";
|
||||||
import React, { HTMLProps } from "react";
|
import React, { HTMLProps } from "react";
|
||||||
import { Alert, AlertTitle } from "@material-ui/lab";
|
import { Alert, AlertTitle } from "@material-ui/lab";
|
||||||
@ -15,15 +15,19 @@ import { useDeadlines } from "@/hooks";
|
|||||||
import { InternshipDocument } from "@/api/dto/internship-registration";
|
import { InternshipDocument } from "@/api/dto/internship-registration";
|
||||||
import { FileInfo } from "@/components/fileinfo";
|
import { FileInfo } from "@/components/fileinfo";
|
||||||
import { useSpacing } from "@/styles";
|
import { useSpacing } from "@/styles";
|
||||||
|
import { AcceptanceActions } from "@/components/acceptance-action";
|
||||||
|
import { InternshipPlanActions, useDispatch } from "@/state/actions";
|
||||||
|
|
||||||
const PlanActions = () => {
|
const PlanActions = () => {
|
||||||
const status = useSelector<AppState, SubmissionStatus>(state => getSubmissionStatus(state.plan));
|
const status = useSelector<AppState, SubmissionStatus>(state => getSubmissionStatus(state.plan));
|
||||||
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const history = useHistory();
|
||||||
|
|
||||||
const FormAction = ({ children = t('steps.plan.form'), ...props }: ButtonProps) =>
|
const FormAction = ({ children = t('steps.plan.submit'), ...props }: ButtonProps) =>
|
||||||
<Button to={ route("internship_plan") } variant="contained" color="primary" component={ RouterLink } startIcon={ <FileUploadOutline /> }>
|
<Button to={ route("internship_plan") } variant="contained" color="primary" component={ RouterLink } startIcon={ <FileUploadOutline /> }>
|
||||||
{ t('steps.plan.submit') }
|
{ children }
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
const TemplateAction = (props: ButtonProps) =>
|
const TemplateAction = (props: ButtonProps) =>
|
||||||
@ -31,9 +35,21 @@ const PlanActions = () => {
|
|||||||
{ t('steps.plan.template') }
|
{ t('steps.plan.template') }
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
|
const handleAccept = (comment?: string) => {
|
||||||
|
dispatch({ type: InternshipPlanActions.Approve, comment: comment || null });
|
||||||
|
history.push(route("home"));
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDiscard = (comment: string) => {
|
||||||
|
dispatch({ type: InternshipPlanActions.Decline, comment: comment });
|
||||||
|
history.push(route("home"));
|
||||||
|
}
|
||||||
|
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case "awaiting":
|
case "awaiting":
|
||||||
return <Actions/>
|
return <Actions>
|
||||||
|
<AcceptanceActions onAccept={ handleAccept } onDiscard={ handleDiscard } label="plan" />
|
||||||
|
</Actions>
|
||||||
case "accepted":
|
case "accepted":
|
||||||
return <Actions>
|
return <Actions>
|
||||||
<FormAction variant="outlined" color="secondary">{ t('send-again') }</FormAction>
|
<FormAction variant="outlined" color="secondary">{ t('send-again') }</FormAction>
|
||||||
|
@ -148,6 +148,14 @@ internship:
|
|||||||
title: "Zaakceptuj zgłoszenie praktyki"
|
title: "Zaakceptuj zgłoszenie praktyki"
|
||||||
info: "Poniższa informacja zostanie przekazana praktykantowi."
|
info: "Poniższa informacja zostanie przekazana praktykantowi."
|
||||||
|
|
||||||
|
plan:
|
||||||
|
discard:
|
||||||
|
title: "Odrzuć indywidualny program praktyki"
|
||||||
|
info: "Poniższa informacja zostanie przekazana praktykantowi w celu poprawy zgłoszenia."
|
||||||
|
accept:
|
||||||
|
title: "Zaakceptuj indywidualny program praktyki"
|
||||||
|
info: "Poniższa informacja zostanie przekazana praktykantowi."
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
personal-data:
|
personal-data:
|
||||||
header: "Uzupełnienie danych"
|
header: "Uzupełnienie danych"
|
||||||
|
Loading…
Reference in New Issue
Block a user