diff --git a/package-lock.json b/package-lock.json index d1b4f84..caf35db 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,10 +11,9 @@ "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.1", "@mui/material": "^7.3.5", - "@mui/x-date-pickers": "^8.19.0", "axios": "^1.13.2", - "dayjs": "^1.11.19", "react": "^19.2.0", + "react-async": "^10.0.1", "react-dom": "^19.2.0", "react-intl": "^7.1.14", "react-router": "^7.9.6" @@ -1075,103 +1074,6 @@ "integrity": "sha512-x3Ax3kNSMIIkyVYhWPyO09bu0uttcAIoecO/um/rKGQ4EltYWVYtyiGkS/3xMynrbVQdS69Jhlv8FXUEZehlzA==", "license": "MIT" }, - "node_modules/@mui/x-date-pickers": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-8.19.0.tgz", - "integrity": "sha512-TQ4FsGUsiGJVs+Ie4q7nHXUmFqZADXL/1hVtZpOKsdr3WQXwpX7C5YmeakZGFR2NZnuv4snFj+WTee3kgyFbyQ==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.28.4", - "@mui/utils": "^7.3.5", - "@mui/x-internals": "8.19.0", - "@types/react-transition-group": "^4.4.12", - "clsx": "^2.1.1", - "prop-types": "^15.8.1", - "react-transition-group": "^4.4.5" - }, - "engines": { - "node": ">=14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" - }, - "peerDependencies": { - "@emotion/react": "^11.9.0", - "@emotion/styled": "^11.8.1", - "@mui/material": "^5.15.14 || ^6.0.0 || ^7.0.0", - "@mui/system": "^5.15.14 || ^6.0.0 || ^7.0.0", - "date-fns": "^2.25.0 || ^3.2.0 || ^4.0.0", - "date-fns-jalali": "^2.13.0-0 || ^3.2.0-0 || ^4.0.0-0", - "dayjs": "^1.10.7", - "luxon": "^3.0.2", - "moment": "^2.29.4", - "moment-hijri": "^2.1.2 || ^3.0.0", - "moment-jalaali": "^0.7.4 || ^0.8.0 || ^0.9.0 || ^0.10.0", - "react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@emotion/react": { - "optional": true - }, - "@emotion/styled": { - "optional": true - }, - "date-fns": { - "optional": true - }, - "date-fns-jalali": { - "optional": true - }, - "dayjs": { - "optional": true - }, - "luxon": { - "optional": true - }, - "moment": { - "optional": true - }, - "moment-hijri": { - "optional": true - }, - "moment-jalaali": { - "optional": true - } - } - }, - "node_modules/@mui/x-date-pickers/node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/@mui/x-internals": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/@mui/x-internals/-/x-internals-8.19.0.tgz", - "integrity": "sha512-mMmiyJAN5fW27srXJjhXhXJa+w2xGO45rwcjws6OQc9rdXGdJqRXhBwJd+OT7J1xwSdFIIUhjZRTz1KAfCSGBg==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.28.4", - "@mui/utils": "^7.3.5", - "reselect": "^5.1.1", - "use-sync-external-store": "^1.6.0" - }, - "engines": { - "node": ">=14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" - }, - "peerDependencies": { - "react": "^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, "node_modules/@napi-rs/wasm-runtime": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.0.7.tgz", @@ -2253,30 +2155,6 @@ "integrity": "sha512-D80T+tiqkd/8B0xNlbstWDG4x6aqVfO52+OlSUNIdkTvmNw0uQpJLeos2J/2XvpyidAFuTPmpad+tUxLndwj6g==", "license": "MIT" }, - "node_modules/date-fns": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", - "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@babel/runtime": "^7.21.0" - }, - "engines": { - "node": ">=0.11" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/date-fns" - } - }, - "node_modules/dayjs": { - "version": "1.11.19", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz", - "integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==", - "license": "MIT" - }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -3852,6 +3730,15 @@ "node": ">=0.10.0" } }, + "node_modules/react-async": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/react-async/-/react-async-10.0.1.tgz", + "integrity": "sha512-ORUz5ca0B57QgBIzEZM5SuhJ6xFjkvEEs0gylLNlWf06vuVcLZsjIw3wx58jJkZG38p+0nUAxRgFW2b7mnVZzA==", + "license": "ISC", + "peerDependencies": { + "react": ">=16.3.1" + } + }, "node_modules/react-dom": { "version": "19.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz", @@ -3943,12 +3830,6 @@ "react-dom": ">=16.6.0" } }, - "node_modules/reselect": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", - "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==", - "license": "MIT" - }, "node_modules/resolve": { "version": "1.22.11", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", @@ -4333,15 +4214,6 @@ "punycode": "^2.1.0" } }, - "node_modules/use-sync-external-store": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", - "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", - "license": "MIT", - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, "node_modules/vite": { "name": "rolldown-vite", "version": "7.2.2", diff --git a/package.json b/package.json index 8da13e6..0bd7b11 100644 --- a/package.json +++ b/package.json @@ -14,10 +14,9 @@ "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.1", "@mui/material": "^7.3.5", - "@mui/x-date-pickers": "^8.19.0", "axios": "^1.13.2", - "dayjs": "^1.11.19", "react": "^19.2.0", + "react-async": "^10.0.1", "react-dom": "^19.2.0", "react-intl": "^7.1.14", "react-router": "^7.9.6" diff --git a/src/App.tsx b/src/App.tsx index 22575ed..6626304 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -14,7 +14,7 @@ import { Grid, Paper } from "@mui/material"; function App() { const [userId, setUserId] = useState( - window.localStorage.getItem("paysplit-user-id") + window.localStorage.getItem("paysplit-user-id"), ); const storeUserId = (id: string) => { window.localStorage.setItem("paysplit-user-id", id.toString()); diff --git a/src/api/client.ts b/src/api/client.ts index 4ed6064..11785cd 100644 --- a/src/api/client.ts +++ b/src/api/client.ts @@ -25,3 +25,16 @@ export const completeBuyFlow = (userId: string) => axios.post("/buy/complete", { userId }) as Promise< AxiosResponse<{ url: string }, unknown, {}> >; + +export interface Session { + id: string; + size: number; + userCount: number; + includesRequester: boolean; + date: string; +} + +export const getAllSessions = (userId: string) => + ( + axios.get(`/session?userId=${userId}`) as Promise> + ).then((response) => response.data); diff --git a/src/pages/Register.tsx b/src/pages/Register.tsx index bccc263..571a029 100644 --- a/src/pages/Register.tsx +++ b/src/pages/Register.tsx @@ -52,7 +52,6 @@ export const Register = () => { const handleRegisterFlow = () => registerUser(userName, password).then((response) => { - console.log(response); setUserId(response.data.userId); navigate("/signup"); }); diff --git a/src/pages/SignUp.tsx b/src/pages/SignUp.tsx index 920527f..d1c840e 100644 --- a/src/pages/SignUp.tsx +++ b/src/pages/SignUp.tsx @@ -1,19 +1,32 @@ -import { Button, Grid, Paper, Typography } from "@mui/material"; -import { DateCalendar } from "@mui/x-date-pickers"; -import { useState } from "react"; +import { + Alert, + Button, + FormControlLabel, + Grid, + Paper, + Radio, + RadioGroup, + Typography, +} from "@mui/material"; +import { useContext, useMemo, useState } from "react"; import { FormattedDate } from "react-intl"; import { useNavigate } from "react-router"; -import { Dayjs } from "dayjs"; +import { Async } from "react-async"; +import { getAllSessions, type Session } from "../api/client"; +import { LoggedInPageContext } from "../context/logged-in-page-context"; export const SignUp = () => { - const [selectedDate, setSelectedDate] = useState(null); const navigate = useNavigate(); + const { userId } = useContext(LoggedInPageContext)!; + const sessionsPromise = useMemo(() => getAllSessions(userId), []) + const [selectedSession, setSelectedSession] = useState(null); - const tuesday = 2; - const thursday = 4; - const isDateDisabled = (day: Dayjs) => - ![tuesday, thursday].includes(day.day()); - const availableSlots: number = 3; + 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 ( @@ -22,23 +35,51 @@ export const SignUp = () => { - + + Loading + > + {(sessions) => + sessions.length === 0 ? ( + No sessions are available + ) : ( + <> + setSelectedSessionFromId(sessions, e.target.value)} + > + {sessions.map((session) => { + const date = new Date(session.date); + return ( + } + label={ + + } + /> + ); + })} + + + + ) + } + + + Something went wrong + + {selectedDate && ( { > - {availableSlots === 0 ? ( + {!availableSlots ? ( There are no available slots for this date. diff --git a/vite.config.ts b/vite.config.ts index 607f62d..a2ae31f 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,7 +1,13 @@ import { defineConfig } from "vite"; import react from "@vitejs/plugin-react"; -const serverRoutes = ["/access", "/buy/start", "/buy/complete", "/buy/cancel"]; +const serverRoutes = [ + "/access", + "/buy/start", + "/buy/complete", + "/buy/cancel", + "/session", +]; const baseServerConfigBuilder = (domain: string) => ({ proxy: Object.fromEntries( serverRoutes.map((key) => [