diff --git a/next.config.mjs b/next.config.mjs index 4678774..61da8b0 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -1,4 +1,16 @@ /** @type {import('next').NextConfig} */ -const nextConfig = {}; +const nextConfig = { + images: { + localPatterns: [ + { + pathname: '/assets/images/**', + search: '', + }, + ], + }, + experimental: { + webpackMemoryOptimizations: true, + } +}; export default nextConfig; diff --git a/package-lock.json b/package-lock.json index b02a649..c56ab74 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,13 +8,30 @@ "name": "infogare-creator", "version": "0.1.0", "dependencies": { - "next": "15.0.3", - "react": "19.0.0-rc-66855b96-20241106", - "react-dom": "19.0.0-rc-66855b96-20241106" + "@emotion/cache": "^11.14.0", + "@emotion/styled": "^11.13.0", + "@mui/icons-material": "^6.3.1", + "@mui/material": "^6.3.1", + "@mui/material-nextjs": "^6.3.1", + "bcryptjs": "^2.4.3", + "cookie": "^1.0.2", + "jose": "^5.9.6", + "jquery": "^3.7.1", + "mysql2": "^3.12.0", + "next": "^15.1.7", + "nodemailer": "^6.9.16", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "server-only": "^0.0.1", + "socket.io": "^4.8.1", + "socket.io-client": "^4.8.1", + "uuid": "^11.0.4" }, "devDependencies": { - "eslint": "^8", - "eslint-config-next": "15.0.3", + "@eslint/eslintrc": "^3", + "cross-env": "^7.0.3", + "eslint": "^9", + "eslint-config-next": "15.1.2", "postcss": "^8", "tailwindcss": "^3.4.1" } @@ -32,6 +49,148 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@babel/code-frame": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz", + "integrity": "sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.26.2", + "@babel/types": "^7.26.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz", + "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.26.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz", + "integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==", + "license": "MIT", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", + "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", + "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/types": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz", + "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@emnapi/runtime": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.3.1.tgz", @@ -42,6 +201,163 @@ "tslib": "^2.4.0" } }, + "node_modules/@emotion/babel-plugin": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.12.0.tgz", + "integrity": "sha512-y2WQb+oP8Jqvvclh8Q55gLUyb7UFvgv7eJfsj7td5TToBrIUtPay2kMrZi4xjq9qw2vD0ZR5fSho0yqoFgX7Rw==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/serialize": "^1.2.0", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/cache": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz", + "integrity": "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==", + "license": "MIT", + "dependencies": { + "@emotion/memoize": "^0.9.0", + "@emotion/sheet": "^1.4.0", + "@emotion/utils": "^1.4.2", + "@emotion/weak-memoize": "^0.4.0", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/hash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==", + "license": "MIT" + }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.3.1.tgz", + "integrity": "sha512-/ACwoqx7XQi9knQs/G0qKvv5teDMhD7bXYns9N/wM8ah8iNb8jZ2uNO0YOgiq2o2poIvVtJS2YALasQuMSQ7Kw==", + "license": "MIT", + "dependencies": { + "@emotion/memoize": "^0.9.0" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==", + "license": "MIT" + }, + "node_modules/@emotion/react": { + "version": "11.13.3", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.13.3.tgz", + "integrity": "sha512-lIsdU6JNrmYfJ5EbUCf4xW1ovy5wKQ2CkPRM4xogziOxH1nXxBSjpC9YqbFAP7circxMfYp+6x676BqWcEiixg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.12.0", + "@emotion/cache": "^11.13.0", + "@emotion/serialize": "^1.3.1", + "@emotion/use-insertion-effect-with-fallbacks": "^1.1.0", + "@emotion/utils": "^1.4.0", + "@emotion/weak-memoize": "^0.4.0", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/react/node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.1.0.tgz", + "integrity": "sha512-+wBOcIV5snwGgI2ya3u99D7/FJquOIniQT1IKyDsBmEgwvpxMNeS65Oib7OnE2d2aY+3BU4OiH+0Wchf8yk3Hw==", + "license": "MIT", + "peer": true, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@emotion/serialize": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz", + "integrity": "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==", + "license": "MIT", + "dependencies": { + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/unitless": "^0.10.0", + "@emotion/utils": "^1.4.2", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/sheet": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", + "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==", + "license": "MIT" + }, + "node_modules/@emotion/styled": { + "version": "11.13.0", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.13.0.tgz", + "integrity": "sha512-tkzkY7nQhW/zC4hztlwucpT8QEZ6eUzpXDRhww/Eej4tFfO0FxQYWRyg/c5CCXa4d/f174kqeXYjuQRnhzf6dA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.12.0", + "@emotion/is-prop-valid": "^1.3.0", + "@emotion/serialize": "^1.3.0", + "@emotion/use-insertion-effect-with-fallbacks": "^1.1.0", + "@emotion/utils": "^1.4.0" + }, + "peerDependencies": { + "@emotion/react": "^11.0.0-rc.0", + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/styled/node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.1.0.tgz", + "integrity": "sha512-+wBOcIV5snwGgI2ya3u99D7/FJquOIniQT1IKyDsBmEgwvpxMNeS65Oib7OnE2d2aY+3BU4OiH+0Wchf8yk3Hw==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@emotion/unitless": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz", + "integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==", + "license": "MIT" + }, + "node_modules/@emotion/utils": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz", + "integrity": "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==", + "license": "MIT" + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", + "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==", + "license": "MIT" + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", @@ -71,17 +387,45 @@ "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, + "node_modules/@eslint/config-array": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz", + "integrity": "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.11.0.tgz", + "integrity": "sha512-DWUB2pksgNEb6Bz2fggIy1wh6fGgZP4Xyy/Mt0QZPiloKKXerbqq9D3SBQTlCRYOrcRPu4vuz+CGjwdfqxnoWA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", + "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", "dev": true, "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", + "espree": "^10.0.1", + "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -89,36 +433,95 @@ "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/@eslint/js": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", - "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "version": "9.20.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.20.0.tgz", + "integrity": "sha512-iZA07H9io9Wn836aVTytRaNqh00Sad+EamwOVJT12GTLw1VGMFV/4JaME+JjLtr9fiGaoWgYnS54wrfWsSs4oQ==", "dev": true, "license": "MIT", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", - "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", - "deprecated": "Use @eslint/config-array instead", + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz", + "integrity": "sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" + "@eslint/core": "^0.10.0", + "levn": "^0.4.1" }, "engines": { - "node": ">=10.10.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit/node_modules/@eslint/core": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.10.0.tgz", + "integrity": "sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, "node_modules/@humanwhocodes/module-importer": { @@ -135,13 +538,19 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", + "node_modules/@humanwhocodes/retry": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", + "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", "dev": true, - "license": "BSD-3-Clause" + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, "node_modules/@img/sharp-darwin-arm64": { "version": "0.33.5", @@ -555,7 +964,6 @@ "version": "0.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/set-array": "^1.2.1", @@ -570,7 +978,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.0.0" @@ -580,7 +987,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.0.0" @@ -590,30 +996,305 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@mui/core-downloads-tracker": { + "version": "6.4.4", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-6.4.4.tgz", + "integrity": "sha512-r+J0EditrekkTtO2CnCBCOGpNaDYwJqz8lH4rj6o/anDcskZFJodBlG8aCJkS8DL/CF/9EHS+Gz53EbmYEnQbw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + } + }, + "node_modules/@mui/icons-material": { + "version": "6.4.4", + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-6.4.4.tgz", + "integrity": "sha512-uF1chGaoFmYdRUomK6f8kgJfWosk9A3HXWiVD0vQm+2mE7f25eTQ1E8RRO11LXpnUBqu8Rbv/uGlpnjT/u1Ksg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.26.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@mui/material": "^6.4.4", + "@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": { + "version": "6.4.4", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-6.4.4.tgz", + "integrity": "sha512-ISVPrIsPQsxnwvS40C4u03AuNSPigFeS2+n1qpuEZ94hDsdMi19dQM2JcC9CHEhXecSIQjP1RTyY0mPiSpSrFQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.26.0", + "@mui/core-downloads-tracker": "^6.4.4", + "@mui/system": "^6.4.3", + "@mui/types": "^7.2.21", + "@mui/utils": "^6.4.3", + "@popperjs/core": "^2.11.8", + "@types/react-transition-group": "^4.4.12", + "clsx": "^2.1.1", + "csstype": "^3.1.3", + "prop-types": "^15.8.1", + "react-is": "^19.0.0", + "react-transition-group": "^4.4.5" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@mui/material-pigment-css": "^6.4.3", + "@types/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" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@mui/material-pigment-css": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/material-nextjs": { + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/@mui/material-nextjs/-/material-nextjs-6.4.3.tgz", + "integrity": "sha512-4ZRLrcD1HeWpvY8c7MrKYKuaUSobtvqcLYeEfGh/x5ezzPgKizhl7C0jpVVEgf6g+C9OgOGbhLTVfks7Y2IBAQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.26.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/cache": "^11.11.0", + "@emotion/react": "^11.11.4", + "@emotion/server": "^11.11.0", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "next": "^13.0.0 || ^14.0.0 || ^15.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/cache": { + "optional": true + }, + "@emotion/server": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/material/node_modules/react-is": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.0.0.tgz", + "integrity": "sha512-H91OHcwjZsbq3ClIDHMzBShc1rotbfACdWENsmEf0IFvZ3FgGPtdHMcsv45bQ1hAbgdfiA8SnxTKfDS+x/8m2g==", + "license": "MIT" + }, + "node_modules/@mui/private-theming": { + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-6.4.3.tgz", + "integrity": "sha512-7x9HaNwDCeoERc4BoEWLieuzKzXu5ZrhRnEM6AUcRXUScQLvF1NFkTlP59+IJfTbEMgcGg1wWHApyoqcksrBpQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.26.0", + "@mui/utils": "^6.4.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@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/styled-engine": { + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-6.4.3.tgz", + "integrity": "sha512-OC402VfK+ra2+f12Gef8maY7Y9n7B6CZcoQ9u7mIkh/7PKwW/xH81xwX+yW+Ak1zBT3HYcVjh2X82k5cKMFGoQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.26.0", + "@emotion/cache": "^11.13.5", + "@emotion/serialize": "^1.3.3", + "@emotion/sheet": "^1.4.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.4.1", + "@emotion/styled": "^11.3.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } + } + }, + "node_modules/@mui/system": { + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-6.4.3.tgz", + "integrity": "sha512-Q0iDwnH3+xoxQ0pqVbt8hFdzhq1g2XzzR4Y5pVcICTNtoCLJmpJS3vI4y/OIM1FHFmpfmiEC2IRIq7YcZ8nsmg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.26.0", + "@mui/private-theming": "^6.4.3", + "@mui/styled-engine": "^6.4.3", + "@mui/types": "^7.2.21", + "@mui/utils": "^6.4.3", + "clsx": "^2.1.1", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/types": { + "version": "7.2.21", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.21.tgz", + "integrity": "sha512-6HstngiUxNqLU+/DPqlUJDIPbzUBxIVHb1MmXP0eTWDIROiCR2viugXpEif0PPe2mLqqakPzzRClWAnK+8UJww==", + "license": "MIT", + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/utils": { + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-6.4.3.tgz", + "integrity": "sha512-jxHRHh3BqVXE9ABxDm+Tc3wlBooYz/4XPa0+4AI+iF38rV1/+btJmSUgG4shDtSWVs/I97aDn5jBCt6SF2Uq2A==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.26.0", + "@mui/types": "^7.2.21", + "@types/prop-types": "^15.7.14", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^19.0.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@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/utils/node_modules/react-is": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.0.0.tgz", + "integrity": "sha512-H91OHcwjZsbq3ClIDHMzBShc1rotbfACdWENsmEf0IFvZ3FgGPtdHMcsv45bQ1hAbgdfiA8SnxTKfDS+x/8m2g==", + "license": "MIT" + }, "node_modules/@next/env": { - "version": "15.0.3", - "resolved": "https://registry.npmjs.org/@next/env/-/env-15.0.3.tgz", - "integrity": "sha512-t9Xy32pjNOvVn2AS+Utt6VmyrshbpfUMhIjFO60gI58deSo/KgLOp31XZ4O+kY/Is8WAGYwA5gR7kOb1eORDBA==", + "version": "15.1.7", + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.1.7.tgz", + "integrity": "sha512-d9jnRrkuOH7Mhi+LHav2XW91HOgTAWHxjMPkXMGBc9B2b7614P7kjt8tAplRvJpbSt4nbO1lugcT/kAaWzjlLQ==", "license": "MIT" }, "node_modules/@next/eslint-plugin-next": { - "version": "15.0.3", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.0.3.tgz", - "integrity": "sha512-3Ln/nHq2V+v8uIaxCR6YfYo7ceRgZNXfTd3yW1ukTaFbO+/I8jNakrjYWODvG9BuR2v5kgVtH/C8r0i11quOgw==", + "version": "15.1.2", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.1.2.tgz", + "integrity": "sha512-sgfw3+WdaYOGPKCvM1L+UucBmRfh8V2Ygefp7ELON0+0vY7uohQwXXnVWg3rY7mXDKharQR3o7uedpfvnU2hlQ==", "dev": true, "license": "MIT", "dependencies": { @@ -621,9 +1302,9 @@ } }, "node_modules/@next/swc-darwin-arm64": { - "version": "15.0.3", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.0.3.tgz", - "integrity": "sha512-s3Q/NOorCsLYdCKvQlWU+a+GeAd3C8Rb3L1YnetsgwXzhc3UTWrtQpB/3eCjFOdGUj5QmXfRak12uocd1ZiiQw==", + "version": "15.1.7", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.1.7.tgz", + "integrity": "sha512-hPFwzPJDpA8FGj7IKV3Yf1web3oz2YsR8du4amKw8d+jAOHfYHYFpMkoF6vgSY4W6vB29RtZEklK9ayinGiCmQ==", "cpu": [ "arm64" ], @@ -637,9 +1318,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "15.0.3", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.0.3.tgz", - "integrity": "sha512-Zxl/TwyXVZPCFSf0u2BNj5sE0F2uR6iSKxWpq4Wlk/Sv9Ob6YCKByQTkV2y6BCic+fkabp9190hyrDdPA/dNrw==", + "version": "15.1.7", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.1.7.tgz", + "integrity": "sha512-2qoas+fO3OQKkU0PBUfwTiw/EYpN+kdAx62cePRyY1LqKtP09Vp5UcUntfZYajop5fDFTjSxCHfZVRxzi+9FYQ==", "cpu": [ "x64" ], @@ -653,9 +1334,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "15.0.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.0.3.tgz", - "integrity": "sha512-T5+gg2EwpsY3OoaLxUIofmMb7ohAUlcNZW0fPQ6YAutaWJaxt1Z1h+8zdl4FRIOr5ABAAhXtBcpkZNwUcKI2fw==", + "version": "15.1.7", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.1.7.tgz", + "integrity": "sha512-sKLLwDX709mPdzxMnRIXLIT9zaX2w0GUlkLYQnKGoXeWUhcvpCrK+yevcwCJPdTdxZEUA0mOXGLdPsGkudGdnA==", "cpu": [ "arm64" ], @@ -669,9 +1350,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "15.0.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.0.3.tgz", - "integrity": "sha512-WkAk6R60mwDjH4lG/JBpb2xHl2/0Vj0ZRu1TIzWuOYfQ9tt9NFsIinI1Epma77JVgy81F32X/AeD+B2cBu/YQA==", + "version": "15.1.7", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.1.7.tgz", + "integrity": "sha512-zblK1OQbQWdC8fxdX4fpsHDw+VSpBPGEUX4PhSE9hkaWPrWoeIJn+baX53vbsbDRaDKd7bBNcXRovY1hEhFd7w==", "cpu": [ "arm64" ], @@ -685,9 +1366,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "15.0.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.0.3.tgz", - "integrity": "sha512-gWL/Cta1aPVqIGgDb6nxkqy06DkwJ9gAnKORdHWX1QBbSZZB+biFYPFti8aKIQL7otCE1pjyPaXpFzGeG2OS2w==", + "version": "15.1.7", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.1.7.tgz", + "integrity": "sha512-GOzXutxuLvLHFDAPsMP2zDBMl1vfUHHpdNpFGhxu90jEzH6nNIgmtw/s1MDwpTOiM+MT5V8+I1hmVFeAUhkbgQ==", "cpu": [ "x64" ], @@ -701,9 +1382,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "15.0.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.0.3.tgz", - "integrity": "sha512-QQEMwFd8r7C0GxQS62Zcdy6GKx999I/rTO2ubdXEe+MlZk9ZiinsrjwoiBL5/57tfyjikgh6GOU2WRQVUej3UA==", + "version": "15.1.7", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.1.7.tgz", + "integrity": "sha512-WrZ7jBhR7ATW1z5iEQ0ZJfE2twCNSXbpCSaAunF3BKcVeHFADSI/AW1y5Xt3DzTqPF1FzQlwQTewqetAABhZRQ==", "cpu": [ "x64" ], @@ -717,9 +1398,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "15.0.3", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.0.3.tgz", - "integrity": "sha512-9TEp47AAd/ms9fPNgtgnT7F3M1Hf7koIYYWCMQ9neOwjbVWJsHZxrFbI3iEDJ8rf1TDGpmHbKxXf2IFpAvheIQ==", + "version": "15.1.7", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.1.7.tgz", + "integrity": "sha512-LDnj1f3OVbou1BqvvXVqouJZKcwq++mV2F+oFHptToZtScIEnhNRJAhJzqAtTE2dB31qDYL45xJwrc+bLeKM2Q==", "cpu": [ "arm64" ], @@ -733,9 +1414,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "15.0.3", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.0.3.tgz", - "integrity": "sha512-VNAz+HN4OGgvZs6MOoVfnn41kBzT+M+tB+OK4cww6DNyWS6wKaDpaAm/qLeOUbnMh0oVx1+mg0uoYARF69dJyA==", + "version": "15.1.7", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.1.7.tgz", + "integrity": "sha512-dC01f1quuf97viOfW05/K8XYv2iuBgAxJZl7mbCKEjMgdQl5JjAKJ0D2qMKZCgPWDeFbFT0Q0nYWwytEW0DWTQ==", "cpu": [ "x64" ], @@ -807,6 +1488,16 @@ "node": ">=14" } }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, "node_modules/@rtsao/scc": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", @@ -821,6 +1512,12 @@ "dev": true, "license": "MIT" }, + "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==", + "license": "MIT" + }, "node_modules/@swc/counter": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", @@ -828,14 +1525,43 @@ "license": "Apache-2.0" }, "node_modules/@swc/helpers": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.13.tgz", - "integrity": "sha512-UoKGxQ3r5kYI9dALKJapMmuK+1zWM/H17Z1+iwnNmzcJRnfFuevZs375TA5rW31pu4BS4NoSy1fRsexDXfWn5w==", + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", + "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==", "license": "Apache-2.0", "dependencies": { - "tslib": "^2.4.0" + "tslib": "^2.8.0" } }, + "node_modules/@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", + "license": "MIT" + }, + "node_modules/@types/cors": { + "version": "2.8.17", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", + "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -843,6 +1569,47 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/node": { + "version": "22.10.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", + "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.20.0" + } + }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", + "license": "MIT" + }, + "node_modules/@types/prop-types": { + "version": "15.7.14", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", + "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==", + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.3.12", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz", + "integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-transition-group": { + "version": "4.4.12", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz", + "integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*" + } + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.14.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.14.0.tgz", @@ -1089,12 +1856,18 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true, - "license": "ISC" + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } }, "node_modules/acorn": { "version": "8.14.0", @@ -1388,6 +2161,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/aws-ssl-profiles": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz", + "integrity": "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==", + "license": "MIT", + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/axe-core": { "version": "4.10.2", "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.2.tgz", @@ -1408,6 +2190,21 @@ "node": ">= 0.4" } }, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1415,6 +2212,21 @@ "dev": true, "license": "MIT" }, + "node_modules/base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "license": "MIT", + "engines": { + "node": "^4.5.0 || >= 5.9" + } + }, + "node_modules/bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==", + "license": "MIT" + }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -1487,7 +2299,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -1584,6 +2395,15 @@ "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", "license": "MIT" }, + "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": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", @@ -1646,10 +2466,82 @@ "dev": true, "license": "MIT" }, + "node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "license": "MIT" + }, + "node_modules/cookie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", + "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "license": "MIT", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cosmiconfig/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "bin": { + "cross-env": "src/bin/cross-env.js", + "cross-env-shell": "src/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=10.14", + "npm": ">=6", + "yarn": ">=1" + } + }, "node_modules/cross-spawn": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.5.tgz", - "integrity": "sha512-ZVJrKKYunU38/76t0RMOulHOnUcbU9GbpWKAOZ0mhjr7CX6FVrH+4FrAapSOekrgFQ3f/8gwMEuIft0aKq6Hug==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "license": "MIT", "dependencies": { @@ -1674,6 +2566,12 @@ "node": ">=4" } }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "license": "MIT" + }, "node_modules/damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", @@ -1739,7 +2637,6 @@ "version": "4.3.7", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -1796,6 +2693,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.10" + } + }, "node_modules/detect-libc": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", @@ -1820,17 +2726,14 @@ "dev": true, "license": "MIT" }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "license": "Apache-2.0", + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "license": "MIT", "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" } }, "node_modules/eastasianwidth": { @@ -1847,6 +2750,58 @@ "dev": true, "license": "MIT" }, + "node_modules/engine.io": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.2.tgz", + "integrity": "sha512-gmNvsYi9C8iErnZdVcJnvCpSKbWTt1E8+JZo8b+daLninywUWi5NQ5STSHZ9rFjFO7imNcvb8Pc5pe/wMR5xEw==", + "license": "MIT", + "dependencies": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.7.2", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.17.1" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/engine.io-client": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.2.tgz", + "integrity": "sha512-TAr+NKeoVTjEVW8P3iHguO1LO6RlUz9O5Y8o7EY0fU+gY1NYqas7NN3slpFtbXEsLMHk0h90fJMfKjRkQ0qUIw==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.17.1", + "xmlhttprequest-ssl": "~2.1.1" + } + }, + "node_modules/engine.io-parser": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io/node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/enhanced-resolve": { "version": "5.17.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", @@ -1861,6 +2816,21 @@ "node": ">=10.13.0" } }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/error-ex/node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "license": "MIT" + }, "node_modules/es-abstract": { "version": "1.23.4", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.4.tgz", @@ -2032,7 +3002,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -2042,70 +3011,73 @@ } }, "node_modules/eslint": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", - "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", - "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "version": "9.20.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.20.1.tgz", + "integrity": "sha512-m1mM33o6dBUjxl2qb6wv6nGNwCAsns1eKtaQ4l/NPHeTvhiUPbtdfMyktxN4B3fgHIgsYh1VT3V9txblpQHq+g==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.1", - "@humanwhocodes/config-array": "^0.13.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.19.0", + "@eslint/core": "^0.11.0", + "@eslint/eslintrc": "^3.2.0", + "@eslint/js": "9.20.0", + "@eslint/plugin-kit": "^0.2.5", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", + "@humanwhocodes/retry": "^0.4.1", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", + "cross-spawn": "^7.0.6", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" + "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, "node_modules/eslint-config-next": { - "version": "15.0.3", - "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-15.0.3.tgz", - "integrity": "sha512-IGP2DdQQrgjcr4mwFPve4DrCqo7CVVez1WoYY47XwKSrYO4hC0Dlb+iJA60i0YfICOzgNADIb8r28BpQ5Zs0wg==", + "version": "15.1.2", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-15.1.2.tgz", + "integrity": "sha512-PrMm1/4zWSJ689wd/ypWIR5ZF1uvmp3EkgpgBV1Yu6PhEobBjXMGgT8bVNelwl17LXojO8D5ePFRiI4qXjsPRA==", "dev": true, "license": "MIT", "dependencies": { - "@next/eslint-plugin-next": "15.0.3", + "@next/eslint-plugin-next": "15.1.2", "@rushstack/eslint-patch": "^1.10.3", "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", @@ -2113,7 +3085,7 @@ "eslint-import-resolver-typescript": "^3.5.2", "eslint-plugin-import": "^2.31.0", "eslint-plugin-jsx-a11y": "^6.10.0", - "eslint-plugin-react": "^7.35.0", + "eslint-plugin-react": "^7.37.0", "eslint-plugin-react-hooks": "^5.0.0" }, "peerDependencies": { @@ -2427,9 +3399,9 @@ } }, "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", + "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -2437,7 +3409,7 @@ "estraverse": "^5.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -2456,19 +3428,45 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.9.0", + "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "eslint-visitor-keys": "^4.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -2582,16 +3580,16 @@ } }, "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "license": "MIT", "dependencies": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16.0.0" } }, "node_modules/fill-range": { @@ -2607,6 +3605,12 @@ "node": ">=8" } }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "license": "MIT" + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -2625,24 +3629,23 @@ } }, "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "license": "MIT", "dependencies": { "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "keyv": "^4.5.4" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16" } }, "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", + "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", "dev": true, "license": "ISC" }, @@ -2673,13 +3676,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true, - "license": "ISC" - }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -2699,7 +3695,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2734,6 +3729,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "license": "MIT", + "dependencies": { + "is-property": "^1.0.2" + } + }, "node_modules/get-intrinsic": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", @@ -2785,28 +3789,6 @@ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -2821,16 +3803,13 @@ } }, "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -2959,7 +3938,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -2968,6 +3946,28 @@ "node": ">= 0.4" } }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -2982,7 +3982,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, "license": "MIT", "dependencies": { "parent-module": "^1.0.0", @@ -3005,25 +4004,6 @@ "node": ">=0.8.19" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, - "license": "ISC" - }, "node_modules/internal-slot": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", @@ -3149,7 +4129,6 @@ "version": "2.15.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", - "dev": true, "license": "MIT", "dependencies": { "hasown": "^2.0.2" @@ -3307,15 +4286,11 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } + "node_modules/is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==", + "license": "MIT" }, "node_modules/is-regex": { "version": "1.1.4", @@ -3511,11 +4486,25 @@ "jiti": "bin/jiti.js" } }, + "node_modules/jose": { + "version": "5.9.6", + "resolved": "https://registry.npmjs.org/jose/-/jose-5.9.6.tgz", + "integrity": "sha512-AMlnetc9+CV9asI19zHmrgS/WYsWUwCn2R7RzlbJWD7F9eWYUTGyBmU9o6PxngtLGOiDGPRu+Uc4fhKzbpteZQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/jquery": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz", + "integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==", + "license": "MIT" + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, "license": "MIT" }, "node_modules/js-yaml": { @@ -3531,6 +4520,18 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsesc": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -3538,6 +4539,12 @@ "dev": true, "license": "MIT" }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "license": "MIT" + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -3639,7 +4646,6 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true, "license": "MIT" }, "node_modules/locate-path": { @@ -3665,11 +4671,16 @@ "dev": true, "license": "MIT" }, + "node_modules/long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", + "license": "Apache-2.0" + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, "license": "MIT", "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" @@ -3685,6 +4696,21 @@ "dev": true, "license": "ISC" }, + "node_modules/lru.min": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.1.tgz", + "integrity": "sha512-FbAj6lXil6t8z4z3j0E5mfRlPzxkySotzUHwRXjlpRh10vc6AI6WN62ehZj82VG7M20rqogJ0GLwar2Xa05a8Q==", + "license": "MIT", + "engines": { + "bun": ">=1.0.0", + "deno": ">=1.30.0", + "node": ">=8.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wellwelwel" + } + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -3709,6 +4735,27 @@ "node": ">=8.6" } }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -3746,9 +4793,28 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, "license": "MIT" }, + "node_modules/mysql2": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.12.0.tgz", + "integrity": "sha512-C8fWhVysZoH63tJbX8d10IAoYCyXy4fdRFz2Ihrt9jtPILYynFEKUUzpp1U7qxzDc3tMbotvaBH+sl6bFnGZiw==", + "license": "MIT", + "dependencies": { + "aws-ssl-profiles": "^1.1.1", + "denque": "^2.1.0", + "generate-function": "^2.3.1", + "iconv-lite": "^0.6.3", + "long": "^5.2.1", + "lru.min": "^1.0.0", + "named-placeholders": "^1.1.3", + "seq-queue": "^0.0.5", + "sqlstring": "^2.3.2" + }, + "engines": { + "node": ">= 8.0" + } + }, "node_modules/mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", @@ -3761,6 +4827,27 @@ "thenify-all": "^1.0.0" } }, + "node_modules/named-placeholders": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz", + "integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==", + "license": "MIT", + "dependencies": { + "lru-cache": "^7.14.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/named-placeholders/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", @@ -3786,15 +4873,24 @@ "dev": true, "license": "MIT" }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/next": { - "version": "15.0.3", - "resolved": "https://registry.npmjs.org/next/-/next-15.0.3.tgz", - "integrity": "sha512-ontCbCRKJUIoivAdGB34yCaOcPgYXr9AAkV/IwqFfWWTXEPUgLYkSkqBhIk9KK7gGmgjc64B+RdoeIDM13Irnw==", + "version": "15.1.7", + "resolved": "https://registry.npmjs.org/next/-/next-15.1.7.tgz", + "integrity": "sha512-GNeINPGS9c6OZKCvKypbL8GTsT5GhWPp4DM0fzkXJuXMilOO2EeFxuAY6JZbtk6XIl6Ws10ag3xRINDjSO5+wg==", "license": "MIT", "dependencies": { - "@next/env": "15.0.3", + "@next/env": "15.1.7", "@swc/counter": "0.1.3", - "@swc/helpers": "0.5.13", + "@swc/helpers": "0.5.15", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", @@ -3807,22 +4903,22 @@ "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "15.0.3", - "@next/swc-darwin-x64": "15.0.3", - "@next/swc-linux-arm64-gnu": "15.0.3", - "@next/swc-linux-arm64-musl": "15.0.3", - "@next/swc-linux-x64-gnu": "15.0.3", - "@next/swc-linux-x64-musl": "15.0.3", - "@next/swc-win32-arm64-msvc": "15.0.3", - "@next/swc-win32-x64-msvc": "15.0.3", + "@next/swc-darwin-arm64": "15.1.7", + "@next/swc-darwin-x64": "15.1.7", + "@next/swc-linux-arm64-gnu": "15.1.7", + "@next/swc-linux-arm64-musl": "15.1.7", + "@next/swc-linux-x64-gnu": "15.1.7", + "@next/swc-linux-x64-musl": "15.1.7", + "@next/swc-win32-arm64-msvc": "15.1.7", + "@next/swc-win32-x64-msvc": "15.1.7", "sharp": "^0.33.5" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.41.2", "babel-plugin-react-compiler": "*", - "react": "^18.2.0 || 19.0.0-rc-66855b96-20241106", - "react-dom": "^18.2.0 || 19.0.0-rc-66855b96-20241106", + "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "peerDependenciesMeta": { @@ -3868,6 +4964,15 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/nodemailer": { + "version": "6.9.16", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.16.tgz", + "integrity": "sha512-psAuZdTIRN08HKVd/E8ObdV6NO7NTBY3KsC30F7M4H1OnmLCUNaS56FpYxyb26zWLSyYF9Ozch9KYHhHegsiOQ==", + "license": "MIT-0", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -3882,7 +4987,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -4007,16 +5111,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -4078,7 +5172,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, "license": "MIT", "dependencies": { "callsites": "^3.0.0" @@ -4087,6 +5180,24 @@ "node": ">=6" } }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -4097,16 +5208,6 @@ "node": ">=8" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -4121,7 +5222,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, "license": "MIT" }, "node_modules/path-scurry": { @@ -4141,6 +5241,15 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -4367,7 +5476,6 @@ "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, "license": "MIT", "dependencies": { "loose-envify": "^1.4.0", @@ -4407,33 +5515,48 @@ "license": "MIT" }, "node_modules/react": { - "version": "19.0.0-rc-66855b96-20241106", - "resolved": "https://registry.npmjs.org/react/-/react-19.0.0-rc-66855b96-20241106.tgz", - "integrity": "sha512-klH7xkT71SxRCx4hb1hly5FJB21Hz0ACyxbXYAECEqssUjtJeFUAaI2U1DgJAzkGEnvEm3DkxuBchMC/9K4ipg==", + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.0.0.tgz", + "integrity": "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==", "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/react-dom": { - "version": "19.0.0-rc-66855b96-20241106", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0-rc-66855b96-20241106.tgz", - "integrity": "sha512-D25vdaytZ1wFIRiwNU98NPQ/upS2P8Co4/oNoa02PzHbh8deWdepjm5qwZM/46OdSiGv4WSWwxP55RO9obqJEQ==", + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0.tgz", + "integrity": "sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==", "license": "MIT", "dependencies": { - "scheduler": "0.25.0-rc-66855b96-20241106" + "scheduler": "^0.25.0" }, "peerDependencies": { - "react": "19.0.0-rc-66855b96-20241106" + "react": "^19.0.0" } }, "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==", - "dev": true, "license": "MIT" }, + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "license": "BSD-3-Clause", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -4479,6 +5602,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "license": "MIT" + }, "node_modules/regexp.prototype.flags": { "version": "1.5.3", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", @@ -4502,7 +5631,6 @@ "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "dev": true, "license": "MIT", "dependencies": { "is-core-module": "^2.13.0", @@ -4520,7 +5648,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -4547,23 +5674,6 @@ "node": ">=0.10.0" } }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -4625,10 +5735,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, "node_modules/scheduler": { - "version": "0.25.0-rc-66855b96-20241106", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0-rc-66855b96-20241106.tgz", - "integrity": "sha512-HQXp/Mnp/MMRSXMQF7urNFla+gmtXW/Gr1KliuR0iboTit4KvZRY8KYaq5ccCTAOJiUqQh2rE2F3wgUekmgdlA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0.tgz", + "integrity": "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==", "license": "MIT" }, "node_modules/semver": { @@ -4644,6 +5760,17 @@ "node": ">=10" } }, + "node_modules/seq-queue": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", + "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" + }, + "node_modules/server-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/server-only/-/server-only-0.0.1.tgz", + "integrity": "sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==", + "license": "MIT" + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -4783,6 +5910,71 @@ "is-arrayish": "^0.3.1" } }, + "node_modules/socket.io": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz", + "integrity": "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "cors": "~2.8.5", + "debug": "~4.3.2", + "engine.io": "~6.6.0", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/socket.io-adapter": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz", + "integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==", + "license": "MIT", + "dependencies": { + "debug": "~4.3.4", + "ws": "~8.17.1" + } + }, + "node_modules/socket.io-client": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.1.tgz", + "integrity": "sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.2", + "engine.io-client": "~6.6.1", + "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==", + "license": "MIT", + "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", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -4792,6 +5984,15 @@ "node": ">=0.10.0" } }, + "node_modules/sqlstring": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", + "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/streamsearch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", @@ -5048,6 +6249,12 @@ } } }, + "node_modules/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==", + "license": "MIT" + }, "node_modules/sucrase": { "version": "3.35.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", @@ -5135,7 +6342,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -5192,13 +6398,6 @@ "node": ">=6" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true, - "license": "MIT" - }, "node_modules/thenify": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", @@ -5287,19 +6486,6 @@ "node": ">= 0.8.0" } }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/typed-array-buffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", @@ -5378,9 +6564,9 @@ } }, "node_modules/typescript": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", - "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", + "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", "dev": true, "license": "Apache-2.0", "peer": true, @@ -5408,6 +6594,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/undici-types": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "license": "MIT" + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -5425,6 +6617,28 @@ "dev": true, "license": "MIT" }, + "node_modules/uuid": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.5.tgz", + "integrity": "sha512-508e6IcKLrhxKdBbcA2b4KQZlLVp2+J5UwQ6F7Drckkc5N9ZJwFa4TgWtsww9UG8fGHbm6gbV19TdM5pQ4GaIA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -5635,12 +6849,34 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true, - "license": "ISC" + "node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "license": "MIT", + "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.1.2", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz", + "integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==", + "engines": { + "node": ">=0.4.0" + } }, "node_modules/yaml": { "version": "2.6.0", diff --git a/package.json b/package.json index c22373f..91f768f 100644 --- a/package.json +++ b/package.json @@ -9,14 +9,31 @@ "lint": "next lint" }, "dependencies": { - "react": "19.0.0-rc-66855b96-20241106", - "react-dom": "19.0.0-rc-66855b96-20241106", - "next": "15.0.3" + "@emotion/cache": "^11.14.0", + "@emotion/styled": "^11.13.0", + "@mui/icons-material": "^6.3.1", + "@mui/material": "^6.3.1", + "@mui/material-nextjs": "^6.3.1", + "bcryptjs": "^2.4.3", + "cookie": "^1.0.2", + "jose": "^5.9.6", + "jquery": "^3.7.1", + "mysql2": "^3.12.0", + "next": "^15.1.7", + "nodemailer": "^6.9.16", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "server-only": "^0.0.1", + "socket.io": "^4.8.1", + "socket.io-client": "^4.8.1", + "uuid": "^11.0.4" }, "devDependencies": { + "@eslint/eslintrc": "^3", + "cross-env": "^7.0.3", + "eslint": "^9", + "eslint-config-next": "15.1.2", "postcss": "^8", - "tailwindcss": "^3.4.1", - "eslint": "^8", - "eslint-config-next": "15.0.3" + "tailwindcss": "^3.4.1" } } diff --git a/public/assets/images/AFL.svg b/public/assets/images/AFL.svg new file mode 100644 index 0000000..c22292e --- /dev/null +++ b/public/assets/images/AFL.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + AFL + \ No newline at end of file diff --git a/public/assets/images/BRGC_T2_R.gif b/public/assets/images/BRGC_T2_R.gif new file mode 100644 index 0000000..fe0ef29 Binary files /dev/null and b/public/assets/images/BRGC_T2_R.gif differ diff --git a/public/assets/images/RATP.svg b/public/assets/images/RATP.svg new file mode 100644 index 0000000..589f525 --- /dev/null +++ b/public/assets/images/RATP.svg @@ -0,0 +1,89 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/public/assets/images/SNCF.svg b/public/assets/images/SNCF.svg new file mode 100644 index 0000000..f5dfde6 --- /dev/null +++ b/public/assets/images/SNCF.svg @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/assets/images/XGC_T2_AB_L.gif b/public/assets/images/XGC_T2_AB_L.gif new file mode 100644 index 0000000..f125344 Binary files /dev/null and b/public/assets/images/XGC_T2_AB_L.gif differ diff --git a/public/assets/images/XGC_T2_R.gif b/public/assets/images/XGC_T2_R.gif new file mode 100644 index 0000000..ab56802 Binary files /dev/null and b/public/assets/images/XGC_T2_R.gif differ diff --git a/public/assets/images/background-moutains.svg b/public/assets/images/background-moutains.svg new file mode 100644 index 0000000..7435e62 --- /dev/null +++ b/public/assets/images/background-moutains.svg @@ -0,0 +1,4315 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Layer 1 + + + + + + Layer 1 + + + + + + Layer 1 + + + + + + Layer 1 + + + + + + Layer 1 + + + + + + Layer 1 + + + + + + Layer 1 + + + + + + Layer 1 + + + + + + Layer 1 + + + + + + Layer 1 + + + + + + Layer 1 + + + + + + Layer 1 + + + + + + Layer 1 + + + + + + Layer 1 + + + + + + Layer 1 + + + + + + Layer 1 + + + + + + Layer 1 + + + + + + Layer 1 + + + + + + Layer 1 + + + + + + + + + + + + + + + + + + + diff --git a/public/assets/images/background.svg b/public/assets/images/background.svg new file mode 100644 index 0000000..55d87d6 --- /dev/null +++ b/public/assets/images/background.svg @@ -0,0 +1,3661 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Layer 1 + + + + + + Layer 1 + + + + + + Layer 1 + + + + + + Layer 1 + + + + + + Layer 1 + + + + + + Layer 1 + + + + + + Layer 1 + + + + + + Layer 1 + + + + + + Layer 1 + + + + + + Layer 1 + + + + + + Layer 1 + + + + + + Layer 1 + + + + + + Layer 1 + + + + + + Layer 1 + + + + + + Layer 1 + + + + + + Layer 1 + + + + + + Layer 1 + + + + + + Layer 1 + + + + + + Layer 1 + + + + + + + + + + + + + + + + + + + diff --git a/public/assets/images/favicon.svg b/public/assets/images/favicon.svg new file mode 100644 index 0000000..955919c --- /dev/null +++ b/public/assets/images/favicon.svg @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/assets/images/upscaled_BRGC_T2_R.gif b/public/assets/images/upscaled_BRGC_T2_R.gif new file mode 100644 index 0000000..30bdbc2 Binary files /dev/null and b/public/assets/images/upscaled_BRGC_T2_R.gif differ diff --git a/public/assets/images/upscaled_XGC_T2_AB_L.gif b/public/assets/images/upscaled_XGC_T2_AB_L.gif new file mode 100644 index 0000000..23ae58c Binary files /dev/null and b/public/assets/images/upscaled_XGC_T2_AB_L.gif differ diff --git a/public/assets/images/upscaled_XGC_T2_R.gif b/public/assets/images/upscaled_XGC_T2_R.gif new file mode 100644 index 0000000..e5b3cf8 Binary files /dev/null and b/public/assets/images/upscaled_XGC_T2_R.gif differ diff --git a/public/file.svg b/public/file.svg deleted file mode 100644 index 004145c..0000000 --- a/public/file.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/globe.svg b/public/globe.svg deleted file mode 100644 index 567f17b..0000000 --- a/public/globe.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/next.svg b/public/next.svg deleted file mode 100644 index 5174b28..0000000 --- a/public/next.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/vercel.svg b/public/vercel.svg deleted file mode 100644 index 7705396..0000000 --- a/public/vercel.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/window.svg b/public/window.svg deleted file mode 100644 index b2b2a44..0000000 --- a/public/window.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/app/(departs)/creator/gare/classique/[id]/departs/TwoRowDepart.js b/src/app/(departs)/creator/gare/classique/[id]/departs/TwoRowDepart.js new file mode 100644 index 0000000..708f007 --- /dev/null +++ b/src/app/(departs)/creator/gare/classique/[id]/departs/TwoRowDepart.js @@ -0,0 +1,57 @@ +import * as React from 'react'; +import $ from 'jquery'; + +export default function TwoRowDepart({ number, timing, gare, type, departure }) { + + React.useEffect(() => { + switch (type) { + case 'TGV': + $('.train-logo').addClass('train-logo-tgv'); + break; + case 'OUIGO': + $('.train-logo').addClass('train-logo-ouigo'); + break; + case 'TER': + $('.train-logo').addClass('train-logo-ter'); + break; + default: + $('.train-logo').addClass('train-logo-sncf'); + break; + } + }, []); + + return ( +
+
+
+
+
+
+
+
+ {type} +
+ {number} +
+
{timing}
+
+
+
{departure}
+
+ {gare} +
+
+
+ +
+
+
+
+
+
+
+
+
+
+ ); +} \ No newline at end of file diff --git a/src/app/(departs)/creator/gare/classique/[id]/departs/layout.js b/src/app/(departs)/creator/gare/classique/[id]/departs/layout.js new file mode 100644 index 0000000..113a3ed --- /dev/null +++ b/src/app/(departs)/creator/gare/classique/[id]/departs/layout.js @@ -0,0 +1,35 @@ +import * as React from 'react'; +import styles from '@/app/styles/departs/trains.css'; +import styles2 from '@/app/fonts/Achemine/style.css' + +export default function Layout({ children }) { + return ( + + +
+
+
+
+
+
+
+
+
+ + + : + +   + +
+
+
+
+
+ {children} +
+
+ + + ); +} \ No newline at end of file diff --git a/src/app/(departs)/creator/gare/classique/[id]/departs/page.js b/src/app/(departs)/creator/gare/classique/[id]/departs/page.js new file mode 100644 index 0000000..f6eddcb --- /dev/null +++ b/src/app/(departs)/creator/gare/classique/[id]/departs/page.js @@ -0,0 +1,111 @@ +'use client' +import * as React from 'react'; +import TwoRowDepart from './TwoRowDepart'; +import $ from 'jquery'; +import io from 'socket.io-client'; + +export default function DepartsPage() { + + const [trains, setTrains] = React.useState([]); + + React.useEffect(() => { + async function listen() { + await fetch('/api/trains/listen', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + }); + } + listen(); + + const socket = io({ + path: '/api/socket', + }); + + socket.on('db-update', (data) => { + setTrains((trains) => [...trains, data]); + console.log(data); + }); + + return () => { + socket.disconnect(); + }; + }, []); + + const clock = () => { + var date = new Date(); + date.setHours(date.getHours() + (date.getTimezoneOffset() / -60)); + + var h = date.getUTCHours(); + if (h < 10) { + h = '0' + h; + } + $('#clock-hours').html(h); + var m = date.getUTCMinutes(); + if (m < 10) { + m = '0' + m; + } + $('#clock-minutes').html(m); + var s = date.getUTCSeconds(); + if (s < 10) { + s = '0' + s; + } + $('#clock-seconds').html(s); + setInterval(clock, '1000'); + return true; + } + + const scollX = () => { + $('.text-scroll-x').each(function () { + + var distance = $(this).width() + $(this).parent().width() + 10; + + + if ($(this).width() > $(this).parent().width()) { + $(this).addClass('animation-scroll-x'); + $(this).css({ + '-webkit-animation-duration': (distance / 150) + 's', + 'animation-duration': (distance / 150) + 's', + 'padding-left': '100%' + }); + } else { + $(this).css({ + 'padding-left': '0%' + }); + } + }); + } + + const scrollY = (limit) => { + var elem = $('.scroll-y'); + var elemHeight = elem.height(); + var parentHeight = elem.parent().height(); + var elemHeightRelative = elemHeight / parentHeight * 100; + + if (elemHeightRelative > limit && limit < 100) { + var distance = (elemHeight - (parentHeight / 1.1)) / $(window).height() * 100; + var time = distance / 6 + 10; + var delay = 5 / time * 100; + + $("").appendTo("head"); + $(elem).css({ + 'animation': 'scrollY ' + time + 's linear infinite 0s' + }); + } else { + $(elem).css({ + 'animation': 'none' + }); + } + } + + React.useEffect(() => { + clock(); + }, []); + + return ( + <> + + + ); +} \ No newline at end of file diff --git a/src/app/(general)/admin/page.js b/src/app/(general)/admin/page.js new file mode 100644 index 0000000..695b5f1 --- /dev/null +++ b/src/app/(general)/admin/page.js @@ -0,0 +1,44 @@ +'use client' +import { Box, Card, CardActions, CardContent, Grid2, Typography, Button } from '@mui/material'; +import Link from 'next/link'; +import * as React from 'react'; + +export default function AdminHome() { + const [usersLength, setUsersLength] = React.useState(0); + + React.useEffect(() => { + const fetchUsersLength = async () => { + const response = await fetch('/api/admin/users?length=true'); + if (response.ok) { + const data = await response.json(); + setUsersLength(data); + } + } + fetchUsersLength(); + }, []); + + return ( + <> + + Administration + Bienvenue sur la page d'dministration d'InfoGare + + + + + + Utilisateurs + Gestion des utilisateurs + Il y a actuellement {usersLength} utilisateurs enregistrés + + + + + + + + + + + ); +} \ No newline at end of file diff --git a/src/app/(general)/admin/users/UserDisableDialog.js b/src/app/(general)/admin/users/UserDisableDialog.js new file mode 100644 index 0000000..8a49348 --- /dev/null +++ b/src/app/(general)/admin/users/UserDisableDialog.js @@ -0,0 +1,29 @@ +import * as React from 'react'; +import { Button, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, TextField } from '@mui/material'; + +export default function UserDisableDialog({ open, user, handleDisable, handleClose }) { + + const [reason, setReason] = React.useState(''); + + const handlePreDisable = () => { + console.log(user.EMAIL); + handleDisable(user.EMAIL, reason); + handleClose(); + } + + return ( + + Désactiver l'utilisateur {user.USERNAME} + + + Êtes-vous sûr de vouloir désactiver l'utilisateur {user.USERNAME} ? + + setReason(e.target.value)} fullWidth /> + + + + + + + ); +} \ No newline at end of file diff --git a/src/app/(general)/admin/users/UserEditDialog.js b/src/app/(general)/admin/users/UserEditDialog.js new file mode 100644 index 0000000..e1231b4 --- /dev/null +++ b/src/app/(general)/admin/users/UserEditDialog.js @@ -0,0 +1,52 @@ +import { Button, Checkbox, Dialog, DialogActions, DialogContent, DialogTitle, TextField, Box, FormControlLabel, Typography } from "@mui/material"; +import * as React from "react"; + +export default function EditUserDialog({ open, user, handleModify, handleClose, handleDelete, handleDisable, handleEnable }) { + + const [username, setUsername] = React.useState(user.USERNAME); + const [email, setEmail] = React.useState(user.EMAIL); + const [email_valid, setEmailValid] = React.useState(user.EMAIL_VALID); + + React.useEffect(() => { + setUsername(user.USERNAME); + setEmail(user.EMAIL); + setEmailValid(user.EMAIL_VALID); + }, [user]); + + const handleMailValidation = async () => { + const response = await fetch(`/api/mail/validate`, { + method: 'POST', + body: JSON.stringify({ email: user.EMAIL }), + headers: { 'Content-Type': 'application/json' } + }); + + if (response.ok) { + console.log('Email sent'); + } + } + + const handlePrepareModify = () => { + handleModify(user.USER_ID, username, email, email_valid); + } + + return ( + + Modifier l'utilisateur {user.USERNAME} + + + setUsername(e.target.value)} value={username} /> + setEmail(e.target.value)} value={email} /> + {email_valid ? <> : } + setEmailValid(e.target.checked)} checked={email_valid} />} label='Email validé' /> + Zone danger ! + {user.ENABLED == 'True' ? : } + + + + + + + + + ); +} \ No newline at end of file diff --git a/src/app/(general)/admin/users/page.js b/src/app/(general)/admin/users/page.js new file mode 100644 index 0000000..c11d132 --- /dev/null +++ b/src/app/(general)/admin/users/page.js @@ -0,0 +1,148 @@ +'use client' +import * as React from 'react'; +import { Box, Table, TableContainer, TableHead, TableRow, TableCell, TableBody, Paper, Typography, TextField, InputAdornment, FormControl, IconButton, OutlinedInput, Stack } from '@mui/material'; +import { Done, Edit, ErrorOutline, Search, Visibility } from '@mui/icons-material'; +import UserEditDialog from './UserEditDialog'; +import UserDisableDialog from './UserDisableDialog'; + +export default function AdminUsers() { + const [users, setUsers] = React.useState([]); + const [length, setLength] = React.useState(0); + const [open, setOpen] = React.useState(false); + const [open1, setOpen1] = React.useState(false); + const [user, setUser] = React.useState({ USER_ID: 0, USERNAME: '', EMAIL: '', EMAIL_VALID: 0, CREATION_TIME: '', LAST_LOGIN: '' }); + + React.useEffect(() => { + const fetchUsers = async () => { + const response = await fetch('/api/admin/users'); + if (response.ok) { + const data = await response.json(); + setUsers(data); + } + } + fetchUsers(); + }, []); + + React.useEffect(() => { + const fetchUsersLength = async () => { + const response = await fetch('/api/admin/users?length=true'); + if (response.ok) { + const data = await response.json(); + setLength(data); + } + } + fetchUsersLength(); + }, []); + + const handleSearch = async (event) => { + const search = event.target.value; + if (search.length > 0) { + const response = await fetch(`/api/admin/users?search=${search}`); + if (response.ok) { + const data = await response.json(); + setUsers(data); + } + } else { + const response = await fetch('/api/admin/users'); + if (response.ok) { + const data = await response.json(); + setUsers(data); + } + } + } + + const handleEdit = (user) => { + setUser(user); + setOpen(true); + } + + const handleUserEdit = async (id, username, email, email_valid) => { + const response = await fetch('/api/admin/users', { + method: 'PUT', + body: JSON.stringify({ id, username, email, email_valid }), + headers: { 'Content-Type': 'application/json' } + }); + + if (response.ok) { + window.location.reload(); + setOpen(false); + } + } + + const handleUserDisable = async (id, reason) => { + const response = await fetch('/api/admin/users/disable', { + method: 'POST', + body: JSON.stringify({ id: id, reason: reason }), + headers: { 'Content-Type': 'application/json' } + }); + + if (response.ok) { + setOpen1(false); + } + } + + const handleEnable = async (id) => { + const response = await fetch('/api/admin/users/enable', { + method: 'POST', + body: JSON.stringify({ id: id }), + headers: { 'Content-Type': 'application/json' } + }); + + if (response.ok) { + window.location.reload(); + setOpen(false); + } + } + + return ( + <> + + + Utilisateurs + + + + + + + UID + Nom d'utilisateur + Email + Email validé ? + Activé ? + Date de création + Date de dernière connexion + Actions + + + + {users.map((user) => ( + + + {user.USER_ID} + + {user.USERNAME} + {user.EMAIL} + {user.EMAIL_VALID == 'True' ? : } + {user.ENABLED == 'True' ? : } + {new Date(user.CREATION_TIME).toLocaleString()} + {new Date(user.LAST_LOGIN).toLocaleString()} + + + + + handleEdit(user)}> + + + + + ))} + +
+
+ setOpen(false)} handleModify={handleUserEdit} handleDisable={(e) => setOpen1(true)} handleEnable={handleEnable} /> + setOpen1(false)} handleDisable={handleUserDisable} /> +
+ + ); +} \ No newline at end of file diff --git a/src/app/(general)/creator/account/page.js b/src/app/(general)/creator/account/page.js new file mode 100644 index 0000000..ab41e8b --- /dev/null +++ b/src/app/(general)/creator/account/page.js @@ -0,0 +1,160 @@ +'use client' + +import * as React from 'react'; +import { Box, Button, Typography, Avatar, Card, CardContent, CardActions, CardActionArea, CardMedia, Grid2, SpeedDial, SpeedDialAction } from '@mui/material'; +import { Add, ContentCopy, Delete, Edit } from '@mui/icons-material'; +import Image from 'next/image'; +import EditDialog from '../gare/classique/EditDialog'; +import { redirect } from 'next/navigation'; + + +export default function LoginPage() { + + const [user, setUser] = React.useState({}); + const [gares, setGares] = React.useState([]); + + const [edit, setEdit] = React.useState(false); + const [initialValues, setInitialValues] = React.useState({}); + const [editId, setEditId] = React.useState(null); + + React.useEffect(() => { + async function getUser() { + const res = await fetch('/api/auth/user', { + method: 'GET', + headers: { 'Content-Type': 'application/json' }, + }); + + if (res.status === 200) { + setUser((await res.json()).user); + } else if (!(await res.json()).isLogedIn) { + redirect('/login'); + } else { + alert('Erreur lors de la récupération de l\'utilisateur'); + } + } + + getUser(); + }, []); + + React.useEffect(() => { + async function getGares() { + const res = await fetch('/api/gares', { + method: 'GET', + headers: { 'Content-Type': 'application/json' }, + }); + + if (res.status === 200) { + setGares(await res.json()); + } else { + alert('Erreur lors de la récupération des gares'); + } + } + + getGares(); + }, []); + + const handleCard = (id, type) => { + if (type === 'Classic') { + window.location.href = `/creator/gare/classique/${id}`; + } else if (type === 'RER') { + window.location.href = `/creator/gare/rer/${id}`; + } else if (type === 'AFL') { + window.location.href = `/creator/gare/afl/${id}`; + } + } + + const handleNewBtn = (key) => { + if (key === 'classic') { + redirect('/creator/gare/classique/new'); + } else if (key === 'rer') { + redirect('/creator/gare/rer/new'); + } else { + redirect('/creator/gare/afl/new'); + } + } + + const handleEdit = (gare) => { + setInitialValues(gare); + setEditId(gare.ID); + setEdit(true); + } + + const handleSubmitEdit = async (values) => { + const res = await fetch('/api/gares?id=' + values.id, { + method: 'PATCH', + body: JSON.stringify(values), + headers: { 'Content-Type': 'application/json' } + }); + if (res.status === 200) { + setEdit(false); + window.location.reload(); + } else { + alert('Erreur lors de la modification de la gare'); + } + } + + return ( + <> + + + + + + + + {user.USERNAME} + + {gares.map(gare => ( + + + handleCard(gare.ID, gare.TYPE)}> + + + {gare.NAME} + + + + + + + + + + ))} + + setEdit(false)} onSubmit={handleSubmitEdit} /> + + } > + } tooltipTitle='Gare classique' onClick={(e) => handleNewBtn('classic')} /> + } tooltipTitle='Gare RER' onClick={(e) => handleNewBtn('rer')} /> + } tooltipTitle='Gare AFL' onClick={(e) => handleNewBtn('afl')} /> + + + ) + +} \ No newline at end of file diff --git a/src/app/(general)/creator/gare/afl/[id]/page.js b/src/app/(general)/creator/gare/afl/[id]/page.js new file mode 100644 index 0000000..e69de29 diff --git a/src/app/(general)/creator/gare/afl/new/page.js b/src/app/(general)/creator/gare/afl/new/page.js new file mode 100644 index 0000000..1895d15 --- /dev/null +++ b/src/app/(general)/creator/gare/afl/new/page.js @@ -0,0 +1,216 @@ +'use client' + +import * as React from 'react'; +import { Box, Button, TextField, Typography, Stepper, Step, StepLabel, StepButton, ButtonGroup, Autocomplete, FormControlLabel, FormLabel, RadioGroup, Radio, Checkbox, FormGroup, Snackbar } from '@mui/material'; +import { Check, NavigateBefore, NavigateNext, SettingsInputComponent } from '@mui/icons-material'; +import { redirect } from 'next/navigation'; + +export default function NewGareAFLPage() { + + const [name, setName] = React.useState(''); + const [folder, setFolder] = React.useState({ label: 'default' }); + const [icon, setIcon] = React.useState({ label: 'SNCF' }); + const [texteInfos, setTexteInfos] = React.useState(''); + const [typeInfos, setTypeInfos] = React.useState('infos_normal'); + const [partage, setPartage] = React.useState(false); + const [copie, setCopie] = React.useState(false); + + const [folders, setFolders] = React.useState([]); + const icons = [ + { label: 'SNCF' }, + { label: 'TER' } + ]; + + const [activeStep, setActiveStep] = React.useState(0); + const [completed1, setCompleted1] = React.useState(false); + const [completed2, setCompleted2] = React.useState(false); + const [completed3, setCompleted3] = React.useState(false); + const [copieDisabled, setCopieDisabled] = React.useState(true); + + const [snackOpen, setSnackOpen] = React.useState(false); + + const step1 = React.createRef(); + const step2 = React.createRef(); + const step3 = React.createRef(); + + React.useEffect(() => { + async function getFolders() { + const res = await fetch('/api/folders', { + method: 'GET', + headers: { 'Content-Type': 'application/json' }, + }); + + if (res.status === 200) { + const fd = []; + (await res.json()).forEach((f) => { + fd.push({ label: f.FOLDER }); + }); + setFolders(fd); + } else { + alert('Erreur lors de la récupération des dossiers'); + } + } + + getFolders(); + }, []); + + const handleNext = () => { + handleStep(activeStep); + if (activeStep !== 2) { + setActiveStep((prevActiveStep) => prevActiveStep + 1); + } + } + + const handleStep = (step) => { + if (step === 0) { + setCompleted1(name !== '' && folder !== ''); + step1.current.style.display = 'none'; + step2.current.style.display = 'block'; + } + if (step === 1) { + setCompleted2(true); + setCompleted3(true); + step2.current.style.display = 'none'; + step3.current.style.display = 'block'; + } + if (step === 2) { + setCompleted3(true); + handleSubmit(); + } + console.log(activeStep); + } + + const handlePrev = () => { + if (activeStep === 1) { + step1.current.style.display = 'block'; + step2.current.style.display = 'none'; + } + if (activeStep === 2) { + step2.current.style.display = 'block'; + step3.current.style.display = 'none'; + setCompleted3(true); + } + setActiveStep((prevActiveStep) => prevActiveStep - 1); + } + + const handleShare = (e) => { + if (e.target.checked === true) { + setPartage(true); + setCopieDisabled(false); + } else { + setPartage(false); + setCopieDisabled(true); + setCopie(false); + } + } + + const handleSubmit = async () => { + setSnackOpen(false); + console.log('submitting...'); + if (completed1 && completed2 && completed3) { + const res = await fetch('/api/gares', { + method: 'POST', + body: JSON.stringify({ name: name, type: 'AFL', folder: folder, infos: texteInfos, infos_type: typeInfos, shared: partage, copy: copie }), + headers: { 'Content-Type': 'application/json' } + }); + if (res.status === 200) { + const data = await res.json(); + redirect(`/creator/gare/afl/${data.id}`); + } + } else { + setSnackOpen(true); + } + } + + return ( + + Nouvelle gare + + + + + Informations générales + + + + + Écran d'informations + + + + + Partage + + + + + + Informations générales + setName(e.target.value)} + variant="outlined" + margin="normal" + fullWidth + required + /> + } + getOptionLabel={(option) => { if (option.label === 'default') return 'Dossier par défaut'; return option.label; }} + value={folder} + onChange={(e, value) => setFolder(value)} + /> + } + getOptionLabel={(option) => option.label} + value={icon} + onChange={(e, value) => setIcon(value)} + /> + + + + + + + + Écran d'informations + setTexteInfos(e.target.value)} + margin="normal" + fullWidth + multiline + rows={4} /> + Type d'informations + setTypeInfos(e.target.value)}> + } label='Informations' /> + } label='Flash circulation' /> + + + + + + + + + + Partage + + } label='Partager cette gare' /> + setCopie(e.target.value)} />} label='Permettre aux autres utilisateurs de copier cette gare' /> + + + + + + + + + + + ); +} \ No newline at end of file diff --git a/src/app/(general)/creator/gare/classique/EditDialog.js b/src/app/(general)/creator/gare/classique/EditDialog.js new file mode 100644 index 0000000..c487383 --- /dev/null +++ b/src/app/(general)/creator/gare/classique/EditDialog.js @@ -0,0 +1,49 @@ +'use client' + +import * as React from 'react'; +import { Dialog, Button, TextField, FormLabel, RadioGroup, FormControlLabel, Radio, DialogTitle, DialogContent, DialogActions } from '@mui/material'; + +export default function EditDialog({ show, values, onClose, onSubmit, id = null }) { + + const [name_, setName] = React.useState(''); + const [infos_, setInfos] = React.useState(''); + const [shared_, setShared] = React.useState(''); + const [infosType_, setInfosType] = React.useState('infos_normal'); + + React.useEffect(() => { + if (values) { + setName(values.NAME || ''); + setInfos(values.INFOS || ''); + setInfosType(values.INFOS_TYPE || 'infos_normal'); + setShared(values.SHARED || 0); + } + }, [values]); + + const handleSubmit = () => { + onSubmit({ name: name_, infos: infos_, infosType: infosType_, shared: shared_, id: id }); + } + + return ( + + Modifier la gares + + setName(e.target.value)} /> + setInfos(e.target.value)} /> + Type d'informations + setInfosType(e.target.value)}> + } label='Informations' /> + } label='Flash circulation' /> + + Partagée + setShared(e.target.value)}> + } label='Partager' /> + } label='Ne pas partager' /> + + + + + + + + ) +} \ No newline at end of file diff --git a/src/app/(general)/creator/gare/classique/[id]/page.js b/src/app/(general)/creator/gare/classique/[id]/page.js new file mode 100644 index 0000000..a9e8c95 --- /dev/null +++ b/src/app/(general)/creator/gare/classique/[id]/page.js @@ -0,0 +1,118 @@ +'use client'; + +import { ContentCopy, Delete, Edit } from '@mui/icons-material'; +import { Typography, Box, Grid2, Card, CardContent, CardActionArea, CardActions, CardMedia, Button, Snackbar } from '@mui/material'; +import Image from 'next/image'; +import { usePathname } from 'next/navigation'; +import EditDialog from '@/app/(general)/creator/gare/classique/EditDialog'; +import * as React from 'react'; + +export default function GareClassique() { + const router = usePathname(); + const id = router.split('/').pop(); + + const [trains, setTrains] = React.useState([]); + const [show, setShow] = React.useState(false); + const [snackbar, setSnackbar] = React.useState(false); + + const [name, setName] = React.useState(''); + const [values, setValues] = React.useState({}); + + React.useEffect(() => { + async function getGare() { + const res = await fetch('/api/gares?id=' + id, { + method: 'GET', + headers: { 'Content-Type': 'application/json' }, + }); + + if (res.status === 200) { + const data = await res.json(); + setName(data.NAME); + setValues(data); + } else { + alert('Erreur lors de la récupération de la gare'); + } + } + + getGare(); + }, []); + + React.useEffect(() => { + async function getTrains() { + const res = await fetch('/api/trains?gare_id=' + id, { + method: 'GET', + headers: { 'Content-Type': 'application/json' }, + }); + + if (res.status === 200) { + setTrains(await res.json()); + } else { + if (res.status === 410) { + setSnackbar(true); + } else { + alert('Erreur lors de la récupération des trains'); + } + } + } + + getTrains(); + }, []); + + const handleCard = (e) => { + + } + + const handleEdit = (e) => { + setShow(true); + } + + const handleEditSubmit = async (data) => { + if (!name) { + return; + } + + const req = await fetch('/api/gares?id=' + id, { + method: 'PATCH', + body: JSON.stringify({ name: data.name, infos: data.infos, infos_type: data.infosType, shared: data.shared }), + headers: { 'Content-Type': 'application/json' }, + }); + + if (req.status == 200) { + setShow(false); + window.location.reload(); + } else { + alert('Erreur lors de la mise à jour de la gare'); + } + } + + return ( + <> + + Gare classique + + + {trains.map((train) => ( + + + handleCard(e)}> + + + {train.DESTINATION} + {train.NUMBER} + + + + + + + + + + ))} + + + + setShow(false)} onSubmit={handleEditSubmit} /> + + ); +} \ No newline at end of file diff --git a/src/app/(general)/creator/gare/classique/new/page.js b/src/app/(general)/creator/gare/classique/new/page.js new file mode 100644 index 0000000..f6a1cc5 --- /dev/null +++ b/src/app/(general)/creator/gare/classique/new/page.js @@ -0,0 +1,204 @@ +'use client' + +import * as React from 'react'; +import { Box, Button, TextField, Typography, Stepper, Step, StepLabel, StepButton, ButtonGroup, Autocomplete, FormControlLabel, FormLabel, RadioGroup, Radio, Checkbox, FormGroup, Snackbar } from '@mui/material'; +import { Check, NavigateBefore, NavigateNext } from '@mui/icons-material'; +import { redirect } from 'next/navigation'; + +export default function NewGareStep1Page() { + + const [name, setName] = React.useState(''); + const [folder, setFolder] = React.useState('default'); + const [texteInfos, setTexteInfos] = React.useState(''); + const [typeInfos, setTypeInfos] = React.useState('infos_normal'); + const [partage, setPartage] = React.useState(false); + const [copie, setCopie] = React.useState(false); + + const [folders, setFolders] = React.useState([]); + + const [activeStep, setActiveStep] = React.useState(0); + const [completed1, setCompleted1] = React.useState(false); + const [completed2, setCompleted2] = React.useState(false); + const [completed3, setCompleted3] = React.useState(false); + const [copieDisabled, setCopieDisabled] = React.useState(true); + + const [snackOpen, setSnackOpen] = React.useState(false); + + const step1 = React.createRef(); + const step2 = React.createRef(); + const step3 = React.createRef(); + + React.useEffect(() => { + async function getFolders() { + const res = await fetch('/api/folders', { + method: 'GET', + headers: { 'Content-Type': 'application/json' }, + }); + + if (res.status === 200) { + const fd = []; + (await res.json()).forEach((f) => { + fd.push({ label: f.FOLDER }); + }); + setFolders(fd); + } else { + alert('Erreur lors de la récupération des dossiers'); + } + } + + getFolders(); + }, []); + + const handleNext = () => { + handleStep(activeStep); + if (activeStep !== 2) { + setActiveStep((prevActiveStep) => prevActiveStep + 1); + } + } + + const handleStep = (step) => { + if (step === 0) { + setCompleted1(name !== '' && folder !== ''); + step1.current.style.display = 'none'; + step2.current.style.display = 'block'; + } + if (step === 1) { + setCompleted2(true); + setCompleted3(true); + step2.current.style.display = 'none'; + step3.current.style.display = 'block'; + } + if (step === 2) { + setCompleted3(true); + handleSubmit(); + } + console.log(activeStep); + } + + const handlePrev = () => { + if (activeStep === 1) { + step1.current.style.display = 'block'; + step2.current.style.display = 'none'; + } + if (activeStep === 2) { + step2.current.style.display = 'block'; + step3.current.style.display = 'none'; + setCompleted3(true); + } + setActiveStep((prevActiveStep) => prevActiveStep - 1); + } + + const handleShare = (e) => { + if (e.target.checked === true) { + setPartage(true); + setCopieDisabled(false); + } else { + setPartage(false); + setCopieDisabled(true); + setCopie(false); + } + } + + const handleSubmit = async () => { + setSnackOpen(false); + console.log('submitting...'); + if (completed1 && completed2 && completed3) { + const res = await fetch('/api/gares', { + method: 'POST', + body: JSON.stringify({ name: name, type: 'Classic', folder: folder, infos: texteInfos, infos_type: typeInfos, shared: partage, copy: copie }), + headers: { 'Content-Type': 'application/json' } + }); + if (res.status === 200) { + const data = await res.json(); + redirect(`/creator/gare/classique/${data.id}`); + } + } else { + setSnackOpen(true); + } + } + + return ( + + Nouvelle gare + + + + + Informations générales + + + + + Écran d'informations + + + + + Partage + + + + + + Informations générales + setName(e.target.value)} + variant="outlined" + margin="normal" + fullWidth + required + /> + } + getOptionLabel={(option) => { if (option.label === 'default') return 'Dossier par défaut'; return option.label; }} + value={{ label: 'default' }} + onChange={(e, value) => setFolder(value)} + /> + + + + + + + + Écran d'informations + setTexteInfos(e.target.value)} + margin="normal" + fullWidth + multiline + rows={4} /> + Type d'informations + setTypeInfos(e.target.value)}> + } label='Informations' /> + } label='Flash circulation' /> + + + + + + + + + + Partage + + } label='Partager cette gare' /> + setCopie(e.target.value)} />} label='Permettre aux autres utilisateurs de copier cette gare' /> + + + + + + + + + + + ); +} \ No newline at end of file diff --git a/src/app/(general)/creator/gare/rer/[id]/page.js b/src/app/(general)/creator/gare/rer/[id]/page.js new file mode 100644 index 0000000..e69de29 diff --git a/src/app/(general)/creator/gare/rer/new/page.js b/src/app/(general)/creator/gare/rer/new/page.js new file mode 100644 index 0000000..e69de29 diff --git a/src/app/(general)/layout.js b/src/app/(general)/layout.js new file mode 100644 index 0000000..456e359 --- /dev/null +++ b/src/app/(general)/layout.js @@ -0,0 +1,37 @@ +import "@/app/globals.css"; +import * as React from "react"; +import { AppRouterCacheProvider } from '@mui/material-nextjs/v15-appRouter'; +import { Container, ThemeProvider } from "@mui/material"; +import Appbar from "../components/appbar"; +import theme from "../theme"; +import { AuthProvider } from "../lib/authContext"; +import { Suspense } from "react"; +import Loading from "./loading"; +import { WebVitals } from "../_components/web-vitals"; + +export const metadata = { + title: "InfoGare", + description: "Generated by create next app", +}; + +export default function RootLayout({ children }) { + return ( + + + + + + + + + }> + {children} + + + + + + + + ); +} diff --git a/src/app/(general)/loading.js b/src/app/(general)/loading.js new file mode 100644 index 0000000..26f6558 --- /dev/null +++ b/src/app/(general)/loading.js @@ -0,0 +1,5 @@ +import { LinearProgress } from "@mui/material"; + +export default function Loading() { + return +} \ No newline at end of file diff --git a/src/app/(general)/login/page.js b/src/app/(general)/login/page.js new file mode 100644 index 0000000..d2a3fc3 --- /dev/null +++ b/src/app/(general)/login/page.js @@ -0,0 +1,40 @@ +'use client' + +import { Box, Button, Typography, TextField } from '@mui/material'; +import * as React from 'react'; + +export default function LoginPage() { + + const [email, setEmail] = React.useState(''); + const [password, setPassword] = React.useState(''); + + const login = async () => { + const res = await fetch('/api/login', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ email, password }), + }); + + if (res.status === 200) { + window.location.href = '/'; + } else if (res.status === 403) { + alert('Compte désactivé'); + } else { + alert('Identifiants incorrects'); + } + } + + return ( + + Connexion + + {setEmail(e.target.value)}} fullWidth />
+ {setPassword(e.target.value)}} fullWidth /> + + + +
+
+ ); + +} \ No newline at end of file diff --git a/src/app/(general)/mail/validate/page.js b/src/app/(general)/mail/validate/page.js new file mode 100644 index 0000000..3866e9c --- /dev/null +++ b/src/app/(general)/mail/validate/page.js @@ -0,0 +1,43 @@ +'use client' +import * as React from 'react'; +import { Box, Typography } from '@mui/material'; +import { Done, ErrorOutline } from '@mui/icons-material'; + +export default function EmailValidate() { + + const [validated, setValidated] = React.useState(false); + const [email, setEmail] = React.useState(''); + + React.useEffect(() => { + const validateEmail = async () => { + const token = window.location.href.split('?token=')[1]; + const response = await fetch(`/api/mail/validate?token=${token}`); + if (response.ok) { + const data = await response.json(); + setValidated(true); + setEmail(data.email); + } else { + setValidated(false); + } + } + validateEmail(); + }, []); + + return ( + <> + + {validated ? <> + Validation de l'email + + Votre email a été validé + Votre email {email} a été validé avec succès + : <> + Validation de l'email + + Erreur lors de la validation de l'email + Une erreur est survenue lors de la validation de votre email. Il peut s'agir de votre jeton qui est expiré ou inexistant. + } + + + ); +} \ No newline at end of file diff --git a/src/app/(general)/page.js b/src/app/(general)/page.js new file mode 100644 index 0000000..4e3b23f --- /dev/null +++ b/src/app/(general)/page.js @@ -0,0 +1,38 @@ +'use client' + +import * as React from 'react'; + +export default function Home() { + const [train, setTrain] = React.useState({ train: { NUMBER: 0, DESTINATION: '' }, user: [{ USERNAME: '' }] }); + + React.useEffect(() => { + const fetchTrain = async () => { + const response = await fetch('/api/tod'); + if (response.ok) { + const data = await response.json(); + if (data.train) { + setTrain(data); + document.querySelector('.train').classList.add('moving'); + } + } + } + fetchTrain(); + fetch('/api/stats', { method: 'POST', body: JSON.stringify({ type: 'VISIT', page: window.location.pathname, element: 'no' }) }); + }, []); + + return ( +
+

InfoGare

+
+
+
+
Train N°{train.train.NUMBER} à destination de {train.train.DESTINATION} ({train.user[0].USERNAME})
+
+
+
+
+
+
+
+ ); +} diff --git a/src/app/(general)/register/page.js b/src/app/(general)/register/page.js new file mode 100644 index 0000000..0285ba0 --- /dev/null +++ b/src/app/(general)/register/page.js @@ -0,0 +1,48 @@ +'use client' + +import * as React from 'react'; +import { Box, Button, TextField, Typography, Stepper, Step, StepLabel, StepButton, ButtonGroup, Autocomplete, FormControlLabel, FormLabel, RadioGroup, Radio, Checkbox, FormGroup } from '@mui/material'; + +export default function RegisterPage() { + + const [name, setName] = React.useState(''); + const [email, setEmail] = React.useState(''); + const [password, setPassword] = React.useState(''); + + const [emailValid, setEmailValid] = React.useState(false); + const [passwordValid, setPasswordValid] = React.useState(false); + const [nameValid, setNameValid] = React.useState(false); + + const register = () => { + const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + setNameValid(name === ''); + setPasswordValid(password === ''); + setEmailValid(!emailRegex.test(email)); + + if (name === '' || password === '' || !emailRegex.test(email)) { + return; + } + + fetch('/api/register', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ username: name, email: email, password: password }), + }).then((res) => { + if (res.status === 200) { + alert('Inscription réussie'); + } else { + alert('Erreur lors de l\'inscription'); + } + }); + } + + return ( + + Inscription + setName(e.target.value)} error={nameValid} fullWidth /> + setEmail(e.target.value)} error={emailValid} fullWidth /> + setPassword(e.target.value)} error={passwordValid} fullWidth /> + + + ); +} \ No newline at end of file diff --git a/src/app/(general)/verifyEmail/page.js b/src/app/(general)/verifyEmail/page.js new file mode 100644 index 0000000..0813a0e --- /dev/null +++ b/src/app/(general)/verifyEmail/page.js @@ -0,0 +1,31 @@ +'use client' + +import * as React from 'react'; +import { Box, Button, TextField, Typography } from '@mui/material'; + +export default function VerifyEmailPage() { + + const [code, setCode] = React.useState(''); + + const verify = () => { + fetch('/api/verifyEmail', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ code: code }), + }).then((res) => { + if (res.status === 200) { + alert('Email vérifié'); + } else { + alert('Erreur lors de la vérification de l\'email'); + } + }); + } + + return ( + + Vérification de l'email + setCode(e.target.value)} fullWidth /> + + + ); +} \ No newline at end of file diff --git a/src/app/_components/web-vitals.js b/src/app/_components/web-vitals.js new file mode 100644 index 0000000..4431fc3 --- /dev/null +++ b/src/app/_components/web-vitals.js @@ -0,0 +1,15 @@ +'use client' + +import { useReportWebVitals } from 'next/web-vitals'; + +export function WebVitals() { + useReportWebVitals((metric) => { + fetch('/api/stats', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(metric), + }); + }); +} \ No newline at end of file diff --git a/src/app/api/admin/users/disable/route.js b/src/app/api/admin/users/disable/route.js new file mode 100644 index 0000000..c8c6a2a --- /dev/null +++ b/src/app/api/admin/users/disable/route.js @@ -0,0 +1,38 @@ +import { transporter, baseMail } from "@/app/lib/mailer"; +import { NextResponse } from "next/server"; +import { db } from "@/app/lib/db"; + +export async function POST(req) { + const { id, reason } = await req.json(); + + if (!id) { + return NextResponse.json({ message: 'Invalid ID' }, { status: 400 }); + } + + (await db).query('UPDATE users SET ENABLED = ? WHERE USER_ID = ?', ['False', id]); + + const [rows] = await (await db).query('SELECT EMAIL FROM users WHERE USER_ID = ?', [id]); + + console.log(rows); + + const mailOptions = { + from: '"InfoGare" ', + to: rows[0].EMAIL, + replyTo: 'contact@infogare.fr', + subject: 'Désactivation de votre compte InfoGare', + html: baseMail('Désactivation de votre compte InfoGare', ` +

Bonjour,

+

Votre compte InfoGare a été désactivé par un administrateur pour la raison suivante : ${reason}. + Vous pouvez demander la réactivation de votre compte par email

+

L'équipe InfoGare

+ `), + }; + + const res = await transporter.sendMail(mailOptions); + + if (res.accepted.length === 0) { + return NextResponse.json({ message: 'Invalid email' }, { status: 400 }); + } else { + return NextResponse.json({ message: 'OK' }); + } +} \ No newline at end of file diff --git a/src/app/api/admin/users/enable/route.js b/src/app/api/admin/users/enable/route.js new file mode 100644 index 0000000..1f266d8 --- /dev/null +++ b/src/app/api/admin/users/enable/route.js @@ -0,0 +1,37 @@ +import { NextResponse } from "next/server"; +import { db } from "@/app/lib/db"; +import { transporter, baseMail } from "@/app/lib/mailer"; + +export async function POST(req) { + const { id } = await req.json(); + + if (!id) { + return NextResponse.json({ message: 'Invalid ID' }, { status: 400 }); + } + + (await db).query('UPDATE users SET ENABLED = ? WHERE USER_ID = ?', ['True', id]); + + const [rows] = await (await db).query('SELECT EMAIL FROM users WHERE USER_ID = ?', [id]); + + console.log(rows); + + const mailOptions = { + from: '"InfoGare" ', + to: rows[0].EMAIL, + replyTo: 'contact@infogare.fr', + subject: 'Activation de votre compte InfoGare', + html: baseMail('Activation de votre compte InfoGare', ` +

Bonjour,

+

Votre compte InfoGare a été activé par un administrateur.

+

L'équipe InfoGare

+ `), + }; + + const res = await transporter.sendMail(mailOptions); + + if (res.accepted.length === 0) { + return NextResponse.json({ message: 'Invalid email' }, { status: 400 }); + } else { + return NextResponse.json({ message: 'OK' }); + } +} \ No newline at end of file diff --git a/src/app/api/admin/users/route.js b/src/app/api/admin/users/route.js new file mode 100644 index 0000000..ebce3de --- /dev/null +++ b/src/app/api/admin/users/route.js @@ -0,0 +1,29 @@ +import { NextResponse } from "next/server"; +import { db } from "@/app/lib/db"; + +export async function GET(req) { + const length = req.nextUrl.searchParams.get('length'); + const search = req.nextUrl.searchParams.get('search'); + + if (length) { + const [rows] = await (await db).query('SELECT COUNT(USER_ID) FROM users'); + + return NextResponse.json(rows[0]['COUNT(USER_ID)']); + } else if (search) { + const [rows] = await (await db).query('SELECT USER_ID, EMAIL, EMAIL_VALID, USERNAME, CREATION_TIME, LAST_LOGIN, ENABLED FROM users WHERE USERNAME LIKE ? OR EMAIL LIKE ? LIMIT 25', [`%${search}%`, `%${search}%`]); + + return NextResponse.json(rows); + } else { + const [rows] = await (await db).query('SELECT USER_ID, EMAIL, EMAIL_VALID, USERNAME, CREATION_TIME, LAST_LOGIN, ENABLED FROM users LIMIT 25'); + + return NextResponse.json(rows); + } +} + +export async function PUT(req) { + const { id, username, email, email_valid } = await req.json(); + + await (await db).query('UPDATE users SET USERNAME = ?, EMAIL = ?, EMAIL_VALID = ? WHERE USER_ID = ?', [username, email, email_valid, id]); + + return NextResponse.json({ message: 'OK' }); +} \ No newline at end of file diff --git a/src/app/api/auth/user/route.js b/src/app/api/auth/user/route.js new file mode 100644 index 0000000..7d6f81c --- /dev/null +++ b/src/app/api/auth/user/route.js @@ -0,0 +1,22 @@ +import { db } from "@/app/lib/db"; +import { cookies } from "next/headers"; +import { NextResponse } from "next/server"; + +export async function GET(req) { + const sessionId = (await cookies()).get('session')?.value; + + if (!sessionId) { + return NextResponse.json({ isLoggedIn: false }, { status: 401 }); + } + + const [rows] = await (await db).query('SELECT USER_ID FROM sessions WHERE SESSION_ID = ?', [sessionId]); + + if (rows.length === 0) { + return NextResponse.json({ isLoggedIn: false }, { status: 401 }); + } + + const userId = rows[0].USER_ID; + const [user] = await (await db).query('SELECT USERNAME, EMAIL, EMAIL_VALID, RIGHTS FROM users WHERE USER_ID = ?', [userId]); + + return NextResponse.json({ isLoggedIn: true, user: user.length ? user[0] : null }, { status: 200 }); +} \ No newline at end of file diff --git a/src/app/api/folders/route.js b/src/app/api/folders/route.js new file mode 100644 index 0000000..ba7ea4f --- /dev/null +++ b/src/app/api/folders/route.js @@ -0,0 +1,20 @@ +import { NextResponse } from "next/server"; +import { db } from "@/app/lib/db"; +import { getUserFromSession } from "@/app/lib/auth"; + +export async function GET(req) { + const { user } = await getUserFromSession(); + + if (!user) { + return NextResponse.json({ error: 'Vous devez être connecté pour accéder à cette ressource' }, { status: 401 }); + } + + const [rows] = await (await db).query('SELECT DISTINCT FOLDER FROM gares WHERE USER_ID = ?', [user.USER_ID]); + + + if (rows.length === 0) { + return NextResponse.json({ error: 'Il n\'existe aucun dossier ou vous n\'aves pas le droit d\'accéder à cette ressource !' }, { status: 404 }); + } + + return NextResponse.json(rows); +} \ No newline at end of file diff --git a/src/app/api/gares/route.js b/src/app/api/gares/route.js new file mode 100644 index 0000000..04e0f34 --- /dev/null +++ b/src/app/api/gares/route.js @@ -0,0 +1,69 @@ +import { db } from "@/app/lib/db"; +import { NextResponse } from "next/server"; +import { getUserFromSession } from "@/app/lib/auth"; + +export async function GET(req) { + const id = req.nextUrl.searchParams.get('id'); + + const { user } = await getUserFromSession(); + + if (!user) { + return NextResponse.json({ error: 'Vous devez être connecté pour accéder à cette ressource' }, { status: 401 }); + } + + if (!id) { + const [rows] = await (await db).query('SELECT * FROM gares WHERE USER_ID = ? ORDER BY NAME ASC', [user.USER_ID]); + return NextResponse.json(rows); + } + + const [rows] = await (await db).query('SELECT * FROM gares WHERE id = ? AND USER_ID = ?', [id, user.USER_ID]); + + + if (rows.length === 0) { + return NextResponse.json({ error: 'La gare demandée n\'existe pas ou vous n\'avez pas les droits pour y accéder' }, { status: 404 }); + } + + return NextResponse.json(rows[0]); +} + +export async function POST(req) { + const { user } = await getUserFromSession(); + + if (!user) { + return NextResponse.json({ error: 'Vous devez être connecté pour accéder à cette ressource' }, { status: 401 }); + } + + const { name, folder, infos, infos_type, shared, copy } = await req.json(); + + const id = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15); + + const [rows] = await (await db).query('INSERT INTO gares (ID, USER_ID, NAME, FOLDER, INFOS, INFOS_TYPE, SHARED, CAN_COPY) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', [id, user.USER_ID, name, folder, infos, infos_type, shared, copy]); + + return NextResponse.json({ id: id }); +} + +export async function PATCH(req) { + const id = req.nextUrl.searchParams.get('id'); + const { user } = await getUserFromSession(); + + if (!user) { + return NextResponse.json({ error: 'Vous devez être connecté pour accéder à cette ressource' }, { status: 401 }); + } + + const { name, folder, shared, infos_type, infos } = await req.json(); + var query = [] + + if (name) query.push(`NAME = '${name}'`); + if (folder) query.push(`FOLDER = '${folder}'`); + if (shared) query.push(`SHARED = '${shared}'`); + if (infos_type) query.push(`INFOS_TYPE = '${infos_type}'`); + if (infos) query.push(`INFOS = '${infos}'`); + + const [rows] = await (await db).query(`UPDATE gares SET ${query.join(', ')} WHERE ID = ? AND USER_ID = ?`, [id, user.USER_ID]); + + if (rows.affectedRows === 0) { + return NextResponse.json({ error: 'La gare demandée n\'existe pas ou vous n\'avez pas les droits pour y accéder' }, { status: 404 }); + } + + return NextResponse.json({ success: true }); +} \ No newline at end of file diff --git a/src/app/api/login/route.js b/src/app/api/login/route.js new file mode 100644 index 0000000..7253012 --- /dev/null +++ b/src/app/api/login/route.js @@ -0,0 +1,40 @@ +import { db } from "../../lib/db"; +import bcrypt from "bcryptjs"; +import { v4 as uuidv4 } from "uuid"; +import { serialize } from "cookie"; +import { NextResponse } from "next/server"; + +export async function POST(req) { + const { email, password } = await req.json(); + + const [rows] = await (await db).query('SELECT EMAIL, PASSWORD, USER_ID, ENABLED FROM users WHERE email = ?', [email]); + + if (rows.length === 0) { + return NextResponse.json({ message: 'Unauthorized' }, { status: 401 }); + } + + const user = rows[0]; + + if (!await bcrypt.compare(password, user.PASSWORD)) { + return NextResponse.json({ message: 'Bad credentials' }, { status: 406 }); + } + + if (!user.ENABLED) { + return NextResponse.json({ message: 'Account disabled' }, { status: 403 }); + } + + const sessionId = uuidv4(); + await (await db).query('INSERT INTO sessions (SESSION_ID, USER_ID) VALUES (?, ?)', [sessionId, user.USER_ID]); + + await (await db).query('UPDATE users SET LAST_LOGIN = NOW() WHERE USER_ID = ?', [user.USER_ID]); + + const response = NextResponse.json({ message: 'OK' }); + response.headers.set('Set-Cookie', serialize('session', sessionId, { + httpOnly: true, + secure: false, //process.env.NODE_ENV === 'production', + maxAge: 60 * 60 * 24 * 7, + path: '/', + })); + + return response; +} \ No newline at end of file diff --git a/src/app/api/logout/route.js b/src/app/api/logout/route.js new file mode 100644 index 0000000..ed27b12 --- /dev/null +++ b/src/app/api/logout/route.js @@ -0,0 +1,22 @@ +import { NextResponse } from 'next/server'; +import { serialize } from 'cookie'; +import { db } from '@/app/lib/db'; +import { cookies } from 'next/headers'; + +export async function POST() { + const session_id = (await cookies()).get('session'); + const [rows] = await (await db).query('DELETE FROM sessions WHERE SESSION_ID = ?', [session_id.value]); + + if (rows.affectedRows === 0) { + return NextResponse.json({ message: 'No session with the provided ID' }, { status: 500 }); + } + + const response = NextResponse.json({ message: 'OK' }); + response.headers.set('Set-Cookie', serialize('session', '', { + httpOnly: true, + secure: process.env.NODE_ENV === 'production', + maxAge: -1, + path: '/', + })); + return response; +} \ No newline at end of file diff --git a/src/app/api/mail/validate/route.js b/src/app/api/mail/validate/route.js new file mode 100644 index 0000000..bfad79c --- /dev/null +++ b/src/app/api/mail/validate/route.js @@ -0,0 +1,67 @@ +import { baseMail, transporter } from "@/app/lib/mailer"; +import { NextResponse } from "next/server"; +import { db } from "@/app/lib/db"; + +export async function POST(req) { + const { email } = await req.json(); + + if (!email) { + return NextResponse.json({ message: 'Invalid email' }, { status: 400 }); + } + + const validate_token = Math.random().toString(36).substr(2, 10); + + await (await db).query('UPDATE users SET VALIDATE_TOKEN = ? WHERE EMAIL = ?', [validate_token, email]); + + const mailOptions = { + from: '"InfoGare" ', + to: email, + replyTo: 'contact@infogare.fr', + subject: 'Validation de votre email', + html: baseMail('Validation de votre email', ` +

Bonjour,

+

+ Merci de nous avoir rejoints ! Nous sommes ravis de vous compter parmi + nous. Cliquez sur le bouton ci-dessous pour confirmer votre email et + commencer à utiliser InfoGare. +

+ +

+ Si vous avez des questions, n'hésitez pas à nous contacter à + contact@infogare.fr. +

+

Merci,

+

L'équipe InfoGare

+ `) + }; + + const res = await transporter.sendMail(mailOptions); + + if (res.accepted.length === 0) { + return NextResponse.json({ message: 'Invalid email' }, { status: 400 }); + } else { + return NextResponse.json({ message: 'OK' }); + } +} + +export async function GET(req) { + const token = req.nextUrl.searchParams.get('token'); + + if (!token) { + return NextResponse.json({ message: 'Invalid token' }, { status: 400 }); + } + + const [rows] = await (await db).query('SELECT EMAIL FROM users WHERE VALIDATE_TOKEN = ?', [token]); + + if (rows.length === 0) { + return NextResponse.json({ message: 'Invalid token' }, { status: 400 }); + } + + await (await db).query('UPDATE users SET EMAIL_VALID = 1, VALIDATE_TOKEN = NULL WHERE VALIDATE_TOKEN = ?', [token]); + + return NextResponse.json({ email: rows[0].EMAIL }); +} \ No newline at end of file diff --git a/src/app/api/register/route.js b/src/app/api/register/route.js new file mode 100644 index 0000000..519b005 --- /dev/null +++ b/src/app/api/register/route.js @@ -0,0 +1,22 @@ +import { db } from "../../lib/db"; +import bcrypt from "bcrypt"; +import { NextResponse } from "next/server"; +import { v4 as uuidv4 } from "uuid"; + +export async function POST(req) { + + const { email, password, username } = await req.json(); + const userId = uuidv4(); + + const [rows] = await (await db).query('SELECT * FROM users WHERE EMAIL = ? OR USERNAME = ? OR USER_ID = ?', [email, username, userId]); + + if (rows.length !== 0) { + return NextResponse.json({ message: 'User already exists' }, { status: 409 }); + } + + + const hash = await bcrypt.hash(password, 10); + await (await db).query('INSERT INTO users (USER_ID, EMAIL, PASSWORD, USERNAME) VALUES (?, ?, ?, ?)', [userId, email, hash, username]); + + return NextResponse.json({ message: 'OK' }); +} \ No newline at end of file diff --git a/src/app/api/socket/route.js b/src/app/api/socket/route.js new file mode 100644 index 0000000..9da22fc --- /dev/null +++ b/src/app/api/socket/route.js @@ -0,0 +1,52 @@ +import { Server } from "socket.io"; +import { NextResponse } from "next/server"; + +let io; + +export async function POST(req) { + if (!res.socket.server) { + console.log('Init socket server'); + io = new Server(req.socket.server, { + cors: { + origin: '*', + methods: ['GET', 'POST'], + }, + }); + + io.on('connection', (socket) => { + console.log('Client connected'); + + socket.on('disconnect', () => { + console.log('Client disconnected'); + }); + }); + + res.socket.server = io; + } + + return NextResponse.json({ message: 'Socket server initialized' }, { status: 200 }); +} + +export async function GET(req) { + if (!res.socket.server) { + console.log('Init socket server'); + io = new Server(req.socket.server, { + cors: { + origin: '*', + methods: ['GET', 'POST'], + }, + }); + + io.on('connection', (socket) => { + console.log('Client connected'); + + socket.on('disconnect', () => { + console.log('Client disconnected'); + }); + }); + + res.socket.server = io; + } + + return NextResponse.json({ message: 'Socket server initialized' }, { status: 200 }); +} \ No newline at end of file diff --git a/src/app/api/stats/route.js b/src/app/api/stats/route.js new file mode 100644 index 0000000..f7c7776 --- /dev/null +++ b/src/app/api/stats/route.js @@ -0,0 +1,21 @@ +import { getUserFromSession } from "@/app/lib/auth"; +import { db } from "@/app/lib/db"; +import { NextResponse } from "next/server"; + +export async function POST(req) { + const { delta, entries, id, name, navigationType, rating, value } = await req.json(); + const { user } = await getUserFromSession(); + + if (!user) { + user = { USER_ID: null }; + } + + const headers = (await req).headers; + + const [rows] = await (await db).query( + "INSERT INTO statistics (DELTA, ENTRIES, EVENT_ID, NAME, NAVIGATION_TYPE, RATING, VALUE, USER, PAGE) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", + [delta, JSON.stringify(entries), id, name, navigationType, rating, value, user.USER_ID, headers.get("referer")], + ); + + return NextResponse.json({ success: true }); +} \ No newline at end of file diff --git a/src/app/api/tod/route.js b/src/app/api/tod/route.js new file mode 100644 index 0000000..64093bb --- /dev/null +++ b/src/app/api/tod/route.js @@ -0,0 +1,21 @@ +import { NextResponse } from "next/server"; +import { db } from "@/app/lib/db"; + +export async function GET(req) { + const [rows] = await (await db).query("SELECT ID, USER_ID FROM gares WHERE SHARED = 1"); + + if (rows.length === 0) { + return NextResponse.json({ train: {}, user: {} }, { status: 404 }); + } + + // Select a random row + const randomRow = rows[Math.floor(Math.random() * rows.length)]; + const [rows1] = await (await db).query("SELECT DESTINATION, NUMBER FROM trains WHERE GARE_ID = ?", [randomRow.ID]); + + // Select a random row + const randomRow1 = rows1[Math.floor(Math.random() * rows1.length)]; + + const [rows2] = await (await db).query("SELECT USERNAME FROM users WHERE USER_ID = ?", [randomRow.USER_ID]); + + return NextResponse.json({ train: randomRow1, user: rows2 }); +} \ No newline at end of file diff --git a/src/app/api/trains/route.js b/src/app/api/trains/route.js new file mode 100644 index 0000000..27ae375 --- /dev/null +++ b/src/app/api/trains/route.js @@ -0,0 +1,27 @@ +import { db } from "@/app/lib/db"; +import { notifyClients } from "@/app/lib/socket_server"; +import { NextResponse } from "next/server"; + +export async function GET(req) { + const id = req.nextUrl.searchParams.get('gare_id'); + + if (!id) { + return NextResponse.json({ error: 'Missing id' }, { status: 400 }); + } + + const [rows] = await (await db).query("SELECT * FROM trains WHERE GARE_ID = ?", [id]); + const [rows2] = await (await db).query("SELECT ID FROM gares WHERE ID = ?", [id]); + + if (rows.length === 0 && rows2.length === 0) { + return NextResponse.json({ error: 'Not found' }, { status: 404 }); + } else if (rows.length === 0 && rows2.length !== 0) { + return NextResponse.json({ error: 'No trains found for this station' }, { status: 410 }); + } + + return NextResponse.json(rows); +} + +export async function POST(req) { + notifyClients('db-update', req.body); + return NextResponse.json({ message: 'OK'}, { status: 200 }) +} \ No newline at end of file diff --git a/src/app/assets/logos-monochrome/Thumbs.db b/src/app/assets/logos-monochrome/Thumbs.db new file mode 100644 index 0000000..69f8e8e Binary files /dev/null and b/src/app/assets/logos-monochrome/Thumbs.db differ diff --git a/src/app/assets/logos-monochrome/logo-aleop.svg b/src/app/assets/logos-monochrome/logo-aleop.svg new file mode 100644 index 0000000..5f5165b --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-aleop.svg @@ -0,0 +1,164 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/assets/logos-monochrome/logo-auvergerhonealpes.svg b/src/app/assets/logos-monochrome/logo-auvergerhonealpes.svg new file mode 100644 index 0000000..eb0f7a9 --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-auvergerhonealpes.svg @@ -0,0 +1,88 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/src/app/assets/logos-monochrome/logo-breizhgo.svg b/src/app/assets/logos-monochrome/logo-breizhgo.svg new file mode 100644 index 0000000..66374ce --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-breizhgo.svg @@ -0,0 +1,108 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/src/app/assets/logos-monochrome/logo-cfl.svg b/src/app/assets/logos-monochrome/logo-cfl.svg new file mode 100644 index 0000000..bbe7eeb --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-cfl.svg @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/app/assets/logos-monochrome/logo-db.svg b/src/app/assets/logos-monochrome/logo-db.svg new file mode 100644 index 0000000..e0097ae --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-db.svg @@ -0,0 +1,5 @@ + + + + diff --git a/src/app/assets/logos-monochrome/logo-eurostar.svg b/src/app/assets/logos-monochrome/logo-eurostar.svg new file mode 100644 index 0000000..d8bcd0e --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-eurostar.svg @@ -0,0 +1,314 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/assets/logos-monochrome/logo-fluo.svg b/src/app/assets/logos-monochrome/logo-fluo.svg new file mode 100644 index 0000000..ca4808e --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-fluo.svg @@ -0,0 +1,40 @@ + + + + + + + + + + diff --git a/src/app/assets/logos-monochrome/logo-frecciarossa.svg b/src/app/assets/logos-monochrome/logo-frecciarossa.svg new file mode 100644 index 0000000..a6d51a2 --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-frecciarossa.svg @@ -0,0 +1,74 @@ + + + + + + + + + + + + + diff --git a/src/app/assets/logos-monochrome/logo-hautsdefrance.svg b/src/app/assets/logos-monochrome/logo-hautsdefrance.svg new file mode 100644 index 0000000..7920781 --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-hautsdefrance.svg @@ -0,0 +1,221 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/src/app/assets/logos-monochrome/logo-ice.svg b/src/app/assets/logos-monochrome/logo-ice.svg new file mode 100644 index 0000000..04edf83 --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-ice.svg @@ -0,0 +1 @@ +ice \ No newline at end of file diff --git a/src/app/assets/logos-monochrome/logo-inoui.svg b/src/app/assets/logos-monochrome/logo-inoui.svg new file mode 100644 index 0000000..2e7aff3 --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-inoui.svg @@ -0,0 +1 @@ +inoui \ No newline at end of file diff --git a/src/app/assets/logos-monochrome/logo-intercites.svg b/src/app/assets/logos-monochrome/logo-intercites.svg new file mode 100644 index 0000000..4ca3e44 --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-intercites.svg @@ -0,0 +1,107 @@ + + + +image/svg+xml + + + \ No newline at end of file diff --git a/src/app/assets/logos-monochrome/logo-ler.svg b/src/app/assets/logos-monochrome/logo-ler.svg new file mode 100644 index 0000000..654c54d --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-ler.svg @@ -0,0 +1,214 @@ + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/app/assets/logos-monochrome/logo-lio.svg b/src/app/assets/logos-monochrome/logo-lio.svg new file mode 100644 index 0000000..6d98c14 --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-lio.svg @@ -0,0 +1,43 @@ + \ No newline at end of file diff --git a/src/app/assets/logos-monochrome/logo-lunea.svg b/src/app/assets/logos-monochrome/logo-lunea.svg new file mode 100644 index 0000000..269d090 --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-lunea.svg @@ -0,0 +1,74 @@ + + + + + + + + + + + + + diff --git a/src/app/assets/logos-monochrome/logo-lyria.svg b/src/app/assets/logos-monochrome/logo-lyria.svg new file mode 100644 index 0000000..6cab5c2 --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-lyria.svg @@ -0,0 +1 @@ +lyria \ No newline at end of file diff --git a/src/app/assets/logos-monochrome/logo-metrolor.svg b/src/app/assets/logos-monochrome/logo-metrolor.svg new file mode 100644 index 0000000..167f70d --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-metrolor.svg @@ -0,0 +1,338 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/assets/logos-monochrome/logo-mobigo.svg b/src/app/assets/logos-monochrome/logo-mobigo.svg new file mode 100644 index 0000000..378c87b --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-mobigo.svg @@ -0,0 +1,332 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/assets/logos-monochrome/logo-nomad.svg b/src/app/assets/logos-monochrome/logo-nomad.svg new file mode 100644 index 0000000..7bcfed0 --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-nomad.svg @@ -0,0 +1,13 @@ + + + + + Logo Nomad Normandie 2020Plan de travail 8 + + + + + + + + \ No newline at end of file diff --git a/src/app/assets/logos-monochrome/logo-occitanie.svg b/src/app/assets/logos-monochrome/logo-occitanie.svg new file mode 100644 index 0000000..8e16d69 --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-occitanie.svg @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/assets/logos-monochrome/logo-ouigo-classique.svg b/src/app/assets/logos-monochrome/logo-ouigo-classique.svg new file mode 100644 index 0000000..d71246d --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-ouigo-classique.svg @@ -0,0 +1,578 @@ + + + + + + + + + + diff --git a/src/app/assets/logos-monochrome/logo-ouigo.svg b/src/app/assets/logos-monochrome/logo-ouigo.svg new file mode 100644 index 0000000..1df8e54 --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-ouigo.svg @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/assets/logos-monochrome/logo-remi.svg b/src/app/assets/logos-monochrome/logo-remi.svg new file mode 100644 index 0000000..5ce6f2e --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-remi.svg @@ -0,0 +1,381 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/src/app/assets/logos-monochrome/logo-renfeave.svg b/src/app/assets/logos-monochrome/logo-renfeave.svg new file mode 100644 index 0000000..c2ad14b --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-renfeave.svg @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + diff --git a/src/app/assets/logos-monochrome/logo-rer-a.svg b/src/app/assets/logos-monochrome/logo-rer-a.svg new file mode 100644 index 0000000..88c53a9 --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-rer-a.svg @@ -0,0 +1,111 @@ + + + + + + + + + + +]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/assets/logos-monochrome/logo-rer-b.svg b/src/app/assets/logos-monochrome/logo-rer-b.svg new file mode 100644 index 0000000..a436c13 --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-rer-b.svg @@ -0,0 +1,119 @@ + + + + + + + + + + +]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/assets/logos-monochrome/logo-rer-c.svg b/src/app/assets/logos-monochrome/logo-rer-c.svg new file mode 100644 index 0000000..b193af0 --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-rer-c.svg @@ -0,0 +1,116 @@ + + + + + + + + + + +]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/assets/logos-monochrome/logo-rer-d.svg b/src/app/assets/logos-monochrome/logo-rer-d.svg new file mode 100644 index 0000000..87cc429 --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-rer-d.svg @@ -0,0 +1,113 @@ + + + + + + + + + + +]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/assets/logos-monochrome/logo-rer-e.svg b/src/app/assets/logos-monochrome/logo-rer-e.svg new file mode 100644 index 0000000..104ca17 --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-rer-e.svg @@ -0,0 +1,198 @@ + + + +image/svg+xml + + .st0{display:none;} + .st1{display:inline;fill:none;} + .st2{display:inline;fill:#050D9E;} + .st3{fill:#FFFFFF;} + .st4{fill:none;} + .st5{fill:#5E9620;} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/app/assets/logos-monochrome/logo-sbb.svg b/src/app/assets/logos-monochrome/logo-sbb.svg new file mode 100644 index 0000000..290a9a2 --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-sbb.svg @@ -0,0 +1,5 @@ + + +SBB CFF FFS logo notext + + diff --git a/src/app/assets/logos-monochrome/logo-sncb.svg b/src/app/assets/logos-monochrome/logo-sncb.svg new file mode 100644 index 0000000..b0b4ef8 --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-sncb.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/app/assets/logos-monochrome/logo-sncf.svg b/src/app/assets/logos-monochrome/logo-sncf.svg new file mode 100644 index 0000000..1ff9399 --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-sncf.svg @@ -0,0 +1,99 @@ + + + +image/svg+xml + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/app/assets/logos-monochrome/logo-sncf1985.svg b/src/app/assets/logos-monochrome/logo-sncf1985.svg new file mode 100644 index 0000000..8148792 --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-sncf1985.svg @@ -0,0 +1,63 @@ + + + + + + + + + image/svg+xml + + + + + + + + diff --git a/src/app/assets/logos-monochrome/logo-sncf1992.svg b/src/app/assets/logos-monochrome/logo-sncf1992.svg new file mode 100644 index 0000000..30bf7d8 --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-sncf1992.svg @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/app/assets/logos-monochrome/logo-t-h.svg b/src/app/assets/logos-monochrome/logo-t-h.svg new file mode 100644 index 0000000..d9a48bc --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-t-h.svg @@ -0,0 +1,116 @@ + + + + + + + + + + +]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/assets/logos-monochrome/logo-t-j.svg b/src/app/assets/logos-monochrome/logo-t-j.svg new file mode 100644 index 0000000..22264bc --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-t-j.svg @@ -0,0 +1,123 @@ + + + + + + + + + + +]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/assets/logos-monochrome/logo-t-k.svg b/src/app/assets/logos-monochrome/logo-t-k.svg new file mode 100644 index 0000000..ecb584b --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-t-k.svg @@ -0,0 +1,125 @@ + + + + + + + + + + +]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/assets/logos-monochrome/logo-t-l.svg b/src/app/assets/logos-monochrome/logo-t-l.svg new file mode 100644 index 0000000..25b1040 --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-t-l.svg @@ -0,0 +1,124 @@ + + + + + + + + + + +]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/assets/logos-monochrome/logo-t-n.svg b/src/app/assets/logos-monochrome/logo-t-n.svg new file mode 100644 index 0000000..429d848 --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-t-n.svg @@ -0,0 +1,138 @@ + + + + + + + + + + +]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/assets/logos-monochrome/logo-t-p.svg b/src/app/assets/logos-monochrome/logo-t-p.svg new file mode 100644 index 0000000..7352116 --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-t-p.svg @@ -0,0 +1,134 @@ + + + + + + + + + + +]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/assets/logos-monochrome/logo-t-r.svg b/src/app/assets/logos-monochrome/logo-t-r.svg new file mode 100644 index 0000000..8b3a779 --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-t-r.svg @@ -0,0 +1,138 @@ + + + + + + + + + + +]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/assets/logos-monochrome/logo-t-u.svg b/src/app/assets/logos-monochrome/logo-t-u.svg new file mode 100644 index 0000000..ea80349 --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-t-u.svg @@ -0,0 +1,133 @@ + + + + + + + + + + +]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/assets/logos-monochrome/logo-teoz.svg b/src/app/assets/logos-monochrome/logo-teoz.svg new file mode 100644 index 0000000..dfa76cc --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-teoz.svg @@ -0,0 +1,74 @@ + + + + + + + + + + + + + diff --git a/src/app/assets/logos-monochrome/logo-ter-rhone-alpes.svg b/src/app/assets/logos-monochrome/logo-ter-rhone-alpes.svg new file mode 100644 index 0000000..73114e9 --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-ter-rhone-alpes.svg @@ -0,0 +1,401 @@ + + + + diff --git a/src/app/assets/logos-monochrome/logo-ter.svg b/src/app/assets/logos-monochrome/logo-ter.svg new file mode 100644 index 0000000..7218a81 --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-ter.svg @@ -0,0 +1 @@ +ter \ No newline at end of file diff --git a/src/app/assets/logos-monochrome/logo-teralsace.svg b/src/app/assets/logos-monochrome/logo-teralsace.svg new file mode 100644 index 0000000..d3792b4 --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-teralsace.svg @@ -0,0 +1,146 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/assets/logos-monochrome/logo-teraquitaine.svg b/src/app/assets/logos-monochrome/logo-teraquitaine.svg new file mode 100644 index 0000000..17fb86d --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-teraquitaine.svg @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/assets/logos-monochrome/logo-terbassenormandie.svg b/src/app/assets/logos-monochrome/logo-terbassenormandie.svg new file mode 100644 index 0000000..ee82ffd --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-terbassenormandie.svg @@ -0,0 +1,254 @@ + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/assets/logos-monochrome/logo-terbourgogne.svg b/src/app/assets/logos-monochrome/logo-terbourgogne.svg new file mode 100644 index 0000000..983d201 --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-terbourgogne.svg @@ -0,0 +1,120 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/assets/logos-monochrome/logo-terbretagne.svg b/src/app/assets/logos-monochrome/logo-terbretagne.svg new file mode 100644 index 0000000..47a3c07 --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-terbretagne.svg @@ -0,0 +1,186 @@ + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/assets/logos-monochrome/logo-tercentre.svg b/src/app/assets/logos-monochrome/logo-tercentre.svg new file mode 100644 index 0000000..03d9542 --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-tercentre.svg @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + diff --git a/src/app/assets/logos-monochrome/logo-terlanguedocroussillon.svg b/src/app/assets/logos-monochrome/logo-terlanguedocroussillon.svg new file mode 100644 index 0000000..8453520 --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-terlanguedocroussillon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/app/assets/logos-monochrome/logo-termidipyrenees.svg b/src/app/assets/logos-monochrome/logo-termidipyrenees.svg new file mode 100644 index 0000000..fee1a9b --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-termidipyrenees.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/app/assets/logos-monochrome/logo-ternordpasdecalais.svg b/src/app/assets/logos-monochrome/logo-ternordpasdecalais.svg new file mode 100644 index 0000000..c6aaa8f --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-ternordpasdecalais.svg @@ -0,0 +1,293 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/assets/logos-monochrome/logo-terpoitoucharentes.svg b/src/app/assets/logos-monochrome/logo-terpoitoucharentes.svg new file mode 100644 index 0000000..33c1838 --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-terpoitoucharentes.svg @@ -0,0 +1,367 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/assets/logos-monochrome/logo-tgv.svg b/src/app/assets/logos-monochrome/logo-tgv.svg new file mode 100644 index 0000000..657ba99 --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-tgv.svg @@ -0,0 +1,211 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + diff --git a/src/app/assets/logos-monochrome/logo-thalys.svg b/src/app/assets/logos-monochrome/logo-thalys.svg new file mode 100644 index 0000000..41a6abc --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-thalys.svg @@ -0,0 +1,94 @@ + + + +image/svg+xml + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/app/assets/logos-monochrome/logo-thello.svg b/src/app/assets/logos-monochrome/logo-thello.svg new file mode 100644 index 0000000..6a6513e --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-thello.svg @@ -0,0 +1,678 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/src/app/assets/logos-monochrome/logo-tramtrain.svg b/src/app/assets/logos-monochrome/logo-tramtrain.svg new file mode 100644 index 0000000..4e66679 --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-tramtrain.svg @@ -0,0 +1,112 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + diff --git a/src/app/assets/logos-monochrome/logo-trenitalia.svg b/src/app/assets/logos-monochrome/logo-trenitalia.svg new file mode 100644 index 0000000..4924915 --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-trenitalia.svg @@ -0,0 +1,74 @@ + + + + + + + + + + + + + diff --git a/src/app/assets/logos-monochrome/logo-zou.svg b/src/app/assets/logos-monochrome/logo-zou.svg new file mode 100644 index 0000000..2936f2f --- /dev/null +++ b/src/app/assets/logos-monochrome/logo-zou.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/app/assets/logos-monochrome/track-car.svg b/src/app/assets/logos-monochrome/track-car.svg new file mode 100644 index 0000000..a7f0b0e --- /dev/null +++ b/src/app/assets/logos-monochrome/track-car.svg @@ -0,0 +1,25 @@ + + + + + + + + + + diff --git a/src/app/assets/row-background-arrivals.svg b/src/app/assets/row-background-arrivals.svg new file mode 100644 index 0000000..32367fa --- /dev/null +++ b/src/app/assets/row-background-arrivals.svg @@ -0,0 +1,140 @@ + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/app/assets/row-background-departures.svg b/src/app/assets/row-background-departures.svg new file mode 100644 index 0000000..a7b4128 --- /dev/null +++ b/src/app/assets/row-background-departures.svg @@ -0,0 +1,136 @@ + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/app/assets/train_court.png b/src/app/assets/train_court.png new file mode 100644 index 0000000..598e681 Binary files /dev/null and b/src/app/assets/train_court.png differ diff --git a/src/app/assets/train_long.png b/src/app/assets/train_long.png new file mode 100644 index 0000000..42d91c3 Binary files /dev/null and b/src/app/assets/train_long.png differ diff --git a/src/app/components/appbar.js b/src/app/components/appbar.js new file mode 100644 index 0000000..6b3247a --- /dev/null +++ b/src/app/components/appbar.js @@ -0,0 +1,78 @@ +'use client' +import * as React from 'react'; +import Image from 'next/image'; +import Link from 'next/link'; + +import { Avatar, IconButton, Menu, MenuItem, Typography, Toolbar, Box, AppBar } from '@mui/material'; +import LogoutDialog from './logoutdialog'; +import { Login } from '@mui/icons-material'; + + +function ResponsiveAppBar() { + + const [anchorEl, setAnchorEl] = React.useState(null); + const [logoutOpen, setLogoutOpen] = React.useState(false); + const [user, setUser] = React.useState({ isLoggedIn: false }); + + React.useEffect(() => { + const getUser = async () => { + const res = await fetch('/api/auth/user', { + method: 'GET', + headers: { 'Content-Type': 'application/json' }, + }); + + if (res.status === 200) { + const user = await res.json(); + setUser({ isLoggedIn: true, username: user.user.USERNAME, email: user.user.EMAIL, rights: user.user.RIGHTS }); + } else { + setUser({ isLoggedIn: false }); + } + } + + getUser(); + }, []); + + const handleOpenUserMenu = (event) => { + setAnchorEl(event.currentTarget); + } + + const handleCloseUserMenu = () => { + setAnchorEl(null); + } + + const setLogoutOpenState = (open) => () => { + setLogoutOpen(open); + } + + return ( + + + + + Logo + + + InfoGare + + {user.isLoggedIn ? <> + + {user.username.substring(0, 1)} + + + {user.username} + InfoGare Creator + {user.rights.includes('admin') ? Administration : null} + Se déconnecter + + : <> + + + + } + + + { setLogoutOpen(false) }} /> + + ); +} +export default ResponsiveAppBar; \ No newline at end of file diff --git a/src/app/components/logoutdialog.js b/src/app/components/logoutdialog.js new file mode 100644 index 0000000..ef570fe --- /dev/null +++ b/src/app/components/logoutdialog.js @@ -0,0 +1,33 @@ +'use client' +import * as React from 'react'; +import { Button, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle } from '@mui/material'; +import { redirect } from 'next/navigation'; + +export default function LogoutDialog({ open, handleClose }) { + + const handleLogout = () => { + fetch('/api/logout', { method: 'POST' }) + .then(response => { + if (response.status === 200) { + redirect('/'); + } else { + console.error('Failed to logout'); + } + }); + } + + return ( + + Se déconnecter + + + Êtes-vous sûr de vouloir vous déconnecter ? + + + + + + + + ); +} \ No newline at end of file diff --git a/src/app/fonts/Achemine/achemin_italic.eot b/src/app/fonts/Achemine/achemin_italic.eot new file mode 100644 index 0000000..675ab56 Binary files /dev/null and b/src/app/fonts/Achemine/achemin_italic.eot differ diff --git a/src/app/fonts/Achemine/achemin_italic.svg b/src/app/fonts/Achemine/achemin_italic.svg new file mode 100644 index 0000000..8a713c3 --- /dev/null +++ b/src/app/fonts/Achemine/achemin_italic.svg @@ -0,0 +1,566 @@ + + + + +Created by FontForge 20090622 at Wed Mar 22 13:48:55 2017 + By deploy user +(c) SNCF, 2007. Auteur Bruno Bernard. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/fonts/Achemine/achemin_italic.ttf b/src/app/fonts/Achemine/achemin_italic.ttf new file mode 100644 index 0000000..0e231b5 Binary files /dev/null and b/src/app/fonts/Achemine/achemin_italic.ttf differ diff --git a/src/app/fonts/Achemine/achemin_italic.woff b/src/app/fonts/Achemine/achemin_italic.woff new file mode 100644 index 0000000..2bd9a8d Binary files /dev/null and b/src/app/fonts/Achemine/achemin_italic.woff differ diff --git a/src/app/fonts/Achemine/achemine_bold.eot b/src/app/fonts/Achemine/achemine_bold.eot new file mode 100644 index 0000000..2f6017e Binary files /dev/null and b/src/app/fonts/Achemine/achemine_bold.eot differ diff --git a/src/app/fonts/Achemine/achemine_bold.svg b/src/app/fonts/Achemine/achemine_bold.svg new file mode 100644 index 0000000..aa4f93d --- /dev/null +++ b/src/app/fonts/Achemine/achemine_bold.svg @@ -0,0 +1,284 @@ + + + + +Created by FontForge 20090622 at Fri Aug 28 01:46:46 2015 + By deploy user + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/app/fonts/Achemine/achemine_bold.ttf b/src/app/fonts/Achemine/achemine_bold.ttf new file mode 100644 index 0000000..543c81a Binary files /dev/null and b/src/app/fonts/Achemine/achemine_bold.ttf differ diff --git a/src/app/fonts/Achemine/achemine_bold.woff b/src/app/fonts/Achemine/achemine_bold.woff new file mode 100644 index 0000000..5d9fd55 Binary files /dev/null and b/src/app/fonts/Achemine/achemine_bold.woff differ diff --git a/src/app/fonts/Achemine/achemine_extrabold.eot b/src/app/fonts/Achemine/achemine_extrabold.eot new file mode 100644 index 0000000..7722875 Binary files /dev/null and b/src/app/fonts/Achemine/achemine_extrabold.eot differ diff --git a/src/app/fonts/Achemine/achemine_extrabold.svg b/src/app/fonts/Achemine/achemine_extrabold.svg new file mode 100644 index 0000000..2216dd4 --- /dev/null +++ b/src/app/fonts/Achemine/achemine_extrabold.svg @@ -0,0 +1,681 @@ + + + + +Created by FontForge 20161013 at Tue Dec 20 21:35:14 2016 + By ,,, +(c) SNCF, 2007. Auteur Bruno Bernard. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/fonts/Achemine/achemine_extrabold.ttf b/src/app/fonts/Achemine/achemine_extrabold.ttf new file mode 100644 index 0000000..0477fe3 Binary files /dev/null and b/src/app/fonts/Achemine/achemine_extrabold.ttf differ diff --git a/src/app/fonts/Achemine/achemine_extrabold.woff b/src/app/fonts/Achemine/achemine_extrabold.woff new file mode 100644 index 0000000..133bebb Binary files /dev/null and b/src/app/fonts/Achemine/achemine_extrabold.woff differ diff --git a/src/app/fonts/Achemine/achemine_normal.eot b/src/app/fonts/Achemine/achemine_normal.eot new file mode 100644 index 0000000..63f02d0 Binary files /dev/null and b/src/app/fonts/Achemine/achemine_normal.eot differ diff --git a/src/app/fonts/Achemine/achemine_normal.svg b/src/app/fonts/Achemine/achemine_normal.svg new file mode 100644 index 0000000..a30631f --- /dev/null +++ b/src/app/fonts/Achemine/achemine_normal.svg @@ -0,0 +1,272 @@ + + + + +Created by FontForge 20090622 at Fri Aug 28 01:45:28 2015 + By deploy user + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/app/fonts/Achemine/achemine_normal.ttf b/src/app/fonts/Achemine/achemine_normal.ttf new file mode 100644 index 0000000..351d7dc Binary files /dev/null and b/src/app/fonts/Achemine/achemine_normal.ttf differ diff --git a/src/app/fonts/Achemine/achemine_normal.woff b/src/app/fonts/Achemine/achemine_normal.woff new file mode 100644 index 0000000..ab3e4a5 Binary files /dev/null and b/src/app/fonts/Achemine/achemine_normal.woff differ diff --git a/src/app/fonts/Achemine/style.css b/src/app/fonts/Achemine/style.css new file mode 100644 index 0000000..3a229fa --- /dev/null +++ b/src/app/fonts/Achemine/style.css @@ -0,0 +1,40 @@ +@font-face { + font-family: "Achemine"; + src: url("achemine_normal.eot#iefix") format("embedded-opentype"), + url("achemine_normal.woff") format("woff"), + url("achemine_normal.ttf") format("truetype"), + url("achemine_normal.svg") format("svg"); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: "Achemine"; + src: url("achemine_bold.eot#iefix") format("embedded-opentype"), + url("achemine_bold.woff") format("woff"), + url("achemine_bold.ttf") format("truetype"), + url("achemine_bold.svg") format("svg"); + font-weight: bold; + font-style: normal; +} + +@font-face { + font-family: "Achemine"; + src: url("achemine_extrabold.eot#iefix") format("embedded-opentype"), + url("achemine_extrabold.woff") format("woff"), + url("achemine_extrabold.ttf") format("truetype"), + url("achemine_extrabold.svg") format("svg"); + font-weight: 800; + font-style: normal; +} + + +@font-face { + font-family: "Achemine"; + src: url("achemin_italic.eot#iefix") format("embedded-opentype"), + url("achemin_italic.woff") format("woff"), + url("achemin_italic.ttf") format("truetype"), + url("achemin_italic.svg#Achemine-Italic") format("svg"); + font-weight: normal; + font-style: italic; +} \ No newline at end of file diff --git a/src/app/fonts/Avenir/Metropolis-Bold.otf b/src/app/fonts/Avenir/Metropolis-Bold.otf new file mode 100644 index 0000000..a42b941 Binary files /dev/null and b/src/app/fonts/Avenir/Metropolis-Bold.otf differ diff --git a/src/app/fonts/Avenir/Metropolis-Light.otf b/src/app/fonts/Avenir/Metropolis-Light.otf new file mode 100644 index 0000000..b8b917c Binary files /dev/null and b/src/app/fonts/Avenir/Metropolis-Light.otf differ diff --git a/src/app/fonts/Avenir/Metropolis-Medium.otf b/src/app/fonts/Avenir/Metropolis-Medium.otf new file mode 100644 index 0000000..239d69d Binary files /dev/null and b/src/app/fonts/Avenir/Metropolis-Medium.otf differ diff --git a/src/app/fonts/Avenir/Metropolis-Regular.otf b/src/app/fonts/Avenir/Metropolis-Regular.otf new file mode 100644 index 0000000..737760b Binary files /dev/null and b/src/app/fonts/Avenir/Metropolis-Regular.otf differ diff --git a/src/app/fonts/Avenir/avenir_regular.eot b/src/app/fonts/Avenir/avenir_regular.eot new file mode 100644 index 0000000..2436099 Binary files /dev/null and b/src/app/fonts/Avenir/avenir_regular.eot differ diff --git a/src/app/fonts/Avenir/avenir_regular.svg b/src/app/fonts/Avenir/avenir_regular.svg new file mode 100644 index 0000000..1fdda7b --- /dev/null +++ b/src/app/fonts/Avenir/avenir_regular.svg @@ -0,0 +1,255 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/app/fonts/Avenir/avenir_regular.ttf b/src/app/fonts/Avenir/avenir_regular.ttf new file mode 100644 index 0000000..2ff74a0 Binary files /dev/null and b/src/app/fonts/Avenir/avenir_regular.ttf differ diff --git a/src/app/fonts/Avenir/avenir_regular.ttfg b/src/app/fonts/Avenir/avenir_regular.ttfg new file mode 100644 index 0000000..add67d3 Binary files /dev/null and b/src/app/fonts/Avenir/avenir_regular.ttfg differ diff --git a/src/app/fonts/Avenir/avenir_regular.woff b/src/app/fonts/Avenir/avenir_regular.woff new file mode 100644 index 0000000..096ad99 Binary files /dev/null and b/src/app/fonts/Avenir/avenir_regular.woff differ diff --git a/src/app/fonts/Avenir/style.css b/src/app/fonts/Avenir/style.css new file mode 100644 index 0000000..073bbb1 --- /dev/null +++ b/src/app/fonts/Avenir/style.css @@ -0,0 +1,10 @@ +@font-face { + font-family: 'Avenir'; + src: url('avenir_regular.eot'); + src: url('avenir_regular.eot?#iefix') format('embedded-opentype'), + url('avenir_regular.woff') format('woff'), + url('avenir_regular.ttf') format('truetype'), + url('avenir_regular.svg#avenirregular') format('svg'); + font-weight: normal; + font-style: normal; +} \ No newline at end of file diff --git a/src/app/globals.css b/src/app/globals.css index 6b717ad..ee651f5 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -2,20 +2,132 @@ @tailwind components; @tailwind utilities; +@import url('https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap'); + :root { - --background: #ffffff; - --foreground: #171717; + --background: #ffffff; + --foreground: #171717; } @media (prefers-color-scheme: dark) { - :root { - --background: #0a0a0a; - --foreground: #ededed; - } + :root { + --background: #171717; + --foreground: #ededed; + } } body { - color: var(--foreground); - background: var(--background); - font-family: Arial, Helvetica, sans-serif; + color: var(--foreground); + background: var(--background); + font-family: Arial, Helvetica, sans-serif; } + +.home-background { + z-index: -1; + background-color: #2f4f4f; + height: 100vh; + width: 100vw; + position: absolute; + top: 0; + left: 0; + overflow: hidden; +} + +.home-background h2 { + font-family: 'Montserrat' sans-serif; + font-weight: bold; + font-size: 3vw; + text-transform: uppercase; + text-shadow: 3px 3px #16a085; +} + +.home-background .bg-1 { + position: absolute; + left: 0; + right: 0; + bottom: 0; + height: 40vw; + background-image: url('/assets/images/background.svg'); + background-size: cover; +} + +.home-background .bg-2 { + z-index: 999; + position: absolute; + top: 0; + bottom: 0; + right: 0; + left: 0; + background-image: url('/assets/images/background-moutains.svg'); + background-repeat: no-repeat; + background-position: bottom; + background-size: contain; +} + +.home-background .train { + position: absolute; + bottom: 0; + left: -50vw; + width: 100vw; + height: 22.5vw; + /* overflow: hidden; */ +} + +.train.moving { + animation: moving-train 20s linear infinite; +} + +.train .train-text { + font-family: 'Montserrat' sans-serif; + position: absolute; + top: -50px; + left: 25vw; + word-wrap: normal; + max-width: 250px; + height: 80px; + padding-left: 5px; + border-left: solid 1px #FFF; +} + +.train .moving-train { + display: flex; + align-items: baseline; +} + +.moving-train .wagon-l { + background-image: url('/assets/images/XGC_T2_AB_L.gif'); + background-size: contain; + background-repeat: no-repeat; + background-position: bottom right; + height: 3.7vw; + width: 16vw; +} + +.moving-train .wagon-m { + background-image: url('/assets/images/BRGC_T2_R.gif'); + background-size: contain; + background-repeat: no-repeat; + background-position: bottom; + height: 5vw; + width: 11.5vw; +} + +.moving-train .wagon-r { + background-image: url('/assets/images/XGC_T2_R.gif'); + background-size: contain; + background-repeat: no-repeat; + background-position: bottom left; + height: 3.7vw; + width: 16vw; +} + +@keyframes moving-train { + 0% { + left: -50vw; + ; + } + + 100% { + left: 125vw; + } +} \ No newline at end of file diff --git a/src/app/layout.js b/src/app/layout.js deleted file mode 100644 index 9800bf8..0000000 --- a/src/app/layout.js +++ /dev/null @@ -1,30 +0,0 @@ -import localFont from "next/font/local"; -import "./globals.css"; - -const geistSans = localFont({ - src: "./fonts/GeistVF.woff", - variable: "--font-geist-sans", - weight: "100 900", -}); -const geistMono = localFont({ - src: "./fonts/GeistMonoVF.woff", - variable: "--font-geist-mono", - weight: "100 900", -}); - -export const metadata = { - title: "Create Next App", - description: "Generated by create next app", -}; - -export default function RootLayout({ children }) { - return ( - - - {children} - - - ); -} diff --git a/src/app/lib/auth.js b/src/app/lib/auth.js new file mode 100644 index 0000000..37a35cf --- /dev/null +++ b/src/app/lib/auth.js @@ -0,0 +1,20 @@ +import { db } from "./db"; +import { cookies } from "next/headers"; + +export async function getUserFromSession() { + const sessionId = (await cookies()).get('session')?.value; + + if (!sessionId) { + return null; + } + + const [rows] = await (await db).query('SELECT * FROM sessions WHERE SESSION_ID = ?', [sessionId]); + if (rows.length === 0) { + return null; + } + + const [userRows] = await (await db).query('SELECT * FROM users WHERE USER_ID = ?', [rows[0].USER_ID]); + + + return { user: userRows.length ? userRows[0] : null, session: rows.length ? rows[0] : null }; +} \ No newline at end of file diff --git a/src/app/lib/authContext.js b/src/app/lib/authContext.js new file mode 100644 index 0000000..8899527 --- /dev/null +++ b/src/app/lib/authContext.js @@ -0,0 +1,37 @@ +'use client' + +import { createContext, useContext, useEffect, useState } from 'react'; + +export const AuthContext = createContext(); + +export function AuthProvider({ children }) { + const [user, setUser] = useState(null); + + useEffect(() => { + async function fetchUser() { + try { + const response = await fetch('/api/auth/user', { method: 'GET' }); + if (response.ok) { + const data = await response.json(); + setUser(data); + } else { + setUser({ isLoggedIn: false }); + } + } catch (error) { + console.error(error); + setUser({ isLoggedIn: false }); + } + } + fetchUser(); + }, []); + + return ( + + {children} + + ); +} + +export function useAuth() { + return useContext(AuthContext); +} \ No newline at end of file diff --git a/src/app/lib/authMiddleware.js b/src/app/lib/authMiddleware.js new file mode 100644 index 0000000..6bcab98 --- /dev/null +++ b/src/app/lib/authMiddleware.js @@ -0,0 +1,18 @@ +import { db } from "./db"; + +export async function middleware(handler) { + return async (req, res) => { + const sessionId = req.cookies.session; + if (!sessionId) { + return NextResponse.json({ message: 'Unauthorized' }, { status: 401 }); + } + + const [rows] = await (await db).query('SELECT * FROM sessions WHERE SESSION_ID = ?', [sessionId]); + if (rows.length === 0) { + return NextResponse.json({ message: 'Unauthorized' }, { status: 401 }); + } + + req.user = rows[0].USER_ID; + return handler(req); + }; +} \ No newline at end of file diff --git a/src/app/lib/db.js b/src/app/lib/db.js new file mode 100644 index 0000000..d71a31c --- /dev/null +++ b/src/app/lib/db.js @@ -0,0 +1,8 @@ +import { createConnection } from "mysql2/promise"; + +export const db = createConnection({ + host: "192.168.1.7", //"88.167.179.152", + user: 'infogare', + password: 'QTftGGEi3qUxcQON$', + database: 'infogare', +}); \ No newline at end of file diff --git a/src/app/lib/mailer.js b/src/app/lib/mailer.js new file mode 100644 index 0000000..542c365 --- /dev/null +++ b/src/app/lib/mailer.js @@ -0,0 +1,98 @@ +import nodemailer from 'nodemailer'; + +const transporter = nodemailer.createTransport({ + host: process.env.EMAIL_SMTP, + port: process.env.EMAIL_PORT, + secure: true, + auth: { + user: process.env.EMAIL_USER, + pass: process.env.EMAIL_PASS + } +}); + +const baseMail = (title, body) => { + return ` + + + + + + + + + + + + `; +} + +export { baseMail, transporter }; \ No newline at end of file diff --git a/src/app/lib/socket_server.js b/src/app/lib/socket_server.js new file mode 100644 index 0000000..5aa6e91 --- /dev/null +++ b/src/app/lib/socket_server.js @@ -0,0 +1,23 @@ +import { Server } from "socket.io"; + +let io; + +export function initSocketServer(server) { + if (!io) { + io = new Server(server); + + io.on('connection', (socket) => { + console.log('Client connected'); + + socket.on('disconnect', () => { + console.log('Client disconnected'); + }); + }); + } +} + +export function notifyClients(event, data) { + if (io) { + io.emit(event, data); + } +} \ No newline at end of file diff --git a/src/app/page.js b/src/app/page.js deleted file mode 100644 index 61edd89..0000000 --- a/src/app/page.js +++ /dev/null @@ -1,101 +0,0 @@ -import Image from "next/image"; - -export default function Home() { - return ( -
-
- Next.js logo -
    -
  1. - Get started by editing{" "} - - src/app/page.js - - . -
  2. -
  3. Save and see your changes instantly.
  4. -
- - -
- -
- ); -} diff --git a/src/app/styles/departs/trains.css b/src/app/styles/departs/trains.css new file mode 100644 index 0000000..f6d3879 --- /dev/null +++ b/src/app/styles/departs/trains.css @@ -0,0 +1,1517 @@ +/* -- compass -- */ +/* -- sass files -- */ +/* -- colors -- */ +/* -- colors (screen) -- */ +/* -- widths -- */ +/* -- base -- */ +@import url("https://fonts.googleapis.com/css?family=Roboto:100,300,100italic,300italic"); + +html, body { + width: 100%; + height: 100%; + margin: 0; + padding: 0; + -moz-text-size-adjust: none; + -ms-text-size-adjust: none; + -webkit-text-size-adjust: none; + text-size-adjust: none; + overflow-x: hidden; + -moz-background-size: contain; + -o-background-size: contain; + -webkit-background-size: contain; + background-size: contain; +} + +body { + font-family: 'Achemine'; + font-size: 1vh; + font-weight: normal; + line-height: 1; +} + +*, +:after, +:before { + outline: none; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +*:focus, +*:active, +:after:focus, +:after:active, +:before:focus, +:before:active { + outline: none; +} + +a { + color: inherit; + text-decoration: none; +} + +.rows { + position: relative; + left: 0; + width: 100%; + height: 100%; + -moz-transition: left 0.3s ease; + -o-transition: left 0.3s ease; + -webkit-transition: left 0.3s ease; + transition: left 0.3s ease; +} + +.rows .row-group { + height: 10%; +} + +.rows .row-group:hover { + cursor: default; +} + +.rows .row-group>.row { + display: table; + table-layout: fixed; + width: 100%; + height: 100%; + color: #fff; +} + +.rows .row-group>.row>div { + display: table-cell; + overflow: hidden; + line-height: 1.2; + vertical-align: text-bottom; +} + +.rows .row-group-hidden { + display: none; +} + + +/* -- sizes -- */ + +.rows .row-group.row-group-2 { + height: 20%; +} + +.rows .row-group.row-group-10 { + height: 100%; +} + + +/* -- bar -- */ + +.row-group-bar { + position: absolute; + bottom: 0; + height: 10%; + padding-left: 2vh; +} + +.row-group-bar.row-group-bar-yellow { + background: #ffbf51 !important; +} + +.row-group-bar.row-group-bar-yellow .text-scroll-x { + color: #003a79; + font-style: normal !important; +} + +.row-group-bar.row-group-bar-red { + background: #cd0037 !important; +} + +.row-group-bar.row-group-bar-red .text-scroll-x { + color: #ffffff; + font-style: normal !important; +} + +.row-group-bar.row-group-bar-purple { + background: #50077D !important; +} + +.row-group-bar.row-group-bar-purple .text-scroll-x { + color: #ffffff; + font-style: normal !important; +} + +.row-group-bar.row-group-bar-black { + background: #000000; +} + +.row-group-bar.row-group-bar-black .text-scroll-x { + color: #ffffff; + font-style: normal !important; +} + +.row-group-bar .col-first { + width: auto !important; + vertical-align: middle !important; +} + +.row-group-bar .col-first .bar-informations { + font-size: 7em; +} + +.row-group-bar .col-first .bar-informations { + font-size: 7em; +} + +.row-group-bar .col-second { + width: 30vh; + text-align: center; + vertical-align: bottom !important; +} + + +/* -- selection -- */ + +::selection { + color: white; + background: #006f94; +} + +::-moz-selection { + color: white; + background: #006f94; +} + +.alert { + position: relative; + margin-bottom: 20px; + padding: 20px 20px 20px 80px; + color: #fff; + font-size: 16px; + font-family: 'Roboto'; + line-height: 1.3; + background: #e74c3c; +} + +.alert.alert-flash { + position: fixed; + top: 7px; + right: 0; + margin-bottom: 0; + z-index: 5000; + animation: alert 4s ease forwards; +} + +.alert.alert-success { + background: #006f94; +} + +.alert.alert-success .icon { + background: #006f94; +} + +.alert.alert-success .icon:before { + content: '\e116'; +} + +.alert.alert-info { + color: #878787; + background: #ededed; +} + +.alert.alert-info .icon { + background: #e0e0e0; +} + +.alert.alert-info .icon:before { + content: '\e60a'; +} + +.alert .icon { + position: absolute; + top: 0; + left: 0; + width: 60px; + height: 100%; + padding: 22px 0; + font-family: 'icomoon'; + text-align: center; + background: #d62c1a; +} + +.alert .icon:before { + content: '\e117'; +} + +@keyframes alert { + 0% { + opacity: 0; + transform: translateX(100%); + } + + 10% { + opacity: 1; + transform: translateX(0%); + } + + 90% { + opacity: 1; + transform: translateX(0%); + } + + 100% { + opacity: 0; + transform: translateX(100%); + } +} + +.sidebar { + position: fixed; + z-index: 5001; + height: 100%; + overflow: hidden; + color: #fff; + font-family: 'Roboto'; + font-size: 16px; + line-height: 1.4; + background: #1c1d26; + -moz-transition: width 0.3s ease, left 0.3s ease, right 0.3s ease; + -o-transition: width 0.3s ease, left 0.3s ease, right 0.3s ease; + -webkit-transition: width 0.3s ease, left 0.3s ease, right 0.3s ease; + transition: width 0.3s ease, left 0.3s ease, right 0.3s ease; +} + +.sidebar.sidebar-left { + width: 76px; + left: -76px; +} + +.sidebar.sidebar-left:hover { + left: 0; +} + +.sidebar.sidebar-left:hover~.rows { + left: 76px; +} + +.sidebar.sidebar-right { + width: 450px; + right: -450px; +} + +.sidebar .sidebar-toggle, +.sidebar .sidebar-header { + display: block; + height: 76px; + line-height: 76px; + margin-bottom: 5px; + text-align: center; + background: #006f94; +} + +.sidebar .sidebar-toggle.sidebar-toggle, +.sidebar .sidebar-header.sidebar-toggle { + position: absolute; + top: 0; + z-index: 5000; + width: 100%; + font-size: 1.8em; + visibility: visible; + opacity: 1; + -moz-transition-delay: 0s; + -o-transition-delay: 0s; + -webkit-transition-delay: 0s; + transition-delay: 0s; +} + +.sidebar .sidebar-inner { + width: 100%; + height: 100%; + margin: 0; + padding: 0; + padding-right: 20px; + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box; + overflow-y: auto; + overflow-x: hidden; + opacity: 0; + -moz-transition: visibility 0s ease 0.2s; + -o-transition: visibility 0s ease 0.2s; + -webkit-transition: visibility 0s ease; + -webkit-transition-delay: 0.2s; + transition: visibility 0s ease 0.2s; + -moz-transition: opacity 0.2s ease; + -o-transition: opacity 0.2s ease; + -webkit-transition: opacity 0.2s ease; + transition: opacity 0.2s ease; +} + +.sidebar .sidebar-inner li { + width: 450px; + position: relative; +} + +.sidebar .sidebar-inner li.sidebar-header a { + padding: 0; + color: #fff; + font-size: 1.3em; + font-family: "Roboto", Helvetica, sans-serif; + font-weight: bold; +} + +.sidebar .sidebar-inner li.sidebar-title { + padding: 20px 40px; + font-size: 1.2em; + font-weight: 500; +} + +.sidebar .sidebar-inner li a { + display: block; + padding: 15px 40px; + color: rgba(250, 250, 250, 0.8); + -moz-transition: color 0.2s ease; + -o-transition: color 0.2s ease; + -webkit-transition: color 0.2s ease; + transition: color 0.2s ease; +} + +.sidebar .sidebar-inner li a:hover, +.sidebar .sidebar-inner li a:focus { + color: #fff; +} + +.sidebar .sidebar-inner li span[class^="icon-"], +.sidebar .sidebar-inner li a.sidebar-btn { + display: inline-block; + position: absolute; + right: 0; + top: 0; + padding: 15px 30px; +} + +.sidebar-overlay { + display: none; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 5000; +} + + +/* -- sidebar-active -- */ + +.sidebar-active { + position: fixed; + z-index: 4000; + top: 0; + left: 0; + width: 76px; + height: 100%; +} + +.sidebar-active:hover~.sidebar-left { + left: 0; +} + +.sidebar-active:hover~.rows { + left: 76px; +} + + +/* -- toggleSidebar -- */ + +.toggle-left .sidebar-left { + left: 0 !important; + width: 450px; +} + +.toggle-left .sidebar-left .sidebar-toggle { + visibility: hidden !important; + opacity: 0; + -moz-transition: visibility 0s ease 0.2s; + -o-transition: visibility 0s ease 0.2s; + -webkit-transition: visibility 0s ease; + -webkit-transition-delay: 0.2s; + transition: visibility 0s ease 0.2s; + -moz-transition: opacity 0.2s ease; + -o-transition: opacity 0.2s ease; + -webkit-transition: opacity 0.2s ease; + transition: opacity 0.2s ease; +} + +.toggle-left .sidebar-left .sidebar-inner { + visibility: visible; + opacity: 1; +} + +.toggle-left .sidebar-overlay { + display: block; +} + +.toggle-left .rows { + left: 450px !important; +} + +.toggle-right .sidebar-right { + right: 0 !important; +} + +.toggle-right .sidebar-right .sidebar-toggle { + visibility: hidden !important; + opacity: 0; + -moz-transition: visibility 0s ease 0.2s; + -o-transition: visibility 0s ease 0.2s; + -webkit-transition: visibility 0s ease; + -webkit-transition-delay: 0.2s; + transition: visibility 0s ease 0.2s; + -moz-transition: opacity 0.2s ease; + -o-transition: opacity 0.2s ease; + -webkit-transition: opacity 0.2s ease; + transition: opacity 0.2s ease; +} + +.toggle-right .sidebar-right .sidebar-inner { + visibility: visible; + opacity: 1; +} + +.toggle-right .sidebar-overlay { + display: block; +} + +.toggle-right .rows { + left: -450px !important; +} + + +/* -- informations -- */ + +.bar-informations { + display: inline-block; + white-space: nowrap; + font-style: italic; +} + + +/* -- clock -- */ + +.bar-clock { + display: inline-block; + position: relative; + z-index: 5000; + width: 80%; + height: 7.5vh; + font-size: 5vh; + font-weight: 700; + line-height: 1.5; + border: solid 0.5vh #fff; + border-bottom: none; + border-radius: 0.8vh 0.8vh 0 0; + background: #003a79; +} + +.bar-clock small { + display: inline-block; + color: #ff9f17; +} + + +/* -- blink -- */ + +.animation-blink { + position: relative; +} + +.animation-blink .animation-blink-1, +.animation-blink .animation-blink-2 { + position: absolute; + top: 50%; + transform: translateY(-50%); + will-change: visibility; + animation: blink 4s steps(2, start) infinite; + -webkit-animation: blink 4s steps(2, start) infinite; +} + +.animation-blink .animation-blink-2 { + visibility: hidden; + animation-delay: 2s; + -webkit-animation-delay: 2s; +} + +.animation-blink .animation-blink-clock { + animation: blink 1.5s steps(2, start) infinite; + -webkit-animation: blink 1.5s steps(2, start) infinite; +} + +@keyframes blink { + from { + visibility: visible; + } + + to { + visibility: hidden; + } +} + +@-webkit-keyframes blink { + from { + visibility: visible; + } + + to { + visibility: hidden; + } +} + +/* -- provenance in departures -- */ + +.scroll-provenance { + animation: scrollstop 3s linear infinite; + -webkit-animation: scrollstop 3s linear infinite; +} + +@-webkit-keyframes scrollstop { + from { + transform: translateX(0%); + } + + to { + transform: translateX(-100%); + } +} + +@keyframes scrollstop { + from { + transform: translateX(0%); + } + + to { + transform: translateX(-100%); + } +} + +/* -- scroll-x -- */ + +.animation-scroll-x { + transform: translateZ(0); + will-change: transform; + animation: scrollX 0s linear infinite; + -webkit-animation: scrollX 0s linear infinite; +} + +@keyframes scrollX { + from { + transform: translateX(0%); + } + + to { + transform: translateX(-100%); + } +} + +@-webkit-keyframes scrollX { + from { + transform: translateX(0%); + } + + to { + transform: translateX(-100%); + } +} + + +@keyframes scrollY { + + /* 0% { transform: translateY(100%); } + 25% { transform: translateY(-100%); } + 50% { transform: translateY(100%); } + 75% { transform: translateY(0%); } + 100% { transform: translateY(-100%); } */ + from { + transform: translateY(0%); + } + + 50% { + transform: translateY(100%); + } + + to { + transform: translateY(100%); + } +} + +@-webkit-keyframes scrollY { + from { + transform: translateY(0%); + } + + to { + transform: translateY(100%); + animation-timing-function: ease-in-out + } +} + +/* -- scroll-y -- */ + +.row-group-informations .scroll-y { + transform: translateZ(0); + will-change: transform; + position: absolute; +} + +.row-group-train .scroll-y { + transform: translateZ(0); + will-change: transform; + position: relative; +} + + +/* -- texts -- */ + +.text-scroll-x { + display: inline-block; + padding-left: 100%; + color: rgba(255, 255, 255, 0.7); + font-size: 8em; + white-space: nowrap; +} + +.text-scroll-x span { + display: inline; +} + +.text-scroll-x span:after { + content: ''; + display: inline-block; + width: 2.5vh; + height: 2.5vh; + margin: 0 1.5vh; + margin-bottom: 0.5vh; + border-radius: 50%; + background: #f5f900; +} + +.text-scroll-x span:last-child:after { + display: none; +} + +.text-type { + line-height: 1; + font-size: 3.3em; + font-weight: 100; + font-family: 'Achemine'; + display: inline-block; +} + +.text-number { + line-height: 1; + font-size: 4em; + font-weight: bold; + display: inline-block; +} + +.text-time { + color: #f5f900; + font-size: 6.5em; + font-weight: bold; +} + +.text-time-rer { + color: #f5f900; + font-size: 5em; + font-weight: bold; +} + +.text-time.minutes { + font-size: 5em; +} + +.text-time.retard { + color: #f9a200; +} + +.text-features-1 { + margin-top: 2%; + font-size: 3.5em; + font-weight: bold; +} + +.text-features-2 { + color: #fff; + font-size: 0.8em; + font-weight: bold; +} + +.text-features-3 { + color: #f5f900; + font-size: 3.5em; + font-weight: bold; +} + + +/* -- background -- */ + +.row-background { + position: absolute; + right: 5vh; + bottom: 10vh; + width: 23vh; + height: 90%; + background-repeat: no-repeat; +} + + +/* -- cols -- */ + +.row-group { + height: 10%; +} + +.row-group .row { + position: relative; +} + +.row-group .row .col-first { + width: 17vh; +} + +.row-group .row .col-first-details { + display: relative; + color: #f5f900; + width: 60vh; + font-size: 5em; + text-align: center; + white-space: nowrap; +} + +.row-group .row .col-second { + position: relative; +} + +.row-group .row .col-second-first { + width: 20vh; + vertical-align: middle !important; +} + +.row-group .row .col-second-second { + width: 24vh; +} + +.row-group .row .col-second-third { + font-size: 8em; + white-space: nowrap; +} + +.row-group .row .col-second-merged { + width: 44vh; +} + +.row-group .row .col-second-merged>div { + display: table; +} + +.row-group .row .col-second-merged>div>div { + display: table-cell; + vertical-align: middle; +} + +.row-group .row .col-hide { + display: block; + position: relative; + width: 0; + overflow: visible !important; +} + +.row-group .row .col-hide .col-hide-inner { + position: absolute; + top: 0; + bottom: 0; + right: -1vh; + width: 100vh; + overflow: hidden; +} + +.row-group .row .col-third { + position: relative; + z-index: 1; + width: 18vh; + overflow: visible !important; +} + + +/* -- sizes -- */ + +.rows .row-group-2 .row:nth-of-type(1) { + height: 55%; +} + +.rows .row-group-2 .row:nth-of-type(1)>div { + line-height: 1; +} + +.rows .row-group-2 .row:nth-of-type(1) .col-second-first { + vertical-align: text-bottom !important; +} + +.rows .row-group-2 .row:nth-of-type(1) .col-second-first .animation-blink { + height: 6vh; +} + +.rows .row-group-2 .row:nth-of-type(1) .col-second-third { + font-size: 10em; +} + +.rows .row-group-2 .row:nth-of-type(1) .col-second-third .animation-rotate { + height: 11vh; +} + +.rows .row-group-2 .row:nth-of-type(1) .col-second-third .animation-rotate div { + margin-bottom: 1vh; +} + +.rows .row-group-2 .row:nth-of-type(1) .text-time { + font-size: 7.5em; +} + +.rows .row-group-2 .row:nth-of-type(1) .text-time.minutes { + font-size: 5em; +} + +.rows .row-group-2 .row:nth-of-type(1) .train-track { + height: 11vh; + width: 11vh; + font-size: 7.5em; + line-height: 1.4; +} + +.rows .row-group-2 .row:nth-of-type(1) .train-track.train-track-p:before { + width: 10.25vh; + height: 10.25vh; +} + +.rows .row-group-2 .row:nth-of-type(1) .train-track.train-track-h:not(.train-track-view) { + line-height: 0.4; +} + +.rows .row-group-2 .row:nth-of-type(2) { + height: 45%; +} + +.rows .row-group-2 .row:nth-of-type(2)>div { + line-height: 1.05; +} + + +/* -- styles -- */ + +.rows.rows-departures.scroll-y { + transform: translateZ(0); + will-change: transform; + animation: scrollY 10s linear infinite; + -webkit-animation: scrollY 10s linear infinite; +} + +.rows.rows-departures, +.rows.rows-transilien { + background: #0064aa; +} + +.rows.rows-departures .row-group:nth-of-type(odd), +.rows.rows-transilien .row-group:nth-of-type(odd) { + background: #0064aa; +} + +.rows.rows-departures .row-group:nth-of-type(odd) .train-track-h:not(.train-track-view), +.rows.rows-transilien .row-group:nth-of-type(odd) .train-track-h:not(.train-track-view) { + color: #0064aa; +} + +.rows.rows-departures .row-group:nth-of-type(even), +.rows.rows-transilien .row-group:nth-of-type(even) { + background: #003a79; +} + +.rows.rows-departures .row-group:nth-of-type(even) .train-track-h:not(.train-track-view), +.rows.rows-transilien .row-group:nth-of-type(even) .train-track-h:not(.train-track-view) { + color: #003a79; +} + +.rows.rows-departures .row-background, +.rows.rows-transilien .row-background { + background-image: url(../../assets/row-background-departures.svg); +} + +.rows.rows-arrivals { + background: #217a42; +} + +.rows.rows-arrivals .row-group:nth-of-type(odd) { + background: #217a42; +} + +.rows.rows-arrivals .row-group:nth-of-type(odd) .train-track-h:not(.train-track-view) { + color: #217a42; +} + +.rows.rows-arrivals .row-group:nth-of-type(even) { + background: #0c5639; +} + +.rows.rows-arrivals .row-group:nth-of-type(even) .train-track-h:not(.train-track-view) { + color: #0c5639; +} + +.rows.rows-arrivals .row-background { + background-image: url(../../assets/row-background-arrivals.svg); +} + +.rows.rows-error { + background: #ec0e0e; +} + +.rows.rows-error .row-group:nth-of-type(odd) { + background: #a00e0e; +} + + +/* -- logo -- */ + +.train-logo { + height: 6vh; + background: no-repeat center; + -moz-background-size: contain; + -o-background-size: contain; + -webkit-background-size: contain; + background-size: contain; +} + +.train-logo.train-logo-sncf { + background-image: url(../../assets/logos-monochrome/logo-sncf.svg); +} + +.train-logo.train-logo-inoui { + background-image: url(../../assets/logos-monochrome/logo-inoui.svg); +} + +.train-logo.train-logo-ter { + background-image: url(../../assets/logos-monochrome/logo-ter.svg); +} + +.train-logo.train-logo-tgv { + background-image: url(../../assets/logos-monochrome/logo-tgv.svg); +} + +.train-logo.train-logo-ice { + background-image: url(../../assets/logos-monochrome/logo-ice.svg); +} + +.train-logo.train-logo-lyria { + background-image: url(../../assets/logos-monochrome/logo-lyria.svg); +} + +.train-logo.train-logo-ouigo { + background-image: url(../../assets/logos-monochrome/logo-ouigo.svg); +} + +.train-logo.train-logo-ouigo-classique { + background-image: url(../../assets/logos-monochrome/logo-ouigo-classique.svg); +} + +.train-logo.train-logo-ler { + background-image: url(../../assets/logos-monochrome/logo-ler.svg); +} + +.train-logo.train-logo-fluo { + background-image: url(../../assets/logos-monochrome/logo-fluo.svg); +} + +.train-logo.train-logo-occitanie { + background-image: url(../../assets/logos-monochrome/logo-occitanie.svg); +} + +.train-logo.train-logo-intercite { + background-image: url(../../assets/logos-monochrome/logo-intercites.svg); + margin-left: 10%; + margin-right: 10%; +} + +.train-logo.train-logo-aleop { + background-image: url(../../assets/logos-monochrome/logo-aleop.svg); +} + +.train-logo.train-logo-auvergne-rhone-alpes { + background-image: url(../../assets/logos-monochrome/logo-auvergerhonealpes.svg); +} + +.train-logo.train-logo-breizhgo { + background-image: url(../../assets/logos-monochrome/logo-breizhgo.svg); +} + +.train-logo.train-logo-db { + background-image: url(../../assets/logos-monochrome/logo-db.svg); +} + +.train-logo.train-logo-ter-hauts-de-france { + background-image: url(../../assets/logos-monochrome/logo-hautsdefrance.svg); +} + +.train-logo.train-logo-lio { + background-image: url(../../assets/logos-monochrome/logo-lio.svg); +} + +.train-logo.train-logo-ter-metrolor { + background-image: url(../../assets/logos-monochrome/logo-metrolor.svg); +} + +.train-logo.train-logo-mobigo { + background-image: url(../../assets/logos-monochrome/logo-mobigo.svg); +} + +.train-logo.train-logo-nomad { + background-image: url(../../assets/logos-monochrome/logo-nomad.svg); +} + +.train-logo.train-logo-remi { + background-image: url(../../assets/logos-monochrome/logo-remi.svg); +} + +.train-logo.train-logo-renfe-ave { + background-image: url(../../assets/logos-monochrome/logo-renfeave.svg); +} + +.train-logo.train-logo-sbb { + background-image: url(../../assets/logos-monochrome/logo-sbb.svg); +} + +.train-logo.train-logo-sncf-1985 { + background-image: url(../../assets/logos-monochrome/logo-sncf1985.svg); +} + +.train-logo.train-logo-sncf-1992 { + background-image: url(../../assets/logos-monochrome/logo-sncf1992.svg); +} + +.train-logo.train-logo-ter-alsace { + background-image: url(../../assets/logos-monochrome/logo-teralsace.svg); +} + +.train-logo.train-logo-ter-aquitaine { + background-image: url(../../assets/logos-monochrome/logo-teraquitaine.svg); +} + +.train-logo.train-logo-ter-basse-normandie { + background-image: url(../../assets/logos-monochrome/logo-terbassenormandie.svg); +} + +.train-logo.train-logo-ter-bourgogne { + background-image: url(../../assets/logos-monochrome/logo-terbourgogne.svg); +} + +.train-logo.train-logo-ter-bretagne { + background-image: url(../../assets/logos-monochrome/logo-terbretagne.svg); +} + +.train-logo.train-logo-ter-centre { + background-image: url(../../assets/logos-monochrome/logo-tercentre.svg); +} + +.train-logo.train-logo-ter-languedoc-roussillon { + background-image: url(../../assets/logos-monochrome/logo-terlanguedocroussillon.svg); +} + +.train-logo.train-logo-ter-midi-pyrenees { + background-image: url(../../assets/logos-monochrome/logo-termidipyrenees.svg); +} + +.train-logo.train-logo-ter-nord-pas-de-calais { + background-image: url(../../assets/logos-monochrome/logo-ternordpasdecalais.svg); +} + +.train-logo.train-logo-poitou-charentes { + background-image: url(../../assets/logos-monochrome/logo-terpoitoucharentes.svg); +} + +.train-logo.train-logo-thello { + background-image: url(../../assets/logos-monochrome/logo-thello.svg); +} + +.train-logo.train-logo-tram-train { + background-image: url(../../assets/logos-monochrome/logo-tramtrain.svg); +} + +.train-logo.train-logo-zou { + background-image: url(../../assets/logos-monochrome/logo-zou.svg); +} + +.train-logo.train-logo-eurostar { + background-image: url(../../assets/logos-monochrome/logo-eurostar.svg); +} + +.train-logo.train-logo-thalys { + background-image: url(../../assets/logos-monochrome/logo-thalys.svg); +} + +.train-logo.train-logo-rer-a { + background-image: url(../../assets/logos-monochrome/logo-rer-a.svg); +} + +.train-logo.train-logo-rer-b { + background-image: url(../../assets/logos-monochrome/logo-rer-b.svg); +} + +.train-logo.train-logo-rer-c { + background-image: url(../../assets/logos-monochrome/logo-rer-c.svg); +} + +.train-logo.train-logo-rer-d { + background-image: url(../../assets/logos-monochrome/logo-rer-d.svg); +} + +.train-logo.train-logo-rer-e { + background-image: url(../../assets/logos-monochrome/logo-rer-e.svg); +} + +.train-logo.train-logo-t-h { + background-image: url(../../assets/logos-monochrome/logo-t-h.svg); +} + +.train-logo.train-logo-t-j { + background-image: url(../../assets/logos-monochrome/logo-t-j.svg); +} + +.train-logo.train-logo-t-k { + background-image: url(../../assets/logos-monochrome/logo-t-k.svg); +} + +.train-logo.train-logo-t-l { + background-image: url(../../assets/logos-monochrome/logo-t-l.svg); +} + +.train-logo.train-logo-t-n { + background-image: url(../../assets/logos-monochrome/logo-t-n.svg); +} + +.train-logo.train-logo-t-p { + background-image: url(../../assets/logos-monochrome/logo-t-p.svg); +} + +.train-logo.train-logo-t-r { + background-image: url(../../assets/logos-monochrome/logo-t-r.svg); +} + +.train-logo.train-logo-t-u { + background-image: url(../../assets/logos-monochrome/logo-t-u.svg); +} + +.train-logo.train-logo-lunea { + background-image: url(../../assets/logos-monochrome/logo-lunea.svg); +} + +.train-logo.train-logo-teoz { + background-image: url(../../assets/logos-monochrome/logo-teoz.svg); +} + +.train-logo.train-logo-frecciarossa { + background-image: url(../../assets/logos-monochrome/logo-frecciarossa.svg); +} + +.train-logo.train-logo-trenitalia { + background-image: url(../../assets/logos-monochrome/logo-trenitalia.svg); +} + +.train-logo.train-logo-cfl { + background-image: url(../../assets/logos-monochrome/logo-cfl.svg); +} + +.train-logo.train-logo-sncb { + background-image: url(../../assets/logos-monochrome/logo-sncb.svg); +} + + +/* -- rer --*/ + +.rer.train-lng { + height: 75%; + background: no-repeat center; + -moz-background-size: contain; + -o-background-size: contain; + -webkit-background-size: contain; + background-size: contain; +} + +.rer.train-lng.train-long { + background-image: url(../../assets/train_long.png); +} + +.rer.train-lng.train-court { + background-image: url(../../assets/train_court.png); +} + +.rer-hour-mode { + font-size: 4em; +} + +/* -- type - number -- */ + +.train-type-number { + display: inline-block; +} + + +/* -- information-dynamic -- */ + +.train-information-dynamic { + position: absolute; + right: 0; + top: 0.7vh; + bottom: 0.7vh; + width: 55vh; + padding-left: 2vh; + font-size: 4em; + line-height: 1; + border-left: 0.5vh #fff solid; +} + +.row-group:nth-of-type(odd) .train-information-dynamic { + background-color: #0064aa; +} + +.row-group:nth-of-type(even) .train-information-dynamic { + background-color: #003a79; +} + +.train-information-dynamic.train-information-dynamic-yellow { + color: #f5f900; + border-color: #f5f900; +} + +.train-information-dynamic-station { + display: block; + width: 100%; + overflow: hidden; +} + + +/* -- track -- */ + +.train-track { + display: none; + position: absolute; + top: 0.75vh; + right: 3vh; + width: 8vh; + height: 8vh; + font-size: 5.6em; + font-weight: bold; + line-height: 1.3; + text-align: center; + border: solid 0.35vh #fff; + border-radius: 10%; + z-index: 1000; +} + +.train-track span { + display: none; +} + +.train-track.train-track-view { + display: block; +} + +.train-track.train-track-view span { + display: inline; +} + +.train-track.train-track-view h1, +.train-track.train-track-view small { + display: none; +} + +.train-track.train-track-p { + display: block; +} + +.train-track.train-track-p.train-track-view { + background: transparent !important; +} + +.train-track.train-track-p.train-track-view:before { + content: ''; + position: absolute; + z-index: -1; + display: block; + width: 7.25vh; + height: 7.25vh; +} + +.train-track.train-track-p.train-track-view.train-track-y:before { + box-shadow: 1.25vh 1.25vh 0 #f5f900; +} + +.train-track.train-track-p.train-track-view.train-track-b:before { + box-shadow: 1.25vh 1.25vh 0 #115db6; +} + +.train-track.train-track-p.train-track-y { + background: #f5f900; +} + +.train-track.train-track-p.train-track-b { + background: #115db6; +} + +.train-track.train-track-h:not(.train-track-view) { + display: block; + line-height: 0.4; + background: #fff; +} + +.train-track.train-track-h:not(.train-track-view) h1 { + margin: 0; + font-size: 0.75em; +} + +.train-track.train-track-h:not(.train-track-view) small { + font-size: 0.4em; +} + +.train-track.train-track-view.noview { + border: dashed 0.35vh #fff; +} + +.train-track.train-track-car { + border: none; + background: url(../../assets/logos-monochrome/track-car.svg) no-repeat center; + background-size: cover; +} + + +/* -- rotate -- */ + +.animation-rotate { + height: 10vh; + overflow: hidden; + transform: translateZ(0); + will-change: transform; +} + +.animation-rotate .animation-rotate-inner { + height: 100%; + animation: rotate 9s linear infinite; + -webkit-animation: rotate 9s linear infinite; +} + +.animation-rotate .animation-rotate-inner div { + margin-bottom: 0.5vh; +} + +@keyframes rotate { + 33% { + transform: translateY(0%); + } + + 50%, + 83.33% { + transform: translateY(-100%); + } + + 100% { + transform: translateY(-200%); + } +} + +@-webkit-keyframes rotate { + 33% { + transform: translateY(0%); + } + + 50%, + 83.33% { + transform: translateY(-100%); + } + + 100% { + transform: translateY(-200%); + } +} + + +/* -- dynamic -- */ + +.animation-dynamic { + transform: translateX(100%) translateZ(0); + will-change: transform; + animation: dynamic 13s linear infinite; + -webkit-animation: dynamic 13s linear infinite; +} + +@keyframes dynamic { + 0% { + transform: translateX(100%) translateZ(0); + } + + 20%, + 60% { + transform: translateX(0%) translateZ(0); + } + + 80% { + transform: translateX(100%) translateZ(0); + } +} + +@-webkit-keyframes dynamic { + 0% { + transform: translateX(100%) translateZ(0); + } + + 20%, + 60% { + transform: translateX(0%) translateZ(0); + } + + 80% { + transform: translateX(100%) translateZ(0); + } +} + + +/* -- animation-dynamic-station -- */ + +.animation-dynamic-station { + width: calc(100% - 0vh); + transform: translateZ(0); + will-change: width; + animation: dynamic_station 13s linear infinite; + -webkit-animation: dynamic_station 13s linear infinite; +} + +@keyframes dynamic_station { + 0% { + width: calc(100% - 0vh); + } + + 20%, + 60% { + width: calc(100% - 55vh); + } + + 80% { + width: calc(100% - 0vh); + } +} + +@-webkit-keyframes dynamic_station { + 0% { + width: calc(100% - 0vh); + } + + 20%, + 60% { + width: calc(100% - 55vh); + } + + 80% { + width: calc(100% - 0vh); + } +} \ No newline at end of file diff --git a/src/app/theme.js b/src/app/theme.js new file mode 100644 index 0000000..fa603f6 --- /dev/null +++ b/src/app/theme.js @@ -0,0 +1,105 @@ +'use client'; + +import { outlinedInputClasses } from '@mui/material'; +import { createTheme } from '@mui/material/styles'; +import { Roboto } from 'next/font/google'; + +const roboto = Roboto({ + weight: ['300', '400', '500', '700'], + subsets: ['latin'], + display: 'swap', +}); + +const theme = createTheme({ + palette: { + mode: 'dark', + background: { + default: '#121212', + paper: '#1e1e1e', + }, + primary: { + main: '#217a42', + }, + secondary: { + main: '#0c5639', + }, + error: { + main: '#f44336', + }, + warning: { + main: '#ff9800', + }, + info: { + main: '#2196f3', + }, + success: { + main: '#4caf50', + }, + }, + typography: { + fontFamily: roboto.style.fontFamily, + h5: { + fontWeight: 400, + fontSize: '1.5rem', + } + }, + components: { + MuiCssBaseline: { + styleOverrides: ` + :root { + ${roboto.style.fontFamily} + } + `, + }, + MuiTextField: { + defaultProps: { + variant: 'outlined', + margin: 'dense', + }, + styleOverrides: { + root: { + '--TextField-brandBorderColor': '#217a42', + '--TextField-brandHoverBorderColor': '#FFFFFF', + '--TextField-brandFocusBorderColor': '#0c5639', + '& label.Mui-focused': { + color: 'var(--TextField-brandFocusBorderColor)', + }, + '& label': { + color: 'var(--TextField-brandBorderColor)', + }, + }, + }, + }, + MuiOutlinedInput: { + styleOverrides: { + notchedOutline: { + borderColor: 'var(--TextField-brandBorderColor)', + }, + root: { + [`&:hover .${outlinedInputClasses.notchedOutline}`]: { + borderColor: 'var(--TextField-brandHoverBorderColor)', + }, + [`&.Mui-focused .${outlinedInputClasses.notchedOutline}`]: { + borderColor: 'var(--TextField-brandFocusBorderColor)', + }, + [`& .${outlinedInputClasses.input}`]: { + color: '#FFFFFF', + }, + }, + }, + }, + MuiButton: { + defaultProps: { + variant: 'contained', + color: 'primary', + }, + }, + MuiAppBar: { + styleOverrides: { + + }, + }, + }, +}); + +export default theme; \ No newline at end of file