From d7f550a66376b836ed8737c979b801984562ba16 Mon Sep 17 00:00:00 2001 From: Rehan Khalil <rehkha@utu.fi> Date: Thu, 27 Jun 2024 12:28:16 +0300 Subject: [PATCH] feature: Specific room calendar based on dynamic url, updated readme, improvised UI and fixed ui bug to show dates if title of event is missing --- README.md | 25 +- package-lock.json | 564 +----------------- package.json | 10 +- public/assets/calendar.png | Bin 0 -> 1553 bytes public/assets/dashboard.png | Bin 0 -> 323 bytes public/assets/eventlogo.png | Bin 0 -> 1675 bytes public/assets/illustrations/notfound.svg | 40 ++ public/assets/info.png | Bin 0 -> 1367 bytes public/assets/ongoingevent.png | Bin 0 -> 2667 bytes public/assets/share.png | Bin 0 -> 898 bytes public/assets/today.png | Bin 0 -> 1761 bytes src/App.jsx | 10 +- .../Calendar/CustomMonthEventView.jsx | 18 + src/components/Calendar/FullCalendar.jsx | 9 +- .../DateAndStatus/DateAndStatus.jsx | 3 +- src/components/ErrorMessage.jsx | 43 ++ src/components/NavBar.jsx | 26 +- src/components/TimeSlot.jsx | 17 +- src/components/TodayAvailableSlots.jsx | 46 +- src/components/TodayMeetings.jsx | 23 +- src/i18n/en.js | 9 +- src/i18n/fi.js | 7 +- src/pages/HomePage/HomePage.jsx | 154 +++-- src/pages/NotFound/NotFoundPage.jsx | 54 ++ src/store/store.js | 9 - src/withAppProvider.jsx | 5 +- 26 files changed, 401 insertions(+), 671 deletions(-) create mode 100644 public/assets/calendar.png create mode 100644 public/assets/dashboard.png create mode 100644 public/assets/eventlogo.png create mode 100644 public/assets/illustrations/notfound.svg create mode 100644 public/assets/info.png create mode 100644 public/assets/ongoingevent.png create mode 100644 public/assets/share.png create mode 100644 public/assets/today.png create mode 100644 src/components/Calendar/CustomMonthEventView.jsx create mode 100644 src/components/ErrorMessage.jsx create mode 100644 src/pages/NotFound/NotFoundPage.jsx diff --git a/README.md b/README.md index 1f47c3b..bc3c107 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,33 @@ # Meeting Room Calendar Viewer -View room reservation status on the go from anywhere. +View room reservation status on the go from anywhere. Allows users to view today's meetings, check available time slots, and navigate through upcoming or previous meetings on an interactive calendar. +## API Reference + +#### Standard API for any room calendar + +```http + GET https://tt.utu.fi/rooms/api/{room} + +``` + +where `room` can be any. For example, ag408, ag407a, ag407b etc. + +#### Standard Room Url Format + +```http +https://tt.utu.fi/rooms/?room={any} +``` + +| Parameter | Type | Description | +| :-------- | :------- | :---------------------------------------------------------------------------------------------------------------------------------- | +| `room` | `string` | **Required**. Specific room identifier with respect to Calendar API for that specific room. For example, ag408, ag407a, ag407b etc. | + ## Demo -https://flavoria.fi/reservations +https://tt.utu.fi/rooms/?room=ag408 ## Run Locally diff --git a/package-lock.json b/package-lock.json index 0496839..5932b41 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,29 +16,23 @@ "@mui/material": "^5.15.16", "@reduxjs/toolkit": "^2.2.3", "@vitejs/plugin-legacy": "^5.4.1", - "apexcharts": "^3.49.0", "axios": "^1.7.1", "date-fns": "^3.6.0", - "framer-motion": "^11.1.8", "i18next": "^23.11.3", "lottie-react": "^2.4.0", "moment": "^2.30.1", "qrcode.react": "^3.1.0", "react": "^18.2.0", - "react-apexcharts": "^1.4.1", "react-big-calendar": "^1.12.2", "react-device-detect": "^2.2.3", "react-dom": "^18.2.0", + "react-helmet-async": "^2.0.5", "react-i18next": "^14.1.1", - "react-lottie": "^1.2.4", "react-player": "^2.16.0", "react-redux": "^9.1.2", "react-responsive-carousel": "^3.2.23", "react-router-dom": "^6.23.0", - "react-share": "^5.1.0", - "recharts": "^2.12.6", - "redux-logger": "^3.0.6", - "socket.io-client": "^4.7.5" + "react-share": "^5.1.0" }, "devDependencies": { "@types/react": "^18.2.66", @@ -2966,11 +2960,6 @@ "win32" ] }, - "node_modules/@socket.io/component-emitter": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", - "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==" - }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -3012,60 +3001,6 @@ "@babel/types": "^7.20.7" } }, - "node_modules/@types/d3-array": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz", - "integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==" - }, - "node_modules/@types/d3-color": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", - "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==" - }, - "node_modules/@types/d3-ease": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", - "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==" - }, - "node_modules/@types/d3-interpolate": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", - "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", - "dependencies": { - "@types/d3-color": "*" - } - }, - "node_modules/@types/d3-path": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.0.tgz", - "integrity": "sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ==" - }, - "node_modules/@types/d3-scale": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.8.tgz", - "integrity": "sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==", - "dependencies": { - "@types/d3-time": "*" - } - }, - "node_modules/@types/d3-shape": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.6.tgz", - "integrity": "sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA==", - "dependencies": { - "@types/d3-path": "*" - } - }, - "node_modules/@types/d3-time": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.3.tgz", - "integrity": "sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw==" - }, - "node_modules/@types/d3-timer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", - "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==" - }, "node_modules/@types/estree": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", @@ -3177,11 +3112,6 @@ "vite": "^4.2.0 || ^5.0.0" } }, - "node_modules/@yr/monotone-cubic-spline": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@yr/monotone-cubic-spline/-/monotone-cubic-spline-1.0.3.tgz", - "integrity": "sha512-FQXkOta0XBSUPHndIKON2Y9JeQz5ZeMqLYZVVK93FliNBFm7LNMIZmY6FrMEB9XPcDbE2bekMbZD6kzDkxwYjA==" - }, "node_modules/acorn": { "version": "8.11.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", @@ -3257,20 +3187,6 @@ "node": ">= 8" } }, - "node_modules/apexcharts": { - "version": "3.49.1", - "resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-3.49.1.tgz", - "integrity": "sha512-MqGtlq/KQuO8j0BBsUJYlRG8VBctKwYdwuBtajHgHTmSgUU3Oai+8oYN/rKCXwXzrUlYA+GiMgotAIbXY2BCGw==", - "dependencies": { - "@yr/monotone-cubic-spline": "^1.0.3", - "svg.draggable.js": "^2.2.2", - "svg.easing.js": "^2.0.0", - "svg.filter.js": "^2.0.2", - "svg.pathmorphing.js": "^0.1.3", - "svg.resize.js": "^1.4.3", - "svg.select.js": "^3.0.1" - } - }, "node_modules/arg": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", @@ -3539,20 +3455,6 @@ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==", - "dependencies": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - } - }, - "node_modules/babel-runtime/node_modules/regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -3816,13 +3718,6 @@ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" }, - "node_modules/core-js": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", - "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", - "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", - "hasInstallScript": true - }, "node_modules/core-js-compat": { "version": "3.37.1", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", @@ -3881,116 +3776,6 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, - "node_modules/d3-array": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", - "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", - "dependencies": { - "internmap": "1 - 2" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-color": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", - "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-ease": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", - "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-format": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", - "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-interpolate": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", - "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", - "dependencies": { - "d3-color": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-path": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", - "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-scale": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", - "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", - "dependencies": { - "d3-array": "2.10.0 - 3", - "d3-format": "1 - 3", - "d3-interpolate": "1.2.0 - 3", - "d3-time": "2.1.1 - 3", - "d3-time-format": "2 - 4" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-shape": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", - "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", - "dependencies": { - "d3-path": "^3.1.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-time": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", - "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", - "dependencies": { - "d3-array": "2 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-time-format": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", - "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", - "dependencies": { - "d3-time": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-timer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", - "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", - "engines": { - "node": ">=12" - } - }, "node_modules/data-view-buffer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", @@ -4077,16 +3862,6 @@ } } }, - "node_modules/decimal.js-light": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", - "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==" - }, - "node_modules/deep-diff": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/deep-diff/-/deep-diff-0.3.8.tgz", - "integrity": "sha512-yVn6RZmHiGnxRKR9sJb3iVV2XTF1Ghh2DiWRZ3dMnGc43yUdWWF/kX6lQyk3+P84iprfWKU/8zFTrlkvtFm1ug==" - }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -4201,26 +3976,6 @@ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true }, - "node_modules/engine.io-client": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.3.tgz", - "integrity": "sha512-9Z0qLB0NIisTRt1DZ/8U2k12RJn8yls/nXMZLn+/N8hANT3TcYjKFKcwbw5zFQiN4NTde3TSY9zb79e1ij6j9Q==", - "dependencies": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.1", - "engine.io-parser": "~5.2.1", - "ws": "~8.11.0", - "xmlhttprequest-ssl": "~2.0.0" - } - }, - "node_modules/engine.io-parser": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz", - "integrity": "sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==", - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -4751,25 +4506,12 @@ "node": ">=0.10.0" } }, - "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, - "node_modules/fast-equals": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.0.1.tgz", - "integrity": "sha512-WF1Wi8PwwSY7/6Kx0vKXtw8RwuSGoM1bvDaJbu7MxDlR1vovZjIAKrnzyrThgAjm6JDTu0fVgWXDlMGspodfoQ==", - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", @@ -4954,30 +4696,6 @@ "url": "https://github.com/sponsors/rawify" } }, - "node_modules/framer-motion": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.2.0.tgz", - "integrity": "sha512-LRfLVPEwtO9IXJCAsWvtj3XZxrdZDcTxNNkZEq30aQ8p7/wimfUkDy67TDWdtzPiyKDkqOHDhaQC6XVrQ4Fh7A==", - "dependencies": { - "tslib": "^2.4.0" - }, - "peerDependencies": { - "@emotion/is-prop-valid": "*", - "react": "^18.0.0", - "react-dom": "^18.0.0" - }, - "peerDependenciesMeta": { - "@emotion/is-prop-valid": { - "optional": true - }, - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } - } - }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -5349,14 +5067,6 @@ "node": ">= 0.4" } }, - "node_modules/internmap": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", - "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", - "engines": { - "node": ">=12" - } - }, "node_modules/invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", @@ -6723,18 +6433,6 @@ "node": ">=0.10.0" } }, - "node_modules/react-apexcharts": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/react-apexcharts/-/react-apexcharts-1.4.1.tgz", - "integrity": "sha512-G14nVaD64Bnbgy8tYxkjuXEUp/7h30Q0U33xc3AwtGFijJB9nHqOt1a6eG0WBn055RgRg+NwqbKGtqPxy15d0Q==", - "dependencies": { - "prop-types": "^15.8.1" - }, - "peerDependencies": { - "apexcharts": "^3.41.0", - "react": ">=0.13" - } - }, "node_modules/react-big-calendar": { "version": "1.12.2", "resolved": "https://registry.npmjs.org/react-big-calendar/-/react-big-calendar-1.12.2.tgz", @@ -6815,6 +6513,19 @@ "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==" }, + "node_modules/react-helmet-async": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-2.0.5.tgz", + "integrity": "sha512-rYUYHeus+i27MvFE+Jaa4WsyBKGkL6qVgbJvSBoX8mbsWoABJXdEO0bZyi0F6i+4f0NuIb8AvqPMj3iXFHkMwg==", + "dependencies": { + "invariant": "^2.2.4", + "react-fast-compare": "^3.2.2", + "shallowequal": "^1.1.0" + }, + "peerDependencies": { + "react": "^16.6.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-i18next": { "version": "14.1.1", "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-14.1.1.tgz", @@ -6846,21 +6557,6 @@ "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" }, - "node_modules/react-lottie": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/react-lottie/-/react-lottie-1.2.4.tgz", - "integrity": "sha512-kBGxI+MIZGBf4wZhNCWwHkMcVP+kbpmrLWH/SkO0qCKc7D7eSPcxQbfpsmsCo8v2KCBYjuGSou+xTqK44D/jMg==", - "dependencies": { - "babel-runtime": "^6.26.0", - "lottie-web": "^5.1.3" - }, - "engines": { - "npm": "^3.0.0" - }, - "peerDependencies": { - "react": ">=15.0.0" - } - }, "node_modules/react-overlays": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/react-overlays/-/react-overlays-5.2.1.tgz", @@ -6978,20 +6674,6 @@ "react": "^17 || ^18" } }, - "node_modules/react-smooth": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.1.tgz", - "integrity": "sha512-OE4hm7XqR0jNOq3Qmk9mFLyd6p2+j6bvbPJ7qlB7+oo0eNcL2l7WQzG6MBnT3EXY6xzkLMUBec3AfewJdA0J8w==", - "dependencies": { - "fast-equals": "^5.0.1", - "prop-types": "^15.8.1", - "react-transition-group": "^4.4.5" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, "node_modules/react-transition-group": { "version": "4.4.5", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", @@ -7028,54 +6710,11 @@ "node": ">=8.10.0" } }, - "node_modules/recharts": { - "version": "2.12.7", - "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.12.7.tgz", - "integrity": "sha512-hlLJMhPQfv4/3NBSAyq3gzGg4h2v69RJh6KU7b3pXYNNAELs9kEoXOjbkxdXpALqKBoVmVptGfLpxdaVYqjmXQ==", - "dependencies": { - "clsx": "^2.0.0", - "eventemitter3": "^4.0.1", - "lodash": "^4.17.21", - "react-is": "^16.10.2", - "react-smooth": "^4.0.0", - "recharts-scale": "^0.4.4", - "tiny-invariant": "^1.3.1", - "victory-vendor": "^36.6.8" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "react": "^16.0.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/recharts-scale": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.5.tgz", - "integrity": "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==", - "dependencies": { - "decimal.js-light": "^2.4.1" - } - }, - "node_modules/recharts/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, "node_modules/redux": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==" }, - "node_modules/redux-logger": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/redux-logger/-/redux-logger-3.0.6.tgz", - "integrity": "sha512-JoCIok7bg/XpqA1JqCqXFypuqBbQzGQySrhFzewB7ThcnysTO30l4VCst86AuB9T9tuT03MAA56Jw2PNhRSNCg==", - "dependencies": { - "deep-diff": "^0.3.5" - } - }, "node_modules/redux-thunk": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz", @@ -7381,6 +7020,11 @@ "node": ">= 0.4" } }, + "node_modules/shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -7432,32 +7076,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/socket.io-client": { - "version": "4.7.5", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.5.tgz", - "integrity": "sha512-sJ/tqHOCe7Z50JCBCXrsY3I2k03iOiUe+tj1OmKeD2lXPiGH/RUCdTZFoqVyN7l1MnpIzPrGtLcijffmeouNlQ==", - "dependencies": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.2", - "engine.io-client": "~6.5.2", - "socket.io-parser": "~4.2.4" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/socket.io-parser": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", - "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", - "dependencies": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.1" - }, - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -7765,89 +7383,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/svg.draggable.js": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/svg.draggable.js/-/svg.draggable.js-2.2.2.tgz", - "integrity": "sha512-JzNHBc2fLQMzYCZ90KZHN2ohXL0BQJGQimK1kGk6AvSeibuKcIdDX9Kr0dT9+UJ5O8nYA0RB839Lhvk4CY4MZw==", - "dependencies": { - "svg.js": "^2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/svg.easing.js": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/svg.easing.js/-/svg.easing.js-2.0.0.tgz", - "integrity": "sha512-//ctPdJMGy22YoYGV+3HEfHbm6/69LJUTAqI2/5qBvaNHZ9uUFVC82B0Pl299HzgH13rKrBgi4+XyXXyVWWthA==", - "dependencies": { - "svg.js": ">=2.3.x" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/svg.filter.js": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/svg.filter.js/-/svg.filter.js-2.0.2.tgz", - "integrity": "sha512-xkGBwU+dKBzqg5PtilaTb0EYPqPfJ9Q6saVldX+5vCRy31P6TlRCP3U9NxH3HEufkKkpNgdTLBJnmhDHeTqAkw==", - "dependencies": { - "svg.js": "^2.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/svg.js": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/svg.js/-/svg.js-2.7.1.tgz", - "integrity": "sha512-ycbxpizEQktk3FYvn/8BH+6/EuWXg7ZpQREJvgacqn46gIddG24tNNe4Son6omdXCnSOaApnpZw6MPCBA1dODA==" - }, - "node_modules/svg.pathmorphing.js": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/svg.pathmorphing.js/-/svg.pathmorphing.js-0.1.3.tgz", - "integrity": "sha512-49HWI9X4XQR/JG1qXkSDV8xViuTLIWm/B/7YuQELV5KMOPtXjiwH4XPJvr/ghEDibmLQ9Oc22dpWpG0vUDDNww==", - "dependencies": { - "svg.js": "^2.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/svg.resize.js": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/svg.resize.js/-/svg.resize.js-1.4.3.tgz", - "integrity": "sha512-9k5sXJuPKp+mVzXNvxz7U0uC9oVMQrrf7cFsETznzUDDm0x8+77dtZkWdMfRlmbkEEYvUn9btKuZ3n41oNA+uw==", - "dependencies": { - "svg.js": "^2.6.5", - "svg.select.js": "^2.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/svg.resize.js/node_modules/svg.select.js": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/svg.select.js/-/svg.select.js-2.1.2.tgz", - "integrity": "sha512-tH6ABEyJsAOVAhwcCjF8mw4crjXSI1aa7j2VQR8ZuJ37H2MBUbyeqYr5nEO7sSN3cy9AR9DUwNg0t/962HlDbQ==", - "dependencies": { - "svg.js": "^2.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/svg.select.js": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/svg.select.js/-/svg.select.js-3.0.1.tgz", - "integrity": "sha512-h5IS/hKkuVCbKSieR9uQCj9w+zLHoPh+ce19bBYyqF53g6mnPB8sAtIbe1s9dh2S2fCmYX2xel1Ln3PJBbK4kw==", - "dependencies": { - "svg.js": "^2.6.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/systemjs": { "version": "6.15.1", "resolved": "https://registry.npmjs.org/systemjs/-/systemjs-6.15.1.tgz", @@ -7941,11 +7476,6 @@ "node": ">=0.8" } }, - "node_modules/tiny-invariant": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", - "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==" - }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -7972,11 +7502,6 @@ "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", "dev": true }, - "node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -8213,27 +7738,6 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, - "node_modules/victory-vendor": { - "version": "36.9.2", - "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.9.2.tgz", - "integrity": "sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==", - "dependencies": { - "@types/d3-array": "^3.0.3", - "@types/d3-ease": "^3.0.0", - "@types/d3-interpolate": "^3.0.1", - "@types/d3-scale": "^4.0.2", - "@types/d3-shape": "^3.1.0", - "@types/d3-time": "^3.0.0", - "@types/d3-timer": "^3.0.0", - "d3-array": "^3.1.6", - "d3-ease": "^3.0.1", - "d3-interpolate": "^3.0.1", - "d3-scale": "^4.0.2", - "d3-shape": "^3.1.0", - "d3-time": "^3.0.0", - "d3-timer": "^3.0.1" - } - }, "node_modules/vite": { "version": "5.2.11", "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.11.tgz", @@ -8540,34 +8044,6 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, - "node_modules/ws": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", - "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xmlhttprequest-ssl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", - "integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==", - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", diff --git a/package.json b/package.json index 293a801..7e12b83 100644 --- a/package.json +++ b/package.json @@ -18,29 +18,23 @@ "@mui/material": "^5.15.16", "@reduxjs/toolkit": "^2.2.3", "@vitejs/plugin-legacy": "^5.4.1", - "apexcharts": "^3.49.0", "axios": "^1.7.1", "date-fns": "^3.6.0", - "framer-motion": "^11.1.8", "i18next": "^23.11.3", "lottie-react": "^2.4.0", "moment": "^2.30.1", "qrcode.react": "^3.1.0", "react": "^18.2.0", - "react-apexcharts": "^1.4.1", "react-big-calendar": "^1.12.2", "react-device-detect": "^2.2.3", "react-dom": "^18.2.0", + "react-helmet-async": "^2.0.5", "react-i18next": "^14.1.1", - "react-lottie": "^1.2.4", "react-player": "^2.16.0", "react-redux": "^9.1.2", "react-responsive-carousel": "^3.2.23", "react-router-dom": "^6.23.0", - "react-share": "^5.1.0", - "recharts": "^2.12.6", - "redux-logger": "^3.0.6", - "socket.io-client": "^4.7.5" + "react-share": "^5.1.0" }, "devDependencies": { "@types/react": "^18.2.66", diff --git a/public/assets/calendar.png b/public/assets/calendar.png new file mode 100644 index 0000000000000000000000000000000000000000..6fc1ab18160a69fa086eded4ae68d060aeac57e3 GIT binary patch literal 1553 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 NgQu&X%Q~loCID5N?gan< literal 0 HcmV?d00001 diff --git a/public/assets/dashboard.png b/public/assets/dashboard.png new file mode 100644 index 0000000000000000000000000000000000000000..101b28440a37b3119bb3d66d6fe1d2d833aaefd6 GIT binary patch literal 323 zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4mJh`hH$2z?F<YIoCO|{#S9GG!XV7ZFl&wk z0|UcXPZ!6KiaBp*oaSvd5O8^^^zGz~tfmb0LMhI5+B;YlG%}PcEvXSHcGzad&GmW7 z-gRjv*_$mq85j~K%jm5WIJWiD4#Oo!Zkiqn*?C`I`+ck4?y%c+JS(r1^=>-6=DyP8 z2>~DTg_o`RTL)tON=~|#KQZFt`cJ=)c3nT;#MsGF)e|6KapZqlua@-_L$#pWS6^Al zgqt7eYiXQ1(c{7P+q%_ES8nU>X8bmBiopk7A&%Bx7dEOZ_)I-MW5$v0%emWjKiIv= z%p;+kGv$bW<{P%4NAV72%(H$-vamThGRa9SyxSY#Rnxoae~{Lr=_aq<iZL)u^8LVI Y%yFjW%tMAu1_lNOPgg&ebxsLQ08eR!W&i*H literal 0 HcmV?d00001 diff --git a/public/assets/eventlogo.png b/public/assets/eventlogo.png new file mode 100644 index 0000000000000000000000000000000000000000..ca82e194a383d4ffd03fce50b754d1fd89eb7ab4 GIT binary patch literal 1675 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 literal 0 HcmV?d00001 diff --git a/public/assets/illustrations/notfound.svg b/public/assets/illustrations/notfound.svg new file mode 100644 index 0000000..bd59d64 --- /dev/null +++ b/public/assets/illustrations/notfound.svg @@ -0,0 +1,40 @@ +<svg width="480" height="360" fill="none" xmlns="http://www.w3.org/2000/svg"> + <path fill-rule="evenodd" clip-rule="evenodd" + d="M0 198.781c0 41.457 14.945 79.235 39.539 107.785 28.214 32.765 69.128 53.365 114.734 53.434a148.458 148.458 0 0056.495-11.036c9.051-3.699 19.182-3.274 27.948 1.107a75.774 75.774 0 0033.957 8.011c5.023 0 9.942-.495 14.7-1.434 13.581-2.67 25.94-8.99 36.089-17.94 6.379-5.627 14.548-8.456 22.898-8.446h.142c27.589 0 53.215-8.732 74.492-23.696 19.021-13.36 34.554-31.696 44.904-53.225C474.92 234.581 480 213.388 480 190.958c0-76.931-59.774-139.305-133.498-139.305-7.516 0-14.88.663-22.063 1.899C305.418 21.42 271.355 0 232.498 0a103.647 103.647 0 00-45.879 10.661c-13.24 6.487-25.011 15.705-34.641 26.939-32.697.544-62.93 11.69-87.675 30.291C25.351 97.155 0 144.882 0 198.781z" + fill="url(#prefix__paint0_linear)" opacity=".2" /> + <g filter="url(#prefix__filter0_d)"> + <circle opacity=".15" cx="182.109" cy="97.623" r="44.623" fill="#FFC107" /> + <circle cx="182.109" cy="97.623" r="23.406" fill="url(#prefix__paint1_linear)" /> + <path fill-rule="evenodd" clip-rule="evenodd" + d="M244.878 306.611c34.56 0 62.575-28.016 62.575-62.575 0-34.56-28.015-62.576-62.575-62.576-34.559 0-62.575 28.016-62.575 62.576 0 34.559 28.016 62.575 62.575 62.575zm0-23.186c21.754 0 39.389-17.635 39.389-39.389 0-21.755-17.635-39.39-39.389-39.39s-39.389 17.635-39.389 39.39c0 21.754 17.635 39.389 39.389 39.389z" + fill="#061B64" /> + <path fill-rule="evenodd" clip-rule="evenodd" + d="M174.965 264.592c0-4.133-1.492-5.625-5.637-5.625h-11.373v-66.611c0-4.476-1.492-5.637-5.638-5.637h-9.172a9.866 9.866 0 00-7.948 3.974l-55.03 68.274a11.006 11.006 0 00-1.957 6.787v5.968c0 4.145 1.492 5.637 5.625 5.637h54.676v21.707c0 4.133 1.492 5.625 5.625 5.625h8.12c4.146 0 5.638-1.492 5.638-5.625v-21.707h11.434c4.414 0 5.637-1.492 5.637-5.637v-7.13zm-72.42-5.625l35.966-44.415v44.415h-35.966zM411.607 264.592c0-4.133-1.492-5.625-5.638-5.625h-11.422v-66.611c0-4.476-1.492-5.637-5.637-5.637h-9.111a9.87 9.87 0 00-7.949 3.974l-55.03 68.274a11.011 11.011 0 00-1.981 6.787v5.968c0 4.145 1.492 5.637 5.626 5.637h54.687v21.707c0 4.133 1.492 5.625 5.626 5.625h8.12c4.145 0 5.637-1.492 5.637-5.625v-21.707h11.434c4.476 0 5.638-1.492 5.638-5.637v-7.13zm-72.42-5.625l35.965-44.415v44.415h-35.965z" + fill="#2065D1" /> + <path opacity=".24" + d="M425.621 117.222a8.267 8.267 0 00-9.599-8.157 11.129 11.129 0 00-9.784-5.87h-.403a13.23 13.23 0 00-20.365-14.078 13.23 13.23 0 00-5.316 14.078h-.403a11.153 11.153 0 100 22.293h38.68v-.073a8.279 8.279 0 007.19-8.193zM104.258 199.045a7.093 7.093 0 00-7.093-7.092c-.381.007-.761.039-1.138.097a9.552 9.552 0 00-8.425-5.026h-.343a11.348 11.348 0 10-22.012 0h-.342a9.564 9.564 0 100 19.114h33.177v-.061a7.107 7.107 0 006.176-7.032z" + fill="#2065D1" /> + </g> + <defs> + <linearGradient id="prefix__paint0_linear" x1="328.81" y1="424.032" x2="505.393" y2="26.048" + gradientUnits="userSpaceOnUse"> + <stop stop-color="#2065D1" /> + <stop offset="1" stop-color="#2065D1" stop-opacity=".01" /> + </linearGradient> + <linearGradient id="prefix__paint1_linear" x1="135.297" y1="97.623" x2="182.109" y2="144.436" + gradientUnits="userSpaceOnUse"> + <stop stop-color="#FFE16A" /> + <stop offset="1" stop-color="#B78103" /> + </linearGradient> + <filter id="prefix__filter0_d" x="51" y="49" width="394.621" height="277.611" filterUnits="userSpaceOnUse" + color-interpolation-filters="sRGB"> + <feFlood flood-opacity="0" result="BackgroundImageFix" /> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" /> + <feOffset dx="8" dy="8" /> + <feGaussianBlur stdDeviation="6" /> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.12 0" /> + <feBlend in2="BackgroundImageFix" result="effect1_dropShadow" /> + <feBlend in="SourceGraphic" in2="effect1_dropShadow" result="shape" /> + </filter> + </defs> +</svg> diff --git a/public/assets/info.png b/public/assets/info.png new file mode 100644 index 0000000000000000000000000000000000000000..75ffe11e0e80ad0abda0b0c6be6bf4fbec510a10 GIT binary patch literal 1367 zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4mJh`hH$2z?F<YIoCO|{#S9GG!XV7ZFl&wk z0|P6kr;B4q#hkY@Jbk3YC62d;<#wGF+IC~ju{1+#i7O#{zg%+GxBVLQ^@8{9kX0co zgRZU!)n?tAq%N`feWLM<84k_Nd<kp3LW8%8Rx23X3pbdVcx>gO1sYoMrgpai+0RR_ zk^A9YEc>@E|K9g!zvbFupD2kxRL%caq_Qr;?%#@<&Rvn)JanhL><{-A_wfG6l&L#U zJ-oa0$X_Mdi%~0-?au9XUzYs8J>=z{rcbHAW*u_)AGWciCTgFH<4+~l)bITZL+W`{ zxmBi|nH*5l-=HMR*jmgYa<7($)!v@%=bMZ1tmS?CrrcLeQs#?W(t2IH_e<$fuF@q2 z7Xmi=IL`Q>FyFH2kG1;*^S6tOw(gUbj0!Jtc_7-Rp06GD!uBW^ugwAHb=TN;Zs&Jg zX1U>{$-eUQqWdm+)Gv-$82^EHzVT5GnWmgezxzYp{uN~Icr;x`Vb!G<`72F+J^b^4 z-@&So;bxY;$1&SitM*;JUh#On(XY^n&EK0+&TvO6=kbQ|uK&RJKlaE&ciRb;j~aUt z!<mKl9P-$Exb*z#t$8PcXDjC4;i;4oXRk0%;o0eTxy|N%ant#$hnIRO_ZBzmU%KJ& zw}au;6W0fl_Z1cD?+D5L(KTPfzf&>y!qdq-xAog~19m>ze=zgua@&B<#~E3kFK3UN zurl`HA?I5S+(Ex(Pi=Ux{?$o~*2YCU-~9ZesqSN^<jkU0#xbGqmgNC!$1AUGJYN+o zn;YqnxM2UYs0}}(^kbsSS~zMJZEr5QBWkv1hrR;CqCEGrGg-B!z0{p@S<OAS`TTU5 z0&#Wb^UHbuY-qKv>1PhwC3DVLc6Dl-`p-QwQ>FM%xaBIyZfx{<>(;dY(piohiW@I~ z6Z`#2dWC+#!{TFWCfIJ^p7bwv!k4!WVek1o+Rk`<I61e>BX4`%`G2fp{q2GEK|D1D zM!V$~9W1}0u<@)_IUD1v@+<Z_n_nq1#oqS#;Q7|fBOvno4c0G9gtyvG_+rN+c;dw! zrzZcLWELI&NLH_}Dy_F}r+jVUT2h{)cu;-Snh6WG%t?x>_-fDE^_<f_D|y<@y|PLZ zu5IjOyPws1+KW3OC%5dR%}dv}TJc&J_I2{e-%qkjyz6w-Dv5ckY8scB#md~-9UsIx zvdyd`S-YNfXkMwCr+MQ+N2s*NhmU8)I&w|)H*$%b5xl>MPub^S8^@MBg@eaUXG%7@ zebYDaj&q&6WJVKjpU2KVF8(IA&(&*~&KRoB|5~}Dzww>JLAK{!r>%tcY+(GJeD$08 z4ORo5$>)Da?L1`ct{S}Ipy$q==Opcx9b`FFRU=@Xof4HF_HN62OYw?lD^j@3TozRJ z8rS&9)@iM|tAF^A=egYbx_!nu3lf?q-`R4Eci%mhLs6G?#PXI*whQcgHsP7k;jSqQ znLK@8%RKy;KK)f;<P9dqPR{%3bJA|~?L9CreH-uQPoBNm6PDcJmEU)crAg|KRokST zuLo6LsT|FG`r1bzcJuy*8vj!<)!xT!_PfdK6T9EH{#k+imrVxZ-ZPcou?xoh^mV-4 zC-K;LWo?|}u?^X3Odq^Cd9PKxiD43$YWL!wR_TGCZ)6_K=g#^dU$JvyTK9_kilW~w z(~s`$3$A<c@#u_Of0=YHdA{5@wY%y~vgX}y%O4(otZw*q*~%AIbN;S-e#h0SJV|Kx z8+n!Ox2-1M%BfddmGkdH;*n3~Ig2w*w;jBqzUKD-4}ZQ{`U{%MbG2%%_E=D|#Hgue h?{_8fgFnvhZ_PdP?7@Q-J`4;D44$rjF6*2Ung9=fg>C=< literal 0 HcmV?d00001 diff --git a/public/assets/ongoingevent.png b/public/assets/ongoingevent.png new file mode 100644 index 0000000000000000000000000000000000000000..6d8cba3a652463c905233b924d1e61f3fec46b5a GIT binary patch literal 2667 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 literal 0 HcmV?d00001 diff --git a/public/assets/share.png b/public/assets/share.png new file mode 100644 index 0000000000000000000000000000000000000000..b5e720386ad3c4437e8e3f1b05a676ba2f34c550 GIT binary patch literal 898 zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4mJh`hH$2z?F<YIoCO|{#S9GG!XV7ZFl&wk z0|T>(r;B4q#hkY@;yr=`Wsc{&I{E|$w@0XG&0IQr<wX670&e<Wh0e`0c@-x<^Tph0 z%f8?8($0>UxhO$x;w|}>iKbIRnmQJ(_`~d!x$dX_cC(rFX7VZ-`z@HW`Cq*|T3W96 zhWq))L+!=q=b!&6)S|zy!~T=r?vniTZ$f{1XV=%XmnNR?e%X2>{n<W=wL6u(vL^{y zsQ<h=M`>gAwP_bjnK$`qA9=Yfv3xgcS?1Xdo8PLt*qYr^itc&IvhRa&-_!?-=g&~s zbd^Jpzusb-sqeDn?Kwi>Gk@;?a5i|u--9YG=6+||O(mT<W16njFopm4Ei7=&fNx>x z;-@Tn6U!sne;n|BeOzJ3wF~YKgd*Foo@2LLQYO;0ir0*(UE|6t-;ZyXx!Qe*Ud<~I zuyp=+tsOxt?|7`dvF6O?=f@|_Vy`^Ne(zHA|FeScbrf5jHZnE_Ydy1Gn)EOvj&n)Y zmOT%)XSg{OCI9HU@aDD0t}ha<#>^ZwnG;NyB`bN3Z0Y&jIRA4ne=CREJYVBXk+U^r ztmU#V^kp>Hx=)`HU9taE;_+wMhmW%|hKm`nd(5ibE41TuLCUk37gO%m1wYxdBy47- z<AbR`Q#Do2zOZOuUYS(A;?SliOY<-CcI&NtAmyBYLAKd;fmi<b>ou=kv+I0Mw{@$| zJEz^bJYyU0*%j3l&vLh|(wTbTpwMD@e_fefcRsy)vUAb>cj<F}HkfTzcwnO|$QQq+ zIPXO2!_2Y?Itd~#Oq2??9+Bm(I&mU(j{D>N$&>zeovYm%wRfICv+A;#s#kxwRnAHY zSnS%tVHlaz^6c^YHO8$wJw!S3-PO{(T{<sE<}BLma{b7*=wCmhk}7^y*GvoOxfXNq zy3pjV=#Mv#1V&B15}8`i!oSCkqic>(O<$nMmBS0PnwwRfv}(oIcjsuXXpcNA^jE9> zjpiyho6x3y)g<j=r&n8Kmgh}*-~8;sV*jHNWs76xO>x(L=a}@J=fR!cbw5_vPdtBU zpPzBZBI($5VV<ii&&kS7&%3hq#;yC`TE%U`?rN+Odunxh(fO*QX?y?Od*x=Ex>rcQ zWU<`lxXufASG2Fat{7qdD)aSJj;p=vR1^QNmi~HF{7~*ch7Zz9WM-Qlz0JVDz~JfX K=d#Wzp$PzGxT+KY literal 0 HcmV?d00001 diff --git a/public/assets/today.png b/public/assets/today.png new file mode 100644 index 0000000000000000000000000000000000000000..1e10f745af501c3e8c03b050b6c0ed44832ddb4d GIT binary patch literal 1761 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 literal 0 HcmV?d00001 diff --git a/src/App.jsx b/src/App.jsx index 65d177c..d5f9e20 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,8 +1,14 @@ import React, { useEffect, useState } from "react"; import { withAppProvider } from "./withAppProvider"; -import { BrowserRouter as Router, Route, Routes } from "react-router-dom"; +import { + BrowserRouter as Router, + Route, + Routes, + Navigate, +} from "react-router-dom"; import { HomePage } from "./pages/HomePage/HomePage"; import { Layout } from "./pages/Layout/Layout"; +import { NotFoundPage } from "./pages/NotFound/NotFoundPage"; const App = () => { return ( @@ -10,7 +16,9 @@ const App = () => { <Routes> <Route path="/" element={<Layout />}> <Route index element={<HomePage />} /> + <Route path="/404" element={<NotFoundPage />} /> </Route> + <Route path="*" element={<Navigate to="/404" replace />} /> </Routes> </Router> ); diff --git a/src/components/Calendar/CustomMonthEventView.jsx b/src/components/Calendar/CustomMonthEventView.jsx new file mode 100644 index 0000000..a90b698 --- /dev/null +++ b/src/components/Calendar/CustomMonthEventView.jsx @@ -0,0 +1,18 @@ +import { Typography } from "@mui/material"; +import moment from "moment"; +import { useSelector } from "react-redux"; +import { selectGlobalSlice } from "../../store/slices/globalSlice"; + +export const CustomMonthEventView = ({ event }) => { + const { selectedLanguage } = useSelector(selectGlobalSlice); + return event?.title ? ( + <Typography className="text-[0.7rem] md:text-xs font-bold"> + {event.title} + </Typography> + ) : ( + <Typography className="text-[0.6rem] md:text-[0.7rem] font-bold"> + {`${moment(event.start).locale(selectedLanguage).format("HH:mm")} - + ${moment(event.end).locale(selectedLanguage).format("HH:mm")}`} + </Typography> + ); +}; diff --git a/src/components/Calendar/FullCalendar.jsx b/src/components/Calendar/FullCalendar.jsx index a58f5fd..28cc783 100644 --- a/src/components/Calendar/FullCalendar.jsx +++ b/src/components/Calendar/FullCalendar.jsx @@ -23,6 +23,7 @@ import { useTranslation } from "react-i18next"; import { CustomToolbar } from "./CustomToolbar"; import { isWholeDayEvent } from "../../utils/isWholeDayEvent"; import { Grow } from "@mui/material"; +import { CustomMonthEventView } from "./CustomMonthEventView"; const locales = { "en-US": enUS, @@ -118,7 +119,13 @@ export const FullCalendar = ({ calendarData }) => { onSelectSlot={handleSelectSlot} startAccessor="start" showMultiDayTimes={true} - components={{ event: EventInfo, toolbar: CustomToolbar }} + components={{ + event: EventInfo, + toolbar: CustomToolbar, + month: { + event: CustomMonthEventView, + }, + }} endAccessor="end" defaultView={isMobile ? "day" : "week"} views={["month", "week", "day"]} diff --git a/src/components/DateAndStatus/DateAndStatus.jsx b/src/components/DateAndStatus/DateAndStatus.jsx index a2dd299..406582b 100644 --- a/src/components/DateAndStatus/DateAndStatus.jsx +++ b/src/components/DateAndStatus/DateAndStatus.jsx @@ -9,7 +9,6 @@ import redSignal from "../../animations/redsignal.json"; import { getCurrentReservationStatus } from "../../utils/getCurrentReservationStatus"; import Lottie from "lottie-react"; import loader from "../../animations/loader.json"; -import { isMobile } from "react-device-detect"; export const DateAndStatus = ({ todayEvents }) => { const { t } = useTranslation(); @@ -87,7 +86,7 @@ export const DateAndStatus = ({ todayEvents }) => { </Grow> </div> - <Divider flexItem /> + <Divider className="border-dashed" flexItem /> </div> ); }; diff --git a/src/components/ErrorMessage.jsx b/src/components/ErrorMessage.jsx new file mode 100644 index 0000000..aae1df1 --- /dev/null +++ b/src/components/ErrorMessage.jsx @@ -0,0 +1,43 @@ +import { Box, Button, Container, Typography } from "@mui/material"; +import React from "react"; +import { useTranslation } from "react-i18next"; +import { useNavigate } from "react-router-dom"; + +export const ErrorMessage = () => { + const { t } = useTranslation(); + return ( + <Container> + <Box + sx={{ + py: 12, + maxWidth: 480, + mx: "auto", + display: "flex", + minHeight: "100vh", + textAlign: "center", + alignItems: "center", + flexDirection: "column", + justifyContent: "center", + }} + > + <Typography variant="h3" sx={{ mb: 3 }}> + {t("sorry_room_not_found_title")} + </Typography> + + <Typography sx={{ color: "text.secondary" }}> + {t("sorry_room_not_found_detail")} + </Typography> + + <Box + component="img" + src="/assets/illustrations/notfound.svg" + sx={{ + mx: "auto", + height: 260, + my: { xs: 5, sm: 10 }, + }} + /> + </Box> + </Container> + ); +}; diff --git a/src/components/NavBar.jsx b/src/components/NavBar.jsx index a23307c..ffbc215 100644 --- a/src/components/NavBar.jsx +++ b/src/components/NavBar.jsx @@ -1,9 +1,6 @@ import React, { useState } from "react"; import Tabs from "@mui/material/Tabs"; import Tab from "@mui/material/Tab"; -import DashboardOutlinedIcon from "@mui/icons-material/DashboardOutlined"; -import CalendarMonthIcon from "@mui/icons-material/CalendarMonth"; -import ShareIcon from "@mui/icons-material/Share"; import { Box } from "@mui/material"; import { useDispatch } from "react-redux"; import { setCurrentTabIndex } from "../store/slices/globalSlice"; @@ -32,27 +29,27 @@ export const NavBar = () => { > <Tab classes={{ - root: "min-h-10 h-10 px-2", + root: "min-h-10 h-10 px-2 gap-2", }} - icon={<DashboardOutlinedIcon fontSize="small" />} + icon={<NavIcon iconName="dashboard" />} iconPosition="start" label={t("home")} className="!text-xs !md:text-sm " /> <Tab classes={{ - root: "min-h-10 h-10 px-2", + root: "min-h-10 h-10 px-2 gap-2", }} - icon={<CalendarMonthIcon fontSize="small" />} + icon={<NavIcon iconName="calendar" />} iconPosition="start" className="!text-xs !md:text-sm " label={t("calendar")} /> <Tab classes={{ - root: "min-h-10 h-10 px-2", + root: "min-h-10 h-10 px-2 gap-2", }} - icon={<ShareIcon fontSize="small" />} + icon={<NavIcon iconName="share" />} iconPosition="start" className="!text-xs !md:text-sm " label={t("share")} @@ -61,3 +58,14 @@ export const NavBar = () => { </Box> ); }; + +const NavIcon = ({ iconName }) => ( + <Box + sx={{ + width: 24, + height: 24, + }} + > + <img alt="icon" src={`/assets/${iconName}.png`} /> + </Box> +); diff --git a/src/components/TimeSlot.jsx b/src/components/TimeSlot.jsx index 1ed138b..120d2c6 100644 --- a/src/components/TimeSlot.jsx +++ b/src/components/TimeSlot.jsx @@ -1,15 +1,16 @@ -import { Grow, Typography } from "@mui/material"; +import { Typography } from "@mui/material"; import moment from "moment"; import React from "react"; export const TimeSlot = ({ slot }) => { return ( - <Grow key={slot?.index} in={true} {...{ timeout: slot?.index * 200 }}> - <div className=" flex items-center justify-center h-10 bg-[#eee9ff] border-[#5127bb40] border rounded-md"> - <Typography className="text-[#5127bb] text-sm md:text-base "> - {moment.unix(slot?.start).format("HH:mm")} - </Typography> - </div> - </Grow> + <div + key={slot?.index} + className=" flex items-center justify-center h-10 bg-[#eee9ff] border-[#5127bb40] border rounded-md" + > + <Typography className="text-[#5127bb] text-sm md:text-base "> + {moment.unix(slot?.start).format("HH:mm")} + </Typography> + </div> ); }; diff --git a/src/components/TodayAvailableSlots.jsx b/src/components/TodayAvailableSlots.jsx index 5366536..ce9683c 100644 --- a/src/components/TodayAvailableSlots.jsx +++ b/src/components/TodayAvailableSlots.jsx @@ -1,12 +1,10 @@ -import { Divider, Grow, Paper, Typography } from "@mui/material"; +import { Box, Divider, Grow, Paper, Typography, alpha } from "@mui/material"; import React, { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import Welcome from "/assets/welcome.svg"; import Lottie from "lottie-react"; import loader from "../animations/loader.json"; import { TimeSlot } from "./TimeSlot"; -import EventAvailableOutlinedIcon from "@mui/icons-material/EventAvailableOutlined"; -import InfoOutlinedIcon from "@mui/icons-material/InfoOutlined"; import { useSelector } from "react-redux"; import { selectGlobalSlice } from "../store/slices/globalSlice"; import { isMobile } from "react-device-detect"; @@ -32,19 +30,32 @@ export const TodayAvailableSlots = ({ todayAvailableSlots }) => { return ( <Paper + sx={{ + boxShadow: `0 0 2px 0 ${alpha( + "#919EAB", + 0.6 + )}, 0 12px 24px -4px ${alpha("#919EAB", 0.15)}`, + }} className="w-full rounded-lg p-2 flex flex-col items-start gap-4 min-h-80" elevation={2} > - <div className="w-full flex flex-col gap-1"> + <div className="w-full flex flex-col gap-2"> <div className="w-full flex items-center justify-between"> <div className="flex items-center gap-2"> - <EventAvailableOutlinedIcon /> - <Typography className="text-[#000] text-base md:text-lg lg:text-xl font-medium"> + <Box + sx={{ + width: 30, + height: 30, + }} + > + <img alt="icon" src="/assets/today.png" /> + </Box> + <Typography className="text-[#000] text-base md:text-lg lg:text-xl font-semibold"> {t("today_available_slots")} </Typography> </div> </div> - <Divider flexItem /> + <Divider className="border-dashed" flexItem /> </div> <div className="w-full h-full flex flex-col overflow-y-auto"> {loading ? ( @@ -62,20 +73,21 @@ export const TodayAvailableSlots = ({ todayAvailableSlots }) => { ) : ( <> {availableSlots && availableSlots?.length > 0 ? ( - <div className=" flex flex-col w-full gap-2"> + <div className=" flex flex-col w-full gap-4"> <div className="flex items-center gap-2 w-full justify-end"> - <InfoOutlinedIcon className="text-sm text-[#999]" /> + <Box + sx={{ + width: 18, + height: 18, + }} + > + <img alt="icon" src="/assets/info.png" /> + </Box> <div className="flex gap-1 items-center"> - <Typography - className="text-[#999] text-xs md:text-sm" - display="inline" - > + <Typography variant="body2" display="inline"> {`${t("slot_duration")} :`} </Typography> - <Typography - className="text-[#999] text-xs md:text-sm" - display="inline" - > + <Typography variant="body2" display="inline"> {`${meetingSlotDuration} ${t("minutes")}`} </Typography> </div> diff --git a/src/components/TodayMeetings.jsx b/src/components/TodayMeetings.jsx index a0e0ba6..8e96af1 100644 --- a/src/components/TodayMeetings.jsx +++ b/src/components/TodayMeetings.jsx @@ -1,4 +1,4 @@ -import { Divider, Grow, Paper, Typography } from "@mui/material"; +import { Box, Divider, Grow, Paper, Typography, alpha } from "@mui/material"; import React, { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import Welcome from "/assets/welcome.svg"; @@ -30,18 +30,31 @@ export const TodayMeetings = ({ todayEvents }) => { return ( <Paper + sx={{ + boxShadow: `0 0 2px 0 ${alpha( + "#919EAB", + 0.6 + )}, 0 12px 24px -4px ${alpha("#919EAB", 0.15)}`, + }} className="w-full rounded-lg p-2 flex flex-col items-start gap-4 min-h-80" elevation={2} > - <div className="w-full flex flex-col gap-1"> + <div className="w-full flex flex-col gap-2"> <div className="w-full flex justify-start gap-2 items-center"> - <EventNoteOutlinedIcon className="" /> + <Box + sx={{ + width: 30, + height: 30, + }} + > + <img alt="icon" src="/assets/ongoingevent.png" /> + </Box> - <Typography className="text-[#000] text-base md:text-lg lg:text-xl font-medium"> + <Typography className="text-[#000] text-base md:text-lg lg:text-xl font-semibold "> {t("today_meetings")} </Typography> </div> - <Divider flexItem /> + <Divider className="border-dashed " flexItem /> </div> <div className="w-full h-full flex flex-col overflow-y-auto"> {loading ? ( diff --git a/src/i18n/en.js b/src/i18n/en.js index 3391cc8..f13196c 100644 --- a/src/i18n/en.js +++ b/src/i18n/en.js @@ -15,12 +15,17 @@ const locale = { share_this_link_via: "Share this link via", copy_link: "Copy link", calendar: "Calendar", - home: "Home", + home: "Reservations", share: "Share", ok: "Ok", start: "Start", end: "End", - + sorry_room_not_found_title: "Sorry, room not found!", + sorry_room_not_found_detail: + "Sorry, we couldn't find the room you're looking for. Perhaps you've mistyped the room number? Be sure to check your spelling.", + sorry_page_not_found_title: "Sorry, page not found!", + sorry_page_not_found_detail: + "Sorry, we couldn't find the page you're looking for. Perhaps you've mistyped the URL? Be sure to check your spelling.", event_details: "Event Details", website_link: "https://ict-box.utu.fi/rooms/", diff --git a/src/i18n/fi.js b/src/i18n/fi.js index 64f2812..236497a 100644 --- a/src/i18n/fi.js +++ b/src/i18n/fi.js @@ -16,7 +16,12 @@ const locale = { share_this_link_via: "Jaa verkossa:", copy_link: "Skannaa QR tai kopioi kalenterin osoite", ok: "Ok", - + sorry_room_not_found_title: "Anteeksi, huonetta ei löytynyt!", + sorry_room_not_found_detail: + "Valitettavasti emme löytäneet etsimääsi huonetta. Ehkä olet kirjoittanut huoneen numeron väärin? Muista tarkistaa oikeinkirjoitus.", + sorry_page_not_found_title: "Anteeksi, sivua ei löydy!", + sorry_page_not_found_detail: + "Valitettavasti emme löytäneet etsimääsi sivua. Ehkä kirjoitit URL-osoitteen väärin? Muista tarkistaa oikeinkirjoitus.", calendar: "Kalenteri", home: "Varaukset", share: "Jakaminen", diff --git a/src/pages/HomePage/HomePage.jsx b/src/pages/HomePage/HomePage.jsx index 7f7f264..114a617 100644 --- a/src/pages/HomePage/HomePage.jsx +++ b/src/pages/HomePage/HomePage.jsx @@ -2,8 +2,8 @@ import React, { useEffect, useState } from "react"; import "./HomePage.css"; import { useSelector } from "react-redux"; import { selectGlobalSlice } from "../../store/slices/globalSlice"; -import { useNavigate, redirect } from "react-router-dom"; -import { Divider, Paper, Typography } from "@mui/material"; +import { useSearchParams } from "react-router-dom"; +import { Paper, Typography } from "@mui/material"; import { useTranslation } from "react-i18next"; import { TodayAvailableSlots } from "../../components/TodayAvailableSlots"; @@ -17,8 +17,11 @@ import axios from "axios"; import { Share } from "../../components/Share/Share"; import { EventInfoModal } from "../../components/EventInfoModal"; +import loadingAnimation from "../../animations/loader.json"; +import Lottie from "lottie-react"; +import { ErrorMessage } from "../../components/ErrorMessage"; + export const HomePage = () => { - const navigate = useNavigate(); const { isEventInfoModalVisible } = useSelector(selectGlobalSlice); const { t } = useTranslation(); const { currentTabIndex } = useSelector(selectGlobalSlice); @@ -27,11 +30,11 @@ export const HomePage = () => { const [calendarData, setCalendarData] = useState(); const [loading, setLoading] = useState(true); - const handleFetchCalendarData = async () => { + const [searchParams] = useSearchParams(); + + const handleFetchCalendarData = async (room) => { try { - const response = await axios.get( - "https://tt.utu.fi/rooms/api/ag408" - ); + const response = await axios.get(`https://tt.utu.fi/rooms/api/${room}`); if (Array.isArray(response.data)) { setCalendarData(response.data); const todayEvents = getUpcomingTodayEvents(response.data); @@ -53,68 +56,97 @@ export const HomePage = () => { useEffect(() => { let interval; - handleFetchCalendarData(); - interval = setInterval(() => { - (async () => { - handleFetchCalendarData(); - })(); - }, 1000 * 60); - + if (searchParams) { + const room = searchParams.get("room"); + if (room) { + handleFetchCalendarData(room); + interval = setInterval(() => { + (async () => { + handleFetchCalendarData(room); + })(); + }, 1000 * 60); + } else { + setLoading(false); + } + } return () => clearInterval(interval); - }, []); + }, [searchParams]); return ( <div className="h-full w-full flex flex-col lg:flex-row "> - <div className="relative w-full lg:w-[40%] h-[30%] lg:h-full flex flex-col items-center justify-center px-6 lg:px-8"> - <img - src="assets/aistikattila.jpeg" - className="absolute blur-sm object-cover h-full w-full -z-10" - /> - <Paper className="flex flex-col items-center bg-[#000] opacity-80 p-3 md:p-4 rounded-lg"> - <Typography className=" text-2xl md:text-3xl lg:text-5xl text-white font-semibold text-center"> - {t("title")} - </Typography> - </Paper> - <div className="w-full flex text-center justify-center items-center absolute bottom-1 lg:bottom-6 px-4 py-3 md:py-4"> - <Typography - component="span" - className="text-white text-xs md:text-base" - > - {t("for_reservations")}{" "} - <Typography - component="span" - className="underline text-white text-xs md:text-base" - > - {t("email")} - </Typography> - </Typography> - </div> - </div> - <div className="w-full lg:w-[60%] h-[70%] lg:h-full bg-white px-2 pt-1 pb-3 gap-4 flex flex-col"> - <div className="w-full flex flex-col "> - <DateAndStatus todayEvents={todayEvents} /> - <NavBar /> + {loading ? ( + <div className="w-full h-full flex flex-col justify-center items-center"> + <Lottie + animationData={loadingAnimation} + autoPlay + loop + style={{ + height: 100, + }} + /> </div> - <div - className={`overflow-auto h-full gap-4 flex flex-col ${ - currentTabIndex === 0 ? "px-1 py-1" : "px-1 py-1" - }`} - > - {currentTabIndex === 0 && ( + ) : ( + <> + {calendarData ? ( <> - <TodayMeetings todayEvents={todayEvents} /> - <TodayAvailableSlots todayAvailableSlots={todayAvailableSlots} /> + <div className="relative w-full lg:w-[40%] h-[30%] lg:h-full flex flex-col items-center justify-center px-6 lg:px-8"> + <img + src="/assets/aistikattila.jpeg" + className="absolute blur-sm object-cover h-full w-full -z-10" + /> + <Paper className="flex flex-col items-center bg-[#000] opacity-80 p-3 md:p-4 rounded-lg"> + <Typography className=" text-2xl md:text-3xl lg:text-5xl text-white font-semibold text-center"> + {t("title")} + </Typography> + </Paper> + <div className="w-full flex text-center justify-center items-center absolute bottom-1 lg:bottom-6 px-4 py-3 md:py-4"> + <Typography + component="span" + className="text-white text-xs md:text-base" + > + {t("for_reservations")}{" "} + <Typography + component="span" + className="underline text-white text-xs md:text-base" + > + {t("email")} + </Typography> + </Typography> + </div> + </div> + <div className="w-full lg:w-[60%] h-[70%] lg:h-full bg-[#f9fafb] px-2 pt-1 pb-6 gap-4 flex flex-col"> + <div className="w-full flex flex-col "> + <DateAndStatus todayEvents={todayEvents} /> + <NavBar /> + </div> + <div + className={`overflow-auto h-full gap-4 flex flex-col ${ + currentTabIndex === 0 ? "px-1 py-1" : "px-1 py-1" + }`} + > + {currentTabIndex === 0 && ( + <> + <TodayMeetings todayEvents={todayEvents} /> + <TodayAvailableSlots + todayAvailableSlots={todayAvailableSlots} + /> + </> + )} + {currentTabIndex === 1 && ( + <div className="h-full"> + <FullCalendar calendarData={calendarData} /> + </div> + )} + {currentTabIndex === 2 && <Share />} + </div> + </div> + {isEventInfoModalVisible && <EventInfoModal />} </> + ) : ( + <ErrorMessage /> )} - {currentTabIndex === 1 && ( - <div className="h-full"> - <FullCalendar calendarData={calendarData} /> - </div> - )} - {currentTabIndex === 2 && <Share />} - </div> - </div> - {isEventInfoModalVisible && <EventInfoModal />} + </> + )} </div> ); }; diff --git a/src/pages/NotFound/NotFoundPage.jsx b/src/pages/NotFound/NotFoundPage.jsx new file mode 100644 index 0000000..3fde067 --- /dev/null +++ b/src/pages/NotFound/NotFoundPage.jsx @@ -0,0 +1,54 @@ +import { Helmet } from "react-helmet-async"; + +import Box from "@mui/material/Box"; +import Container from "@mui/material/Container"; +import Typography from "@mui/material/Typography"; + +import { useTranslation } from "react-i18next"; + +// ---------------------------------------------------------------------- + +export const NotFoundPage = () => { + const { t } = useTranslation(); + return ( + <> + <Helmet> + <title> 404 Page Not Found </title> + </Helmet> + + <Container> + <Box + sx={{ + py: 12, + maxWidth: 480, + mx: "auto", + display: "flex", + minHeight: "100vh", + textAlign: "center", + alignItems: "center", + flexDirection: "column", + justifyContent: "center", + }} + > + <Typography variant="h3" sx={{ mb: 3 }}> + {t("sorry_page_not_found_title")} + </Typography> + + <Typography sx={{ color: "text.secondary" }}> + {t("sorry_page_not_found_detail")} + </Typography> + + <Box + component="img" + src="/assets/illustrations/notfound.svg" + sx={{ + mx: "auto", + height: 260, + my: { xs: 5, sm: 10 }, + }} + /> + </Box> + </Container> + </> + ); +}; diff --git a/src/store/store.js b/src/store/store.js index 1c133e6..5c773c6 100644 --- a/src/store/store.js +++ b/src/store/store.js @@ -1,17 +1,8 @@ import { configureStore } from "@reduxjs/toolkit"; import { createReducer } from "./rootReducer"; -import { createLogger } from "redux-logger"; const middlewares = []; -if (process.env.NODE_ENV === `development`) { - const logger = createLogger({ - collapsed: (getState, action, logEntry) => !logEntry.error, - }); - - middlewares.push(logger); -} - export const store = configureStore({ reducer: createReducer(), middleware: (getDefaultMiddleware) => diff --git a/src/withAppProvider.jsx b/src/withAppProvider.jsx index ceacc9c..7fc348c 100644 --- a/src/withAppProvider.jsx +++ b/src/withAppProvider.jsx @@ -7,6 +7,7 @@ import "./i18n"; import { theme } from "./theme/theme"; import moment from "moment"; import "moment/dist/locale/fi"; +import { HelmetProvider } from "react-helmet-async"; export const withAppProvider = (Component) => { const WrapperComponent = () => { @@ -14,7 +15,9 @@ export const withAppProvider = (Component) => { <StyledEngineProvider injectFirst> <ThemeProvider theme={theme}> <CssBaseline /> - <Component /> + <HelmetProvider> + <Component /> + </HelmetProvider> </ThemeProvider> </StyledEngineProvider> ); -- GitLab