Implement join/leave session and simplify UI

main
MiguelMLorente 2025-12-01 22:59:56 +01:00
parent 703408fc12
commit f96d20eaf2
2 changed files with 81 additions and 73 deletions

View File

@ -38,3 +38,17 @@ export const getAllSessions = (userId: string) =>
( (
axios.get(`/session?userId=${userId}`) as Promise<AxiosResponse<Session[]>> axios.get(`/session?userId=${userId}`) as Promise<AxiosResponse<Session[]>>
).then((response) => response.data); ).then((response) => response.data);
export const joinSession = (userId: string, sessionId: string) =>
(
axios.post("/session/join", { userId, sessionId }) as Promise<
AxiosResponse<Session[]>
>
).then((response) => response.data);
export const leaveSession = (userId: string, sessionId: string) =>
(
axios.post("/session/leave", { userId, sessionId }) as Promise<
AxiosResponse<Session[]>
>
).then((response) => response.data);

View File

@ -1,32 +1,33 @@
import { import {
Alert, Alert,
Button, Button,
FormControlLabel,
Grid, Grid,
Paper, Paper,
Radio, Table,
RadioGroup, TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
Typography, Typography,
} from "@mui/material"; } from "@mui/material";
import { useContext, useMemo, useState } from "react"; import { useContext, useMemo } from "react";
import { FormattedDate } from "react-intl"; import { FormattedDate } from "react-intl";
import { useNavigate } from "react-router"; import { useNavigate } from "react-router";
import { Async } from "react-async"; import { Async } from "react-async";
import { getAllSessions, type Session } from "../api/client"; import {
getAllSessions,
joinSession,
leaveSession,
type Session,
} from "../api/client";
import { LoggedInPageContext } from "../context/logged-in-page-context"; import { LoggedInPageContext } from "../context/logged-in-page-context";
export const SignUp = () => { export const SignUp = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const { userId } = useContext(LoggedInPageContext)!; const { userId } = useContext(LoggedInPageContext)!;
const sessionsPromise = useMemo(() => getAllSessions(userId), []) const sessionsPromise = useMemo(() => getAllSessions(userId), []);
const [selectedSession, setSelectedSession] = useState<Session | null>(null);
const setSelectedSessionFromId = (sessions: Session[], id: string) => setSelectedSession(
sessions.find(s => s.id === id) || null);
const selectedSessionId = selectedSession && selectedSession.id;
const selectedDate = selectedSession && new Date(selectedSession.date);
const availableSlots = selectedSession && selectedSession?.size - selectedSession.userCount;
const availableTokens: number = 0; const availableTokens: number = 0;
return ( return (
@ -47,32 +48,63 @@ export const SignUp = () => {
sessions.length === 0 ? ( sessions.length === 0 ? (
<Alert severity="warning">No sessions are available</Alert> <Alert severity="warning">No sessions are available</Alert>
) : ( ) : (
<> <TableContainer component={Paper}>
<RadioGroup <Table>
value={selectedSessionId} <TableHead>
onChange={(e) => setSelectedSessionFromId(sessions, e.target.value)} <TableRow>
> <TableCell>Date</TableCell>
{sessions.map((session) => { <TableCell>Slots</TableCell>
const date = new Date(session.date); <TableCell>Sign-in/out</TableCell>
return ( </TableRow>
<FormControlLabel </TableHead>
key={session.id} <TableBody>
value={session.id} {sessions.map((session) => (
control={<Radio />} <TableRow key={session.id}>
label={ <TableCell>
<FormattedDate <FormattedDate
value={date} value={new Date(session.date)}
day="numeric" day="numeric"
month="long" month="short"
year="numeric" year="numeric"
/> />
} </TableCell>
/> <TableCell>
); {session.userCount}/{session.size}
})} </TableCell>
</RadioGroup> <TableCell>
<Button></Button> {session.includesRequester ? (
</> <Button
variant="contained"
color="primary"
sx={{ width: "100%" }}
onClick={async () => {
await leaveSession(userId, session.id);
window.location.reload();
}}
>
Sign out
</Button>
) : session.userCount >= session.size ? (
"UNAVAILABLE"
) : (
<Button
variant="contained"
color="primary"
sx={{ width: "100%" }}
onClick={async () => {
await joinSession(userId, session.id);
window.location.reload();
}}
>
Sign in
</Button>
)}
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
) )
} }
</Async.Fulfilled> </Async.Fulfilled>
@ -81,44 +113,6 @@ export const SignUp = () => {
</Async.Rejected> </Async.Rejected>
</Async> </Async>
</Paper> </Paper>
{selectedDate && (
<Paper
variant="outlined"
sx={{
p: 3,
bgcolor: "aliceblue",
borderRadius: 4,
}}
>
<Typography variant="h5">
<FormattedDate
value={selectedDate}
day="numeric"
month="long"
year="numeric"
/>
</Typography>
{!availableSlots ? (
<Typography variant="subtitle1">
There are no available slots for this date.
</Typography>
) : (
<>
<Typography variant="subtitle1">
There are {availableSlots} available slots for this date.
</Typography>
<Button
variant="contained"
color="primary"
sx={{ width: "100%" }}
disabled={!availableTokens}
>
Sign up
</Button>
</>
)}
</Paper>
)}
{!availableTokens && ( {!availableTokens && (
<Paper <Paper
variant="outlined" variant="outlined"