Create session scheduling page

main
MiguelMLorente 2025-12-07 16:00:36 +01:00
parent 9607c3f83f
commit 6b4b1aea55
5 changed files with 161 additions and 0 deletions

View File

@ -10,6 +10,7 @@ import { BuyReturn } from "./pages/buy/BuyReturn.tsx";
import { Grid, Paper } from "@mui/material"; import { Grid, Paper } from "@mui/material";
import { AuthenticatedRoute } from "./pages/auth/AuthenticatedRoute.tsx"; import { AuthenticatedRoute } from "./pages/auth/AuthenticatedRoute.tsx";
import { InvoicePage } from "./pages/invoice/InvoicePage.tsx"; import { InvoicePage } from "./pages/invoice/InvoicePage.tsx";
import { SchedulerPage } from "./pages/scheduling/SchedulerPage.tsx";
const App = () => ( const App = () => (
<Paper <Paper
@ -40,6 +41,7 @@ const App = () => (
<Route path="/buy" element={<Buy />} /> <Route path="/buy" element={<Buy />} />
<Route path="/buy/return" element={<BuyReturn />} /> <Route path="/buy/return" element={<BuyReturn />} />
<Route path="/summary" element={<InvoicePage />} /> <Route path="/summary" element={<InvoicePage />} />
<Route path="/schedule" element={<SchedulerPage />} />
</Route> </Route>
<Route path="*" element={<NotFound />} /> <Route path="*" element={<NotFound />} />
</Routes> </Routes>

View File

@ -106,3 +106,10 @@ export const getInvoicingSummary = () =>
AxiosResponse<InvoiceSummary> AxiosResponse<InvoiceSummary>
> >
).then((response) => response.data); ).then((response) => response.data);
export const openSession = (sessionId: string) =>
axios.post("/session/open", { sessionId }, getJwtHeader());
export const closeSession = (sessionId: string) =>
axios.post("/session/close", { sessionId }, getJwtHeader());
export const cancelSession = (sessionId: string) =>
axios.post("/session/cancel", { sessionId }, getJwtHeader());

View File

@ -0,0 +1,22 @@
import { Button } from "@mui/material";
import { cancelSession, type Session } from "../../api/client";
export const CancellingAction = (props: { session: Session }) => {
const { session } = props;
const { status, id } = session;
if (status === "CANCELLED" || status === "CLOSED") {
return "N/A";
}
return (
<Button
variant="contained"
color="secondary"
sx={{ width: "100%" }}
onClick={() => cancelSession(id)}
>
CANCEL
</Button>
);
};

View File

@ -0,0 +1,93 @@
import {
Grid,
Paper,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TablePagination,
TableRow,
Typography,
} from "@mui/material";
import { FormattedDate } from "react-intl";
import { getAllSessions, type Session } from "../../api/client";
import { Async } from "react-async";
import { useState } from "react";
import { SchedulingAction } from "./SchedulingAction";
import { CancellingAction } from "./CancellingAction";
export const SchedulerPage = () => {
const sessionsPromise = getAllSessions();
const [page, setPage] = useState(0);
const rowsPerPage = 10;
return (
<Async promise={sessionsPromise}>
<Async.Fulfilled<Session[]>>
{(sessions) => (
<Grid container direction="column" spacing={2} alignItems="center">
<Typography variant="h3">All sessions</Typography>
<TableContainer component={Paper}>
<Table>
<TableHead>
<TableRow>
<TableCell align="center" sx={{ fontWeight: "bold" }}>
Date
</TableCell>
<TableCell align="center" sx={{ fontWeight: "bold" }}>
Slots
</TableCell>
<TableCell align="center" sx={{ fontWeight: "bold" }}>
Status
</TableCell>
<TableCell align="center" sx={{ fontWeight: "bold" }}>
Scheduling
</TableCell>
<TableCell align="center" sx={{ fontWeight: "bold" }}>
Cancel
</TableCell>
</TableRow>
</TableHead>
<TableBody>
{sessions
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
.map((session) => (
<TableRow key={session.id}>
<TableCell align="center">
<FormattedDate
value={new Date(session.date)}
day="numeric"
month="short"
year="numeric"
/>
</TableCell>
<TableCell align="center">
{session.userCount}/{session.size}
</TableCell>
<TableCell align="center">{session.status}</TableCell>
<TableCell align="center">
<SchedulingAction session={session} />
</TableCell>
<TableCell align="center">
<CancellingAction session={session} />
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
<TablePagination
component="div"
count={sessions.length}
rowsPerPage={rowsPerPage}
page={page}
onPageChange={(_, newPage) => setPage(newPage)}
rowsPerPageOptions={[]}
/>
</Grid>
)}
</Async.Fulfilled>
</Async>
);
};

View File

@ -0,0 +1,37 @@
import { Button } from "@mui/material";
import { closeSession, openSession, type Session } from "../../api/client";
export const SchedulingAction = (props: { session: Session }) => {
const { session } = props;
const { status, id } = session;
if (status === "CANCELLED" || status === "CLOSED") {
return ("N/A");
}
if (status === "SCHEDULED") {
return (
<Button
variant="contained"
color="primary"
sx={{ width: "100%" }}
onClick={() => openSession(id)}
>
OPEN
</Button>
);
}
if (status === "OPEN") {
return (
<Button
variant="contained"
color="primary"
sx={{ width: "100%" }}
onClick={() => closeSession(id)}
>
CLOSE
</Button>
);
}
};