Skip to content

Commit

Permalink
Merge pull request #120 from lennygir/feat/180-student-make-tsr-change
Browse files Browse the repository at this point in the history
Feat: student make changes to thesis start request
  • Loading branch information
valerianoCarlos authored Jan 16, 2024
2 parents df87c52 + 70f383b commit c36f9cd
Show file tree
Hide file tree
Showing 11 changed files with 175 additions and 46 deletions.
5 changes: 3 additions & 2 deletions client/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -184,10 +184,11 @@ function Main() {
<Route path="/" element={user ? <RootPage loading={loading} setAlert={setAlert} setDirty={setDirty} currentDate={currentDate} fetchProposals={fetchProposals} fetchApplications={fetchApplications} fetchNotifications={fetchNotifications} fetchRequests={fetchRequests} /> : <LoginPage />}>
<Route path="proposals" element={user ? <ProposalsPage setAlert={setAlert} setDirty={setDirty} currentDate={currentDate} proposals={proposals} applications={applications} teachers={teachers} groups={groups} getTeacherById={getTeacherById} /> : <Navigate replace to="/" />} />
<Route path="proposals/:proposalId" element={user ? <ViewProposalPage setDirty={setDirty} setAlert={setAlert} getTeacherById={getTeacherById} getDegreeById={getDegreeById} applications={applications} /> : <Navigate replace to="/" />} />
<Route path="add-request" element={user ? <CreateRequestPage fetchRequests={fetchRequests} teachers={teachers} getTeacherById={getTeacherById} setAlert={setAlert} /> : <Navigate replace to="/" />} />
<Route path="add-start-request" element={user ? <CreateRequestPage fetchRequests={fetchRequests} teachers={teachers} getTeacherById={getTeacherById} setAlert={setAlert} /> : <Navigate replace to="/" />} />
<Route path="edit-start-request" element={user ? <CreateRequestPage fetchRequests={fetchRequests} teachers={teachers} getTeacherById={getTeacherById} setAlert={setAlert} /> : <Navigate replace to="/" />} />
<Route path="edit-proposal/:proposalId" element={user ? <EditProposalPage currentDate={currentDate} fetchProposals={fetchProposals} teachers={teachers} degrees={degrees} setAlert={setAlert} /> : <Navigate replace to="/" />} />
<Route path="applications" element={user ? <ApplicationsPage applications={applications} /> : <Navigate replace to="/" /> } />
<Route path="applications/:applicationId" element={user ? <ViewApplicationPage fetchApplications={fetchApplications} fetchNotifications={fetchNotifications} setAlert={setAlert} applications={applications} /> : <Navigate replace to="/" />} />
<Route path="applications/:applicationId" element={user ? <ViewApplicationPage fetchApplications={fetchApplications} fetchNotifications={fetchNotifications} setAlert={setAlert} applications={applications} requests={requests} /> : <Navigate replace to="/" />} />
<Route path="notifications" element={user ? <NotificationsPage notifications={notifications} fetchNotifications={fetchNotifications} /> : <Navigate replace to="/" />} />
<Route path="requests" element={user ? <RequestsPage requests={requests} teachers={teachers} /> : <Navigate replace to="/" /> } />
<Route path="requests/:requestId" element={user ? <ViewRequestPage fetchRequests={fetchRequests} setAlert={setAlert} requests={requests} /> : <Navigate replace to="/" /> } />
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/RequestDetails.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import AccessTimeIcon from "@mui/icons-material/AccessTime";
import CheckCircleOutlineIcon from "@mui/icons-material/CheckCircleOutline";
import EditNotificationsIcon from "@mui/icons-material/EditNotifications";
import HighlightOffIcon from "@mui/icons-material/HighlightOff";
import ModeEditIcon from "@mui/icons-material/ModeEdit";
import ScheduleSendIcon from "@mui/icons-material/ScheduleSend";
import ConfirmationDialog from "./ConfirmationDialog";
import UserContext from "../contexts/UserContext";
Expand Down Expand Up @@ -61,6 +60,7 @@ function RequestDetails(props) {
const status = requests.find((req) => req.id === request.id).status;
switch (status) {
case "secretary_accepted":
case "changed":
if (user.role === "secretary_clerk") {
return (
<Box sx={{ display: "flex", flexDirection: "column", alignItems: "center" }}>
Expand Down
51 changes: 39 additions & 12 deletions client/src/components/RequestForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,30 @@ import TextField from "@mui/material/TextField";
import CustomPaper from "./CustomPaper";

function RequestForm(props) {
const { createRequest, teachers, getTeacherById, proposal } = props;

const supervisor = proposal ? getTeacherById(proposal.supervisor) : null;
const { createRequest, editRequest, teachers, getTeacherById, proposal, request } = props;

const initFormData = () => {
const form = {
title: "",
description: "",
supervisor: null,
coSupervisors: []
};
if (proposal) {
form.title = proposal.title;
form.description = proposal.description;
form.supervisor = getTeacherById(proposal.supervisor).email;
form.coSupervisors = proposal.co_supervisors.split(", ");
} else if (request) {
form.title = request.title;
form.description = request.description;
form.supervisor = request.supervisor;
form.coSupervisors = request.co_supervisors || [];
}
return form;
};

const [formData, setFormData] = useState({
title: proposal ? proposal.title : "",
description: proposal ? proposal.description : "",
supervisor: supervisor ? supervisor.email : null,
coSupervisors: proposal ? proposal.co_supervisors.split(", ") : []
});
const [formData, setFormData] = useState(initFormData());

const [formErrors, setFormErrors] = useState({
title: "",
Expand Down Expand Up @@ -90,7 +104,12 @@ function RequestForm(props) {
supervisor: supervisor.id,
co_supervisors: formData.coSupervisors
};
createRequest(data);
if (!request) {
createRequest(data);
} else {
data.id = request.id;
editRequest(data);
}
};

const ChipProps = { sx: { height: 26 } };
Expand Down Expand Up @@ -144,6 +163,7 @@ function RequestForm(props) {
value={formData.supervisor}
onChange={(event, value) => handleFormInputChange("supervisor", value)}
PaperComponent={CustomPaper}
disabled={!!proposal || !!request}
renderInput={(params) => (
<TextField
{...params}
Expand Down Expand Up @@ -185,17 +205,24 @@ function RequestForm(props) {
</FormControl>
</Stack>
<Button fullWidth type="submit" variant="contained" sx={{ mt: 4, mb: 2 }}>
Create Request
{request ? "Edit Request" : "Create Request"}
</Button>
</Box>
);
}

RequestForm.propTypes = {
createRequest: PropTypes.func,
editRequest: PropTypes.func,
teachers: PropTypes.array,
getTeacherById: PropTypes.func,
proposal: PropTypes.object
proposal: PropTypes.object,
request: PropTypes.object
};

RequestForm.defaultProps = {
proposal: null,
request: null
};

export default RequestForm;
1 change: 1 addition & 0 deletions client/src/components/RequestRow.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ function RequestRow(props) {
const renderStatus = () => {
switch (request.status) {
case "secretary_accepted":
case "changed":
return <Chip label={user.role === "secretary_clerk" ? "APPROVED" : "PENDING"} size="small" color="info" />;
case "requested":
return <Chip label="REQUESTED" size="small" color="default" />;
Expand Down
18 changes: 17 additions & 1 deletion client/src/routes/CreateRequestPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ function CreateRequestPage(props) {
const location = useLocation();

const proposal = location.state?.proposal;
const request = location.state?.request;

const createRequest = (request) => {
API.createRequest(request)
Expand All @@ -32,6 +33,19 @@ function CreateRequestPage(props) {
.catch((err) => handleErrors(err));
};

const editRequest = (request) => {
API.updateRequest(request)
.then(() => {
setAlert({
message: "Request updated successfully",
severity: "success"
});
fetchRequests();
navigate(-1);
})
.catch((err) => handleErrors(err));
};

return (
<div id="create-request-page">
<Stack
Expand All @@ -51,15 +65,17 @@ function CreateRequestPage(props) {
</Button>
</Stack>
<Typography variant="h4" sx={{ paddingY: 4, marginLeft: { md: 4, xs: 0 } }}>
Thesis Start Request
{request ? "Edit Thesis Start Request" : "New Thesis Start Request"}
</Typography>
<Paper elevation={1} sx={{ mb: 5, pt: 2, borderRadius: 4, mx: { md: 4, xs: 0 } }}>
<Box paddingX={5} sx={{ px: { md: 5, xs: 3 } }} paddingBottom={3}>
<RequestForm
createRequest={createRequest}
editRequest={editRequest}
teachers={teachers}
getTeacherById={getTeacherById}
proposal={proposal}
request={request}
/>
</Box>
</Paper>
Expand Down
62 changes: 52 additions & 10 deletions client/src/routes/RequestsPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useContext, useState } from "react";
import { Link } from "react-router-dom";
import { Alert, Box, Button, Fab, Hidden, Paper, Stack, Step, StepLabel, Stepper, Typography } from "@mui/material";
import AddIcon from "@mui/icons-material/Add";
import ModeEditIcon from "@mui/icons-material/ModeEdit";
import ScheduleSendIcon from "@mui/icons-material/ScheduleSend";
import RequestTable from "../components/RequestTable";
import UserContext from "../contexts/UserContext";
Expand All @@ -19,13 +20,21 @@ function RequestsPage(props) {

const [lastActiveStep, setLastActiveStep] = useState(-1);

const getLastRequest = () => {
const lastRequest = requests[requests.length - 1];
return lastRequest;
};

const getActiveRequest = () => {
const lastRequest = requests[requests.length - 1];
if (lastRequest?.status === "rejected") {
return null;
}
return lastRequest;
};

const getActiveStep = () => {
const request = getActiveRequest();
const request = getLastRequest();
if (!request) {
return -1;
}
Expand All @@ -42,6 +51,8 @@ function RequestsPage(props) {
break;
case "changes_requested":
return 2;
case "changed":
return 2;
default:
return lastActiveStep;
}
Expand All @@ -52,8 +63,38 @@ function RequestsPage(props) {
};

const isStartRequestButtonDisabled = () => {
const activeRequest = getActiveRequest();
return activeRequest && activeRequest.status !== "rejected";
const activeRequest = getLastRequest();
return activeRequest && activeRequest.status !== "rejected" && activeRequest.status !== "changes_requested";
};

const renderButtonIcon = () => {
const activeRequest = getLastRequest();
if (activeRequest) {
if (isStartRequestButtonDisabled()) {
return <ScheduleSendIcon />;
} else if (activeRequest.status === "rejected") {
return <AddIcon />;
} else if (activeRequest.status === "changes_requested") {
return <ModeEditIcon />;
}
} else {
return <AddIcon />;
}
};

const renderButtonLabel = () => {
const activeRequest = getLastRequest();
if (activeRequest) {
if (isStartRequestButtonDisabled()) {
return "Request sent";
} else if (activeRequest.status === "rejected") {
return "Start request";
} else if (activeRequest.status === "changes_requested") {
return "Edit request";
}
} else {
return "Start request";
}
};

return (
Expand All @@ -66,13 +107,14 @@ function RequestsPage(props) {
<Hidden smDown>
<Button
component={Link}
to="/add-request"
to={getLastRequest()?.status === "changes_requested" ? "/edit-start-request" : "/add-start-request"}
state={{ request: getActiveRequest() }}
disabled={isStartRequestButtonDisabled()}
variant="contained"
sx={{ mr: 4 }}
startIcon={isStartRequestButtonDisabled() ? <ScheduleSendIcon /> : <AddIcon />}
startIcon={renderButtonIcon()}
>
{isStartRequestButtonDisabled() ? "Request sent" : "Start Request"}
{renderButtonLabel()}
</Button>
</Hidden>
)}
Expand All @@ -89,10 +131,10 @@ function RequestsPage(props) {
</Step>
))}
</Stepper>
{getActiveRequest() ? (
{getLastRequest() ? (
<Paper elevation={1} sx={{ mb: 5, pt: 1, mt: 3, borderRadius: 4, mx: { md: 4, xs: 0 } }}>
<Box paddingX={5} sx={{ px: { md: 5, xs: 3 } }} paddingBottom={3}>
<RequestDetails request={getActiveRequest()} requests={requests} />
<RequestDetails request={getLastRequest()} requests={requests} />
</Box>
</Paper>
) : (
Expand All @@ -116,12 +158,12 @@ function RequestsPage(props) {
>
<Fab
component={Link}
to="/add-request"
to="/add-start-request"
aria-label="Add"
color="primary"
disabled={isStartRequestButtonDisabled()}
>
{isStartRequestButtonDisabled() ? <ScheduleSendIcon /> : <AddIcon />}
{renderButtonIcon()}
</Fab>
</Stack>
</Hidden>
Expand Down
13 changes: 10 additions & 3 deletions client/src/routes/ViewApplicationPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import API from "../utils/API";

function ViewApplicationPage(props) {
const location = useLocation();
const { fetchApplications, fetchNotifications, setAlert, applications } = props;
const { fetchApplications, fetchNotifications, setAlert, applications, requests } = props;
const user = useContext(UserContext);
const handleErrors = useContext(ErrorContext);

Expand Down Expand Up @@ -43,6 +43,11 @@ function ViewApplicationPage(props) {
}
}, []);

const isStartRequestButtonDisabled = () => {
const activeRequest = requests[requests.length - 1];
return activeRequest && activeRequest.status !== "rejected";
};

return (
<div id="view-application-page">
<Stack
Expand All @@ -64,8 +69,9 @@ function ViewApplicationPage(props) {
{user.role === "student" && application.state === "accepted" && (
<Button
component={Link}
to="/add-request"
to="/add-start-request"
state={{ proposal: proposal }}
disabled={isStartRequestButtonDisabled()}
variant="contained"
startIcon={<AddIcon />}
sx={{ mr: { md: 4, xs: 0 } }}
Expand Down Expand Up @@ -96,7 +102,8 @@ ViewApplicationPage.propTypes = {
fetchApplications: PropTypes.func,
fetchNotifications: PropTypes.func,
setAlert: PropTypes.func,
applications: PropTypes.array
applications: PropTypes.array,
requests: PropTypes.array
};

export default ViewApplicationPage;
12 changes: 9 additions & 3 deletions client/src/routes/ViewRequestPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,9 @@ function ViewRequestPage(props) {
Back
</Button>
{user.role === "teacher" &&
(request.status === "secretary_accepted" || request.status === "changes_requested") && (
(request.status === "secretary_accepted" ||
request.status === "changes_requested" ||
request.status === "changed") && (
<Button
disabled={request.status === "changes_requested"}
variant="contained"
Expand All @@ -108,7 +110,7 @@ function ViewRequestPage(props) {
<Typography variant="h4" sx={{ paddingY: 4, marginLeft: { md: 4, xs: 0 } }}>
Request Details
</Typography>
{request.status === "changes_requested" && (
{(request.status === "changes_requested" || request.status === "changed") && (
<Paper elevation={1} sx={{ mb: 3, borderRadius: 4, mx: { md: 4, xs: 0 } }}>
<Stack
paddingX={5}
Expand All @@ -122,7 +124,11 @@ function ViewRequestPage(props) {
<span style={{ fontWeight: "bold" }}>Changes requested: </span>
{request.changes_requested}
</Typography>
<Chip label="WAITING FOR CHANGES" size="small" color="info" />
<Chip
label={request.status === "changes_requested" ? "WAITING FOR CHANGES" : "CHANGES MADE"}
size="small"
color={request.status === "changes_requested" ? "info" : "success"}
/>
</Stack>
</Paper>
)}
Expand Down
Loading

0 comments on commit c36f9cd

Please sign in to comment.