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[]>>
).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 {
Alert,
Button,
FormControlLabel,
Grid,
Paper,
Radio,
RadioGroup,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
Typography,
} from "@mui/material";
import { useContext, useMemo, useState } from "react";
import { useContext, useMemo } from "react";
import { FormattedDate } from "react-intl";
import { useNavigate } from "react-router";
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";
export const SignUp = () => {
const navigate = useNavigate();
const { userId } = useContext(LoggedInPageContext)!;
const sessionsPromise = useMemo(() => getAllSessions(userId), [])
const [selectedSession, setSelectedSession] = useState<Session | null>(null);
const sessionsPromise = useMemo(() => getAllSessions(userId), []);
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;
return (
@ -47,32 +48,63 @@ export const SignUp = () => {
sessions.length === 0 ? (
<Alert severity="warning">No sessions are available</Alert>
) : (
<>
<RadioGroup
value={selectedSessionId}
onChange={(e) => setSelectedSessionFromId(sessions, e.target.value)}
>
{sessions.map((session) => {
const date = new Date(session.date);
return (
<FormControlLabel
key={session.id}
value={session.id}
control={<Radio />}
label={
<TableContainer component={Paper}>
<Table>
<TableHead>
<TableRow>
<TableCell>Date</TableCell>
<TableCell>Slots</TableCell>
<TableCell>Sign-in/out</TableCell>
</TableRow>
</TableHead>
<TableBody>
{sessions.map((session) => (
<TableRow key={session.id}>
<TableCell>
<FormattedDate
value={date}
value={new Date(session.date)}
day="numeric"
month="long"
month="short"
year="numeric"
/>
}
/>
);
})}
</RadioGroup>
<Button></Button>
</>
</TableCell>
<TableCell>
{session.userCount}/{session.size}
</TableCell>
<TableCell>
{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>
@ -81,44 +113,6 @@ export const SignUp = () => {
</Async.Rejected>
</Async>
</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 && (
<Paper
variant="outlined"