Create session scheduling component

main
MiguelMLorente 2025-12-07 20:06:02 +01:00
parent 6b4b1aea55
commit 1ac9f7ae1e
7 changed files with 318 additions and 138 deletions

240
package-lock.json generated
View File

@ -10,8 +10,11 @@
"dependencies": { "dependencies": {
"@emotion/react": "^11.14.0", "@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.1", "@emotion/styled": "^11.14.1",
"@mui/icons-material": "^7.3.6",
"@mui/material": "^7.3.5", "@mui/material": "^7.3.5",
"@mui/x-date-pickers": "^8.21.0",
"axios": "^1.13.2", "axios": "^1.13.2",
"dayjs": "^1.11.19",
"react": "^19.2.0", "react": "^19.2.0",
"react-async": "^10.0.1", "react-async": "^10.0.1",
"react-dom": "^19.2.0", "react-dom": "^19.2.0",
@ -829,26 +832,52 @@
} }
}, },
"node_modules/@mui/core-downloads-tracker": { "node_modules/@mui/core-downloads-tracker": {
"version": "7.3.5", "version": "7.3.6",
"resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-7.3.5.tgz", "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-7.3.6.tgz",
"integrity": "sha512-kOLwlcDPnVz2QMhiBv0OQ8le8hTCqKM9cRXlfVPL91l3RGeOsxrIhNRsUt3Xb8wb+pTVUolW+JXKym93vRKxCw==", "integrity": "sha512-QaYtTHlr8kDFN5mE1wbvVARRKH7Fdw1ZuOjBJcFdVpfNfRYKF3QLT4rt+WaB6CKJvpqxRsmEo0kpYinhH5GeHg==",
"license": "MIT", "license": "MIT",
"funding": { "funding": {
"type": "opencollective", "type": "opencollective",
"url": "https://opencollective.com/mui-org" "url": "https://opencollective.com/mui-org"
} }
}, },
"node_modules/@mui/icons-material": {
"version": "7.3.6",
"resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-7.3.6.tgz",
"integrity": "sha512-0FfkXEj22ysIq5pa41A2NbcAhJSvmcZQ/vcTIbjDsd6hlslG82k5BEBqqS0ZJprxwIL3B45qpJ+bPHwJPlF7uQ==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.28.4"
},
"engines": {
"node": ">=14.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/mui-org"
},
"peerDependencies": {
"@mui/material": "^7.3.6",
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
"react": "^17.0.0 || ^18.0.0 || ^19.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@mui/material": { "node_modules/@mui/material": {
"version": "7.3.5", "version": "7.3.6",
"resolved": "https://registry.npmjs.org/@mui/material/-/material-7.3.5.tgz", "resolved": "https://registry.npmjs.org/@mui/material/-/material-7.3.6.tgz",
"integrity": "sha512-8VVxFmp1GIm9PpmnQoCoYo0UWHoOrdA57tDL62vkpzEgvb/d71Wsbv4FRg7r1Gyx7PuSo0tflH34cdl/NvfHNQ==", "integrity": "sha512-R4DaYF3dgCQCUAkr4wW1w26GHXcf5rCmBRHVBuuvJvaGLmZdD8EjatP80Nz5JCw0KxORAzwftnHzXVnjR8HnFw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.28.4", "@babel/runtime": "^7.28.4",
"@mui/core-downloads-tracker": "^7.3.5", "@mui/core-downloads-tracker": "^7.3.6",
"@mui/system": "^7.3.5", "@mui/system": "^7.3.6",
"@mui/types": "^7.4.8", "@mui/types": "^7.4.9",
"@mui/utils": "^7.3.5", "@mui/utils": "^7.3.6",
"@popperjs/core": "^2.11.8", "@popperjs/core": "^2.11.8",
"@types/react-transition-group": "^4.4.12", "@types/react-transition-group": "^4.4.12",
"clsx": "^2.1.1", "clsx": "^2.1.1",
@ -867,7 +896,7 @@
"peerDependencies": { "peerDependencies": {
"@emotion/react": "^11.5.0", "@emotion/react": "^11.5.0",
"@emotion/styled": "^11.3.0", "@emotion/styled": "^11.3.0",
"@mui/material-pigment-css": "^7.3.5", "@mui/material-pigment-css": "^7.3.6",
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
"react": "^17.0.0 || ^18.0.0 || ^19.0.0", "react": "^17.0.0 || ^18.0.0 || ^19.0.0",
"react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
@ -887,15 +916,6 @@
} }
} }
}, },
"node_modules/@mui/material/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/material/node_modules/react-is": { "node_modules/@mui/material/node_modules/react-is": {
"version": "19.2.0", "version": "19.2.0",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.0.tgz", "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.0.tgz",
@ -903,13 +923,13 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@mui/private-theming": { "node_modules/@mui/private-theming": {
"version": "7.3.5", "version": "7.3.6",
"resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-7.3.5.tgz", "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-7.3.6.tgz",
"integrity": "sha512-cTx584W2qrLonwhZLbEN7P5pAUu0nZblg8cLBlTrZQ4sIiw8Fbvg7GvuphQaSHxPxrCpa7FDwJKtXdbl2TSmrA==", "integrity": "sha512-Ws9wZpqM+FlnbZXaY/7yvyvWQo1+02Tbx50mVdNmzWEi51C51y56KAbaDCYyulOOBL6BJxuaqG8rNNuj7ivVyw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.28.4", "@babel/runtime": "^7.28.4",
"@mui/utils": "^7.3.5", "@mui/utils": "^7.3.6",
"prop-types": "^15.8.1" "prop-types": "^15.8.1"
}, },
"engines": { "engines": {
@ -930,9 +950,9 @@
} }
}, },
"node_modules/@mui/styled-engine": { "node_modules/@mui/styled-engine": {
"version": "7.3.5", "version": "7.3.6",
"resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-7.3.5.tgz", "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-7.3.6.tgz",
"integrity": "sha512-zbsZ0uYYPndFCCPp2+V3RLcAN6+fv4C8pdwRx6OS3BwDkRCN8WBehqks7hWyF3vj1kdQLIWrpdv/5Y0jHRxYXQ==", "integrity": "sha512-+wiYbtvj+zyUkmDB+ysH6zRjuQIJ+CM56w0fEXV+VDNdvOuSywG+/8kpjddvvlfMLsaWdQe5oTuYGBcodmqGzQ==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.28.4", "@babel/runtime": "^7.28.4",
@ -964,16 +984,16 @@
} }
}, },
"node_modules/@mui/system": { "node_modules/@mui/system": {
"version": "7.3.5", "version": "7.3.6",
"resolved": "https://registry.npmjs.org/@mui/system/-/system-7.3.5.tgz", "resolved": "https://registry.npmjs.org/@mui/system/-/system-7.3.6.tgz",
"integrity": "sha512-yPaf5+gY3v80HNkJcPi6WT+r9ebeM4eJzrREXPxMt7pNTV/1eahyODO4fbH3Qvd8irNxDFYn5RQ3idHW55rA6g==", "integrity": "sha512-8fehAazkHNP1imMrdD2m2hbA9sl7Ur6jfuNweh5o4l9YPty4iaZzRXqYvBCWQNwFaSHmMEj2KPbyXGp7Bt73Rg==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.28.4", "@babel/runtime": "^7.28.4",
"@mui/private-theming": "^7.3.5", "@mui/private-theming": "^7.3.6",
"@mui/styled-engine": "^7.3.5", "@mui/styled-engine": "^7.3.6",
"@mui/types": "^7.4.8", "@mui/types": "^7.4.9",
"@mui/utils": "^7.3.5", "@mui/utils": "^7.3.6",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"csstype": "^3.1.3", "csstype": "^3.1.3",
"prop-types": "^15.8.1" "prop-types": "^15.8.1"
@ -1003,19 +1023,10 @@
} }
} }
}, },
"node_modules/@mui/system/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/types": { "node_modules/@mui/types": {
"version": "7.4.8", "version": "7.4.9",
"resolved": "https://registry.npmjs.org/@mui/types/-/types-7.4.8.tgz", "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.4.9.tgz",
"integrity": "sha512-ZNXLBjkPV6ftLCmmRCafak3XmSn8YV0tKE/ZOhzKys7TZXUiE0mZxlH8zKDo6j6TTUaDnuij68gIG+0Ucm7Xhw==", "integrity": "sha512-dNO8Z9T2cujkSIaCnWwprfeKmTWh97cnjkgmpFJ2sbfXLx8SMZijCYHOtP/y5nnUb/Rm2omxbDMmtUoSaUtKaw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.28.4" "@babel/runtime": "^7.28.4"
@ -1030,13 +1041,13 @@
} }
}, },
"node_modules/@mui/utils": { "node_modules/@mui/utils": {
"version": "7.3.5", "version": "7.3.6",
"resolved": "https://registry.npmjs.org/@mui/utils/-/utils-7.3.5.tgz", "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-7.3.6.tgz",
"integrity": "sha512-jisvFsEC3sgjUjcPnR4mYfhzjCDIudttSGSbe1o/IXFNu0kZuR+7vqQI0jg8qtcVZBHWrwTfvAZj9MNMumcq1g==", "integrity": "sha512-jn+Ba02O6PiFs7nKva8R2aJJ9kJC+3kQ2R0BbKNY3KQQ36Qng98GnPRFTlbwYTdMD6hLEBKaMLUktyg/rTfd2w==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.28.4", "@babel/runtime": "^7.28.4",
"@mui/types": "^7.4.8", "@mui/types": "^7.4.9",
"@types/prop-types": "^15.7.15", "@types/prop-types": "^15.7.15",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"prop-types": "^15.8.1", "prop-types": "^15.8.1",
@ -1059,20 +1070,99 @@
} }
} }
}, },
"node_modules/@mui/utils/node_modules/clsx": { "node_modules/@mui/utils/node_modules/react-is": {
"version": "2.1.1", "version": "19.2.1",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.1.tgz",
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", "integrity": "sha512-L7BnWgRbMwzMAubQcS7sXdPdNLmKlucPlopgAzx7FtYbksWZgEWiuYM5x9T6UqS2Ne0rsgQTq5kY2SGqpzUkYA==",
"license": "MIT"
},
"node_modules/@mui/x-date-pickers": {
"version": "8.21.0",
"resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-8.21.0.tgz",
"integrity": "sha512-nQ6T6RIHTO7AcUlh7+mICcbwcTOlu+GSSrBsF1Z6pdqbMaxxucABRW3cnC8PdYrSok4+zkkSdTzgKOSCGW+c1g==",
"license": "MIT", "license": "MIT",
"dependencies": {
"@babel/runtime": "^7.28.4",
"@mui/utils": "^7.3.5",
"@mui/x-internals": "8.21.0",
"@types/react-transition-group": "^4.4.12",
"clsx": "^2.1.1",
"prop-types": "^15.8.1",
"react-transition-group": "^4.4.5"
},
"engines": { "engines": {
"node": ">=6" "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/utils/node_modules/react-is": { "node_modules/@mui/x-internals": {
"version": "19.2.0", "version": "8.21.0",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.0.tgz", "resolved": "https://registry.npmjs.org/@mui/x-internals/-/x-internals-8.21.0.tgz",
"integrity": "sha512-x3Ax3kNSMIIkyVYhWPyO09bu0uttcAIoecO/um/rKGQ4EltYWVYtyiGkS/3xMynrbVQdS69Jhlv8FXUEZehlzA==", "integrity": "sha512-tOU6iKi9phIQXWVzQvslKR/y5q+L/NKiBpSqtTDMV7aAxm2mOtCiO6POH2je1nw8iromrQAJfpV9pXDDRgZ01w==",
"license": "MIT" "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": { "node_modules/@napi-rs/wasm-runtime": {
"version": "1.0.7", "version": "1.0.7",
@ -2054,6 +2144,15 @@
"url": "https://github.com/chalk/chalk?sponsor=1" "url": "https://github.com/chalk/chalk?sponsor=1"
} }
}, },
"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/color-convert": { "node_modules/color-convert": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
@ -2155,6 +2254,12 @@
"integrity": "sha512-D80T+tiqkd/8B0xNlbstWDG4x6aqVfO52+OlSUNIdkTvmNw0uQpJLeos2J/2XvpyidAFuTPmpad+tUxLndwj6g==", "integrity": "sha512-D80T+tiqkd/8B0xNlbstWDG4x6aqVfO52+OlSUNIdkTvmNw0uQpJLeos2J/2XvpyidAFuTPmpad+tUxLndwj6g==",
"license": "MIT" "license": "MIT"
}, },
"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": { "node_modules/debug": {
"version": "4.4.3", "version": "4.4.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
@ -3830,6 +3935,12 @@
"react-dom": ">=16.6.0" "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": { "node_modules/resolve": {
"version": "1.22.11", "version": "1.22.11",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz",
@ -4214,6 +4325,15 @@
"punycode": "^2.1.0" "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": { "node_modules/vite": {
"name": "rolldown-vite", "name": "rolldown-vite",
"version": "7.2.2", "version": "7.2.2",

View File

@ -13,8 +13,11 @@
"dependencies": { "dependencies": {
"@emotion/react": "^11.14.0", "@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.1", "@emotion/styled": "^11.14.1",
"@mui/icons-material": "^7.3.6",
"@mui/material": "^7.3.5", "@mui/material": "^7.3.5",
"@mui/x-date-pickers": "^8.21.0",
"axios": "^1.13.2", "axios": "^1.13.2",
"dayjs": "^1.11.19",
"react": "^19.2.0", "react": "^19.2.0",
"react-async": "^10.0.1", "react-async": "^10.0.1",
"react-dom": "^19.2.0", "react-dom": "^19.2.0",

View File

@ -113,3 +113,6 @@ export const closeSession = (sessionId: string) =>
axios.post("/session/close", { sessionId }, getJwtHeader()); axios.post("/session/close", { sessionId }, getJwtHeader());
export const cancelSession = (sessionId: string) => export const cancelSession = (sessionId: string) =>
axios.post("/session/cancel", { sessionId }, getJwtHeader()); axios.post("/session/cancel", { sessionId }, getJwtHeader());
export const createSession = (date: number, size: number) =>
axios.post("/session/create", { date, size }, getJwtHeader());

View File

@ -3,13 +3,17 @@ import { createRoot } from "react-dom/client";
import App from "./App.tsx"; import App from "./App.tsx";
import { BrowserRouter } from "react-router"; import { BrowserRouter } from "react-router";
import { IntlProvider } from "react-intl"; import { IntlProvider } from "react-intl";
import { LocalizationProvider } from "@mui/x-date-pickers";
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
createRoot(document.getElementById("root")!).render( createRoot(document.getElementById("root")!).render(
<StrictMode> <StrictMode>
<LocalizationProvider dateAdapter={AdapterDayjs}>
<BrowserRouter> <BrowserRouter>
<IntlProvider locale="es-ES" messages={{}}> <IntlProvider locale="es-ES" messages={{}}>
<App /> <App />
</IntlProvider> </IntlProvider>
</BrowserRouter> </BrowserRouter>
</LocalizationProvider>
</StrictMode>, </StrictMode>,
); );

View File

@ -14,7 +14,7 @@ export const CancellingAction = (props: { session: Session }) => {
variant="contained" variant="contained"
color="secondary" color="secondary"
sx={{ width: "100%" }} sx={{ width: "100%" }}
onClick={() => cancelSession(id)} onClick={() => cancelSession(id).then(() => window.location.reload())}
> >
CANCEL CANCEL
</Button> </Button>

View File

@ -1,4 +1,5 @@
import { import {
Button,
Grid, Grid,
Paper, Paper,
Table, Table,
@ -8,26 +9,39 @@ import {
TableHead, TableHead,
TablePagination, TablePagination,
TableRow, TableRow,
TextField,
Typography, Typography,
} from "@mui/material"; } from "@mui/material";
import { FormattedDate } from "react-intl"; import { FormattedDate } from "react-intl";
import { getAllSessions, type Session } from "../../api/client"; import { createSession, getAllSessions, type Session } from "../../api/client";
import { Async } from "react-async"; import { Async } from "react-async";
import { useState } from "react"; import { useMemo, useState } from "react";
import { SchedulingAction } from "./SchedulingAction"; import { SchedulingAction } from "./SchedulingAction";
import { CancellingAction } from "./CancellingAction"; import { CancellingAction } from "./CancellingAction";
import { DatePicker } from "@mui/x-date-pickers";
import dayjs from "dayjs";
export const SchedulerPage = () => { export const SchedulerPage = () => {
const sessionsPromise = getAllSessions(); const sessionsPromise = useMemo(getAllSessions, []);
const [page, setPage] = useState(0); const [page, setPage] = useState(0);
const [date, setDate] = useState<dayjs.Dayjs | null>(dayjs());
const [sessionSize, setSessionSize] = useState(10);
const rowsPerPage = 10; const rowsPerPage = 10;
return ( return (
<Grid container direction="column" spacing={2} alignItems="center">
<Typography variant="h3">All sessions</Typography>
<Async promise={sessionsPromise}> <Async promise={sessionsPromise}>
<Async.Fulfilled<Session[]>> <Async.Fulfilled<Session[]>>
{(sessions) => ( {(sessions) => (
<Grid container direction="column" spacing={2} alignItems="center"> <Paper
<Typography variant="h3">All sessions</Typography> variant="outlined"
sx={{
p: 3,
bgcolor: "aliceblue",
borderRadius: 4,
}}
>
<TableContainer component={Paper}> <TableContainer component={Paper}>
<Table> <Table>
<TableHead> <TableHead>
@ -51,7 +65,10 @@ export const SchedulerPage = () => {
</TableHead> </TableHead>
<TableBody> <TableBody>
{sessions {sessions
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage) .slice(
page * rowsPerPage,
page * rowsPerPage + rowsPerPage,
)
.map((session) => ( .map((session) => (
<TableRow key={session.id}> <TableRow key={session.id}>
<TableCell align="center"> <TableCell align="center">
@ -85,9 +102,42 @@ export const SchedulerPage = () => {
onPageChange={(_, newPage) => setPage(newPage)} onPageChange={(_, newPage) => setPage(newPage)}
rowsPerPageOptions={[]} rowsPerPageOptions={[]}
/> />
</Grid> </Paper>
)} )}
</Async.Fulfilled> </Async.Fulfilled>
</Async> </Async>
<Typography variant="h3">New session</Typography>
<Paper
variant="outlined"
sx={{
p: 3,
bgcolor: "aliceblue",
borderRadius: 4,
}}
>
<Grid container direction="column" spacing={2}>
<DatePicker label="Select date" value={date} onChange={setDate} />
<TextField
label="Number"
type="number"
value={sessionSize}
onChange={(e) => setSessionSize(parseInt(e.target.value))}
/>
<Button
variant="contained"
color="secondary"
disabled={date === null}
sx={{ width: "100%" }}
onClick={() =>
createSession(date!.valueOf(), 10).then(() =>
window.location.reload(),
)
}
>
Create session
</Button>
</Grid>
</Paper>
</Grid>
); );
}; };

View File

@ -6,7 +6,7 @@ export const SchedulingAction = (props: { session: Session }) => {
const { status, id } = session; const { status, id } = session;
if (status === "CANCELLED" || status === "CLOSED") { if (status === "CANCELLED" || status === "CLOSED") {
return ("N/A"); return "N/A";
} }
if (status === "SCHEDULED") { if (status === "SCHEDULED") {
@ -15,7 +15,7 @@ export const SchedulingAction = (props: { session: Session }) => {
variant="contained" variant="contained"
color="primary" color="primary"
sx={{ width: "100%" }} sx={{ width: "100%" }}
onClick={() => openSession(id)} onClick={() => openSession(id).then(() => window.location.reload())}
> >
OPEN OPEN
</Button> </Button>
@ -28,7 +28,7 @@ export const SchedulingAction = (props: { session: Session }) => {
variant="contained" variant="contained"
color="primary" color="primary"
sx={{ width: "100%" }} sx={{ width: "100%" }}
onClick={() => closeSession(id)} onClick={() => closeSession(id).then(() => window.location.reload())}
> >
CLOSE CLOSE
</Button> </Button>