everything rendering
This commit is contained in:
20
bun.lock
20
bun.lock
@ -4,6 +4,7 @@
|
|||||||
"": {
|
"": {
|
||||||
"name": "nguhmap",
|
"name": "nguhmap",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@types/bun": "^1.2.22",
|
||||||
"@types/jsdom": "^21.1.7",
|
"@types/jsdom": "^21.1.7",
|
||||||
"@types/leaflet": "^1.9.20",
|
"@types/leaflet": "^1.9.20",
|
||||||
"@types/react-leaflet": "^3.0.0",
|
"@types/react-leaflet": "^3.0.0",
|
||||||
@ -11,6 +12,7 @@
|
|||||||
"jsdom": "^27.0.0",
|
"jsdom": "^27.0.0",
|
||||||
"leaflet": "^1.9.4",
|
"leaflet": "^1.9.4",
|
||||||
"next": "15.5.4",
|
"next": "15.5.4",
|
||||||
|
"next-auth": "^5.0.0-beta.29",
|
||||||
"react": "19.1.0",
|
"react": "19.1.0",
|
||||||
"react-dom": "19.1.0",
|
"react-dom": "19.1.0",
|
||||||
"react-leaflet": "^5.0.0",
|
"react-leaflet": "^5.0.0",
|
||||||
@ -34,6 +36,8 @@
|
|||||||
|
|
||||||
"@asamuzakjp/nwsapi": ["@asamuzakjp/nwsapi@2.3.9", "", {}, "sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q=="],
|
"@asamuzakjp/nwsapi": ["@asamuzakjp/nwsapi@2.3.9", "", {}, "sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q=="],
|
||||||
|
|
||||||
|
"@auth/core": ["@auth/core@0.40.0", "", { "dependencies": { "@panva/hkdf": "^1.2.1", "jose": "^6.0.6", "oauth4webapi": "^3.3.0", "preact": "10.24.3", "preact-render-to-string": "6.5.11" }, "peerDependencies": { "@simplewebauthn/browser": "^9.0.1", "@simplewebauthn/server": "^9.0.2", "nodemailer": "^6.8.0" }, "optionalPeers": ["@simplewebauthn/browser", "@simplewebauthn/server", "nodemailer"] }, "sha512-n53uJE0RH5SqZ7N1xZoMKekbHfQgjd0sAEyUbE+IYJnmuQkbvuZnXItCU7d+i7Fj8VGOgqvNO7Mw4YfBTlZeQw=="],
|
||||||
|
|
||||||
"@csstools/color-helpers": ["@csstools/color-helpers@5.1.0", "", {}, "sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA=="],
|
"@csstools/color-helpers": ["@csstools/color-helpers@5.1.0", "", {}, "sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA=="],
|
||||||
|
|
||||||
"@csstools/css-calc": ["@csstools/css-calc@2.1.4", "", { "peerDependencies": { "@csstools/css-parser-algorithms": "^3.0.5", "@csstools/css-tokenizer": "^3.0.4" } }, "sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ=="],
|
"@csstools/css-calc": ["@csstools/css-calc@2.1.4", "", { "peerDependencies": { "@csstools/css-parser-algorithms": "^3.0.5", "@csstools/css-tokenizer": "^3.0.4" } }, "sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ=="],
|
||||||
@ -154,6 +158,8 @@
|
|||||||
|
|
||||||
"@nolyfill/is-core-module": ["@nolyfill/is-core-module@1.0.39", "", {}, "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA=="],
|
"@nolyfill/is-core-module": ["@nolyfill/is-core-module@1.0.39", "", {}, "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA=="],
|
||||||
|
|
||||||
|
"@panva/hkdf": ["@panva/hkdf@1.2.1", "", {}, "sha512-6oclG6Y3PiDFcoyk8srjLfVKyMfVCKJ27JwNPViuXziFpmdz+MZnZN/aKY0JGXgYuO/VghU0jcOAZgWXZ1Dmrw=="],
|
||||||
|
|
||||||
"@react-leaflet/core": ["@react-leaflet/core@3.0.0", "", { "peerDependencies": { "leaflet": "^1.9.0", "react": "^19.0.0", "react-dom": "^19.0.0" } }, "sha512-3EWmekh4Nz+pGcr+xjf0KNyYfC3U2JjnkWsh0zcqaexYqmmB5ZhH37kz41JXGmKzpaMZCnPofBBm64i+YrEvGQ=="],
|
"@react-leaflet/core": ["@react-leaflet/core@3.0.0", "", { "peerDependencies": { "leaflet": "^1.9.0", "react": "^19.0.0", "react-dom": "^19.0.0" } }, "sha512-3EWmekh4Nz+pGcr+xjf0KNyYfC3U2JjnkWsh0zcqaexYqmmB5ZhH37kz41JXGmKzpaMZCnPofBBm64i+YrEvGQ=="],
|
||||||
|
|
||||||
"@rtsao/scc": ["@rtsao/scc@1.1.0", "", {}, "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g=="],
|
"@rtsao/scc": ["@rtsao/scc@1.1.0", "", {}, "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g=="],
|
||||||
@ -164,6 +170,8 @@
|
|||||||
|
|
||||||
"@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
|
"@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
|
||||||
|
|
||||||
|
"@types/bun": ["@types/bun@1.2.22", "", { "dependencies": { "bun-types": "1.2.22" } }, "sha512-5A/KrKos2ZcN0c6ljRSOa1fYIyCKhZfIVYeuyb4snnvomnpFqC0tTsEkdqNxbAgExV384OETQ//WAjl3XbYqQA=="],
|
||||||
|
|
||||||
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
|
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
|
||||||
|
|
||||||
"@types/geojson": ["@types/geojson@7946.0.16", "", {}, "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg=="],
|
"@types/geojson": ["@types/geojson@7946.0.16", "", {}, "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg=="],
|
||||||
@ -294,6 +302,8 @@
|
|||||||
|
|
||||||
"braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
|
"braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
|
||||||
|
|
||||||
|
"bun-types": ["bun-types@1.2.22", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-hwaAu8tct/Zn6Zft4U9BsZcXkYomzpHJX28ofvx7k0Zz2HNz54n1n+tDgxoWFGB4PcFvJXJQloPhaV2eP3Q6EA=="],
|
||||||
|
|
||||||
"call-bind": ["call-bind@1.0.8", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" } }, "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww=="],
|
"call-bind": ["call-bind@1.0.8", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" } }, "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww=="],
|
||||||
|
|
||||||
"call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="],
|
"call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="],
|
||||||
@ -542,6 +552,8 @@
|
|||||||
|
|
||||||
"iterator.prototype": ["iterator.prototype@1.1.5", "", { "dependencies": { "define-data-property": "^1.1.4", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.6", "get-proto": "^1.0.0", "has-symbols": "^1.1.0", "set-function-name": "^2.0.2" } }, "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g=="],
|
"iterator.prototype": ["iterator.prototype@1.1.5", "", { "dependencies": { "define-data-property": "^1.1.4", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.6", "get-proto": "^1.0.0", "has-symbols": "^1.1.0", "set-function-name": "^2.0.2" } }, "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g=="],
|
||||||
|
|
||||||
|
"jose": ["jose@6.1.0", "", {}, "sha512-TTQJyoEoKcC1lscpVDCSsVgYzUDg/0Bt3WE//WiTPK6uOCQC2KZS4MpugbMWt/zyjkopgZoXhZuCi00gLudfUA=="],
|
||||||
|
|
||||||
"js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
|
"js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
|
||||||
|
|
||||||
"js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="],
|
"js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="],
|
||||||
@ -598,6 +610,10 @@
|
|||||||
|
|
||||||
"next": ["next@15.5.4", "", { "dependencies": { "@next/env": "15.5.4", "@swc/helpers": "0.5.15", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "15.5.4", "@next/swc-darwin-x64": "15.5.4", "@next/swc-linux-arm64-gnu": "15.5.4", "@next/swc-linux-arm64-musl": "15.5.4", "@next/swc-linux-x64-gnu": "15.5.4", "@next/swc-linux-x64-musl": "15.5.4", "@next/swc-win32-arm64-msvc": "15.5.4", "@next/swc-win32-x64-msvc": "15.5.4", "sharp": "^0.34.3" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-xH4Yjhb82sFYQfY3vbkJfgSDgXvBB6a8xPs9i35k6oZJRoQRihZH+4s9Yo2qsWpzBmZ3lPXaJ2KPXLfkvW4LnA=="],
|
"next": ["next@15.5.4", "", { "dependencies": { "@next/env": "15.5.4", "@swc/helpers": "0.5.15", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "15.5.4", "@next/swc-darwin-x64": "15.5.4", "@next/swc-linux-arm64-gnu": "15.5.4", "@next/swc-linux-arm64-musl": "15.5.4", "@next/swc-linux-x64-gnu": "15.5.4", "@next/swc-linux-x64-musl": "15.5.4", "@next/swc-win32-arm64-msvc": "15.5.4", "@next/swc-win32-x64-msvc": "15.5.4", "sharp": "^0.34.3" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-xH4Yjhb82sFYQfY3vbkJfgSDgXvBB6a8xPs9i35k6oZJRoQRihZH+4s9Yo2qsWpzBmZ3lPXaJ2KPXLfkvW4LnA=="],
|
||||||
|
|
||||||
|
"next-auth": ["next-auth@5.0.0-beta.29", "", { "dependencies": { "@auth/core": "0.40.0" }, "peerDependencies": { "@simplewebauthn/browser": "^9.0.1", "@simplewebauthn/server": "^9.0.2", "next": "^14.0.0-0 || ^15.0.0-0", "nodemailer": "^6.6.5", "react": "^18.2.0 || ^19.0.0-0" }, "optionalPeers": ["@simplewebauthn/browser", "@simplewebauthn/server", "nodemailer"] }, "sha512-Ukpnuk3NMc/LiOl32njZPySk7pABEzbjhMUFd5/n10I0ZNC7NCuVv8IY2JgbDek2t/PUOifQEoUiOOTLy4os5A=="],
|
||||||
|
|
||||||
|
"oauth4webapi": ["oauth4webapi@3.8.1", "", {}, "sha512-olkZDELNycOWQf9LrsELFq8n05LwJgV8UkrS0cburk6FOwf8GvLam+YB+Uj5Qvryee+vwWOfQVeI5Vm0MVg7SA=="],
|
||||||
|
|
||||||
"object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],
|
"object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],
|
||||||
|
|
||||||
"object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="],
|
"object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="],
|
||||||
@ -640,6 +656,10 @@
|
|||||||
|
|
||||||
"postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="],
|
"postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="],
|
||||||
|
|
||||||
|
"preact": ["preact@10.24.3", "", {}, "sha512-Z2dPnBnMUfyQfSQ+GBdsGa16hz35YmLmtTLhM169uW944hYL6xzTYkJjC07j+Wosz733pMWx0fgON3JNw1jJQA=="],
|
||||||
|
|
||||||
|
"preact-render-to-string": ["preact-render-to-string@6.5.11", "", { "peerDependencies": { "preact": ">=10" } }, "sha512-ubnauqoGczeGISiOh6RjX0/cdaF8v/oDXIjO85XALCQjwQP+SB4RDXXtvZ6yTYSjG+PC1QRP2AhPgCEsM2EvUw=="],
|
||||||
|
|
||||||
"prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="],
|
"prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="],
|
||||||
|
|
||||||
"prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="],
|
"prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="],
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
"lint": "eslint"
|
"lint": "eslint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@types/bun": "^1.2.22",
|
||||||
"@types/jsdom": "^21.1.7",
|
"@types/jsdom": "^21.1.7",
|
||||||
"@types/leaflet": "^1.9.20",
|
"@types/leaflet": "^1.9.20",
|
||||||
"@types/react-leaflet": "^3.0.0",
|
"@types/react-leaflet": "^3.0.0",
|
||||||
@ -16,6 +17,7 @@
|
|||||||
"jsdom": "^27.0.0",
|
"jsdom": "^27.0.0",
|
||||||
"leaflet": "^1.9.4",
|
"leaflet": "^1.9.4",
|
||||||
"next": "15.5.4",
|
"next": "15.5.4",
|
||||||
|
"next-auth": "^5.0.0-beta.29",
|
||||||
"react": "19.1.0",
|
"react": "19.1.0",
|
||||||
"react-dom": "19.1.0",
|
"react-dom": "19.1.0",
|
||||||
"react-leaflet": "^5.0.0",
|
"react-leaflet": "^5.0.0",
|
||||||
|
10
public/legend/poi.svg
Normal file
10
public/legend/poi.svg
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="12px"
|
||||||
|
height="12x"
|
||||||
|
viewBox="0 0 12 12"
|
||||||
|
version="1.1"
|
||||||
|
>
|
||||||
|
<circle style="stroke-width:2px;stroke:#000;fill:#fff" x="1" y="1" r="5" transform="translate(6,6)"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 286 B |
2
src/app/api/auth/[...nextauth]/route.ts
Normal file
2
src/app/api/auth/[...nextauth]/route.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
import { handlers } from "@/auth"
|
||||||
|
export const { GET, POST } = handlers
|
15
src/app/client.tsx
Normal file
15
src/app/client.tsx
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
"use client";
|
||||||
|
import dynamic from "next/dynamic";
|
||||||
|
import { useMemo } from "react";
|
||||||
|
import type {MapData} from "@/app/map"
|
||||||
|
|
||||||
|
export function Map(props: {data: MapData}) {
|
||||||
|
const It = useMemo(() => dynamic(
|
||||||
|
() => import("@/app/map"),
|
||||||
|
{
|
||||||
|
loading: () => <p>Loading</p>,
|
||||||
|
ssr: false,
|
||||||
|
}
|
||||||
|
), [])
|
||||||
|
return <It {...props} />;
|
||||||
|
}
|
149
src/app/map.tsx
149
src/app/map.tsx
@ -1,20 +1,135 @@
|
|||||||
import { MapContainer, Rectangle, TileLayer } from "react-leaflet";
|
import { MapContainer, Marker, Rectangle, TileLayer, Tooltip, Polyline, Polygon } from "react-leaflet";
|
||||||
import L from "leaflet";
|
import L, { Icon } from "leaflet";
|
||||||
|
|
||||||
export default function Map() {
|
export type CountryEntry = {
|
||||||
|
code2: string;
|
||||||
|
code3: string;
|
||||||
|
common_name: string;
|
||||||
|
name?: string;
|
||||||
|
ruler?: string | string[];
|
||||||
|
ruler_title?: string;
|
||||||
|
ruler_link?: string;
|
||||||
|
founded?: string;
|
||||||
|
capital?: string;
|
||||||
|
ung?: "MEMBER" | "OBSERVER" | "FORMER";
|
||||||
|
ung_joined?: string;
|
||||||
|
ung_demoted?: string;
|
||||||
|
ung_left?: string;
|
||||||
|
dissolved?: string | true;
|
||||||
|
dissolved_date?: string;
|
||||||
|
disputed?: string | true;
|
||||||
|
not_ngation?: true;
|
||||||
|
condominium?: string[]
|
||||||
|
};
|
||||||
|
|
||||||
|
export type POI = {
|
||||||
|
coordinates: string;
|
||||||
|
label: string;
|
||||||
|
id: number;
|
||||||
|
last_editor: number | string
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Road = {
|
||||||
|
id: number;
|
||||||
|
path: string;
|
||||||
|
network: string;
|
||||||
|
name: string;
|
||||||
|
last_editor: number | string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type CountryPart = {
|
||||||
|
id: number;
|
||||||
|
country: string;
|
||||||
|
shape: string;
|
||||||
|
last_editor: number | string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type RailLine = {
|
||||||
|
id: String;
|
||||||
|
path: String;
|
||||||
|
last_editor: number | string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Settlement = {
|
||||||
|
id: number;
|
||||||
|
coordinates: string;
|
||||||
|
name: string;
|
||||||
|
last_editor: number | string
|
||||||
|
}
|
||||||
|
export type TransitStop = {
|
||||||
|
id: string;
|
||||||
|
coordinates: string;
|
||||||
|
last_editor: number | string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type MapData = {
|
||||||
|
countries: CountryEntry[];
|
||||||
|
parts: CountryPart[];
|
||||||
|
pois: POI[];
|
||||||
|
farms: POI[];
|
||||||
|
rails: RailLine[];
|
||||||
|
roads: Road[];
|
||||||
|
settlements: Settlement[];
|
||||||
|
stops: TransitStop[];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function find_entry(code: string, entries: CountryEntry[]) : CountryEntry|undefined {
|
||||||
|
return entries.find((it) => it.code2 === code || it.code3 === code)
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseCoords(desc: string) : [number, number][] {
|
||||||
|
console.log(desc);
|
||||||
|
const foo = [...desc.matchAll(/\((-?\d+),(-?\d+)\)/g)]
|
||||||
|
return foo.map(it => [-+it[2] - .5, +it[1] + .5])
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Map(props: { data: MapData }) {
|
||||||
|
const { data } = props;
|
||||||
return (
|
return (
|
||||||
<MapContainer
|
<>
|
||||||
id="map"
|
<MapContainer
|
||||||
center={[0, 0]}
|
id="map"
|
||||||
maxBounds={[[-8192, -8192], [8192, 8192]]}
|
center={[0, 0]}
|
||||||
crs={L.CRS.Simple}
|
maxBounds={[[-8192, -8192], [8192, 8192]]}
|
||||||
zoom={0}>
|
crs={L.CRS.Simple}
|
||||||
<TileLayer
|
zoom={0}>
|
||||||
url="/tiles/{z}/{x}_{y}.png"
|
<TileLayer
|
||||||
tileSize={512}
|
url="/tiles/{z}/{x}_{y}.png"
|
||||||
minZoom={-4}
|
tileSize={512}
|
||||||
maxNativeZoom={0} />
|
minZoom={-4}
|
||||||
<Rectangle bounds={[[-8000, -8000], [8000, 8000]]} pathOptions={{ color: "#000", stroke: true, fill: false, weight: 2 }} />
|
maxNativeZoom={0} />
|
||||||
</MapContainer>
|
<Rectangle bounds={[[-8000, -8000], [8000, 8000]]} pathOptions={{ color: "#000", stroke: true, fill: false, weight: 2 }} />
|
||||||
)
|
{
|
||||||
|
data.pois.map(it =>
|
||||||
|
<Marker key={it.id} position={parseCoords(it.coordinates)[0]} icon={new Icon({iconUrl: "/legend/poi.svg", iconAnchor: [6, 6]})}>
|
||||||
|
<Tooltip>{it.label}</Tooltip>
|
||||||
|
</Marker>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
data.settlements.map(it =>
|
||||||
|
<Marker key={it.id} position={parseCoords(it.coordinates)[0]} icon={new Icon({iconUrl: "/legend/city.svg", iconAnchor: [6, 6]})}>
|
||||||
|
<Tooltip>{it.name}</Tooltip>
|
||||||
|
</Marker>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
data.roads.map(it =>
|
||||||
|
<Polyline key={it.id} positions={parseCoords(it.path)} stroke={true} color="#FFF">
|
||||||
|
<Tooltip>{find_entry(it.network, data.countries)?.common_name} — {it.name}</Tooltip>
|
||||||
|
</Polyline>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
data.parts.map(it =>
|
||||||
|
<Polygon key={it.id} positions={parseCoords(it.shape)} stroke={true} color="#A00" fill={true} fillOpacity={.5} fillColor="#A00">
|
||||||
|
<Tooltip position={parseCoords(it.shape)[0]}>{find_entry(it.country, data.countries)?.common_name}</Tooltip>
|
||||||
|
</Polygon>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
{data.stops.map(it => <Marker key={it.id} position={parseCoords(it.coordinates)[0]}><Tooltip>{it.id}</Tooltip></Marker>)}
|
||||||
|
</MapContainer>
|
||||||
|
|
||||||
|
</>)
|
||||||
}
|
}
|
@ -1,60 +1,46 @@
|
|||||||
"use client";
|
import { auth, signIn } from "@/auth";
|
||||||
import { useMemo } from "react";
|
import { Map } from "@/app/client";
|
||||||
import Modal from "react-modal";
|
import type {MapData, CountryEntry, CountryPart, POI, RailLine, Settlement, TransitStop, Road} from "@/app/map"
|
||||||
import dynamic from "next/dynamic";
|
import { sql } from "bun"
|
||||||
|
import { JSDOM } from "jsdom"
|
||||||
|
|
||||||
type SetState<T> = (_: T) => void;
|
|
||||||
type StateInit<T> = [T, SetState<T>];
|
|
||||||
|
|
||||||
function Login(params: { modal: StateInit<boolean>, login: StateInit<string | undefined>; }) {
|
|
||||||
const { modal, login } = params;
|
|
||||||
const customStyles = {
|
|
||||||
content: {
|
|
||||||
top: '50%',
|
|
||||||
left: '50%',
|
|
||||||
right: 'auto',
|
|
||||||
bottom: 'auto',
|
|
||||||
marginRight: '-50%',
|
|
||||||
transform: 'translate(-50%, -50%)',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const openModal = () => modal[1](true)
|
|
||||||
const afterOpenModal = () => { }
|
export async function getCountries () : Promise<CountryEntry[]> {
|
||||||
const closeModal = () => modal[1](false)
|
let data_raw = await fetch("https://mc.nguh.org/w/api.php?action=parse&page=Data:UŊCDSO%2FCountries&prop=text&format=json")
|
||||||
return (<>
|
let data = await data_raw.json()
|
||||||
<button type="button" onClick={openModal}>Log In</button>
|
let parsed_text : string = data.parse.text["*"];
|
||||||
<Modal
|
let parsed_xml = new JSDOM(parsed_text);
|
||||||
isOpen={modal[0]}
|
let json_text = parsed_xml.window.document.querySelector("#jsondata")?.textContent
|
||||||
onAfterOpen={afterOpenModal}
|
if (json_text != undefined)
|
||||||
onRequestClose={closeModal}
|
return JSON.parse(json_text);
|
||||||
style={customStyles}
|
else return [];
|
||||||
contentLabel="Log In"
|
|
||||||
ariaHideApp={false}
|
|
||||||
>
|
|
||||||
<h2>Authentification</h2>
|
|
||||||
<form action={(e: FormData) => {
|
|
||||||
// TODO Check Auth
|
|
||||||
const l = e.get("login")
|
|
||||||
if (l == null) return;
|
|
||||||
closeModal()
|
|
||||||
login[1](l.toString())
|
|
||||||
}}>
|
|
||||||
<input name="login" type="text" placeholder="Login" required={true} /><br />
|
|
||||||
<input name="password" type="password" placeholder="Password" required={true} /><br />
|
|
||||||
<button id="auth!submit" type="submit">Log In</button>
|
|
||||||
</form>
|
|
||||||
</Modal>
|
|
||||||
</>)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Home() {
|
async function getMapData() : Promise<MapData> {
|
||||||
const Map = useMemo(() => dynamic(
|
const [countries, parts, pois, farms, rails, roads, settlements, stops] :
|
||||||
() => import("@/app/map"),
|
[CountryEntry[], CountryPart[], POI[], POI[], RailLine[], Road[], Settlement[], TransitStop[]] = await Promise.all([
|
||||||
{
|
getCountries(),
|
||||||
loading: () => <p>Loading</p>,
|
sql`SELECT * from country_parts`,
|
||||||
ssr: false,
|
sql`SELECT * from points_of_interest`,
|
||||||
}
|
sql`SELECT * from public_farms`,
|
||||||
), [])
|
sql`SELECT * from rail_lines`,
|
||||||
return <Map />
|
sql`SELECT * from roads`,
|
||||||
|
sql`SELECT * from settlements`,
|
||||||
|
sql`SELECT * from transit_stops`
|
||||||
|
])
|
||||||
|
|
||||||
|
return { countries, parts, pois, farms, rails, roads, settlements, stops }
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async function Home() {
|
||||||
|
const session = await auth();
|
||||||
|
return <>
|
||||||
|
<Map data={await getMapData()}/>
|
||||||
|
{(session) ? null : <form action={async () => {
|
||||||
|
'use server';
|
||||||
|
await signIn("discord")
|
||||||
|
}}><button type="submit">Log In</button></form>}
|
||||||
|
</>
|
||||||
}
|
}
|
||||||
|
42
src/auth.ts
Normal file
42
src/auth.ts
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import NextAuth from "next-auth"
|
||||||
|
import Discord from 'next-auth/providers/discord';
|
||||||
|
|
||||||
|
declare module 'next-auth' {
|
||||||
|
interface Session {
|
||||||
|
access_token: string | undefined,
|
||||||
|
discord_id?: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const { handlers, signIn, signOut, auth } = NextAuth({
|
||||||
|
providers: [Discord({
|
||||||
|
authorization: {
|
||||||
|
params: {
|
||||||
|
scope: "identify guilds"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
clientId: process.env.AUTH_DISCORD_ID!,
|
||||||
|
clientSecret: process.env.AUTH_DISCORD_SECRET!,
|
||||||
|
})],
|
||||||
|
callbacks: {
|
||||||
|
async jwt({token, account, profile, user}) {
|
||||||
|
// During sign-in, 'user' is set; this is when we need to save the access_token etc.
|
||||||
|
if (user) return {
|
||||||
|
...token,
|
||||||
|
access_token: account?.access_token,
|
||||||
|
discord_id: profile?.id
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, we’re fetching an existing token, so take care not to override it.
|
||||||
|
return token
|
||||||
|
},
|
||||||
|
|
||||||
|
async session({token, session}) {
|
||||||
|
session.access_token = token.access_token as string
|
||||||
|
session.discord_id = token.discord_id as string
|
||||||
|
return session
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trustHost: true,
|
||||||
|
secret: process.env.AUTH_SECRET!,
|
||||||
|
})
|
1
src/middleware.ts
Normal file
1
src/middleware.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { auth as middleware } from "@/auth"
|
Reference in New Issue
Block a user