diff --git a/env.sample b/env.sample index d20a9d9..a55a9bb 100644 --- a/env.sample +++ b/env.sample @@ -7,6 +7,7 @@ AUTH_GITHUB_SECRET= AUTH_SECRET= GOOGLEMAPS_API_KEY= +NEXT_PUBLIC_GOOGLEMAPS_API_KEY= #for use in the browser ## Mailer related stuff SMTP_HOST=smtp.ethereal.email diff --git a/package-lock.json b/package-lock.json index df7e2b9..f72b9b6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "my-app", "version": "0.1.0", "dependencies": { + "@googlemaps/js-api-loader": "^1.16.8", "@internationalized/date": "^3.5.6", "@nextui-org/calendar": "^2.0.12", "@nextui-org/react": "^2.4.8", @@ -23,11 +24,11 @@ "next": "15.0.3", "next-auth": "^4.24.10", "nodemailer": "^6.9.16", - "npm": "^10.9.0", + "npm": "^10.9.2", "pg": "^8.10.0", "react": "^18.3.1", "react-dom": "^18.3.1", - "repl": "^0.1.3", + "react-toastify": "^10.0.6", "zod": "^3.23.8" }, "devDependencies": { @@ -179,6 +180,12 @@ "tslib": "2" } }, + "node_modules/@googlemaps/js-api-loader": { + "version": "1.16.8", + "resolved": "https://registry.npmjs.org/@googlemaps/js-api-loader/-/js-api-loader-1.16.8.tgz", + "integrity": "sha512-CROqqwfKotdO6EBjZO/gQGVTbeDps5V7Mt9+8+5Q+jTg5CRMi3Ii/L9PmV3USROrt2uWxtGzJHORmByxyo9pSQ==", + "license": "Apache-2.0" + }, "node_modules/@humanwhocodes/config-array": { "version": "0.13.0", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", @@ -8552,9 +8559,9 @@ } }, "node_modules/npm": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/npm/-/npm-10.9.0.tgz", - "integrity": "sha512-ZanDioFylI9helNhl2LNd+ErmVD+H5I53ry41ixlLyCBgkuYb+58CvbAp99hW+zr5L9W4X7CchSoeqKdngOLSw==", + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/npm/-/npm-10.9.2.tgz", + "integrity": "sha512-iriPEPIkoMYUy3F6f3wwSZAU93E0Eg6cHwIR6jzzOXWSy+SD/rOODEs74cVONHKSx2obXtuUoyidVEhISrisgQ==", "bundleDependencies": [ "@isaacs/string-locale-compare", "@npmcli/arborist", @@ -8638,25 +8645,25 @@ "@npmcli/arborist": "^8.0.0", "@npmcli/config": "^9.0.0", "@npmcli/fs": "^4.0.0", - "@npmcli/map-workspaces": "^4.0.1", - "@npmcli/package-json": "^6.0.1", - "@npmcli/promise-spawn": "^8.0.1", + "@npmcli/map-workspaces": "^4.0.2", + "@npmcli/package-json": "^6.1.0", + "@npmcli/promise-spawn": "^8.0.2", "@npmcli/redact": "^3.0.0", "@npmcli/run-script": "^9.0.1", - "@sigstore/tuf": "^2.3.4", + "@sigstore/tuf": "^3.0.0", "abbrev": "^3.0.0", "archy": "~1.0.0", "cacache": "^19.0.1", "chalk": "^5.3.0", - "ci-info": "^4.0.0", + "ci-info": "^4.1.0", "cli-columns": "^4.0.0", "fastest-levenshtein": "^1.0.16", "fs-minipass": "^3.0.3", "glob": "^10.4.5", "graceful-fs": "^4.2.11", - "hosted-git-info": "^8.0.0", + "hosted-git-info": "^8.0.2", "ini": "^5.0.0", - "init-package-json": "^7.0.1", + "init-package-json": "^7.0.2", "is-cidr": "^5.1.0", "json-parse-even-better-errors": "^4.0.0", "libnpmaccess": "^9.0.0", @@ -8666,27 +8673,27 @@ "libnpmhook": "^11.0.0", "libnpmorg": "^7.0.0", "libnpmpack": "^8.0.0", - "libnpmpublish": "^10.0.0", + "libnpmpublish": "^10.0.1", "libnpmsearch": "^8.0.0", "libnpmteam": "^7.0.0", "libnpmversion": "^7.0.0", - "make-fetch-happen": "^14.0.1", + "make-fetch-happen": "^14.0.3", "minimatch": "^9.0.5", "minipass": "^7.1.1", "minipass-pipeline": "^1.2.4", "ms": "^2.1.2", - "node-gyp": "^10.2.0", + "node-gyp": "^11.0.0", "nopt": "^8.0.0", "normalize-package-data": "^7.0.0", "npm-audit-report": "^6.0.0", - "npm-install-checks": "^7.1.0", + "npm-install-checks": "^7.1.1", "npm-package-arg": "^12.0.0", "npm-pick-manifest": "^10.0.0", "npm-profile": "^11.0.1", - "npm-registry-fetch": "^18.0.1", + "npm-registry-fetch": "^18.0.2", "npm-user-validate": "^3.0.0", "p-map": "^4.0.0", - "pacote": "^19.0.0", + "pacote": "^19.0.1", "parse-conflict-json": "^4.0.0", "proc-log": "^5.0.0", "qrcode-terminal": "^0.12.0", @@ -8728,7 +8735,7 @@ } }, "node_modules/npm/node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", + "version": "6.1.0", "inBundle": true, "license": "MIT", "engines": { @@ -8916,7 +8923,7 @@ } }, "node_modules/npm/node_modules/@npmcli/map-workspaces": { - "version": "4.0.1", + "version": "4.0.2", "inBundle": true, "license": "ISC", "dependencies": { @@ -8930,13 +8937,13 @@ } }, "node_modules/npm/node_modules/@npmcli/metavuln-calculator": { - "version": "8.0.0", + "version": "8.0.1", "inBundle": true, "license": "ISC", "dependencies": { "cacache": "^19.0.0", "json-parse-even-better-errors": "^4.0.0", - "pacote": "^19.0.0", + "pacote": "^20.0.0", "proc-log": "^5.0.0", "semver": "^7.3.5" }, @@ -8944,6 +8951,36 @@ "node": "^18.17.0 || >=20.5.0" } }, + "node_modules/npm/node_modules/@npmcli/metavuln-calculator/node_modules/pacote": { + "version": "20.0.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/git": "^6.0.0", + "@npmcli/installed-package-contents": "^3.0.0", + "@npmcli/package-json": "^6.0.0", + "@npmcli/promise-spawn": "^8.0.0", + "@npmcli/run-script": "^9.0.0", + "cacache": "^19.0.0", + "fs-minipass": "^3.0.0", + "minipass": "^7.0.2", + "npm-package-arg": "^12.0.0", + "npm-packlist": "^9.0.0", + "npm-pick-manifest": "^10.0.0", + "npm-registry-fetch": "^18.0.0", + "proc-log": "^5.0.0", + "promise-retry": "^2.0.1", + "sigstore": "^3.0.0", + "ssri": "^12.0.0", + "tar": "^6.1.11" + }, + "bin": { + "pacote": "bin/index.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, "node_modules/npm/node_modules/@npmcli/name-from-folder": { "version": "3.0.0", "inBundle": true, @@ -8961,7 +8998,7 @@ } }, "node_modules/npm/node_modules/@npmcli/package-json": { - "version": "6.0.1", + "version": "6.1.0", "inBundle": true, "license": "ISC", "dependencies": { @@ -8978,7 +9015,7 @@ } }, "node_modules/npm/node_modules/@npmcli/promise-spawn": { - "version": "8.0.1", + "version": "8.0.2", "inBundle": true, "license": "ISC", "dependencies": { @@ -9008,14 +9045,14 @@ } }, "node_modules/npm/node_modules/@npmcli/run-script": { - "version": "9.0.1", + "version": "9.0.2", "inBundle": true, "license": "ISC", "dependencies": { "@npmcli/node-gyp": "^4.0.0", "@npmcli/package-json": "^6.0.0", "@npmcli/promise-spawn": "^8.0.0", - "node-gyp": "^10.0.0", + "node-gyp": "^11.0.0", "proc-log": "^5.0.0", "which": "^5.0.0" }, @@ -9032,25 +9069,6 @@ "node": ">=14" } }, - "node_modules/npm/node_modules/@sigstore/bundle": { - "version": "2.3.2", - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/protobuf-specs": "^0.3.2" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@sigstore/core": { - "version": "1.1.0", - "inBundle": true, - "license": "Apache-2.0", - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, "node_modules/npm/node_modules/@sigstore/protobuf-specs": { "version": "0.3.2", "inBundle": true, @@ -9059,172 +9077,16 @@ "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/npm/node_modules/@sigstore/sign": { - "version": "2.3.2", - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/bundle": "^2.3.2", - "@sigstore/core": "^1.0.0", - "@sigstore/protobuf-specs": "^0.3.2", - "make-fetch-happen": "^13.0.1", - "proc-log": "^4.2.0", - "promise-retry": "^2.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@sigstore/sign/node_modules/@npmcli/agent": { - "version": "2.2.2", - "inBundle": true, - "license": "ISC", - "dependencies": { - "agent-base": "^7.1.0", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.1", - "lru-cache": "^10.0.1", - "socks-proxy-agent": "^8.0.3" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@sigstore/sign/node_modules/@npmcli/fs": { - "version": "3.1.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@sigstore/sign/node_modules/cacache": { - "version": "18.0.4", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/fs": "^3.1.0", - "fs-minipass": "^3.0.0", - "glob": "^10.2.2", - "lru-cache": "^10.0.1", - "minipass": "^7.0.3", - "minipass-collect": "^2.0.1", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "p-map": "^4.0.0", - "ssri": "^10.0.0", - "tar": "^6.1.11", - "unique-filename": "^3.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@sigstore/sign/node_modules/make-fetch-happen": { - "version": "13.0.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/agent": "^2.0.0", - "cacache": "^18.0.0", - "http-cache-semantics": "^4.1.1", - "is-lambda": "^1.0.1", - "minipass": "^7.0.2", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "proc-log": "^4.2.0", - "promise-retry": "^2.0.1", - "ssri": "^10.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@sigstore/sign/node_modules/minipass-fetch": { - "version": "3.0.5", - "inBundle": true, - "license": "MIT", - "dependencies": { - "minipass": "^7.0.3", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, - "node_modules/npm/node_modules/@sigstore/sign/node_modules/proc-log": { - "version": "4.2.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@sigstore/sign/node_modules/ssri": { - "version": "10.0.6", - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@sigstore/sign/node_modules/unique-filename": { - "version": "3.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "unique-slug": "^4.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@sigstore/sign/node_modules/unique-slug": { - "version": "4.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, "node_modules/npm/node_modules/@sigstore/tuf": { - "version": "2.3.4", + "version": "3.0.0", "inBundle": true, "license": "Apache-2.0", "dependencies": { "@sigstore/protobuf-specs": "^0.3.2", - "tuf-js": "^2.2.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@sigstore/verify": { - "version": "1.2.1", - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/bundle": "^2.3.2", - "@sigstore/core": "^1.1.0", - "@sigstore/protobuf-specs": "^0.3.2" + "tuf-js": "^3.0.1" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/npm/node_modules/@tufjs/canonical-json": { @@ -9235,18 +9097,6 @@ "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/npm/node_modules/@tufjs/models": { - "version": "2.0.1", - "inBundle": true, - "license": "MIT", - "dependencies": { - "@tufjs/canonical-json": "2.0.0", - "minimatch": "^9.0.4" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, "node_modules/npm/node_modules/abbrev": { "version": "3.0.0", "inBundle": true, @@ -9457,7 +9307,7 @@ } }, "node_modules/npm/node_modules/ci-info": { - "version": "4.0.0", + "version": "4.1.0", "funding": [ { "type": "github", @@ -9531,7 +9381,7 @@ "license": "ISC" }, "node_modules/npm/node_modules/cross-spawn": { - "version": "7.0.3", + "version": "7.0.6", "inBundle": true, "license": "MIT", "dependencies": { @@ -9569,11 +9419,11 @@ } }, "node_modules/npm/node_modules/debug": { - "version": "4.3.6", + "version": "4.3.7", "inBundle": true, "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -9584,11 +9434,6 @@ } } }, - "node_modules/npm/node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "inBundle": true, - "license": "MIT" - }, "node_modules/npm/node_modules/diff": { "version": "5.2.0", "inBundle": true, @@ -9693,7 +9538,7 @@ "license": "ISC" }, "node_modules/npm/node_modules/hosted-git-info": { - "version": "8.0.0", + "version": "8.0.2", "inBundle": true, "license": "ISC", "dependencies": { @@ -9780,7 +9625,7 @@ } }, "node_modules/npm/node_modules/init-package-json": { - "version": "7.0.1", + "version": "7.0.2", "inBundle": true, "license": "ISC", "dependencies": { @@ -9838,11 +9683,6 @@ "node": ">=8" } }, - "node_modules/npm/node_modules/is-lambda": { - "version": "1.0.1", - "inBundle": true, - "license": "MIT" - }, "node_modules/npm/node_modules/isexe": { "version": "2.0.0", "inBundle": true, @@ -10001,7 +9841,7 @@ } }, "node_modules/npm/node_modules/libnpmpublish": { - "version": "10.0.0", + "version": "10.0.1", "inBundle": true, "license": "ISC", "dependencies": { @@ -10011,7 +9851,7 @@ "npm-registry-fetch": "^18.0.1", "proc-log": "^5.0.0", "semver": "^7.3.7", - "sigstore": "^2.2.0", + "sigstore": "^3.0.0", "ssri": "^12.0.0" }, "engines": { @@ -10062,7 +9902,7 @@ "license": "ISC" }, "node_modules/npm/node_modules/make-fetch-happen": { - "version": "14.0.1", + "version": "14.0.3", "inBundle": true, "license": "ISC", "dependencies": { @@ -10073,7 +9913,7 @@ "minipass-fetch": "^4.0.0", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", + "negotiator": "^1.0.0", "proc-log": "^5.0.0", "promise-retry": "^2.0.1", "ssri": "^12.0.0" @@ -10082,6 +9922,14 @@ "node": "^18.17.0 || >=20.5.0" } }, + "node_modules/npm/node_modules/make-fetch-happen/node_modules/negotiator": { + "version": "1.0.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/npm/node_modules/minimatch": { "version": "9.0.5", "inBundle": true, @@ -10256,16 +10104,8 @@ "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/npm/node_modules/negotiator": { - "version": "0.6.3", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/npm/node_modules/node-gyp": { - "version": "10.2.0", + "version": "11.0.0", "inBundle": true, "license": "MIT", "dependencies": { @@ -10273,189 +10113,76 @@ "exponential-backoff": "^3.1.1", "glob": "^10.3.10", "graceful-fs": "^4.2.6", - "make-fetch-happen": "^13.0.0", - "nopt": "^7.0.0", - "proc-log": "^4.1.0", + "make-fetch-happen": "^14.0.3", + "nopt": "^8.0.0", + "proc-log": "^5.0.0", "semver": "^7.3.5", - "tar": "^6.2.1", - "which": "^4.0.0" + "tar": "^7.4.3", + "which": "^5.0.0" }, "bin": { "node-gyp": "bin/node-gyp.js" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/npm/node_modules/node-gyp/node_modules/@npmcli/agent": { - "version": "2.2.2", + "node_modules/npm/node_modules/node-gyp/node_modules/chownr": { + "version": "3.0.0", "inBundle": true, - "license": "ISC", - "dependencies": { - "agent-base": "^7.1.0", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.1", - "lru-cache": "^10.0.1", - "socks-proxy-agent": "^8.0.3" - }, + "license": "BlueOak-1.0.0", "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": ">=18" } }, - "node_modules/npm/node_modules/node-gyp/node_modules/@npmcli/fs": { - "version": "3.1.1", + "node_modules/npm/node_modules/node-gyp/node_modules/minizlib": { + "version": "3.0.1", "inBundle": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/abbrev": { - "version": "2.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/cacache": { - "version": "18.0.4", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/fs": "^3.1.0", - "fs-minipass": "^3.0.0", - "glob": "^10.2.2", - "lru-cache": "^10.0.1", - "minipass": "^7.0.3", - "minipass-collect": "^2.0.1", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "p-map": "^4.0.0", - "ssri": "^10.0.0", - "tar": "^6.1.11", - "unique-filename": "^3.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/isexe": { - "version": "3.1.1", - "inBundle": true, - "license": "ISC", - "engines": { - "node": ">=16" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/make-fetch-happen": { - "version": "13.0.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/agent": "^2.0.0", - "cacache": "^18.0.0", - "http-cache-semantics": "^4.1.1", - "is-lambda": "^1.0.1", - "minipass": "^7.0.2", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "proc-log": "^4.2.0", - "promise-retry": "^2.0.1", - "ssri": "^10.0.0" + "minipass": "^7.0.4", + "rimraf": "^5.0.5" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": ">= 18" } }, - "node_modules/npm/node_modules/node-gyp/node_modules/minipass-fetch": { - "version": "3.0.5", + "node_modules/npm/node_modules/node-gyp/node_modules/mkdirp": { + "version": "3.0.1", "inBundle": true, "license": "MIT", - "dependencies": { - "minipass": "^7.0.3", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/nopt": { - "version": "7.2.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "abbrev": "^2.0.0" - }, "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/proc-log": { - "version": "4.2.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/ssri": { - "version": "10.0.6", - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.3" + "mkdirp": "dist/cjs/src/bin.js" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/unique-filename": { - "version": "3.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "unique-slug": "^4.0.0" + "node": ">=10" }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/npm/node_modules/node-gyp/node_modules/unique-slug": { - "version": "4.0.0", + "node_modules/npm/node_modules/node-gyp/node_modules/tar": { + "version": "7.4.3", "inBundle": true, "license": "ISC", "dependencies": { - "imurmurhash": "^0.1.4" + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=18" } }, - "node_modules/npm/node_modules/node-gyp/node_modules/which": { - "version": "4.0.0", + "node_modules/npm/node_modules/node-gyp/node_modules/yallist": { + "version": "5.0.0", "inBundle": true, - "license": "ISC", - "dependencies": { - "isexe": "^3.1.1" - }, - "bin": { - "node-which": "bin/which.js" - }, + "license": "BlueOak-1.0.0", "engines": { - "node": "^16.13.0 || >=18.0.0" + "node": ">=18" } }, "node_modules/npm/node_modules/nopt": { @@ -10513,7 +10240,7 @@ } }, "node_modules/npm/node_modules/npm-install-checks": { - "version": "7.1.0", + "version": "7.1.1", "inBundle": true, "license": "BSD-2-Clause", "dependencies": { @@ -10583,7 +10310,7 @@ } }, "node_modules/npm/node_modules/npm-registry-fetch": { - "version": "18.0.1", + "version": "18.0.2", "inBundle": true, "license": "ISC", "dependencies": { @@ -10635,12 +10362,12 @@ } }, "node_modules/npm/node_modules/package-json-from-dist": { - "version": "1.0.0", + "version": "1.0.1", "inBundle": true, "license": "BlueOak-1.0.0" }, "node_modules/npm/node_modules/pacote": { - "version": "19.0.0", + "version": "19.0.1", "inBundle": true, "license": "ISC", "dependencies": { @@ -10658,7 +10385,7 @@ "npm-registry-fetch": "^18.0.0", "proc-log": "^5.0.0", "promise-retry": "^2.0.1", - "sigstore": "^2.2.0", + "sigstore": "^3.0.0", "ssri": "^12.0.0", "tar": "^6.1.11" }, @@ -10742,7 +10469,7 @@ } }, "node_modules/npm/node_modules/promise-call-limit": { - "version": "3.0.1", + "version": "3.0.2", "inBundle": true, "license": "ISC", "funding": { @@ -10885,19 +10612,67 @@ } }, "node_modules/npm/node_modules/sigstore": { - "version": "2.3.1", + "version": "3.0.0", "inBundle": true, "license": "Apache-2.0", "dependencies": { - "@sigstore/bundle": "^2.3.2", - "@sigstore/core": "^1.0.0", + "@sigstore/bundle": "^3.0.0", + "@sigstore/core": "^2.0.0", "@sigstore/protobuf-specs": "^0.3.2", - "@sigstore/sign": "^2.3.2", - "@sigstore/tuf": "^2.3.4", - "@sigstore/verify": "^1.2.1" + "@sigstore/sign": "^3.0.0", + "@sigstore/tuf": "^3.0.0", + "@sigstore/verify": "^2.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/sigstore/node_modules/@sigstore/bundle": { + "version": "3.0.0", + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/protobuf-specs": "^0.3.2" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/sigstore/node_modules/@sigstore/core": { + "version": "2.0.0", + "inBundle": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/sigstore/node_modules/@sigstore/sign": { + "version": "3.0.0", + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/bundle": "^3.0.0", + "@sigstore/core": "^2.0.0", + "@sigstore/protobuf-specs": "^0.3.2", + "make-fetch-happen": "^14.0.1", + "proc-log": "^5.0.0", + "promise-retry": "^2.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/sigstore/node_modules/@sigstore/verify": { + "version": "2.0.0", + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/bundle": "^3.0.0", + "@sigstore/core": "^2.0.0", + "@sigstore/protobuf-specs": "^0.3.2" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/npm/node_modules/smart-buffer": { @@ -10968,7 +10743,7 @@ } }, "node_modules/npm/node_modules/spdx-license-ids": { - "version": "3.0.18", + "version": "3.0.20", "inBundle": true, "license": "CC0-1.0" }, @@ -11114,143 +10889,28 @@ } }, "node_modules/npm/node_modules/tuf-js": { - "version": "2.2.1", + "version": "3.0.1", "inBundle": true, "license": "MIT", "dependencies": { - "@tufjs/models": "2.0.1", - "debug": "^4.3.4", - "make-fetch-happen": "^13.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/tuf-js/node_modules/@npmcli/agent": { - "version": "2.2.2", - "inBundle": true, - "license": "ISC", - "dependencies": { - "agent-base": "^7.1.0", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.1", - "lru-cache": "^10.0.1", - "socks-proxy-agent": "^8.0.3" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/tuf-js/node_modules/@npmcli/fs": { - "version": "3.1.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/tuf-js/node_modules/cacache": { - "version": "18.0.4", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/fs": "^3.1.0", - "fs-minipass": "^3.0.0", - "glob": "^10.2.2", - "lru-cache": "^10.0.1", - "minipass": "^7.0.3", - "minipass-collect": "^2.0.1", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "p-map": "^4.0.0", - "ssri": "^10.0.0", - "tar": "^6.1.11", - "unique-filename": "^3.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/tuf-js/node_modules/make-fetch-happen": { - "version": "13.0.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/agent": "^2.0.0", - "cacache": "^18.0.0", - "http-cache-semantics": "^4.1.1", - "is-lambda": "^1.0.1", - "minipass": "^7.0.2", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "proc-log": "^4.2.0", - "promise-retry": "^2.0.1", - "ssri": "^10.0.0" + "@tufjs/models": "3.0.1", + "debug": "^4.3.6", + "make-fetch-happen": "^14.0.1" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/npm/node_modules/tuf-js/node_modules/minipass-fetch": { - "version": "3.0.5", + "node_modules/npm/node_modules/tuf-js/node_modules/@tufjs/models": { + "version": "3.0.1", "inBundle": true, "license": "MIT", "dependencies": { - "minipass": "^7.0.3", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, - "node_modules/npm/node_modules/tuf-js/node_modules/proc-log": { - "version": "4.2.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/tuf-js/node_modules/ssri": { - "version": "10.0.6", - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/tuf-js/node_modules/unique-filename": { - "version": "3.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "unique-slug": "^4.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/tuf-js/node_modules/unique-slug": { - "version": "4.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4" + "@tufjs/canonical-json": "2.0.0", + "minimatch": "^9.0.5" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/npm/node_modules/unique-filename": { @@ -11381,7 +11041,7 @@ } }, "node_modules/npm/node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "6.0.1", + "version": "6.1.0", "inBundle": true, "license": "MIT", "engines": { @@ -12253,6 +11913,27 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/react-toastify": { + "version": "10.0.6", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-10.0.6.tgz", + "integrity": "sha512-yYjp+omCDf9lhZcrZHKbSq7YMuK0zcYkDFTzfRFgTXkTFHZ1ToxwAonzA4JI5CxA91JpjFLmwEsZEgfYfOqI1A==", + "license": "MIT", + "dependencies": { + "clsx": "^2.1.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, + "node_modules/react-toastify/node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "engines": { + "node": ">=6" + } + }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -12316,14 +11997,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/repl": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/repl/-/repl-0.1.3.tgz", - "integrity": "sha512-C3ZEHaX28+EvM9lPiXl9ruN2g5M5sUvyCIDvZ0M4VCusfA1Cn0+z3tJcQl/lvxPsBm82q4hKHKebPlE3SEhFKg==", - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", diff --git a/package.json b/package.json index 557f7a4..8ebc2b7 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "prisma:deploy": "prisma migrate deploy" }, "dependencies": { + "@googlemaps/js-api-loader": "^1.16.8", "@internationalized/date": "^3.5.6", "@nextui-org/calendar": "^2.0.12", "@nextui-org/react": "^2.4.8", @@ -28,12 +29,11 @@ "next": "15.0.3", "next-auth": "^4.24.10", "nodemailer": "^6.9.16", - "npm": "^10.9.0", + "npm": "^10.9.2", "pg": "^8.10.0", "react": "^18.3.1", "react-dom": "^18.3.1", "react-toastify": "^10.0.6", - "repl": "^0.1.3", "zod": "^3.23.8" }, "devDependencies": { diff --git a/src/app/api/request-schedule/route.ts b/src/app/api/request-schedule/route.ts index 12f1a33..073b207 100644 --- a/src/app/api/request-schedule/route.ts +++ b/src/app/api/request-schedule/route.ts @@ -1,6 +1,7 @@ import { prisma } from "@/lib/prisma"; import { NextResponse } from "next/server"; import { computeRouteMatrix } from "@/lib/utils/google-routes"; +import { TimeSlot } from "@/types/time-slot"; interface Route { originIndex: number; @@ -9,6 +10,16 @@ interface Route { condition: string; } +function determineTimeSlot(accumulatedTime: number): TimeSlot { + const hour = Math.floor(accumulatedTime / 3600); // Convert seconds to hours + + if (hour >= 8 && hour < 11) return TimeSlot.Morning; + if (hour >= 11 && hour < 14) return TimeSlot.Daytime; + if (hour >= 14 && hour < 17) return TimeSlot.Evening; + + throw new Error("Unable to determine time slot for the given hour"); +} + function optimizeRoute(routeMatrix: number[][]): number[] { const numLocations = routeMatrix.length; const visited = new Set(); @@ -101,27 +112,28 @@ export async function GET() { // Optimize route const optimizedOrder = optimizeRoute(routeMatrix); - // Reorder requests - const optimizedRequests = optimizedOrder.map((index) => { - const nextIndex = (index + 1) % requests.length; - const routeKey = `${index}-${nextIndex}`; - const route = routeMap[routeKey]; + // Initialize the starting time (8:00 AM in seconds) + let accumulatedTime = 8 * 60 * 60; // Start time in seconds (8:00 AM) + const stopDuration = 60 * 60; // Assume 1 hour per stop in seconds + + // Reorder requests and assign time slots + const optimizedRequests = optimizedOrder.map((index, idx) => { + const currentRequest = requests[index]; + const nextIndex = (idx + 1) % requests.length; + + const travelTime = routeMatrix[index][nextIndex]; // Travel time in seconds + + // Determine the time slot based on accumulated time + const timeSlot = determineTimeSlot(accumulatedTime); + + // Increment accumulated time by the stop duration and travel time + accumulatedTime += stopDuration + travelTime; return { - ...requests[index], - route: route - ? { - originIndex: route.originIndex, - destinationIndex: route.destinationIndex, - duration: route.duration, - condition: route.condition, - } - : { - originIndex: index, - destinationIndex: nextIndex, - duration: "0s", - condition: "FAILED", - }, + ...currentRequest, + timeSlot, // Assign the time slot + travelTime, // Add travel time to the response + route: routeMap[`${index}-${nextIndex}`], // Add route details }; }); diff --git a/src/app/dashboard/admin/route-manager/page.tsx b/src/app/dashboard/admin/route-manager/page.tsx new file mode 100644 index 0000000..2398898 --- /dev/null +++ b/src/app/dashboard/admin/route-manager/page.tsx @@ -0,0 +1,5 @@ +import RouteManagerComponent from "@/components/route-manager/Route-manager"; + +export default function RouteManager() { + return ; +} diff --git a/src/app/services/collateDailyRequests/collateDailyRequests.ts b/src/app/services/collateDailyRequests/collateDailyRequests.ts index 9c8536d..b0520e9 100644 --- a/src/app/services/collateDailyRequests/collateDailyRequests.ts +++ b/src/app/services/collateDailyRequests/collateDailyRequests.ts @@ -1,14 +1,37 @@ import { ResidentRequestCollation } from "@/types/resident-request-collation"; +import dayjs from "dayjs"; -export async function fetchDailyRequests(): Promise> { +export async function collateDailyRequests( + date: string +): Promise { try { - const response = await fetch("/api/request-schedule"); + const response = await fetch(`/api/request-schedule`); if (!response.ok) { - throw new Error("Failed to fetch requests"); + throw new Error(`Failed to fetch requests: ${response.statusText}`); } - return response.json(); + + const allRequests: ResidentRequestCollation[] = await response.json(); + console.log("Fetched all requests from API:", allRequests); + + // Filter requests by local timezone date + const filteredRequests = allRequests.filter((request) => { + const requestDate = new Date(request.requestedTimeSlot.startTime); + + // Convert UTC to local date without time + const localDate = new Date( + requestDate.getUTCFullYear(), + requestDate.getUTCMonth(), + requestDate.getUTCDate() + ); + + // Compare with the selected date + return dayjs(localDate).format("YYYY-MM-DD") === date; + }); + + console.log(`Filtered requests for date ${date}:`, filteredRequests); + return filteredRequests; } catch (error) { - console.error("Error fetching daily requests:", error); + console.error("Error fetching or filtering requests:", error); throw error; } } diff --git a/src/app/services/collateDailyRequests/loader.ts b/src/app/services/collateDailyRequests/loader.ts new file mode 100644 index 0000000..7e315c6 --- /dev/null +++ b/src/app/services/collateDailyRequests/loader.ts @@ -0,0 +1,46 @@ +import { Loader } from "@googlemaps/js-api-loader"; + +export const googleMapsLoader = new Loader({ + apiKey: process.env.NEXT_PUBLIC_GOOGLEMAPS_API_KEY!, + version: "weekly", + libraries: ["places", "maps", "routes"], +}); + +interface Location { + latitude: number; + longitude: number; + name: string; +} + +interface LocationData { + defaultLat: number; + defaultLng: number; + locations: Location[]; +} + +export async function fetchLocationData(): Promise { + const response = await fetch("/api/locations"); + if (!response.ok) { + throw new Error(`Failed to fetch location data: ${response.statusText}`); + } + return response.json(); // Automatically inferred as LocationData +} + +export async function initializeMapWithJson() { + await googleMapsLoader.load(); + + const locationData = await fetchLocationData(); + + const map = new google.maps.Map(document.getElementById("map") as HTMLElement, { + center: { lat: locationData.defaultLat, lng: locationData.defaultLng }, + zoom: 8, + }); + + locationData.locations.forEach((location) => { + new google.maps.Marker({ + position: { lat: location.latitude, lng: location.longitude }, + map: map, + title: location.name, + }); + }); +} diff --git a/src/components/buttonText.tsx b/src/components/buttonText.tsx index e490aa0..752d352 100644 --- a/src/components/buttonText.tsx +++ b/src/components/buttonText.tsx @@ -1,9 +1,12 @@ +import Spinner from "@/components/spinner/Spinner"; + interface ButtonTextProps { text: string; color: "Green" | "Yellow" | "Red"; name?: string; disabled?: boolean; paddingX?: 2 | 4; + busy?: boolean; onClick?: () => void; } @@ -14,6 +17,7 @@ export function ButtonText({ name, disabled, paddingX, + busy, ...rest }: ButtonTextProps) { return ( @@ -29,6 +33,7 @@ export function ButtonText({ disabled={disabled} {...rest} > + {busy && } {text} ); diff --git a/src/components/dashboards/Admin-dashboard.tsx b/src/components/dashboards/Admin-dashboard.tsx index 6b1c43d..cf22497 100644 --- a/src/components/dashboards/Admin-dashboard.tsx +++ b/src/components/dashboards/Admin-dashboard.tsx @@ -8,6 +8,7 @@ import { AllUserRequestsAdminGetResponse } from "@/types/api-responses/admin-res import { RequestStatus } from "@prisma/client"; import { ResidentRequestService } from "app/services/resident-request-service"; import { useSession } from "next-auth/react"; +import Link from "next/link"; import { useRouter } from "next/navigation"; import { useEffect, useState } from "react"; import FormattedTimeSlotDateTime from "../formatted-time-slot-date-time.tsx/FormattedTimeSlotDateTime"; @@ -163,8 +164,15 @@ export default function AdminDashboard() {
{/* Search and filter panel */} - - +
+ + + Route Manager + +
{isSearching && (
) : ( -

+

Access to this page is denied (admin) -

+

)} ); diff --git a/src/components/route-manager/Route-list.tsx b/src/components/route-manager/Route-list.tsx new file mode 100644 index 0000000..c5e84a5 --- /dev/null +++ b/src/components/route-manager/Route-list.tsx @@ -0,0 +1,41 @@ +import { ResidentRequestCollation } from "@/types/resident-request-collation"; + +interface RouteListProps { + routes?: ResidentRequestCollation[]; // Mark as optional to allow default value +} + +export default function RouteList({ routes = [] }: RouteListProps) { // Default to an empty array + return ( +
    + {routes.length > 0 ? ( + routes.map((route) => ( +
  • +
    +
    +

    + {route.user.name} +

    +

    + {`${route.address.streetNumber} ${route.address.streetName}, ${route.address.city}`} +

    +

    + ETA: {route.route?.duration || "N/A"} +

    +

    + Status: {route.status} +

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

    No routes available.

    +
  • + )} +
+ ); +} diff --git a/src/components/route-manager/Route-manager.tsx b/src/components/route-manager/Route-manager.tsx new file mode 100644 index 0000000..d4755e0 --- /dev/null +++ b/src/components/route-manager/Route-manager.tsx @@ -0,0 +1,133 @@ +"use client"; + +import { parseDate } from "@internationalized/date"; +import { DatePicker } from "@nextui-org/react"; +import dayjs from "dayjs"; +import { useSession } from "next-auth/react"; +import { useRouter } from "next/navigation"; +import { useEffect, useState } from "react"; +import RouteList from "./Route-list"; +import { googleMapsLoader } from "@/services/collateDailyRequests/loader"; +import { collateDailyRequests } from "@/services/collateDailyRequests/collateDailyRequests"; +import { ResidentRequestCollation } from "@/types/resident-request-collation"; + +export default function RouteManager() { + const { data: session, status } = useSession(); + const webRouter = useRouter(); + const [dateValue, setDateValue] = useState(parseDate(dayjs().format("YYYY-MM-DD"))); + const [googleMap, setGoogleMap] = useState(null); + const [filteredRequests, setFilteredRequests] = useState([]); + + useEffect(() => { + if (status === "unauthenticated") { + webRouter.replace("/authenticate"); + } + }, [status, webRouter]); + + const handleCollateDailyRequests = async () => { + try { + const formattedDate = dayjs(dateValue.toString()).format("YYYY-MM-DD"); + console.log("Fetching requests for date:", formattedDate); + + const result = await collateDailyRequests(formattedDate); + console.log("Generated Routes:", result); + + setFilteredRequests(result); // Pass filtered data to RouteList + + if (result.length > 0 && googleMap) { + const directionsService = new google.maps.DirectionsService(); + const directionsRenderer = new google.maps.DirectionsRenderer({ map: googleMap }); + + // Set the starting point, ending point, and waypoints + const waypoints = result.slice(1, -1).map((request) => ({ + location: { + lat: request.address.latitude, + lng: request.address.longitude, + }, + stopover: true, + })); + + const routeRequest: google.maps.DirectionsRequest = { + origin: { + lat: result[0].address.latitude, + lng: result[0].address.longitude, + }, + destination: { + lat: result[result.length - 1].address.latitude, + lng: result[result.length - 1].address.longitude, + }, + waypoints, + travelMode: google.maps.TravelMode.DRIVING, + }; + + directionsService.route(routeRequest, (result, status) => { + if (status === google.maps.DirectionsStatus.OK) { + directionsRenderer.setDirections(result); + } else { + console.error("Error generating directions:", status); + } + }); + } else { + console.warn("No routes found for the selected date."); + } + } catch (error) { + console.error("Error generating routes:", error); + } + }; + + useEffect(() => { + async function initMap() { + const mapElement = document.getElementById("gmap") as HTMLElement; + if (!mapElement) return; + + await googleMapsLoader.load(); + + const map = new google.maps.Map(mapElement, { + center: { lat: 34.0522, lng: -118.2437 }, // Default to Los Angeles + zoom: 10, + }); + + setGoogleMap(map); + } + + initMap(); + }, []); + + return ( + <> + {session?.user?.isAdmin ? ( +
+
+

Route Manager

+
+
+
+ +
+ +
+
+
+
+ {/* Pass routes as props */} +
+
+
+ ) : ( +
+

Not authorized

+
+ )} + + ); +} diff --git a/src/components/submission-form/Submission-form.tsx b/src/components/submission-form/Submission-form.tsx index d049027..0c59400 100644 --- a/src/components/submission-form/Submission-form.tsx +++ b/src/components/submission-form/Submission-form.tsx @@ -195,6 +195,7 @@ export function SubmissionForm() { color="Green" name="next" disabled={isBusy} + busy={isBusy} /> {submitError && ( diff --git a/src/types/resident-request-collation.ts b/src/types/resident-request-collation.ts index 0e1366c..2077b87 100644 --- a/src/types/resident-request-collation.ts +++ b/src/types/resident-request-collation.ts @@ -1,20 +1,38 @@ export interface ResidentRequestCollation { - id: string; - requestedTimeSlot: { startTime: string; endTime: string }; // Time slot details + id: string; // Unique identifier for the request + requestedTimeSlot: { + id: string; + startTime: string; + endTime: string; + description?: string; + } address: { - latitude: number; // Latitude from the database - longitude: number; // Longitude from the database - city: string; - streetName?: string; - streetNumber?: string; - zipCode?: string; - googleAddressComponents?: google.maps.GeocoderAddressComponent[]; // Add this if using Google Geocoding results - geometry?: google.maps.places.PlaceGeometry; // Add this if processing geometry + latitude: number; // lat num + longitude: number; // long num + city: string; // City name + streetName: string; // validation: Street name + streetNumber: string; + zipCode: string; + googleAddressComponents?: google.maps.GeocoderAddressComponent[]; + // validation: Address components from Google Geocoding API + geometry?: google.maps.places.PlaceGeometry; + // }; user: { - id: string; - name: string; - email: string; + id: string; // Unique identifier for the user associated with the request + name: string; // User's full name + email: string; // User's email address + }; + distanceFromPrevious?: number; // Optional: Distance from the previous address in meters + routeDetails?: { + startIndex: number; // Optional: Index of the starting point in the route + endIndex: number; // Optional: Index of the ending point in the route }; - distanceFromPrevious?: number; + status: string; // Add this if it's part of the API response + route?: { + originIndex: number; + destinationIndex: number; + duration: string; + condition: string; + }; // Optional route property } diff --git a/tailwind.config.ts b/tailwind.config.ts index 5e6bab9..b5c7047 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -14,6 +14,7 @@ export default { "simmpy-green": "#6AB04C", "simmpy-yellow": "#F9CA24", "simmpy-red": "#c13f0b", + "simmpy-blue": "#1e3a89", "simmpy-gray-100": "#E1E1E6", "simmpy-gray-200": "#5E5E5E", "simmpy-gray-600": "#444444", diff --git a/tsconfig.json b/tsconfig.json index c193135..3da3f54 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -25,6 +25,7 @@ "@/hooks/*": ["hooks/*"], "@/auth": ["../auth"], "@/lib/*": ["lib/*"], + "@/services/*": ["app/services/*"], } }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],