diff --git a/package-lock.json b/package-lock.json index 2f2328d..2ca21c4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,25 +1,41 @@ { - "name": "testauthclerk", + "name": "airsoftsearch", "version": "0.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "testauthclerk", + "name": "airsoftsearch", "version": "0.1.0", "dependencies": { + "@clerk/nextjs": "^6.9.11", + "@clerk/themes": "^2.2.7", + "@fortawesome/free-solid-svg-icons": "^6.7.2", + "@fortawesome/react-fontawesome": "^0.2.2", + "@headlessui/react": "^2.2.0", + "@heroicons/react": "^2.2.0", + "@material-tailwind/react": "^2.1.10", + "@prisma/client": "^6.2.1", + "bootstrap": "^5.3.3", + "leaflet": "^1.9.4", "next": "15.1.4", "react": "^19.0.0", - "react-dom": "^19.0.0" + "react-bootstrap": "^2.10.7", + "react-dom": "^19.0.0", + "react-fontawesome": "^1.7.1", + "react-leaflet": "^5.0.0", + "slugify": "^1.6.6" }, "devDependencies": { "@eslint/eslintrc": "^3", + "@types/leaflet": "^1.9.16", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", "eslint": "^9", "eslint-config-next": "15.1.4", "postcss": "^8", + "prisma": "^6.2.1", "tailwindcss": "^3.4.1", "typescript": "^5" } @@ -37,6 +53,160 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "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/@clerk/backend": { + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@clerk/backend/-/backend-1.23.0.tgz", + "integrity": "sha512-AcXO0Xs6e5HpU3coSPmnvsMysfuTPtfxv7Zgg+uaLYLD2/3E8OOMyLzPyiRmayacOxP6To1i8ETUJzpA08nRcA==", + "license": "MIT", + "dependencies": { + "@clerk/shared": "^2.20.7", + "@clerk/types": "^4.40.3", + "cookie": "1.0.2", + "snakecase-keys": "8.0.1", + "tslib": "2.4.1" + }, + "engines": { + "node": ">=18.17.0" + } + }, + "node_modules/@clerk/backend/node_modules/tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", + "license": "0BSD" + }, + "node_modules/@clerk/clerk-react": { + "version": "5.21.3", + "resolved": "https://registry.npmjs.org/@clerk/clerk-react/-/clerk-react-5.21.3.tgz", + "integrity": "sha512-v94kVhvLIIAnWSBw3+klod7xbaGigGPd1JWKwCcU10a89XgftRhZyY5HO89E4rtID/lo8DyfJe0+1w3BDAUcBA==", + "license": "MIT", + "dependencies": { + "@clerk/shared": "^2.20.7", + "@clerk/types": "^4.40.3", + "tslib": "2.4.1" + }, + "engines": { + "node": ">=18.17.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0 || ^19.0.0-0", + "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-0" + } + }, + "node_modules/@clerk/clerk-react/node_modules/tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", + "license": "0BSD" + }, + "node_modules/@clerk/nextjs": { + "version": "6.9.11", + "resolved": "https://registry.npmjs.org/@clerk/nextjs/-/nextjs-6.9.11.tgz", + "integrity": "sha512-FThhcOn1nfZDCHRMDS2Lr9mI1QVWR6G1A1ea3Kl7yBPqUcU1ukEatNQJNudCmmZYHIIYOPh/uDofRth62ucTnQ==", + "license": "MIT", + "dependencies": { + "@clerk/backend": "^1.23.0", + "@clerk/clerk-react": "^5.21.3", + "@clerk/shared": "^2.20.7", + "@clerk/types": "^4.40.3", + "crypto-js": "4.2.0", + "server-only": "0.0.1", + "tslib": "2.4.1" + }, + "engines": { + "node": ">=18.17.0" + }, + "peerDependencies": { + "next": "^13.5.4 || ^14.0.3 || ^15.0.0", + "react": "^18.0.0 || ^19.0.0 || ^19.0.0-0", + "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-0" + } + }, + "node_modules/@clerk/nextjs/node_modules/tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", + "license": "0BSD" + }, + "node_modules/@clerk/shared": { + "version": "2.20.7", + "resolved": "https://registry.npmjs.org/@clerk/shared/-/shared-2.20.7.tgz", + "integrity": "sha512-59EbMhqAi1331ovs5botm+OVVw3NHVLllO4X9/zBUb64PVtx1W7RSBYf+NxTFjWIalHp0kfVzpcm+jK3JkfXCw==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@clerk/types": "^4.40.3", + "dequal": "2.0.3", + "glob-to-regexp": "0.4.1", + "js-cookie": "3.0.5", + "std-env": "^3.7.0", + "swr": "^2.2.0" + }, + "engines": { + "node": ">=18.17.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0 || ^19.0.0-0", + "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/@clerk/themes": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/@clerk/themes/-/themes-2.2.7.tgz", + "integrity": "sha512-LM1cOYtG7pbtYotpZnZfiL0pzug1tSYOixw90vzGLXy9354MvWOJ2Hq+7xVslbUheL/eAMouoHzRMtpMGk8rvw==", + "license": "MIT", + "dependencies": { + "@clerk/types": "^4.41.0", + "tslib": "2.4.1" + }, + "engines": { + "node": ">=18.17.0" + } + }, + "node_modules/@clerk/themes/node_modules/tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", + "license": "0BSD" + }, + "node_modules/@clerk/types": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/@clerk/types/-/types-4.41.0.tgz", + "integrity": "sha512-pSIDJ6WKmkPLAThzuXABFt/K581iLjsZSOU7e+hDdb1PRElKi11stMJruDU8UjLBNFksZUG5Cfkt0iGrVQmpXw==", + "license": "MIT", + "dependencies": { + "csstype": "3.1.1" + }, + "engines": { + "node": ">=18.17.0" + } + }, + "node_modules/@clerk/types/node_modules/csstype": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", + "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==", + "license": "MIT" + }, "node_modules/@emnapi/runtime": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.3.1.tgz", @@ -47,6 +217,23 @@ "tslib": "^2.4.0" } }, + "node_modules/@emotion/is-prop-valid": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", + "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==", + "license": "MIT", + "optional": true, + "dependencies": { + "@emotion/memoize": "0.7.4" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz", + "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==", + "license": "MIT", + "optional": true + }, "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", @@ -175,6 +362,134 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@floating-ui/core": { + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.9.tgz", + "integrity": "sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.9" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.6.13", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.13.tgz", + "integrity": "sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.6.0", + "@floating-ui/utils": "^0.2.9" + } + }, + "node_modules/@floating-ui/react": { + "version": "0.26.28", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.28.tgz", + "integrity": "sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw==", + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.1.2", + "@floating-ui/utils": "^0.2.8", + "tabbable": "^6.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz", + "integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz", + "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==", + "license": "MIT" + }, + "node_modules/@fortawesome/fontawesome-common-types": { + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.7.2.tgz", + "integrity": "sha512-Zs+YeHUC5fkt7Mg1l6XTniei3k4bwG/yo3iFUtZWd/pMx9g3fdvkSK9E0FOC+++phXOka78uJcYb8JaFkW52Xg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/fontawesome-svg-core": { + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.7.2.tgz", + "integrity": "sha512-yxtOBWDrdi5DD5o1pmVdq3WMCvnobT0LU6R8RyyVXPvFRd2o79/0NCuQoCjNTeZz9EzA9xS3JxNWfv54RIHFEA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.7.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/free-solid-svg-icons": { + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.7.2.tgz", + "integrity": "sha512-GsBrnOzU8uj0LECDfD5zomZJIjrPhIlWU82AHwa2s40FKH+kcxQaBvBo3Z4TxyZHIyX8XTDxsyA33/Vx9eFuQA==", + "license": "(CC-BY-4.0 AND MIT)", + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.7.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/react-fontawesome": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.2.tgz", + "integrity": "sha512-EnkrprPNqI6SXJl//m29hpaNzOp1bruISWaOiRtkMi/xSvHJlzc2j2JAYS7egxt/EbjSNV/k6Xy0AQI6vB2+1g==", + "license": "MIT", + "dependencies": { + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "@fortawesome/fontawesome-svg-core": "~1 || ~6", + "react": ">=16.3" + } + }, + "node_modules/@headlessui/react": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-2.2.0.tgz", + "integrity": "sha512-RzCEg+LXsuI7mHiSomsu/gBJSjpupm6A1qIZ5sWjd7JhARNlMiSA4kKfJpCKwU9tE+zMRterhhrP74PvfJrpXQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/react": "^0.26.16", + "@react-aria/focus": "^3.17.1", + "@react-aria/interactions": "^3.21.3", + "@tanstack/react-virtual": "^3.8.1" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": "^18 || ^19 || ^19.0.0-rc", + "react-dom": "^18 || ^19 || ^19.0.0-rc" + } + }, + "node_modules/@heroicons/react": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@heroicons/react/-/react-2.2.0.tgz", + "integrity": "sha512-LMcepvRaS9LYHJGsF0zzmgKCUim/X3N/DQKc4jepAXJ7l8QxJ1PmxJzqplF2Z3FE4PqBAIGyJAQ/w4B5dsqbtQ==", + "license": "MIT", + "peerDependencies": { + "react": ">= 16 || ^19.0.0-rc" + } + }, "node_modules/@humanfs/core": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", @@ -673,6 +988,159 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@material-tailwind/react": { + "version": "2.1.10", + "resolved": "https://registry.npmjs.org/@material-tailwind/react/-/react-2.1.10.tgz", + "integrity": "sha512-xGU/mLDKDBp/qZ8Dp2XR7fKcTpDuFeZEBqoL9Bk/29kakKxNxjUGYSRHEFLsyOFf4VIhU6WGHdIS7tOA3QGJHA==", + "license": "MIT", + "dependencies": { + "@floating-ui/react": "0.19.0", + "classnames": "2.3.2", + "deepmerge": "4.2.2", + "framer-motion": "6.5.1", + "material-ripple-effects": "2.0.1", + "prop-types": "15.8.1", + "react": "18.2.0", + "react-dom": "18.2.0", + "tailwind-merge": "1.8.1" + }, + "peerDependencies": { + "react": "^16 || ^17 || ^18", + "react-dom": "^16 || ^17 || ^18" + } + }, + "node_modules/@material-tailwind/react/node_modules/@floating-ui/react": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.19.0.tgz", + "integrity": "sha512-fgYvN4ksCi5OvmPXkyOT8o5a8PSKHMzPHt+9mR6KYWdF16IAjWRLZPAAziI2sznaWT23drRFrYw64wdvYqqaQw==", + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^1.2.2", + "aria-hidden": "^1.1.3", + "tabbable": "^6.0.1" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@material-tailwind/react/node_modules/@floating-ui/react-dom": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-1.3.0.tgz", + "integrity": "sha512-htwHm67Ji5E/pROEAr7f8IKFShuiCKHwUC/UY4vC3I5jiSvGFAYnSYiZO5MlGmads+QqvUkR9ANHEguGrDv72g==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.2.1" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@material-tailwind/react/node_modules/classnames": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", + "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==", + "license": "MIT" + }, + "node_modules/@material-tailwind/react/node_modules/react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@material-tailwind/react/node_modules/react-dom": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, + "node_modules/@material-tailwind/react/node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/@motionone/animation": { + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/@motionone/animation/-/animation-10.18.0.tgz", + "integrity": "sha512-9z2p5GFGCm0gBsZbi8rVMOAJCtw1WqBTIPw3ozk06gDvZInBPIsQcHgYogEJ4yuHJ+akuW8g1SEIOpTOvYs8hw==", + "license": "MIT", + "dependencies": { + "@motionone/easing": "^10.18.0", + "@motionone/types": "^10.17.1", + "@motionone/utils": "^10.18.0", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/dom": { + "version": "10.12.0", + "resolved": "https://registry.npmjs.org/@motionone/dom/-/dom-10.12.0.tgz", + "integrity": "sha512-UdPTtLMAktHiqV0atOczNYyDd/d8Cf5fFsd1tua03PqTwwCe/6lwhLSQ8a7TbnQ5SN0gm44N1slBfj+ORIhrqw==", + "license": "MIT", + "dependencies": { + "@motionone/animation": "^10.12.0", + "@motionone/generators": "^10.12.0", + "@motionone/types": "^10.12.0", + "@motionone/utils": "^10.12.0", + "hey-listen": "^1.0.8", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/easing": { + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/@motionone/easing/-/easing-10.18.0.tgz", + "integrity": "sha512-VcjByo7XpdLS4o9T8t99JtgxkdMcNWD3yHU/n6CLEz3bkmKDRZyYQ/wmSf6daum8ZXqfUAgFeCZSpJZIMxaCzg==", + "license": "MIT", + "dependencies": { + "@motionone/utils": "^10.18.0", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/generators": { + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/@motionone/generators/-/generators-10.18.0.tgz", + "integrity": "sha512-+qfkC2DtkDj4tHPu+AFKVfR/C30O1vYdvsGYaR13W/1cczPrrcjdvYCj0VLFuRMN+lP1xvpNZHCRNM4fBzn1jg==", + "license": "MIT", + "dependencies": { + "@motionone/types": "^10.17.1", + "@motionone/utils": "^10.18.0", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/types": { + "version": "10.17.1", + "resolved": "https://registry.npmjs.org/@motionone/types/-/types-10.17.1.tgz", + "integrity": "sha512-KaC4kgiODDz8hswCrS0btrVrzyU2CSQKO7Ps90ibBVSQmjkrt2teqta6/sOG59v7+dPnKMAg13jyqtMKV2yJ7A==", + "license": "MIT" + }, + "node_modules/@motionone/utils": { + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/@motionone/utils/-/utils-10.18.0.tgz", + "integrity": "sha512-3XVF7sgyTSI2KWvTf6uLlBJ5iAgRgmvp3bpuOiQJvInd4nZ19ET8lX5unn30SlmRH7hXbBbH+Gxd0m0klJ3Xtw==", + "license": "MIT", + "dependencies": { + "@motionone/types": "^10.17.1", + "hey-listen": "^1.0.8", + "tslib": "^2.3.1" + } + }, "node_modules/@next/env": { "version": "15.1.4", "resolved": "https://registry.npmjs.org/@next/env/-/env-15.1.4.tgz", @@ -876,6 +1344,235 @@ "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/@prisma/client": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.2.1.tgz", + "integrity": "sha512-msKY2iRLISN8t5X0Tj7hU0UWet1u0KuxSPHWuf3IRkB4J95mCvGpyQBfQ6ufcmvKNOMQSq90O2iUmJEN2e5fiA==", + "hasInstallScript": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "peerDependencies": { + "prisma": "*" + }, + "peerDependenciesMeta": { + "prisma": { + "optional": true + } + } + }, + "node_modules/@prisma/debug": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.2.1.tgz", + "integrity": "sha512-0KItvt39CmQxWkEw6oW+RQMD6RZ43SJWgEUnzxN8VC9ixMysa7MzZCZf22LCK5DSooiLNf8vM3LHZm/I/Ni7bQ==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/engines": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.2.1.tgz", + "integrity": "sha512-lTBNLJBCxVT9iP5I7Mn6GlwqAxTpS5qMERrhebkUhtXpGVkBNd/jHnNJBZQW4kGDCKaQg/r2vlJYkzOHnAb7ZQ==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.2.1", + "@prisma/engines-version": "6.2.0-14.4123509d24aa4dede1e864b46351bf2790323b69", + "@prisma/fetch-engine": "6.2.1", + "@prisma/get-platform": "6.2.1" + } + }, + "node_modules/@prisma/engines-version": { + "version": "6.2.0-14.4123509d24aa4dede1e864b46351bf2790323b69", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-6.2.0-14.4123509d24aa4dede1e864b46351bf2790323b69.tgz", + "integrity": "sha512-7tw1qs/9GWSX6qbZs4He09TOTg1ff3gYsB3ubaVNN0Pp1zLm9NC5C5MZShtkz7TyQjx7blhpknB7HwEhlG+PrQ==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/fetch-engine": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.2.1.tgz", + "integrity": "sha512-OO7O9d6Mrx2F9i+Gu1LW+DGXXyUFkP7OE5aj9iBfA/2jjDXEJjqa9X0ZmM9NZNo8Uo7ql6zKm6yjDcbAcRrw1A==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.2.1", + "@prisma/engines-version": "6.2.0-14.4123509d24aa4dede1e864b46351bf2790323b69", + "@prisma/get-platform": "6.2.1" + } + }, + "node_modules/@prisma/get-platform": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.2.1.tgz", + "integrity": "sha512-zp53yvroPl5m5/gXYLz7tGCNG33bhG+JYCm74ohxOq1pPnrL47VQYFfF3RbTZ7TzGWCrR3EtoiYMywUBw7UK6Q==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.2.1" + } + }, + "node_modules/@react-aria/focus": { + "version": "3.19.1", + "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.19.1.tgz", + "integrity": "sha512-bix9Bu1Ue7RPcYmjwcjhB14BMu2qzfJ3tMQLqDc9pweJA66nOw8DThy3IfVr8Z7j2PHktOLf9kcbiZpydKHqzg==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/interactions": "^3.23.0", + "@react-aria/utils": "^3.27.0", + "@react-types/shared": "^3.27.0", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/interactions": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.23.0.tgz", + "integrity": "sha512-0qR1atBIWrb7FzQ+Tmr3s8uH5mQdyRH78n0krYaG8tng9+u1JlSi8DGRSaC9ezKyNB84m7vHT207xnHXGeJ3Fg==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/ssr": "^3.9.7", + "@react-aria/utils": "^3.27.0", + "@react-types/shared": "^3.27.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/ssr": { + "version": "3.9.7", + "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.7.tgz", + "integrity": "sha512-GQygZaGlmYjmYM+tiNBA5C6acmiDWF52Nqd40bBp0Znk4M4hP+LTmI0lpI1BuKMw45T8RIhrAsICIfKwZvi2Gg==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + }, + "engines": { + "node": ">= 12" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/utils": { + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.27.0.tgz", + "integrity": "sha512-p681OtApnKOdbeN8ITfnnYqfdHS0z7GE+4l8EXlfLnr70Rp/9xicBO6d2rU+V/B3JujDw2gPWxYKEnEeh0CGCw==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/ssr": "^3.9.7", + "@react-stately/utils": "^3.10.5", + "@react-types/shared": "^3.27.0", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-leaflet/core": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@react-leaflet/core/-/core-3.0.0.tgz", + "integrity": "sha512-3EWmekh4Nz+pGcr+xjf0KNyYfC3U2JjnkWsh0zcqaexYqmmB5ZhH37kz41JXGmKzpaMZCnPofBBm64i+YrEvGQ==", + "license": "Hippocratic-2.1", + "peerDependencies": { + "leaflet": "^1.9.0", + "react": "^19.0.0", + "react-dom": "^19.0.0" + } + }, + "node_modules/@react-stately/utils": { + "version": "3.10.5", + "resolved": "https://registry.npmjs.org/@react-stately/utils/-/utils-3.10.5.tgz", + "integrity": "sha512-iMQSGcpaecghDIh3mZEpZfoFH3ExBwTtuBEcvZ2XnGzCgQjeYXcMdIUwAfVQLXFTdHUHGF6Gu6/dFrYsCzySBQ==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-types/shared": { + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.27.0.tgz", + "integrity": "sha512-gvznmLhi6JPEf0bsq7SwRYTHAKKq/wcmKqFez9sRdbED+SPMUmK5omfZ6w3EwUFQHbYUa4zPBYedQ7Knv70RMw==", + "license": "Apache-2.0", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@restart/hooks": { + "version": "0.4.16", + "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.16.tgz", + "integrity": "sha512-f7aCv7c+nU/3mF7NWLtVVr0Ra80RqsO89hO72r+Y/nvQr5+q0UFGkocElTH6MJApvReVh6JHUFYn2cw1WdHF3w==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.3" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@restart/ui": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@restart/ui/-/ui-1.9.2.tgz", + "integrity": "sha512-MWWqJqSyqUWWPBOOiRQrX57CBc/9CoYONg7sE+uag72GCAuYrHGU5c49vU5s4BUSBgiKNY6rL7TULqGDrouUaA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.26.0", + "@popperjs/core": "^2.11.8", + "@react-aria/ssr": "^3.5.0", + "@restart/hooks": "^0.5.0", + "@types/warning": "^3.0.3", + "dequal": "^2.0.3", + "dom-helpers": "^5.2.0", + "uncontrollable": "^8.0.4", + "warning": "^4.0.3" + }, + "peerDependencies": { + "react": ">=16.14.0", + "react-dom": ">=16.14.0" + } + }, + "node_modules/@restart/ui/node_modules/@restart/hooks": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.5.1.tgz", + "integrity": "sha512-EMoH04NHS1pbn07iLTjIjgttuqb7qu4+/EyhAx27MHpoENcB2ZdSsLTNxmKD+WEPnZigo62Qc8zjGnNxoSE/5Q==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.3" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@restart/ui/node_modules/uncontrollable": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-8.0.4.tgz", + "integrity": "sha512-ulRWYWHvscPFc0QQXvyJjY6LIXU56f0h8pQFvhxiKk5V1fcI8gp9Ht9leVAhrVjzqMw0BgjspBINx9r6oyJUvQ==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.14.0" + } + }, "node_modules/@rtsao/scc": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", @@ -905,6 +1602,33 @@ "tslib": "^2.8.0" } }, + "node_modules/@tanstack/react-virtual": { + "version": "3.11.2", + "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.11.2.tgz", + "integrity": "sha512-OuFzMXPF4+xZgx8UzJha0AieuMihhhaWG0tCqpp6tDzlFwOmNBPYMuLOtMJ1Tr4pXLHmgjcWhG6RlknY2oNTdQ==", + "license": "MIT", + "dependencies": { + "@tanstack/virtual-core": "3.11.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@tanstack/virtual-core": { + "version": "3.11.2", + "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.11.2.tgz", + "integrity": "sha512-vTtpNt7mKCiZ1pwU9hfKPhpdVO2sVzFQsxoVBGtOSHxlrRRzYr8iQ2TlwbAcRYCcEiZ9ECAM8kBzH0v2+VzfKw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, "node_modules/@types/estree": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", @@ -912,6 +1636,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/geojson": { + "version": "7946.0.15", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.15.tgz", + "integrity": "sha512-9oSxFzDCT2Rj6DfcHF8G++jxBKS7mBqXl5xrRW+Kbvjry6Uduya2iiwqHPhVXpasAVMBYKkEPGgKhd3+/HZ6xA==", + "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", @@ -926,6 +1657,16 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/leaflet": { + "version": "1.9.16", + "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.16.tgz", + "integrity": "sha512-wzZoyySUxkgMZ0ihJ7IaUIblG8Rdc8AbbZKLneyn+QjYsj5q1QU7TEKYqwTr10BGSzY5LI7tJk9Ifo+mEjdFRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/geojson": "*" + } + }, "node_modules/@types/node": { "version": "20.17.14", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.14.tgz", @@ -936,11 +1677,16 @@ "undici-types": "~6.19.2" } }, + "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": "19.0.7", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.0.7.tgz", "integrity": "sha512-MoFsEJKkAtZCrC1r6CM8U22GzhG7u2Wir8ons/aCKH6MBdD1ibV24zOSSkdZVUKqN5i396zG5VKLYZ3yaUZdLA==", - "dev": true, "license": "MIT", "dependencies": { "csstype": "^3.0.2" @@ -956,6 +1702,21 @@ "@types/react": "^19.0.0" } }, + "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/@types/warning": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.3.tgz", + "integrity": "sha512-D1XC7WK8K+zZEveUPY+cf4+kgauk8N4eHr/XIHXGlGYkHLud6hK9lYfZk1ry1TNh798cZUCgb6MqGEG8DkJt6Q==", + "license": "MIT" + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.20.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.20.0.tgz", @@ -1296,6 +2057,18 @@ "dev": true, "license": "Python-2.0" }, + "node_modules/aria-hidden": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.4.tgz", + "integrity": "sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/aria-query": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", @@ -1526,6 +2299,25 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/bootstrap": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.3.tgz", + "integrity": "sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/twbs" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + } + ], + "license": "MIT", + "peerDependencies": { + "@popperjs/core": "^2.11.8" + } + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -1706,12 +2498,27 @@ "node": ">= 6" } }, + "node_modules/classnames": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==", + "license": "MIT" + }, "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", "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", @@ -1774,6 +2581,15 @@ "dev": true, "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/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -1789,6 +2605,12 @@ "node": ">= 8" } }, + "node_modules/crypto-js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", + "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==", + "license": "MIT" + }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -1806,7 +2628,6 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true, "license": "MIT" }, "node_modules/damerau-levenshtein": { @@ -1895,6 +2716,15 @@ "dev": true, "license": "MIT" }, + "node_modules/deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/define-data-property": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", @@ -1931,6 +2761,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/detect-libc": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", @@ -1968,6 +2807,26 @@ "node": ">=0.10.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": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -2803,6 +3662,36 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/framer-motion": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-6.5.1.tgz", + "integrity": "sha512-o1BGqqposwi7cgDrtg0dNONhkmPsUFDaLcKXigzuTFC5x58mE8iyTazxSudFzmT6MEyJKfjjU8ItoMe3W+3fiw==", + "license": "MIT", + "dependencies": { + "@motionone/dom": "10.12.0", + "framesync": "6.0.1", + "hey-listen": "^1.0.8", + "popmotion": "11.0.3", + "style-value-types": "5.0.0", + "tslib": "^2.1.0" + }, + "optionalDependencies": { + "@emotion/is-prop-valid": "^0.8.2" + }, + "peerDependencies": { + "react": ">=16.8 || ^17.0.0 || ^18.0.0", + "react-dom": ">=16.8 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/framesync": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/framesync/-/framesync-6.0.1.tgz", + "integrity": "sha512-fUY88kXvGiIItgNC7wcTOl0SNRCVXMKSWW2Yzfmn7EKNc+MpCzcz9DhdHcdjbrtN3c6R4H5dTY2jiCpPdysEjA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -2963,6 +3852,12 @@ "node": ">=10.13.0" } }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "license": "BSD-2-Clause" + }, "node_modules/glob/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -3140,6 +4035,12 @@ "node": ">= 0.4" } }, + "node_modules/hey-listen": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz", + "integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==", + "license": "MIT" + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -3192,6 +4093,15 @@ "node": ">= 0.4" } }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, "node_modules/is-array-buffer": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", @@ -3667,11 +4577,19 @@ "jiti": "bin/jiti.js" } }, + "node_modules/js-cookie": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", + "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, "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": { @@ -3767,6 +4685,12 @@ "node": ">=0.10" } }, + "node_modules/leaflet": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz", + "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==", + "license": "BSD-2-Clause" + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -3828,7 +4752,6 @@ "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" @@ -3837,6 +4760,15 @@ "loose-envify": "cli.js" } }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.3" + } + }, "node_modules/lru-cache": { "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", @@ -3844,6 +4776,24 @@ "dev": true, "license": "ISC" }, + "node_modules/map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/material-ripple-effects": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/material-ripple-effects/-/material-ripple-effects-2.0.1.tgz", + "integrity": "sha512-hHlUkZAuXbP94lu02VgrPidbZ3hBtgXBtjlwR8APNqOIgDZMV8MCIcsclL8FmGJQHvnORyvoQgC965vPsiyXLQ==", + "license": "MIT" + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -4037,6 +4987,16 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "license": "MIT", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -4051,7 +5011,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" @@ -4350,6 +5309,18 @@ "node": ">= 6" } }, + "node_modules/popmotion": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/popmotion/-/popmotion-11.0.3.tgz", + "integrity": "sha512-Y55FLdj3UxkR7Vl3s7Qr4e9m0onSnP8W7d/xQLsoJM40vs6UKHFdygs6SWryasTZYqugMjm3BepCF4CWXDiHgA==", + "license": "MIT", + "dependencies": { + "framesync": "6.0.1", + "hey-listen": "^1.0.8", + "style-value-types": "5.0.0", + "tslib": "^2.1.0" + } + }, "node_modules/possible-typed-array-names": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", @@ -4520,11 +5491,30 @@ "node": ">= 0.8.0" } }, + "node_modules/prisma": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-6.2.1.tgz", + "integrity": "sha512-hhyM0H13pQleQ+br4CkzGizS5I0oInoeTw3JfLw1BRZduBSQxPILlJLwi+46wZzj9Je7ndyQEMGw/n5cN2fknA==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/engines": "6.2.1" + }, + "bin": { + "prisma": "build/index.js" + }, + "engines": { + "node": ">=18.18" + }, + "optionalDependencies": { + "fsevents": "2.3.3" + } + }, "node_modules/prop-types": { "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", @@ -4532,6 +5522,19 @@ "react-is": "^16.13.1" } }, + "node_modules/prop-types-extra": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/prop-types-extra/-/prop-types-extra-1.1.1.tgz", + "integrity": "sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew==", + "license": "MIT", + "dependencies": { + "react-is": "^16.3.2", + "warning": "^4.0.0" + }, + "peerDependencies": { + "react": ">=0.14.0" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -4572,6 +5575,37 @@ "node": ">=0.10.0" } }, + "node_modules/react-bootstrap": { + "version": "2.10.7", + "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.10.7.tgz", + "integrity": "sha512-w6mWb3uytB5A18S2oTZpYghcOUK30neMBBvZ/bEfA+WIF2dF4OGqjzoFVMpVXBjtyf92gkmRToHlddiMAVhQqQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.7", + "@restart/hooks": "^0.4.9", + "@restart/ui": "^1.9.2", + "@types/prop-types": "^15.7.12", + "@types/react-transition-group": "^4.4.6", + "classnames": "^2.3.2", + "dom-helpers": "^5.2.1", + "invariant": "^2.2.4", + "prop-types": "^15.8.1", + "prop-types-extra": "^1.1.0", + "react-transition-group": "^4.4.5", + "uncontrollable": "^7.2.1", + "warning": "^4.0.3" + }, + "peerDependencies": { + "@types/react": ">=16.14.8", + "react": ">=16.14.0", + "react-dom": ">=16.14.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/react-dom": { "version": "19.0.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0.tgz", @@ -4584,13 +5618,63 @@ "react": "^19.0.0" } }, + "node_modules/react-fontawesome": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/react-fontawesome/-/react-fontawesome-1.7.1.tgz", + "integrity": "sha512-kottReWW1I9Uupub6A5YX4VK7qfpFnEjAcm5zB4Aepst7iofONT27GJYdTcRsj7q5uQu9PXBL7GsxAFKANNUVg==", + "license": "MIT", + "dependencies": { + "prop-types": "^15.5.6" + }, + "engines": { + "node": ">=0.10.0" + }, + "peerDependencies": { + "react": ">=0.12.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-leaflet": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/react-leaflet/-/react-leaflet-5.0.0.tgz", + "integrity": "sha512-CWbTpr5vcHw5bt9i4zSlPEVQdTVcML390TjeDG0cK59z1ylexpqC6M1PJFjV8jD7CF+ACBFsLIDs6DRMoLEofw==", + "license": "Hippocratic-2.1", + "dependencies": { + "@react-leaflet/core": "^3.0.0" + }, + "peerDependencies": { + "leaflet": "^1.9.0", + "react": "^19.0.0", + "react-dom": "^19.0.0" + } + }, + "node_modules/react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==", + "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", @@ -4637,6 +5721,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.4", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", @@ -4808,6 +5898,12 @@ "node": ">=10" } }, + "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", @@ -5019,6 +6115,39 @@ "is-arrayish": "^0.3.1" } }, + "node_modules/slugify": { + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.6.tgz", + "integrity": "sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "license": "MIT", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/snakecase-keys": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/snakecase-keys/-/snakecase-keys-8.0.1.tgz", + "integrity": "sha512-Sj51kE1zC7zh6TDlNNz0/Jn1n5HiHdoQErxO8jLtnyrkJW/M5PrI7x05uDgY3BO7OUQYKCvmeMurW6BPUdwEOw==", + "license": "MIT", + "dependencies": { + "map-obj": "^4.1.0", + "snake-case": "^3.0.4", + "type-fest": "^4.15.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -5035,6 +6164,12 @@ "dev": true, "license": "MIT" }, + "node_modules/std-env": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.8.0.tgz", + "integrity": "sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==", + "license": "MIT" + }, "node_modules/streamsearch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", @@ -5283,6 +6418,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/style-value-types": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/style-value-types/-/style-value-types-5.0.0.tgz", + "integrity": "sha512-08yq36Ikn4kx4YU6RD7jWEv27v4V+PUsOGa4n/as8Et3CuODMJQ00ENeAVXAeydX4Z2j1XHZF1K2sX4mGl18fA==", + "license": "MIT", + "dependencies": { + "hey-listen": "^1.0.8", + "tslib": "^2.1.0" + } + }, "node_modules/styled-jsx": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", @@ -5355,6 +6500,31 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/swr": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/swr/-/swr-2.3.0.tgz", + "integrity": "sha512-NyZ76wA4yElZWBHzSgEJc28a0u6QZvhb6w0azeL2k7+Q1gAzVK+IqQYXhVOC/mzi+HZIozrZvBVeSeOZNR2bqA==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.3", + "use-sync-external-store": "^1.4.0" + }, + "peerDependencies": { + "react": "^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/tabbable": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", + "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==", + "license": "MIT" + }, + "node_modules/tailwind-merge": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-1.8.1.tgz", + "integrity": "sha512-+fflfPxvHFr81hTJpQ3MIwtqgvefHZFUHFiIHpVIRXvG/nX9+gu2P7JNlFu2bfDMJ+uHhi/pUgzaYacMoXv+Ww==", + "license": "MIT" + }, "node_modules/tailwindcss": { "version": "3.4.17", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz", @@ -5521,6 +6691,18 @@ "node": ">= 0.8.0" } }, + "node_modules/type-fest": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.32.0.tgz", + "integrity": "sha512-rfgpoi08xagF3JSdtJlCwMq9DGNDE0IMh3Mkpc1wUypg9vPi786AiqeBBKcqvIkq42azsBM85N490fyZjeUftw==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/typed-array-buffer": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", @@ -5632,6 +6814,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/uncontrollable": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.2.1.tgz", + "integrity": "sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.6.3", + "@types/react": ">=16.9.11", + "invariant": "^2.2.4", + "react-lifecycles-compat": "^3.0.4" + }, + "peerDependencies": { + "react": ">=15.0.0" + } + }, "node_modules/undici-types": { "version": "6.19.8", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", @@ -5649,6 +6846,15 @@ "punycode": "^2.1.0" } }, + "node_modules/use-sync-external-store": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz", + "integrity": "sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -5656,6 +6862,15 @@ "dev": true, "license": "MIT" }, + "node_modules/warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index aa1c33c..5387fd7 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "testauthclerk", + "name": "airsoftsearch", "version": "0.1.0", "private": true, "scripts": { @@ -9,19 +9,35 @@ "lint": "next lint" }, "dependencies": { + "@clerk/nextjs": "^6.9.11", + "@clerk/themes": "^2.2.7", + "@fortawesome/free-solid-svg-icons": "^6.7.2", + "@fortawesome/react-fontawesome": "^0.2.2", + "@headlessui/react": "^2.2.0", + "@heroicons/react": "^2.2.0", + "@material-tailwind/react": "^2.1.10", + "@prisma/client": "^6.2.1", + "bootstrap": "^5.3.3", + "leaflet": "^1.9.4", + "next": "15.1.4", "react": "^19.0.0", + "react-bootstrap": "^2.10.7", "react-dom": "^19.0.0", - "next": "15.1.4" + "react-fontawesome": "^1.7.1", + "react-leaflet": "^5.0.0", + "slugify": "^1.6.6" }, "devDependencies": { - "typescript": "^5", + "@eslint/eslintrc": "^3", + "@types/leaflet": "^1.9.16", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", - "postcss": "^8", - "tailwindcss": "^3.4.1", "eslint": "^9", "eslint-config-next": "15.1.4", - "@eslint/eslintrc": "^3" + "postcss": "^8", + "prisma": "^6.2.1", + "tailwindcss": "^3.4.1", + "typescript": "^5" } } diff --git a/prisma/old_schema.prisma b/prisma/old_schema.prisma new file mode 100644 index 0000000..268d267 --- /dev/null +++ b/prisma/old_schema.prisma @@ -0,0 +1,63 @@ +// This is your Prisma schema file, +// learn more about it in the docs: https://pris.ly/d/prisma-schema + +// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions? +// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init + +generator client { + provider = "prisma-client-js" +} + +datasource db { + provider = "postgresql" + url = env("DATABASE_URL") +} + +model Organisation { + id String @id @default(cuid()) + name String @default("") + tag String @default("") + type String @default("") + logo String @default("") + slug String @default("") +} + +model Membre { + id String @id @default(cuid()) + userId String @default("") + organisationid String @default("") + role String @default("") + slug String @default("") +} + +model User { + id String @id @default(cuid()) + userId String @default("") + userName String @default("") + categorie String @default("") + role String @default("") + slug String @default("") +} + +model GameSession{ + id String @id @default(cuid()) + organisationId String @default("") + title String @default("") + date DateTime + startTime DateTime @db.Time + endTime DateTime @db.Time + paf Int @default(0) + maxPlayer Int @default(0) + slug String @default("") +} +model GameSessionTag{ + id String @id @default(cuid()) + gameSessionId String @default("") + tagId String @default("") + slug String @default("") +} +model Tag{ + id String @id @default(cuid()) + title String @default("") + slug String @default("") +} \ No newline at end of file diff --git a/prisma/schema.prisma b/prisma/schema.prisma new file mode 100644 index 0000000..2c0e2ae --- /dev/null +++ b/prisma/schema.prisma @@ -0,0 +1,58 @@ +// This is your Prisma schema file, +// learn more about it in the docs: https://pris.ly/d/prisma-schema + +// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions? +// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init + +generator client { + provider = "prisma-client-js" +} + +datasource db { + provider = "postgresql" + url = env("DATABASE_URL") +} + +model Organisation { + id String @id @default(uuid()) + name String @unique + description String? + logo String? + type String? + tag String? + slug String? + members UserOnOrganisation[] + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt +} + +model User { + id String @id @default(uuid()) + userId String + email String + name String? + slug String? + organisations UserOnOrganisation[] + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt +} + +model Role { + id String @id @default(uuid()) + name String @unique + usersOnOrganisations UserOnOrganisation[] +} + +model UserOnOrganisation { + userId String + organisationId String + roleId String + + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + organisation Organisation @relation(fields: [organisationId], references: [id], onDelete: Cascade) + role Role @relation(fields: [roleId], references: [id], onDelete: Cascade) + + createdAt DateTime @default(now()) + + @@id([userId, organisationId, roleId]) +} \ No newline at end of file diff --git a/public/assets/LogoEAN.png b/public/assets/LogoEAN.png new file mode 100644 index 0000000..1ac3d0b Binary files /dev/null and b/public/assets/LogoEAN.png differ diff --git a/public/assets/image0_0.jpg b/public/assets/image0_0.jpg new file mode 100644 index 0000000..e277f87 Binary files /dev/null and b/public/assets/image0_0.jpg differ diff --git a/public/assets/logoAS.png b/public/assets/logoAS.png new file mode 100644 index 0000000..543d0f0 Binary files /dev/null and b/public/assets/logoAS.png differ diff --git a/public/assets/logoTaff.png b/public/assets/logoTaff.png new file mode 100644 index 0000000..4a6b2f3 Binary files /dev/null and b/public/assets/logoTaff.png differ diff --git a/src/actions/globalFunction.jsx b/src/actions/globalFunction.jsx new file mode 100644 index 0000000..e69de29 diff --git a/src/actions/memberActions.tsx b/src/actions/memberActions.tsx new file mode 100644 index 0000000..7558531 --- /dev/null +++ b/src/actions/memberActions.tsx @@ -0,0 +1,76 @@ +'use server' +import prisma from "@/lib/db"; +import { currentUser } from "@clerk/nextjs/server"; +import { getOrganisation } from "./organisationActions"; +//import { getUserNameWithId } from "./usersActions"; + + +export async function createMember(id : string){ + try{ + const user = await currentUser() + if(!user?.id){ + throw new Error("Error with user") + } + await prisma.membre.create({ + data :{ + userId : user?.id, + organisationid : id, + role: 'ADMIN' + } + }) + return {success : true} + }catch(error){ + return{success : false, error : error instanceof Error ? error.message : 'An unknown error occured'} + } +} + +export async function getMember(id : string){ + try{ + const user = await currentUser() + if(!user?.id){ + throw new Error("Error with user") + } + + const organisation = await getOrganisation(id) + const result = await prisma.membre.findFirst( + { + where :{ + userId : user?.id, + organisationid: organisation.Organisation?.id + }, + select:{ + role:true + } + }) + return {success : true, role: result?.role } + }catch(error){ + return{success : false, error : error instanceof Error ? error.message : 'An unknown error occured'} + } +} + +export async function getMembers(id: string){ + try{ + const user = await currentUser() + const organisation = await getOrganisation(id) + + if(!user?.id){ + throw new Error("Error with user") + } + const result = await prisma.membre.findMany( + { + where :{ + userId : user?.id, + organisationid: organisation.Organisation?.id + } + }) + + const updatedResult = await Promise.all(result.map(async (user) => { + const userName = await getUserNameWithId(user.userId); // Récupère le userName + return { ...user, userName }; // Ajoute le userName à l'élément user + })); + + return {success : true, listMembre: updatedResult } + }catch(error){ + return{success : false, error : error instanceof Error ? error.message : 'An unknown error occured'} + } +} \ No newline at end of file diff --git a/src/actions/organisationActions.tsx b/src/actions/organisationActions.tsx new file mode 100644 index 0000000..52916f5 --- /dev/null +++ b/src/actions/organisationActions.tsx @@ -0,0 +1,285 @@ +'use server' +import prisma from "@/lib/db"; +import { currentUser } from "@clerk/nextjs/server"; +//import { createMember } from "./memberActions"; +import slugify from "slugify"; +import {uploadImage,deleteImage} from '@/lib/uploadFile' + +export async function updateOrganisation( + nameOrganisation : string, + idOrganisation : string, + logoOrganisation : string, + typeOrganisation : string, + tagOrganisation : string){ + try{ + const slugOrganisation = slugify(nameOrganisation) + await prisma.organisation.upsert({ + where: { id: idOrganisation}, + update: {name : nameOrganisation, logo : logoOrganisation, type : typeOrganisation,tag : tagOrganisation, slug: slugOrganisation }, + create: {name : nameOrganisation, logo : logoOrganisation, type : typeOrganisation,tag : tagOrganisation, slug: slugOrganisation } + }) + return {success : true} + }catch(error){ + return{success : false, error : error instanceof Error ? error.message : 'An unknown error occured'} + } +} + +/*export async function createOrganisation(nameOrganisation : string,logoOrganisation : string, typeOrganisation : string,tagOrganisation: string){ + try{ + let slugOrganisation = "" + if(slugOrganisation){ + let slugCandidate = slugify(nameOrganisation,{lower:true,strict:true}) + let slugExist = await getOrganisation(slugCandidate) + let counter = 1 + while(slugExist){ + slugCandidate=`${slugCandidate}-${counter}` + slugExist = await getOrganisation(slugCandidate) + counter++ + } + slugOrganisation = slugCandidate + } + const user = await currentUser() + if(!user?.id){ + throw new Error("Error with user") + } + if(!logoOrganisation){ + logoOrganisation = '/assets/image0_0.jpg' + } + const result = await prisma.organisation.create({ + data : { + name : nameOrganisation, + logo : logoOrganisation, + type : typeOrganisation, + tag : tagOrganisation, + slug : slugOrganisation + } + }) + + await createMember(result.id) + return {success : true} + }catch(error){ + return{success : false, error : error instanceof Error ? error.message : 'An unknown error occured'} + } +} + +export async function getOrganisations(){ + try{ + const user = await currentUser() + if(!user){ + throw new Error ("Error with credential") + } + const listOrganisation = await prisma.membre.findMany( + {where : { + userId:user.id + }, + select:{ + organisationid: true + }}) + const listTemp: ({ id: string; name: string; tag: string; type: string; logo: string; } | null)[] = [] + const organisationPromise = listOrganisation.map(async organisation => { + const temp = await prisma.organisation.findUnique({ + where : { + id: organisation.organisationid + } + }) + + return temp + }) + const result = await Promise.all(organisationPromise) + listTemp.push(...result) + return {success : true, listOrganisation : listTemp} + }catch(error){ + return{success : false, error : error instanceof Error ? error.message : 'An unknown error occured'} + } +} + +export async function deleteOrganisation(idOrganisation : string){ + try{ + await prisma.organisation.delete( + { + where: { + id : idOrganisation + }, + }) + return {success : true} + }catch(error){ + return{success : false, error : error instanceof Error ? error.message : 'An unknown error occured'} + } +} + +export async function getOrganisation(slugOrganisation : string ){ + try{ + const user = currentUser() + if(!user){ + throw new Error("Error with credential") + } + + const result = await prisma.organisation.findFirst({ + where :{ + slug:slugOrganisation + } + }) + + if(!result){ + throw new Error ("Not found") + } + return {success : true, Organisation : result} + }catch(error){ + return{success : false, error : error instanceof Error ? error.message : 'An unknown error occured'} + } +} + + +*/ +export async function createOrganisation(formData : FormData){ + try{ + const {title,file,selectType,tag} = Object.fromEntries(formData) + let slugOrganisation = "" + let logo = "" + if(!slugOrganisation){ + let slugCandidate = slugify(title.toString() ,{lower:true,strict:true}) + let slugExist = await prisma.organisation.findFirst({ + where : { + slug : slugCandidate + } + }) + let counter = 1 + while(slugExist){ + slugCandidate=`${slugCandidate}-${counter}` + slugExist = await prisma.organisation.findFirst({ + where : { + slug : slugCandidate + } + }) + counter++ + } + slugOrganisation = slugCandidate + } + const resultUpdateImage = await uploadImage(file,slugOrganisation) + const user = await currentUser() + if(!user?.id){ + throw new Error("Error with user") + } + if(!resultUpdateImage.success){ + logo = '/assets/image0_0.jpg' + }else{ + logo = resultUpdateImage.imageUrl + } + const result = await prisma.organisation.create({ + data : { + name : title.toString(), + logo : logo, + type : selectType.toString(), + tag : tag.toString(), + slug : slugOrganisation + } + }) + return {success : true, result : result} + }catch(error){ + return{success : false, error : error instanceof Error ? error.message : 'An unknown error occured'} + } + +} + +export async function getListOrganisations(userId : string){ + try{ + const result = await prisma.organisation.findMany({ + where :{ + members:{ + some : { + userId + } + }, + + }, + select:{ + id : true, + name: true, + logo: true, + slug: true + } + }) + if(!result){ + return{success : false, error : 'Error when retrieve all organisation', result : result} + } + return{success : true, result: result} + + }catch(error){ + return{success : false, error : error instanceof Error ? error.message : 'An unknown error occured'} + } +} + +export async function getOrganisation(slug : string){ + try { + + const user = await currentUser(); // 🔍 Récupère l'utilisateur connecté + if (!user || !user.id) { + return { success: false, error: "Utilisateur non authentifié" }; + } + const organisation = await prisma.organisation.findFirst({ + where: { + slug:slug + }, + include: { + members: { + include: { + user: { select: { id: true, userId: true,name: true } }, // Infos de l'utilisateur + role: { select: { id: true, name: true } } // Infos du rôle + } + } + } + }); + const userCurrent = organisation?.members.find(member => member.user.userId === user?.id); + + if (!organisation) { + return { success: false, error: "Organisation not found" }; + } + + return { + success: true, + organisation :{ + name : organisation.name, + tag : organisation.tag, + slug : organisation.slug, + logo : organisation.logo, + members : organisation.members + }, + userCurrent: userCurrent ? { + role: userCurrent.role + } : null + }; + } catch (error) { + return { success: false, error: error instanceof Error ? error.message : "An unknown error occurred" }; + } +} + + +export async function deleteOrganisation(slug : string){ + try{ + + const verifOrga = await prisma.organisation.findFirst({ + where : { + slug : slug + } + }) + if(verifOrga){ + const result = await prisma.organisation.delete({ + where :{ + id: verifOrga.id + } + }) + if(result){ + + if(!result.logo?.includes("image0_0")){ + deleteImage(result.logo) + } + + return { success: true }; + } + } + + return { success: false, error: "pas d'orga trouvé" }; + }catch(error){ + return { success: false, error: error instanceof Error ? error.message : "An unknown error occurred" }; + } +} \ No newline at end of file diff --git a/src/actions/roleActions.tsx b/src/actions/roleActions.tsx new file mode 100644 index 0000000..f6baa60 --- /dev/null +++ b/src/actions/roleActions.tsx @@ -0,0 +1,34 @@ +import prisma from "@/lib/db"; + +export async function createRole(name : string){ + try{ + const result = await prisma.role.create({ + data : { + name:name + } + }) + if(!result){ + return{success : false} + } + return({success : true, result : result}) + }catch(error){ + return{success : false, error : error instanceof Error ? error.message : 'An unknown error occured'} + } +} + +export async function getRole(name : string){ + try{ + const result = await prisma.role.findFirst({ + where : { + name: name + } + }) + if(!result){ + return{success : false} + } + return({success : true, result : result}) + }catch(error){ + return{success : false, error : error instanceof Error ? error.message : 'An unknown error occured'} + } +} + diff --git a/src/actions/userOnOrganisation.tsx b/src/actions/userOnOrganisation.tsx new file mode 100644 index 0000000..de7d512 --- /dev/null +++ b/src/actions/userOnOrganisation.tsx @@ -0,0 +1,22 @@ +"use server" +import prisma from "@/lib/db"; + + +export async function createUserOnOrganisation(userId : string ,organisationId : string, roleId : string){ + try{ + const userOrg = await prisma.userOnOrganisation.create({ + data: { + userId, + organisationId, + roleId + }, + }); + if(!userOrg){ + return({success : false}) + } + return({success : true, userOrg : userOrg}) + }catch(error){ + return{success : false, error : error instanceof Error ? error.message : 'An unknown error occured'} + } + +} \ No newline at end of file diff --git a/src/actions/usersActions.tsx b/src/actions/usersActions.tsx new file mode 100644 index 0000000..245f5fe --- /dev/null +++ b/src/actions/usersActions.tsx @@ -0,0 +1,74 @@ +'use server' +import prisma from "@/lib/db"; +import { currentUser } from "@clerk/nextjs/server" + +import slugify from "slugify"; + +export async function createUser(){ + try{ + const user = await currentUser() + let slugUser = "" + if(!slugUser){ + let slugCandidate = slugify(user?.username || "",{lower:true,strict:true}) + let slugExist = await prisma.user.findFirst({ + where : { + slug: slugCandidate + } + }) + let counter = 1 + while(slugExist){ + slugCandidate=`${slugCandidate}-${counter}` + slugExist = await prisma.user.findFirst({ + where : { + slug: slugCandidate + } + }) + counter++ + } + slugUser = slugCandidate + + } + if(!user){ + throw new Error("error with user") + } + + + const result = await prisma.user.create({ + data :{ + userId : user?.id, + email : user?.emailAddresses[0].emailAddress, + name : user?.username, + slug: slugUser + } + }) + + if(!result ){ + return ({success : false}) + } + return ({success : true, id : result.id}) + }catch(error){ + return{success : false, error : error instanceof Error ? error.message : 'An unknown error occured'} + } + +} + +export async function getUser() { + try{ + const user = await currentUser() + if(!user){ + throw new Error("error with user") + } + const result = await prisma.user.findFirst({ + where :{ + userId : user?.id + } + }) + if(!result ){ + return ({success : false}) + } + return ({success : true, id : result.id}) + }catch(error){ + return{success : false, error : error instanceof Error ? error.message : 'An unknown error occured'} + } + +} \ No newline at end of file diff --git a/src/app/[[...rest]]/page.tsx b/src/app/[[...rest]]/page.tsx new file mode 100644 index 0000000..16f37bf --- /dev/null +++ b/src/app/[[...rest]]/page.tsx @@ -0,0 +1,143 @@ +'use client' +import React, { useState,useEffect } from 'react'; +import 'leaflet/dist/leaflet.css'; +//import L from 'leaflet' +import { LatLngTuple } from 'leaflet'; +import '../../styles/map.css' +//import MapSearch from './MapSearch'; +import { Button,Form } from 'react-bootstrap'; +//import 'bootstrap/dist/css/bootstrap.min.css'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import {faPersonRifle,faCalendarDay,faFile,faEuroSign,faClock,faPeopleGroup} from '@fortawesome/free-solid-svg-icons' +//import ModalMapInfo from '../Informations/ModalMapInscription'; +import dynamic from 'next/dynamic'; +import L from 'leaflet'; // Import du type L + +interface PositionInfo { + name: string; + position: LatLngTuple; + customIcon: L.Icon<{ iconUrl: string; iconSize: [number, number]; iconAnchor: [number, number]; popupAnchor: [number, number]; }>; + date: string; + heure: string; + paf: string; + description: string; + nbParticipant: string; +} + +const MapWithNoSSR = dynamic(() => import('react-leaflet').then(mod => mod.MapContainer), { + ssr: false, // Empêche l'exécution côté serveur +}); +const TileLayer = dynamic(() => import('react-leaflet').then(mod => mod.TileLayer), { ssr: false }); +const Marker = dynamic(() => import('react-leaflet').then(mod => mod.Marker), { ssr: false }); +const Popup = dynamic(() => import('react-leaflet').then(mod => mod.Popup), { ssr: false }); +const ZoomControl = dynamic(() => import('react-leaflet').then(mod => mod.ZoomControl), { ssr: false }); + +export default function Home(){ + + // Hook d'état pour listInfoPosition + const [listInfoPosition,setListInfoPosition] = useState([]); + const position : LatLngTuple = [46.603354, 3.141249] + const [LModule, setLModule] = useState(null); // pour stocker L côté client + + + useEffect(() => { + if (typeof window !== 'undefined') { + import('leaflet').then(L => { + setLModule(L); // Charge le module `L` côté client + }); + } + }, []); // Cela ne s'exécute qu'une seule fois au montage du composant côté client + + useEffect(() => { + const positionTemp : PositionInfo[] = [] + if (LModule) { + const customIcon = new LModule.Icon({ + iconUrl: '/assets/logoEAN.png', // Assurez-vous que le fichier est dans le dossier 'public/images/' + iconSize: [40, 40], + iconAnchor: [16, 32], + popupAnchor: [0, -32], + }); + + const customIconTaff = new LModule.Icon({ + iconUrl: '/assets/logoTaff.png', // Assurez-vous que le fichier est dans le dossier 'public/images/' + iconSize: [32, 32], + iconAnchor: [16, 32], + popupAnchor: [0, -32], + }); + + let positionTempInfo : PositionInfo = + { + name : "Equipe Airsoft Nord", + position : [50.78794581996757, 2.402059344182279], + customIcon : customIcon, + date: "05/01/2025", + heure : "8h30-16h", + paf : "8€", + description : " Ce dimanche 05 janvier, les EAN organisent leur premiere partie de l'année sur leur terrain.", + nbParticipant : "0/20" + } + positionTemp.push(positionTempInfo) + positionTempInfo = + { + name : "Taff", + position : [50.35071567603138, 3.309760157697385], + customIcon : customIconTaff, + date: "05/01/2025", + heure : "8h30-16h", + paf : "10€", + description : "salut c'est la taff", + nbParticipant : "0/40" + } + positionTemp.push(positionTempInfo) + setListInfoPosition(positionTemp) + } + }, [LModule]); + + useEffect(() => { + + },[]) + return( +
+ {/**/} + + {/* Chargement des tuiles OpenStreetMap */} + + + + {/* Ajout d'un marker */} + {listInfoPosition.map((data,index) => + + +
+
+ + : {data.name} + + + : {data.date} : {data.heure} + + + : {data.description} + + + : {data.paf} + + + : {data.nbParticipant} + + + + +
+
+
+
+ )} +
+ {/**/} +
+ ) +} \ No newline at end of file diff --git a/src/app/favicon.ico b/src/app/favicon.ico index 718d6fe..e277f87 100644 Binary files a/src/app/favicon.ico and b/src/app/favicon.ico differ diff --git a/src/app/globals.css b/src/app/globals.css index 6b717ad..0327ea6 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -19,3 +19,37 @@ body { background: var(--background); font-family: Arial, Helvetica, sans-serif; } + +.u-main-container { + @apply w-full sm:max-w-md md:max-w-lg lg:max-w-7xl mx-auto p-3 +} + +.u-padding-content-container{ + @apply pt-32 pb-44 +} + +.u-articles-grid{ + @apply grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-x-4 gap-y-8 mt-4 mb-12 list-none +} + +/* text */ + + +.t-main-title{ + @apply font-bold text-zinc-900 text-4xl mb-2 +} + +.t-main-subtitle{ + @apply mb-12 text-zinc-700 +} + +.f-label{ + @apply block ml-2 mb-2 text-gray-700 font-semibold +} + +.f-input { + @apply shadow appearance-none border rounded p-3 mr-2 text-gray-700 leading-tight mb-5 focus:outline-slate-400 w-1/2 +} +.f-auth-input { + @apply shadow appearance-none border rounded w-full p-3 text-gray-700 leading-tight mb-5 focus:outline-slate-400 +} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index f7fa87e..7d2b8e0 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,20 +1,18 @@ import type { Metadata } from "next"; -import { Geist, Geist_Mono } from "next/font/google"; import "./globals.css"; +//import "../styles/menu.css" +//import 'bootstrap/dist/css/bootstrap.min.css'; +import { + ClerkProvider +} from '@clerk/nextjs' +import Menu from '../components/menu' +import { dark } from '@clerk/themes' -const geistSans = Geist({ - variable: "--font-geist-sans", - subsets: ["latin"], -}); - -const geistMono = Geist_Mono({ - variable: "--font-geist-mono", - subsets: ["latin"], -}); export const metadata: Metadata = { - title: "Create Next App", - description: "Generated by create next app", + title: "Airsoft Search", + description: "Airsoft Search is a platform dedicated to airsoft players worldwide, helping them easily find upcoming events, matches, and meetups near them or internationally. With an intuitive interface, discover scheduled games, register quickly, and join a community of passionate players. Whether you're a beginner or an experienced player, Airsoft Search simplifies the planning of your sessions and connects you with other players globally.", + keywords: "airsoft events, airsoft matches, airsoft community, find airsoft games, airsoft parties, airsoft meetup, airsoft players worldwide, global airsoft events, airsoft calendar, airsoft groups", }; export default function RootLayout({ @@ -23,12 +21,17 @@ export default function RootLayout({ children: React.ReactNode; }>) { return ( - + + - {children} + + {children} + ); } diff --git a/src/app/loading.tsx b/src/app/loading.tsx new file mode 100644 index 0000000..dc677e4 --- /dev/null +++ b/src/app/loading.tsx @@ -0,0 +1,9 @@ +import React from 'react' + +export default function Loading() { + return ( +
+
+
+ ); + } diff --git a/src/app/old_favicon.ico b/src/app/old_favicon.ico new file mode 100644 index 0000000..718d6fe Binary files /dev/null and b/src/app/old_favicon.ico differ diff --git a/src/app/organisations/[slugOrganisation]/game/[slugSession]/page.jsx b/src/app/organisations/[slugOrganisation]/game/[slugSession]/page.jsx new file mode 100644 index 0000000..968cea2 --- /dev/null +++ b/src/app/organisations/[slugOrganisation]/game/[slugSession]/page.jsx @@ -0,0 +1,37 @@ +"use client" + +import React,{useEffect, useState} from 'react' +import Image from 'next/image'; +export default function pageInfoSession({params}) { + + const [image, setImage] = useState(null); + const [slugSession,setSlugSession] = useState("") + + /*useEffect(() => { + const getSlug = async () => { + const {slugSession} = await params + + setSlugSession(slugSession) + } + getSlug() + },[])*/ + + // Fonction qui gère la sélection d'une nouvelle image + const handleImageChange = (e) => { + const file = e.target.files[0]; + if (file) { + // Crée un URL temporaire pour l'image sélectionnée + const imageUrl = URL.createObjectURL(file); + setImage(imageUrl); + } + }; + return ( +
+ +
Partie : {slugSession}
+
+ + + + ) +} diff --git a/src/app/organisations/[slugOrganisation]/game/loading.jsx b/src/app/organisations/[slugOrganisation]/game/loading.jsx new file mode 100644 index 0000000..dc677e4 --- /dev/null +++ b/src/app/organisations/[slugOrganisation]/game/loading.jsx @@ -0,0 +1,9 @@ +import React from 'react' + +export default function Loading() { + return ( +
+
+
+ ); + } diff --git a/src/app/organisations/[slugOrganisation]/game/page.jsx b/src/app/organisations/[slugOrganisation]/game/page.jsx new file mode 100644 index 0000000..d7a1088 --- /dev/null +++ b/src/app/organisations/[slugOrganisation]/game/page.jsx @@ -0,0 +1,7 @@ +import React from 'react' + +export default function pageGame() { + return ( +
Game
+ ) +} diff --git a/src/app/organisations/[slugOrganisation]/loading.tsx b/src/app/organisations/[slugOrganisation]/loading.tsx new file mode 100644 index 0000000..dc677e4 --- /dev/null +++ b/src/app/organisations/[slugOrganisation]/loading.tsx @@ -0,0 +1,9 @@ +import React from 'react' + +export default function Loading() { + return ( +
+
+
+ ); + } diff --git a/src/app/organisations/[slugOrganisation]/page.jsx b/src/app/organisations/[slugOrganisation]/page.jsx new file mode 100644 index 0000000..a45b70c --- /dev/null +++ b/src/app/organisations/[slugOrganisation]/page.jsx @@ -0,0 +1,218 @@ + +"use client" + +import {useEffect, useRef, useState} from 'react' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import {faTrash,faPenToSquare,faCamera,faCheck, faCancel} from '@fortawesome/free-solid-svg-icons' +import Image from 'next/image' +import logoDefault from 'p/assets/image0_0.jpg' +import {getOrganisationMethods,deleteOrganisationMethods } from "@/methods/organisationMethods" +import { useRouter } from 'next/navigation' +import ConfirmDeleteModal from '@/components/ConfirmeDeleteModal' + + +export default function pageOrganisation({params}) { + const router = useRouter() + const [infoOrganisation,setInfoOrganisation] = useState("") + const [listMember,setListMember] = useState([]) + const [error,setError] = useState("") + const [role,setRole] = useState("") + const [isEnable,setIsEnable] = useState(false) + const refImageChange = useRef(null) + const [image, setImage] = useState(null); + const [isModalOpen, setModalOpen] = useState(false); + const [hiddenError,setHiddenError] = useState(true) + + + async function getSlug(){ + const {slugOrganisation } = await params + return slugOrganisation + } + + + + useEffect(() => { + fetchOrganisation() + },[]) + + function handleEnableModify(e){ + e.preventDefault() + setIsEnable(true) + } + + function handleEnableChangeImage(e){ + e.preventDefault() + refImageChange.current.click() + } + // Fonction qui gère la sélection d'une nouvelle image + const handleImageChange = (e) => { + const file = e.target.files[0]; + if (file) { + // Crée un URL temporaire pour l'image sélectionnée + const imageUrl = URL.createObjectURL(file); + setImage(imageUrl); + } + }; + + async function fetchOrganisation() { + try{ + const result = await getOrganisationMethods(await getSlug()) + console.log(result) + if(result.success){ + setInfoOrganisation(result.result.organisation) + setListMember(result.result.organisation.members) + setImage(result.result.organisation.logo) + setRole(result.result.userCurrent.role.name) + } + + }catch(e){ + setError("une erreur s'est produite : " + e) + } + } + async function handleDisableModify(e){ + e.preventDefault() + try{ + fetchOrganisation() + }catch(e){ + setError("une erreur s'est produite : " + e) + } + setIsEnable(false) + } + + async function handleDeleteOrga(e){ + e.preventDefault() + setHiddenError(true) + try{ + const result = await deleteOrganisationMethods(await getSlug()) + if(result){ + router.push('/organisations') + } + setModalOpen(false); + setError('Erreur lors de la suppression essayer plus tard') + setHiddenError(false) + + }catch(err){ + setError("une erreur s'est produite : " + e) + } + } + + return ( +
+ + +
+
+ logo Organisation + + + + + +
+ {role === "ADMIN" && +
+ + +
+ } +
+
+
+ Détail +
+ + setInfoOrganisation({...infoOrganisation, name: e.target.value})}> +
+ +
+ + setInfoOrganisation({...infoOrganisation, tag: e.target.value})}> +
+
+ + setInfoOrganisation({...infoOrganisation, team: e.target.value})}> +
+
+ + +
+
+
+
+ Membres et role + { + Array.isArray(listMember) && listMember.length > 0 ? ( + listMember.map((member) => ( +
+

{member.user.name}

+

|

+

{member.role.name}

+

|

+
+ +
+
+ )) + ) : ( +

Aucun membre trouvé

+ ) + } +
+ setModalOpen(false)} + onConfirm={handleDeleteOrga} + /> +
+ ) +} diff --git a/src/app/organisations/create/page.jsx b/src/app/organisations/create/page.jsx new file mode 100644 index 0000000..b509d59 --- /dev/null +++ b/src/app/organisations/create/page.jsx @@ -0,0 +1,63 @@ +"use client" + +import { useState,useRef } from "react" +//import { createOrganisation } from "@/actions/organisationActions"; +import { createOrganisationMathods } from "@/methods/organisationMethods"; +import { useRouter } from "next/navigation"; + +export default function pageCreate() { + const router = useRouter() + const [valueTagState,setValueTagState] = useState('') + const valueTitle = useRef(null) + const valueTag = useRef(null) + + async function handleSubmit(e){ + e.preventDefault() + const formData = new FormData(e.target) + const result = await createOrganisationMathods(formData) + if(result.success){ + console.log(result.slugOrga) + router.push(`/organisations/${result.slugOrga}`) + } + + } + + function handleCreateTag(e){ + const title = valueTitle.current.value + let words = title.split(" ") + + let result = words.map(word =>{ + return word.charAt(0).toUpperCase() + }) + setValueTagState(result.join('')) + + valueTag.current.value = valueTagState.toString() + } + + return ( +
+

Create a organisation

+

* required

+
+ + + + + + + + {/**/} + + + + + +

Error

+
+
+ ) +} diff --git a/src/app/organisations/loading.tsx b/src/app/organisations/loading.tsx new file mode 100644 index 0000000..dc677e4 --- /dev/null +++ b/src/app/organisations/loading.tsx @@ -0,0 +1,9 @@ +import React from 'react' + +export default function Loading() { + return ( +
+
+
+ ); + } diff --git a/src/app/organisations/page.jsx b/src/app/organisations/page.jsx new file mode 100644 index 0000000..5af57f3 --- /dev/null +++ b/src/app/organisations/page.jsx @@ -0,0 +1,88 @@ + +'use client' +import React, { useEffect, useState } from "react"; +import Image from "next/image"; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import {faSearch,faPlus} from '@fortawesome/free-solid-svg-icons' +import { useRouter } from "next/navigation"; +import Link from "next/link"; +import { getListOrganisationsMethod } from "@/methods/organisationMethods"; + +export default function OrganisationsPage(){ + const [listOrganisation,setListOrganisation] = useState([]) + const router = useRouter() + const [loading, setLoading] = useState(false); + + function handleCreateOrganisation(e){ + router.push('/organisations/create') + } + function handleSearchOrganisation(e){ + router.push('/organisations/search') + } + + useEffect(() => { + const fetchOrganisation = async() => { + try{ + const result = await getListOrganisationsMethod() + if(result.success){ + const listTemp = result.result?.result + setListOrganisation(listTemp) + } + }catch(e){ + setError("une erreur s'est produite : " + e) + } + } + fetchOrganisation() + setLoading(false) + },[]) + + + if (loading) { + return ( +
+
+
+ ); + } + return ( +
+
+
+

Vos organisations :

+
+ + +
+
+ + {listOrganisation.map((organisation) => ( + +
  • +
    +
    + logo +
    +

    {organisation.name}

    +
    +
    +
    +
  • + + ))} + +
    +
    + ) +} \ No newline at end of file diff --git a/src/app/organisations/search/page.jsx b/src/app/organisations/search/page.jsx new file mode 100644 index 0000000..98153c1 --- /dev/null +++ b/src/app/organisations/search/page.jsx @@ -0,0 +1,7 @@ +import React from 'react' + +export default function pageSearch() { + return ( +
    + ) +} diff --git a/src/app/page.tsx b/src/app/page.tsx deleted file mode 100644 index 3eee014..0000000 --- a/src/app/page.tsx +++ /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.tsx - - . -
    2. -
    3. Save and see your changes instantly.
    4. -
    - - -
    - -
    - ); -} diff --git a/src/app/sign-in/[[...rest]]/page.tsx b/src/app/sign-in/[[...rest]]/page.tsx new file mode 100644 index 0000000..b2c885c --- /dev/null +++ b/src/app/sign-in/[[...rest]]/page.tsx @@ -0,0 +1,14 @@ +import { SignIn } from "@clerk/nextjs"; + +export default function SignInPage(){ + return ( +
    + +
    + ) +} \ No newline at end of file diff --git a/src/app/sign-up/[[...rest]]/page.tsx b/src/app/sign-up/[[...rest]]/page.tsx new file mode 100644 index 0000000..0360300 --- /dev/null +++ b/src/app/sign-up/[[...rest]]/page.tsx @@ -0,0 +1,13 @@ +import { SignUp } from "@clerk/nextjs"; + +export default function SingUpPage(){ + return ( +
    + +
    + ) +} \ No newline at end of file diff --git a/src/app/sso-callback/page.tsx b/src/app/sso-callback/page.tsx new file mode 100644 index 0000000..c0c3e33 --- /dev/null +++ b/src/app/sso-callback/page.tsx @@ -0,0 +1,5 @@ +import { AuthenticateWithRedirectCallback } from '@clerk/nextjs' + +export default function Page() { + return +} \ No newline at end of file diff --git a/src/components/ConfirmeDeleteModal.tsx b/src/components/ConfirmeDeleteModal.tsx new file mode 100644 index 0000000..b217039 --- /dev/null +++ b/src/components/ConfirmeDeleteModal.tsx @@ -0,0 +1,45 @@ +"use client"; + +import { useEffect } from "react"; + +interface ConfirmDeleteModalProps { + isOpen: boolean; + onClose: () => void; + onConfirm: () => void; +} + +export default function ConfirmDeleteModal({ isOpen, onClose, onConfirm }: ConfirmDeleteModalProps) { + // Empêche le défilement quand la modale est ouverte + useEffect(() => { + if (isOpen) document.body.style.overflow = "hidden"; + else document.body.style.overflow = "auto"; + }, [isOpen]); + + if (!isOpen) return null; + + return ( +
    + {/* Contenu de la modale */} +
    +

    Confirmer la suppression

    +

    Êtes-vous sûr de vouloir supprimer cette donnée ? Cette action est irréversible.

    + + {/* Boutons */} +
    + + +
    +
    +
    + ); +} diff --git a/src/components/menu.jsx b/src/components/menu.jsx new file mode 100644 index 0000000..6f6ba1e --- /dev/null +++ b/src/components/menu.jsx @@ -0,0 +1,181 @@ +'use client' + +import { Disclosure, DisclosureButton, DisclosurePanel, Menu, MenuButton, MenuItem, MenuItems} from '@headlessui/react' +import { Bars3Icon, BellIcon, XMarkIcon } from '@heroicons/react/24/outline' +import Link from 'next/link' + +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import {faUser,faSignIn,faSignOut} from '@fortawesome/free-solid-svg-icons' +import { useRouter } from 'next/navigation' +import Image from 'next/image' +import logoAs from "../../public/assets/logoAS.png" + +import { + SignedIn, + SignedOut, + UserButton, +} from '@clerk/nextjs' + +import { useEffect } from 'react' +import {createUser,getUser} from "@/actions/usersActions" + + + + +const NavbarsMenu = () => { + + /*useEffect(() =>{ + const verifUser = async () =>{ + try{ + let resultVerif = await getUser() + if(!resultVerif.success){ + const verifCreateUser = await createUser() + if(!verifCreateUser.success){ + throw new Error("Error with create credential") + } + } + }catch(err){ + throw new Error("Error with credential") + } + } + verifUser() + },[])*/ + + + const router = useRouter() + + const handleRedirectConnexion = () => { + router.push('/sign-in'); // Redirige vers la page "/sign-in" + }; + + const handleRedirectInscription = () => { + router.push('/sign-in'); // Redirige vers la page "/sign-in" + }; + + const navigation = [ + { name: 'Organisations', href: '/organisations', current: false } + ] + + function classNames(...classes) { + return classes.filter(Boolean).join(' ') + } + return ( + +
    +
    +
    + {/* Mobile menu button*/} + + + Open main menu + +
    +
    +
    + Airsoft Search +
    +
    +
    + {navigation.map((item) => ( + + {item.name} + + ))} +
    +
    +
    +
    + + + {/* Profile dropdown */} + +
    + + + + Open user menu + + + +
    + + + + +
    + +
    +
    + +
    + +
    +
    +
    + + + + +
    +
    +
    +
    + + +
    + {navigation.map((item) => ( + + {item.name} + + ))} +
    +
    +
    + + ); + }; + + export default NavbarsMenu; \ No newline at end of file diff --git a/src/lib/db.ts b/src/lib/db.ts new file mode 100644 index 0000000..5e2e7ad --- /dev/null +++ b/src/lib/db.ts @@ -0,0 +1,16 @@ +import { PrismaClient } from "@prisma/client"; + +const prismaClientSingleton = () => { + return new PrismaClient() +} + +declare const globalThis:{ + prismaGlobal : ReturnType +} & typeof global + +const prisma = globalThis.prismaGlobal ?? prismaClientSingleton() + +export default prisma + + +if (process.env.NODE_ENV !== "production") globalThis.prismaGlobal = prisma; \ No newline at end of file diff --git a/src/lib/uploadFile.js b/src/lib/uploadFile.js new file mode 100644 index 0000000..3113d05 --- /dev/null +++ b/src/lib/uploadFile.js @@ -0,0 +1,60 @@ +"use server"; + +import fs from "fs"; +import path from "path"; + +export async function uploadImage(file,slug) { + "use server"; + + + // Vérifier le type de fichier (optionnel) + const allowedTypes = ["image/png", "image/jpeg", "image/jpg", "image/webp"]; + if (!allowedTypes.includes(file.type)) { + return { error: "Format non supporté (PNG, JPG, WEBP seulement)" }; + } + + // Lire le fichier en tant que buffer + const bytes = await file.arrayBuffer(); + const buffer = Buffer.from(bytes); + + // Définir le dossier d'upload + const uploadDir = path.join(process.cwd(), "public/assets/avatar/avatarOrganisations"); + if (!fs.existsSync(uploadDir)) { + fs.mkdirSync(uploadDir, { recursive: true }); + } + + // Générer un nouveau nom unique + const fileExt = path.extname(file.name); // Obtenir l'extension (.jpg, .png, etc.) + const newFileName = `${slug}${fileExt}`; // Exemple: image_123e4567-e89b-12d3-a456-426614174000.png + const filePath = path.join(uploadDir, newFileName); + + // Écrire le fichier avec le nouveau nom + fs.writeFileSync(filePath, buffer); + + // URL accessible de l'image + const imageUrl = `/assets/avatar/avatarOrganisations/${newFileName}`; + + // Revalider le cache pour rafraîchir l'affichage + return { success: true, imageUrl }; +} + +export async function deleteImage(imagePath) { + if (!imagePath) { + return { error: "Chemin de l'image non fourni" }; + } + + // Assurer que le fichier est bien dans /public/assets + const fullPath = path.join(process.cwd(), "public", imagePath); + + if (!fs.existsSync(fullPath)) { + return { error: "Fichier introuvable" }; + } + + try { + fs.unlinkSync(fullPath); // Supprime l'image + return { success: true, message: "Image supprimée avec succès" }; + } catch (error) { + return { error: "Erreur lors de la suppression de l'image" , message : error.message }; + } +} + diff --git a/src/methods/organisationMethods.tsx b/src/methods/organisationMethods.tsx new file mode 100644 index 0000000..60a2143 --- /dev/null +++ b/src/methods/organisationMethods.tsx @@ -0,0 +1,84 @@ +"use server" + +import {createOrganisation,getListOrganisations, getOrganisation, deleteOrganisation} from '@/actions/organisationActions' +import { createRole, getRole } from '@/actions/roleActions' +import {createUserOnOrganisation} from '@/actions/userOnOrganisation' +import { createUser, getUser } from '@/actions/usersActions' + +export async function createOrganisationMathods(formData : FormData){ + try{ + + let role = await getRole("ADMIN") + if(!role.success){ + const roleCreate = await createRole("ADMIN") + if(!roleCreate.success){ + throw new Error("Error while create role") + + } + role = roleCreate + } + + let verifUser = await getUser() + if(!verifUser?.success){ + const create = await createUser() + if(!create.success){ + throw new Error ("Error when create user") + } + verifUser = create + } + + const result = await createOrganisation(formData) + if(result.success){ + const resultCreate = await createUserOnOrganisation(verifUser?.id || "",result.result?.id || "", role.result?.id || "") + if(resultCreate){ + return{success : true, slugOrga : result.result?.slug} + } + } + return{success : false} + }catch(error){ + return{success : false, error : error instanceof Error ? error.message : 'An unknown error occured'} + } + +} + + +export async function getListOrganisationsMethod(){ + try{ + const verifUser = await getUser() + if(verifUser.success){ + const result = await getListOrganisations(verifUser?.id || "") + + if(result.success){ + return{success : true, result : result} + } + } + return{success : false, error : 'An unknown error occured'} + }catch(error){ + return{success : false, error : error instanceof Error ? error.message : 'An unknown error occured'} + } +} + +export async function getOrganisationMethods(slug : string){ + try{ + const result = await getOrganisation(slug) + if(result.success){ + return{success : true, result : result} + } + + return{success : false, error : 'An unknown error occured'} + }catch(error){ + return{success : false, error : error instanceof Error ? error.message : 'An unknown error occured'} + } +} + +export async function deleteOrganisationMethods(slug : string){ + try{ + const result = await deleteOrganisation(slug) + if(result.success){ + return{success : true, result : result} + } + return{success : false, error : 'An unknown error occured'} + }catch(error){ + return{success : false, error : error instanceof Error ? error.message : 'An unknown error occured'} + } +} \ No newline at end of file diff --git a/src/middleware.ts b/src/middleware.ts new file mode 100644 index 0000000..9d74cbe --- /dev/null +++ b/src/middleware.ts @@ -0,0 +1,17 @@ +import { clerkMiddleware,createRouteMatcher } from "@clerk/nextjs/server"; + + +const isProtectedRoute = createRouteMatcher(['/organisations(.*)']) + +export default clerkMiddleware(async (auth,req) =>{ + if(isProtectedRoute(req)) await auth.protect() +}) + +export const config = { + matcher: [ + // Skip Next.js internals and all static files, unless found in search params + '/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)', + // Always run for API routes + '/(api|trpc)(.*)', + ], +}; \ No newline at end of file diff --git a/src/styles/map.css b/src/styles/map.css new file mode 100644 index 0000000..84efa8f --- /dev/null +++ b/src/styles/map.css @@ -0,0 +1,23 @@ +#Map { height: 180px; } + +.container { + display: flex; /* Utilisation de Flexbox */ + justify-content: space-between; /* Aligner les éléments sur toute la largeur */ + align-items: center; /* Centrer verticalement les éléments */ + z-index: 2; + } + + /* Bloc de texte à gauche */ + .PopUp-block-text { + flex: auto; /* Permet au bloc de texte de prendre l'espace restant */ + } + + /* Bloc d'image à droite */ + .PopUp-block-img { + flex: auto; /* L'image garde sa taille naturelle */ + } + + .PopUp-block-img img { + max-width: 75%; /* Assurer que l'image s'adapte à son conteneur */ + height: auto; /* Garder les proportions de l'image */ + } \ No newline at end of file diff --git a/src/styles/menu.css b/src/styles/menu.css new file mode 100644 index 0000000..dee9f88 --- /dev/null +++ b/src/styles/menu.css @@ -0,0 +1,41 @@ +.menu { + background: linear-gradient(rgb(68, 68, 68),rgb(187, 186, 186)); + /*ckground-color: #000000;*/ + color: gold; + /* padding: 10px;*/ + display: flex; /* Utilisation de flexbox */ + align-items: center; /* Aligner verticalement les éléments */ + /*justify-content: center; /* Centrer les éléments horizontalement */ + } + + .menu img { + margin-right: 20px; /* Espacement entre l'image et le menu */ + height: 40px; /* Définir une hauteur fixe pour l'image (ajuste la valeur selon tes besoins) */ + } + + .menu ul { + list-style-type: none; + padding: 0; + display: flex; /* Aligner les éléments de la liste horizontalement */ + } + + .menu li { + margin-right: 20px; + padding-top: 12px; + } + + .menu a { + + text-decoration: none; + font-weight: bold; + } + + .menu a:hover { + color: #f5d081; + } + + .dropDownMenu{ + /*background: linear-gradient(rgb(68, 68, 68),rgb(187, 186, 186));*/ + background: gray; + margin-right:"10px" + } \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index c133409..1349bd1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -19,9 +19,10 @@ } ], "paths": { - "@/*": ["./src/*"] + "@/*": ["./src/*"], + "p/*": ["./public/*"] } }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "src/app/organisations/[slug]/game/session/[slug]/page.jsx", "src/app/organisations/[[...rest]]/game/session/page.jsx", "src/components/menu.jsx", "src/app/organisations/components/listOrganisation.jsx", "src/app/organisations/page.jsx"], "exclude": ["node_modules"] }