diff --git a/.github/workflows/frontend-dev.yml b/.github/workflows/frontend-dev.yml
index 39eadac8a..c82985558 100644
--- a/.github/workflows/frontend-dev.yml
+++ b/.github/workflows/frontend-dev.yml
@@ -14,43 +14,46 @@ on:
defaults:
run:
working-directory: frontend
-
+
permissions:
- pull-requests: write
- checks: write
+ pull-requests: write
+ checks: write
jobs:
- build:
+ build:
runs-on: ubuntu-latest
steps:
- name: Set up Repository
uses: actions/checkout@v3
- - name : Set up Node 18.16.0
+ - name: Set up Node 18.16.0
uses: actions/setup-node@v3
with:
node-version: 18.16.0
-
+
- name: Cache node_modules
id: cache
uses: actions/cache@v3
with:
- path: '**/node_modules'
- key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
- restore-keys: |
- ${{ runner.os }}-node-
-
+ path: '**/node_modules'
+ key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
+ restore-keys: |
+ ${{ runner.os }}-node-
+
- name: npm clean install
run: npm ci
if: steps.cache.outputs.cache-hit != 'true'
+ - name: submodule update
+ run: git submodule update --remote --merge
+
- name: npm build dev
run: npm run build-dev
-
+
- name: storyBook build
run: npm run build-storybook
if: always()
-
+
- name: notificate on slack if build failed
uses: 8398a7/action-slack@v3
with:
diff --git a/frontend/cypress/e2e/main.cy.ts b/frontend/cypress/e2e/main.cy.ts
index 2888f68ed..68f1eee47 100644
--- a/frontend/cypress/e2e/main.cy.ts
+++ b/frontend/cypress/e2e/main.cy.ts
@@ -96,6 +96,10 @@ describe('검색창', () => {
.type('아카시')
.wait(500)
+ .get('ul > li')
+ .contains('아카시')
+ .should('be.visible')
+
.get('button[aria-label="이동하기"]')
.click()
@@ -110,6 +114,13 @@ describe('검색창', () => {
cy.get('input')
.type('참')
.wait(500)
+
+ .get('ul > li')
+ .should('be.visible')
+
+ .get('input')
+ .focus()
+
.type('{enter}')
.location('pathname')
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 4f192ae67..895d281a1 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -11,6 +11,7 @@
"dependencies": {
"@pium/stack-component": "^1.0.0",
"@tanstack/react-query": "^5.0.0-beta.20",
+ "firebase": "^10.4.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.14.1",
@@ -2987,6 +2988,624 @@
"integrity": "sha512-cEee/Z+I12mZcFJshKcCqC8tuX5hG3s+d+9nZ3LabqKF1vKdF41B92pJVCBggjAGORAeOzyyDDKrZwIkLffeOQ==",
"dev": true
},
+ "node_modules/@firebase/analytics": {
+ "version": "0.10.0",
+ "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.0.tgz",
+ "integrity": "sha512-Locv8gAqx0e+GX/0SI3dzmBY5e9kjVDtD+3zCFLJ0tH2hJwuCAiL+5WkHuxKj92rqQj/rvkBUCfA1ewlX2hehg==",
+ "dependencies": {
+ "@firebase/component": "0.6.4",
+ "@firebase/installations": "0.6.4",
+ "@firebase/logger": "0.4.0",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/analytics-compat": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.6.tgz",
+ "integrity": "sha512-4MqpVLFkGK7NJf/5wPEEP7ePBJatwYpyjgJ+wQHQGHfzaCDgntOnl9rL2vbVGGKCnRqWtZDIWhctB86UWXaX2Q==",
+ "dependencies": {
+ "@firebase/analytics": "0.10.0",
+ "@firebase/analytics-types": "0.8.0",
+ "@firebase/component": "0.6.4",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/analytics-types": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.8.0.tgz",
+ "integrity": "sha512-iRP+QKI2+oz3UAh4nPEq14CsEjrjD6a5+fuypjScisAh9kXKFvdJOZJDwk7kikLvWVLGEs9+kIUS4LPQV7VZVw=="
+ },
+ "node_modules/@firebase/app": {
+ "version": "0.9.19",
+ "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.9.19.tgz",
+ "integrity": "sha512-t/SHyZ3xWkR77ZU9VMoobDNFLdDKQ5xqoCAn4o16gTsA1C8sJ6ZOMZ02neMOPxNHuQXVE4tA8ukilnDbnK7uJA==",
+ "dependencies": {
+ "@firebase/component": "0.6.4",
+ "@firebase/logger": "0.4.0",
+ "@firebase/util": "1.9.3",
+ "idb": "7.1.1",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@firebase/app-check": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.8.0.tgz",
+ "integrity": "sha512-dRDnhkcaC2FspMiRK/Vbp+PfsOAEP6ZElGm9iGFJ9fDqHoPs0HOPn7dwpJ51lCFi1+2/7n5pRPGhqF/F03I97g==",
+ "dependencies": {
+ "@firebase/component": "0.6.4",
+ "@firebase/logger": "0.4.0",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/app-check-compat": {
+ "version": "0.3.7",
+ "resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.3.7.tgz",
+ "integrity": "sha512-cW682AxsyP1G+Z0/P7pO/WT2CzYlNxoNe5QejVarW2o5ZxeWSSPAiVEwpEpQR/bUlUmdeWThYTMvBWaopdBsqw==",
+ "dependencies": {
+ "@firebase/app-check": "0.8.0",
+ "@firebase/app-check-types": "0.5.0",
+ "@firebase/component": "0.6.4",
+ "@firebase/logger": "0.4.0",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/app-check-interop-types": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.0.tgz",
+ "integrity": "sha512-xAxHPZPIgFXnI+vb4sbBjZcde7ZluzPPaSK7Lx3/nmuVk4TjZvnL8ONnkd4ERQKL8WePQySU+pRcWkh8rDf5Sg=="
+ },
+ "node_modules/@firebase/app-check-types": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.5.0.tgz",
+ "integrity": "sha512-uwSUj32Mlubybw7tedRzR24RP8M8JUVR3NPiMk3/Z4bCmgEKTlQBwMXrehDAZ2wF+TsBq0SN1c6ema71U/JPyQ=="
+ },
+ "node_modules/@firebase/app-compat": {
+ "version": "0.2.19",
+ "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.19.tgz",
+ "integrity": "sha512-QkJDqYqjhvs4fTMcRVXQkP9hbo5yfoJXDWkhU4VA5Vzs8Qsp76VPzYbqx5SD5OmBy+bz/Ot1UV8qySPGI4aKuw==",
+ "dependencies": {
+ "@firebase/app": "0.9.19",
+ "@firebase/component": "0.6.4",
+ "@firebase/logger": "0.4.0",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@firebase/app-types": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.0.tgz",
+ "integrity": "sha512-AeweANOIo0Mb8GiYm3xhTEBVCmPwTYAu9Hcd2qSkLuga/6+j9b1Jskl5bpiSQWy9eJ/j5pavxj6eYogmnuzm+Q=="
+ },
+ "node_modules/@firebase/auth": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.3.0.tgz",
+ "integrity": "sha512-vjK4CHbY9aWdiVOrKi6mpa8z6uxeaf7LB/MZTHuZOiGHMcUoTGB6TeMbRShyqk1uaMrxhhZ5Ar/dR0965E1qyA==",
+ "dependencies": {
+ "@firebase/component": "0.6.4",
+ "@firebase/logger": "0.4.0",
+ "@firebase/util": "1.9.3",
+ "node-fetch": "2.6.7",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x",
+ "@react-native-async-storage/async-storage": "^1.18.1"
+ },
+ "peerDependenciesMeta": {
+ "@react-native-async-storage/async-storage": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@firebase/auth-compat": {
+ "version": "0.4.6",
+ "resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.4.6.tgz",
+ "integrity": "sha512-pKp1d4fSf+yoy1EBjTx9ISxlunqhW0vTICk0ByZ3e+Lp6ZIXThfUy4F1hAJlEafD/arM0oepRiAh7LXS1xn/BA==",
+ "dependencies": {
+ "@firebase/auth": "1.3.0",
+ "@firebase/auth-types": "0.12.0",
+ "@firebase/component": "0.6.4",
+ "@firebase/util": "1.9.3",
+ "node-fetch": "2.6.7",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/auth-compat/node_modules/node-fetch": {
+ "version": "2.6.7",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
+ "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
+ "dependencies": {
+ "whatwg-url": "^5.0.0"
+ },
+ "engines": {
+ "node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@firebase/auth-interop-types": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.1.tgz",
+ "integrity": "sha512-VOaGzKp65MY6P5FI84TfYKBXEPi6LmOCSMMzys6o2BN2LOsqy7pCuZCup7NYnfbk5OkkQKzvIfHOzTm0UDpkyg=="
+ },
+ "node_modules/@firebase/auth-types": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.12.0.tgz",
+ "integrity": "sha512-pPwaZt+SPOshK8xNoiQlK5XIrS97kFYc3Rc7xmy373QsOJ9MmqXxLaYssP5Kcds4wd2qK//amx/c+A8O2fVeZA==",
+ "peerDependencies": {
+ "@firebase/app-types": "0.x",
+ "@firebase/util": "1.x"
+ }
+ },
+ "node_modules/@firebase/auth/node_modules/node-fetch": {
+ "version": "2.6.7",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
+ "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
+ "dependencies": {
+ "whatwg-url": "^5.0.0"
+ },
+ "engines": {
+ "node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@firebase/component": {
+ "version": "0.6.4",
+ "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.4.tgz",
+ "integrity": "sha512-rLMyrXuO9jcAUCaQXCMjCMUsWrba5fzHlNK24xz5j2W6A/SRmK8mZJ/hn7V0fViLbxC0lPMtrK1eYzk6Fg03jA==",
+ "dependencies": {
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@firebase/database": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.0.1.tgz",
+ "integrity": "sha512-VAhF7gYwunW4Lw/+RQZvW8dlsf2r0YYqV9W0Gi2Mz8+0TGg1mBJWoUtsHfOr8kPJXhcLsC4eP/z3x6L/Fvjk/A==",
+ "dependencies": {
+ "@firebase/auth-interop-types": "0.2.1",
+ "@firebase/component": "0.6.4",
+ "@firebase/logger": "0.4.0",
+ "@firebase/util": "1.9.3",
+ "faye-websocket": "0.11.4",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@firebase/database-compat": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-1.0.1.tgz",
+ "integrity": "sha512-ky82yLIboLxtAIWyW/52a6HLMVTzD2kpZlEilVDok73pNPLjkJYowj8iaIWK5nTy7+6Gxt7d00zfjL6zckGdXQ==",
+ "dependencies": {
+ "@firebase/component": "0.6.4",
+ "@firebase/database": "1.0.1",
+ "@firebase/database-types": "1.0.0",
+ "@firebase/logger": "0.4.0",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@firebase/database-types": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.0.tgz",
+ "integrity": "sha512-SjnXStoE0Q56HcFgNQ+9SsmJc0c8TqGARdI/T44KXy+Ets3r6x/ivhQozT66bMnCEjJRywYoxNurRTMlZF8VNg==",
+ "dependencies": {
+ "@firebase/app-types": "0.9.0",
+ "@firebase/util": "1.9.3"
+ }
+ },
+ "node_modules/@firebase/firestore": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.2.0.tgz",
+ "integrity": "sha512-iKZqIdOBJpJUcwY5airLX0W04TLrQSJuActOP1HG5WoIY5oyGTQE4Ml7hl5GW7mBqFieT4ojtUuDXj6MLrn1lA==",
+ "dependencies": {
+ "@firebase/component": "0.6.4",
+ "@firebase/logger": "0.4.0",
+ "@firebase/util": "1.9.3",
+ "@firebase/webchannel-wrapper": "0.10.3",
+ "@grpc/grpc-js": "~1.9.0",
+ "@grpc/proto-loader": "^0.7.8",
+ "node-fetch": "2.6.7",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=10.10.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/firestore-compat": {
+ "version": "0.3.18",
+ "resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.18.tgz",
+ "integrity": "sha512-hkqv4mb1oScKbEtzfcK8Go8c0VpDWmbAvbD6B6XnphLqi27pkXgo9Rp+aSKlD7cBL29VMEekP5bEm9lSVfZpNw==",
+ "dependencies": {
+ "@firebase/component": "0.6.4",
+ "@firebase/firestore": "4.2.0",
+ "@firebase/firestore-types": "3.0.0",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/firestore-types": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-3.0.0.tgz",
+ "integrity": "sha512-Meg4cIezHo9zLamw0ymFYBD4SMjLb+ZXIbuN7T7ddXN6MGoICmOTq3/ltdCGoDCS2u+H1XJs2u/cYp75jsX9Qw==",
+ "peerDependencies": {
+ "@firebase/app-types": "0.x",
+ "@firebase/util": "1.x"
+ }
+ },
+ "node_modules/@firebase/firestore/node_modules/node-fetch": {
+ "version": "2.6.7",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
+ "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
+ "dependencies": {
+ "whatwg-url": "^5.0.0"
+ },
+ "engines": {
+ "node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@firebase/functions": {
+ "version": "0.10.0",
+ "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.10.0.tgz",
+ "integrity": "sha512-2U+fMNxTYhtwSpkkR6WbBcuNMOVaI7MaH3cZ6UAeNfj7AgEwHwMIFLPpC13YNZhno219F0lfxzTAA0N62ndWzA==",
+ "dependencies": {
+ "@firebase/app-check-interop-types": "0.3.0",
+ "@firebase/auth-interop-types": "0.2.1",
+ "@firebase/component": "0.6.4",
+ "@firebase/messaging-interop-types": "0.2.0",
+ "@firebase/util": "1.9.3",
+ "node-fetch": "2.6.7",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/functions-compat": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.3.5.tgz",
+ "integrity": "sha512-uD4jwgwVqdWf6uc3NRKF8cSZ0JwGqSlyhPgackyUPe+GAtnERpS4+Vr66g0b3Gge0ezG4iyHo/EXW/Hjx7QhHw==",
+ "dependencies": {
+ "@firebase/component": "0.6.4",
+ "@firebase/functions": "0.10.0",
+ "@firebase/functions-types": "0.6.0",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/functions-types": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.6.0.tgz",
+ "integrity": "sha512-hfEw5VJtgWXIRf92ImLkgENqpL6IWpYaXVYiRkFY1jJ9+6tIhWM7IzzwbevwIIud/jaxKVdRzD7QBWfPmkwCYw=="
+ },
+ "node_modules/@firebase/functions/node_modules/node-fetch": {
+ "version": "2.6.7",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
+ "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
+ "dependencies": {
+ "whatwg-url": "^5.0.0"
+ },
+ "engines": {
+ "node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@firebase/installations": {
+ "version": "0.6.4",
+ "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.4.tgz",
+ "integrity": "sha512-u5y88rtsp7NYkCHC3ElbFBrPtieUybZluXyzl7+4BsIz4sqb4vSAuwHEUgCgCeaQhvsnxDEU6icly8U9zsJigA==",
+ "dependencies": {
+ "@firebase/component": "0.6.4",
+ "@firebase/util": "1.9.3",
+ "idb": "7.0.1",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/installations-compat": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.4.tgz",
+ "integrity": "sha512-LI9dYjp0aT9Njkn9U4JRrDqQ6KXeAmFbRC0E7jI7+hxl5YmRWysq5qgQl22hcWpTk+cm3es66d/apoDU/A9n6Q==",
+ "dependencies": {
+ "@firebase/component": "0.6.4",
+ "@firebase/installations": "0.6.4",
+ "@firebase/installations-types": "0.5.0",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/installations-types": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.5.0.tgz",
+ "integrity": "sha512-9DP+RGfzoI2jH7gY4SlzqvZ+hr7gYzPODrbzVD82Y12kScZ6ZpRg/i3j6rleto8vTFC8n6Len4560FnV1w2IRg==",
+ "peerDependencies": {
+ "@firebase/app-types": "0.x"
+ }
+ },
+ "node_modules/@firebase/installations/node_modules/idb": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/idb/-/idb-7.0.1.tgz",
+ "integrity": "sha512-UUxlE7vGWK5RfB/fDwEGgRf84DY/ieqNha6msMV99UsEMQhJ1RwbCd8AYBj3QMgnE3VZnfQvm4oKVCJTYlqIgg=="
+ },
+ "node_modules/@firebase/logger": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.0.tgz",
+ "integrity": "sha512-eRKSeykumZ5+cJPdxxJRgAC3G5NknY2GwEbKfymdnXtnT0Ucm4pspfR6GT4MUQEDuJwRVbVcSx85kgJulMoFFA==",
+ "dependencies": {
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@firebase/messaging": {
+ "version": "0.12.4",
+ "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.4.tgz",
+ "integrity": "sha512-6JLZct6zUaex4g7HI3QbzeUrg9xcnmDAPTWpkoMpd/GoSVWH98zDoWXMGrcvHeCAIsLpFMe4MPoZkJbrPhaASw==",
+ "dependencies": {
+ "@firebase/component": "0.6.4",
+ "@firebase/installations": "0.6.4",
+ "@firebase/messaging-interop-types": "0.2.0",
+ "@firebase/util": "1.9.3",
+ "idb": "7.0.1",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/messaging-compat": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.4.tgz",
+ "integrity": "sha512-lyFjeUhIsPRYDPNIkYX1LcZMpoVbBWXX4rPl7c/rqc7G+EUea7IEtSt4MxTvh6fDfPuzLn7+FZADfscC+tNMfg==",
+ "dependencies": {
+ "@firebase/component": "0.6.4",
+ "@firebase/messaging": "0.12.4",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/messaging-interop-types": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.0.tgz",
+ "integrity": "sha512-ujA8dcRuVeBixGR9CtegfpU4YmZf3Lt7QYkcj693FFannwNuZgfAYaTmbJ40dtjB81SAu6tbFPL9YLNT15KmOQ=="
+ },
+ "node_modules/@firebase/messaging/node_modules/idb": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/idb/-/idb-7.0.1.tgz",
+ "integrity": "sha512-UUxlE7vGWK5RfB/fDwEGgRf84DY/ieqNha6msMV99UsEMQhJ1RwbCd8AYBj3QMgnE3VZnfQvm4oKVCJTYlqIgg=="
+ },
+ "node_modules/@firebase/performance": {
+ "version": "0.6.4",
+ "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.6.4.tgz",
+ "integrity": "sha512-HfTn/bd8mfy/61vEqaBelNiNnvAbUtME2S25A67Nb34zVuCSCRIX4SseXY6zBnOFj3oLisaEqhVcJmVPAej67g==",
+ "dependencies": {
+ "@firebase/component": "0.6.4",
+ "@firebase/installations": "0.6.4",
+ "@firebase/logger": "0.4.0",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/performance-compat": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.4.tgz",
+ "integrity": "sha512-nnHUb8uP9G8islzcld/k6Bg5RhX62VpbAb/Anj7IXs/hp32Eb2LqFPZK4sy3pKkBUO5wcrlRWQa6wKOxqlUqsg==",
+ "dependencies": {
+ "@firebase/component": "0.6.4",
+ "@firebase/logger": "0.4.0",
+ "@firebase/performance": "0.6.4",
+ "@firebase/performance-types": "0.2.0",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/performance-types": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.2.0.tgz",
+ "integrity": "sha512-kYrbr8e/CYr1KLrLYZZt2noNnf+pRwDq2KK9Au9jHrBMnb0/C9X9yWSXmZkFt4UIdsQknBq8uBB7fsybZdOBTA=="
+ },
+ "node_modules/@firebase/remote-config": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.4.4.tgz",
+ "integrity": "sha512-x1ioTHGX8ZwDSTOVp8PBLv2/wfwKzb4pxi0gFezS5GCJwbLlloUH4YYZHHS83IPxnua8b6l0IXUaWd0RgbWwzQ==",
+ "dependencies": {
+ "@firebase/component": "0.6.4",
+ "@firebase/installations": "0.6.4",
+ "@firebase/logger": "0.4.0",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/remote-config-compat": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.4.tgz",
+ "integrity": "sha512-FKiki53jZirrDFkBHglB3C07j5wBpitAaj8kLME6g8Mx+aq7u9P7qfmuSRytiOItADhWUj7O1JIv7n9q87SuwA==",
+ "dependencies": {
+ "@firebase/component": "0.6.4",
+ "@firebase/logger": "0.4.0",
+ "@firebase/remote-config": "0.4.4",
+ "@firebase/remote-config-types": "0.3.0",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/remote-config-types": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.3.0.tgz",
+ "integrity": "sha512-RtEH4vdcbXZuZWRZbIRmQVBNsE7VDQpet2qFvq6vwKLBIQRQR5Kh58M4ok3A3US8Sr3rubYnaGqZSurCwI8uMA=="
+ },
+ "node_modules/@firebase/storage": {
+ "version": "0.11.2",
+ "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.11.2.tgz",
+ "integrity": "sha512-CtvoFaBI4hGXlXbaCHf8humajkbXhs39Nbh6MbNxtwJiCqxPy9iH3D3CCfXAvP0QvAAwmJUTK3+z9a++Kc4nkA==",
+ "dependencies": {
+ "@firebase/component": "0.6.4",
+ "@firebase/util": "1.9.3",
+ "node-fetch": "2.6.7",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/storage-compat": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.3.2.tgz",
+ "integrity": "sha512-wvsXlLa9DVOMQJckbDNhXKKxRNNewyUhhbXev3t8kSgoCotd1v3MmqhKKz93ePhDnhHnDs7bYHy+Qa8dRY6BXw==",
+ "dependencies": {
+ "@firebase/component": "0.6.4",
+ "@firebase/storage": "0.11.2",
+ "@firebase/storage-types": "0.8.0",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/storage-types": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.8.0.tgz",
+ "integrity": "sha512-isRHcGrTs9kITJC0AVehHfpraWFui39MPaU7Eo8QfWlqW7YPymBmRgjDrlOgFdURh6Cdeg07zmkLP5tzTKRSpg==",
+ "peerDependencies": {
+ "@firebase/app-types": "0.x",
+ "@firebase/util": "1.x"
+ }
+ },
+ "node_modules/@firebase/storage/node_modules/node-fetch": {
+ "version": "2.6.7",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
+ "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
+ "dependencies": {
+ "whatwg-url": "^5.0.0"
+ },
+ "engines": {
+ "node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@firebase/util": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz",
+ "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==",
+ "dependencies": {
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@firebase/webchannel-wrapper": {
+ "version": "0.10.3",
+ "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.10.3.tgz",
+ "integrity": "sha512-+ZplYUN3HOpgCfgInqgdDAbkGGVzES1cs32JJpeqoh87SkRobGXElJx+1GZSaDqzFL+bYiX18qEcBK76mYs8uA=="
+ },
+ "node_modules/@grpc/grpc-js": {
+ "version": "1.9.5",
+ "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.5.tgz",
+ "integrity": "sha512-iouYNlPxRAwZ2XboDT+OfRKHuaKHiqjB5VFYZ0NFrHkbEF+AV3muIUY9olQsp8uxU4VvRCMiRk9ftzFDGb61aw==",
+ "dependencies": {
+ "@grpc/proto-loader": "^0.7.8",
+ "@types/node": ">=12.12.47"
+ },
+ "engines": {
+ "node": "^8.13.0 || >=10.10.0"
+ }
+ },
+ "node_modules/@grpc/proto-loader": {
+ "version": "0.7.10",
+ "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.10.tgz",
+ "integrity": "sha512-CAqDfoaQ8ykFd9zqBDn4k6iWT9loLAlc2ETmDFS9JCD70gDcnA4L3AFEo2iV7KyAtAAHFW9ftq1Fz+Vsgq80RQ==",
+ "dependencies": {
+ "lodash.camelcase": "^4.3.0",
+ "long": "^5.0.0",
+ "protobufjs": "^7.2.4",
+ "yargs": "^17.7.2"
+ },
+ "bin": {
+ "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/@humanwhocodes/config-array": {
"version": "0.11.10",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz",
@@ -3605,6 +4224,60 @@
"integrity": "sha512-C16M+IYz0rgRhWZdCmK+h58JMv8vijAA61gmz2rspCSwKwzBebpdcsiUmwrtJRdphuY30i6BSLEOP8ppbNLyLg==",
"dev": true
},
+ "node_modules/@protobufjs/aspromise": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
+ "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ=="
+ },
+ "node_modules/@protobufjs/base64": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
+ "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg=="
+ },
+ "node_modules/@protobufjs/codegen": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz",
+ "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg=="
+ },
+ "node_modules/@protobufjs/eventemitter": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
+ "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q=="
+ },
+ "node_modules/@protobufjs/fetch": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz",
+ "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.1",
+ "@protobufjs/inquire": "^1.1.0"
+ }
+ },
+ "node_modules/@protobufjs/float": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
+ "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ=="
+ },
+ "node_modules/@protobufjs/inquire": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz",
+ "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q=="
+ },
+ "node_modules/@protobufjs/path": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
+ "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA=="
+ },
+ "node_modules/@protobufjs/pool": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
+ "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw=="
+ },
+ "node_modules/@protobufjs/utf8": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
+ "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="
+ },
"node_modules/@remix-run/router": {
"version": "1.7.1",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.7.1.tgz",
@@ -7531,8 +8204,7 @@
"node_modules/@types/node": {
"version": "20.3.3",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.3.tgz",
- "integrity": "sha512-wheIYdr4NYML61AjC8MKj/2jrR/kDQri/CIpVoZwldwhnIrD/j9jIU5bJ8yBKuB2VhpFV7Ab6G2XkBjv9r9Zzw==",
- "dev": true
+ "integrity": "sha512-wheIYdr4NYML61AjC8MKj/2jrR/kDQri/CIpVoZwldwhnIrD/j9jIU5bJ8yBKuB2VhpFV7Ab6G2XkBjv9r9Zzw=="
},
"node_modules/@types/node-fetch": {
"version": "2.6.4",
@@ -8598,7 +9270,6 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
"engines": {
"node": ">=8"
}
@@ -9933,7 +10604,6 @@
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
"integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
- "dev": true,
"dependencies": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.1",
@@ -11527,8 +12197,7 @@
"node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "dev": true
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"node_modules/emojis-list": {
"version": "3.0.0",
@@ -12787,7 +13456,6 @@
"version": "0.11.4",
"resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz",
"integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==",
- "dev": true,
"dependencies": {
"websocket-driver": ">=0.5.1"
},
@@ -12961,6 +13629,39 @@
"node": ">=8"
}
},
+ "node_modules/firebase": {
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/firebase/-/firebase-10.4.0.tgz",
+ "integrity": "sha512-3Z8WsNwA7kbcKGZ+nrTZ/ES518pk0K440ZJYD8nUNKN5hV6ll+unhUw30t1msedN6yIFjhsC/9OwT4Z0ohwO2w==",
+ "dependencies": {
+ "@firebase/analytics": "0.10.0",
+ "@firebase/analytics-compat": "0.2.6",
+ "@firebase/app": "0.9.19",
+ "@firebase/app-check": "0.8.0",
+ "@firebase/app-check-compat": "0.3.7",
+ "@firebase/app-compat": "0.2.19",
+ "@firebase/app-types": "0.9.0",
+ "@firebase/auth": "1.3.0",
+ "@firebase/auth-compat": "0.4.6",
+ "@firebase/database": "1.0.1",
+ "@firebase/database-compat": "1.0.1",
+ "@firebase/firestore": "4.2.0",
+ "@firebase/firestore-compat": "0.3.18",
+ "@firebase/functions": "0.10.0",
+ "@firebase/functions-compat": "0.3.5",
+ "@firebase/installations": "0.6.4",
+ "@firebase/installations-compat": "0.2.4",
+ "@firebase/messaging": "0.12.4",
+ "@firebase/messaging-compat": "0.2.4",
+ "@firebase/performance": "0.6.4",
+ "@firebase/performance-compat": "0.2.4",
+ "@firebase/remote-config": "0.4.4",
+ "@firebase/remote-config-compat": "0.2.4",
+ "@firebase/storage": "0.11.2",
+ "@firebase/storage-compat": "0.3.2",
+ "@firebase/util": "1.9.3"
+ }
+ },
"node_modules/flat-cache": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
@@ -13358,7 +14059,6 @@
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
- "dev": true,
"engines": {
"node": "6.* || 8.* || >= 10.*"
}
@@ -14021,8 +14721,7 @@
"node_modules/http-parser-js": {
"version": "0.5.8",
"resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz",
- "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==",
- "dev": true
+ "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q=="
},
"node_modules/http-proxy": {
"version": "1.18.1",
@@ -14145,6 +14844,11 @@
"postcss": "^8.1.0"
}
},
+ "node_modules/idb": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz",
+ "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ=="
+ },
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
@@ -14559,7 +15263,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "dev": true,
"engines": {
"node": ">=8"
}
@@ -16029,6 +16732,11 @@
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
},
+ "node_modules/lodash.camelcase": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
+ "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA=="
+ },
"node_modules/lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
@@ -16224,6 +16932,11 @@
"node": ">=8"
}
},
+ "node_modules/long": {
+ "version": "5.2.3",
+ "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz",
+ "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q=="
+ },
"node_modules/loose-envify": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
@@ -18043,6 +18756,29 @@
"react-is": "^16.13.1"
}
},
+ "node_modules/protobufjs": {
+ "version": "7.2.5",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.5.tgz",
+ "integrity": "sha512-gGXRSXvxQ7UiPgfw8gevrfRWcTlSbOFg+p/N+JVJEK5VhueL2miT6qTymqAmjr1Q5WbOCyJbyrk6JfWKwlFn6A==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.2",
+ "@protobufjs/base64": "^1.1.2",
+ "@protobufjs/codegen": "^2.0.4",
+ "@protobufjs/eventemitter": "^1.1.0",
+ "@protobufjs/fetch": "^1.1.0",
+ "@protobufjs/float": "^1.0.2",
+ "@protobufjs/inquire": "^1.1.0",
+ "@protobufjs/path": "^1.1.2",
+ "@protobufjs/pool": "^1.1.0",
+ "@protobufjs/utf8": "^1.1.0",
+ "@types/node": ">=13.7.0",
+ "long": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
"node_modules/proxy-addr": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
@@ -18826,7 +19562,6 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
- "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -18981,7 +19716,6 @@
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
- "dev": true,
"funding": [
{
"type": "github",
@@ -19747,7 +20481,6 @@
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "dev": true,
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
@@ -19825,7 +20558,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
"dependencies": {
"ansi-regex": "^5.0.1"
},
@@ -20720,8 +21452,7 @@
"node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
- "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
- "dev": true
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
},
"node_modules/trim-newlines": {
"version": "4.1.1",
@@ -21492,8 +22223,7 @@
"node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
- "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
- "dev": true
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
},
"node_modules/webpack": {
"version": "5.88.1",
@@ -21918,7 +22648,6 @@
"version": "0.7.4",
"resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz",
"integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==",
- "dev": true,
"dependencies": {
"http-parser-js": ">=0.5.1",
"safe-buffer": ">=5.1.0",
@@ -21932,7 +22661,6 @@
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz",
"integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==",
- "dev": true,
"engines": {
"node": ">=0.8.0"
}
@@ -21941,7 +22669,6 @@
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
- "dev": true,
"dependencies": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
@@ -22038,7 +22765,6 @@
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
- "dev": true,
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
@@ -22055,7 +22781,6 @@
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dev": true,
"dependencies": {
"color-convert": "^2.0.1"
},
@@ -22070,7 +22795,6 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "dev": true,
"dependencies": {
"color-name": "~1.1.4"
},
@@ -22081,8 +22805,7 @@
"node_modules/wrap-ansi/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "dev": true
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"node_modules/wrappy": {
"version": "1.0.2",
@@ -22136,7 +22859,6 @@
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
- "dev": true,
"engines": {
"node": ">=10"
}
@@ -22159,7 +22881,6 @@
"version": "17.7.2",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
"integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
- "dev": true,
"dependencies": {
"cliui": "^8.0.1",
"escalade": "^3.1.1",
@@ -22177,7 +22898,6 @@
"version": "21.1.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
- "dev": true,
"engines": {
"node": ">=12"
}
@@ -24076,6 +24796,494 @@
"integrity": "sha512-cEee/Z+I12mZcFJshKcCqC8tuX5hG3s+d+9nZ3LabqKF1vKdF41B92pJVCBggjAGORAeOzyyDDKrZwIkLffeOQ==",
"dev": true
},
+ "@firebase/analytics": {
+ "version": "0.10.0",
+ "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.0.tgz",
+ "integrity": "sha512-Locv8gAqx0e+GX/0SI3dzmBY5e9kjVDtD+3zCFLJ0tH2hJwuCAiL+5WkHuxKj92rqQj/rvkBUCfA1ewlX2hehg==",
+ "requires": {
+ "@firebase/component": "0.6.4",
+ "@firebase/installations": "0.6.4",
+ "@firebase/logger": "0.4.0",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/analytics-compat": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.6.tgz",
+ "integrity": "sha512-4MqpVLFkGK7NJf/5wPEEP7ePBJatwYpyjgJ+wQHQGHfzaCDgntOnl9rL2vbVGGKCnRqWtZDIWhctB86UWXaX2Q==",
+ "requires": {
+ "@firebase/analytics": "0.10.0",
+ "@firebase/analytics-types": "0.8.0",
+ "@firebase/component": "0.6.4",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/analytics-types": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.8.0.tgz",
+ "integrity": "sha512-iRP+QKI2+oz3UAh4nPEq14CsEjrjD6a5+fuypjScisAh9kXKFvdJOZJDwk7kikLvWVLGEs9+kIUS4LPQV7VZVw=="
+ },
+ "@firebase/app": {
+ "version": "0.9.19",
+ "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.9.19.tgz",
+ "integrity": "sha512-t/SHyZ3xWkR77ZU9VMoobDNFLdDKQ5xqoCAn4o16gTsA1C8sJ6ZOMZ02neMOPxNHuQXVE4tA8ukilnDbnK7uJA==",
+ "requires": {
+ "@firebase/component": "0.6.4",
+ "@firebase/logger": "0.4.0",
+ "@firebase/util": "1.9.3",
+ "idb": "7.1.1",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/app-check": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.8.0.tgz",
+ "integrity": "sha512-dRDnhkcaC2FspMiRK/Vbp+PfsOAEP6ZElGm9iGFJ9fDqHoPs0HOPn7dwpJ51lCFi1+2/7n5pRPGhqF/F03I97g==",
+ "requires": {
+ "@firebase/component": "0.6.4",
+ "@firebase/logger": "0.4.0",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/app-check-compat": {
+ "version": "0.3.7",
+ "resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.3.7.tgz",
+ "integrity": "sha512-cW682AxsyP1G+Z0/P7pO/WT2CzYlNxoNe5QejVarW2o5ZxeWSSPAiVEwpEpQR/bUlUmdeWThYTMvBWaopdBsqw==",
+ "requires": {
+ "@firebase/app-check": "0.8.0",
+ "@firebase/app-check-types": "0.5.0",
+ "@firebase/component": "0.6.4",
+ "@firebase/logger": "0.4.0",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/app-check-interop-types": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.0.tgz",
+ "integrity": "sha512-xAxHPZPIgFXnI+vb4sbBjZcde7ZluzPPaSK7Lx3/nmuVk4TjZvnL8ONnkd4ERQKL8WePQySU+pRcWkh8rDf5Sg=="
+ },
+ "@firebase/app-check-types": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.5.0.tgz",
+ "integrity": "sha512-uwSUj32Mlubybw7tedRzR24RP8M8JUVR3NPiMk3/Z4bCmgEKTlQBwMXrehDAZ2wF+TsBq0SN1c6ema71U/JPyQ=="
+ },
+ "@firebase/app-compat": {
+ "version": "0.2.19",
+ "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.19.tgz",
+ "integrity": "sha512-QkJDqYqjhvs4fTMcRVXQkP9hbo5yfoJXDWkhU4VA5Vzs8Qsp76VPzYbqx5SD5OmBy+bz/Ot1UV8qySPGI4aKuw==",
+ "requires": {
+ "@firebase/app": "0.9.19",
+ "@firebase/component": "0.6.4",
+ "@firebase/logger": "0.4.0",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/app-types": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.0.tgz",
+ "integrity": "sha512-AeweANOIo0Mb8GiYm3xhTEBVCmPwTYAu9Hcd2qSkLuga/6+j9b1Jskl5bpiSQWy9eJ/j5pavxj6eYogmnuzm+Q=="
+ },
+ "@firebase/auth": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.3.0.tgz",
+ "integrity": "sha512-vjK4CHbY9aWdiVOrKi6mpa8z6uxeaf7LB/MZTHuZOiGHMcUoTGB6TeMbRShyqk1uaMrxhhZ5Ar/dR0965E1qyA==",
+ "requires": {
+ "@firebase/component": "0.6.4",
+ "@firebase/logger": "0.4.0",
+ "@firebase/util": "1.9.3",
+ "node-fetch": "2.6.7",
+ "tslib": "^2.1.0"
+ },
+ "dependencies": {
+ "node-fetch": {
+ "version": "2.6.7",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
+ "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
+ "requires": {
+ "whatwg-url": "^5.0.0"
+ }
+ }
+ }
+ },
+ "@firebase/auth-compat": {
+ "version": "0.4.6",
+ "resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.4.6.tgz",
+ "integrity": "sha512-pKp1d4fSf+yoy1EBjTx9ISxlunqhW0vTICk0ByZ3e+Lp6ZIXThfUy4F1hAJlEafD/arM0oepRiAh7LXS1xn/BA==",
+ "requires": {
+ "@firebase/auth": "1.3.0",
+ "@firebase/auth-types": "0.12.0",
+ "@firebase/component": "0.6.4",
+ "@firebase/util": "1.9.3",
+ "node-fetch": "2.6.7",
+ "tslib": "^2.1.0"
+ },
+ "dependencies": {
+ "node-fetch": {
+ "version": "2.6.7",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
+ "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
+ "requires": {
+ "whatwg-url": "^5.0.0"
+ }
+ }
+ }
+ },
+ "@firebase/auth-interop-types": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.1.tgz",
+ "integrity": "sha512-VOaGzKp65MY6P5FI84TfYKBXEPi6LmOCSMMzys6o2BN2LOsqy7pCuZCup7NYnfbk5OkkQKzvIfHOzTm0UDpkyg=="
+ },
+ "@firebase/auth-types": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.12.0.tgz",
+ "integrity": "sha512-pPwaZt+SPOshK8xNoiQlK5XIrS97kFYc3Rc7xmy373QsOJ9MmqXxLaYssP5Kcds4wd2qK//amx/c+A8O2fVeZA==",
+ "requires": {}
+ },
+ "@firebase/component": {
+ "version": "0.6.4",
+ "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.4.tgz",
+ "integrity": "sha512-rLMyrXuO9jcAUCaQXCMjCMUsWrba5fzHlNK24xz5j2W6A/SRmK8mZJ/hn7V0fViLbxC0lPMtrK1eYzk6Fg03jA==",
+ "requires": {
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/database": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.0.1.tgz",
+ "integrity": "sha512-VAhF7gYwunW4Lw/+RQZvW8dlsf2r0YYqV9W0Gi2Mz8+0TGg1mBJWoUtsHfOr8kPJXhcLsC4eP/z3x6L/Fvjk/A==",
+ "requires": {
+ "@firebase/auth-interop-types": "0.2.1",
+ "@firebase/component": "0.6.4",
+ "@firebase/logger": "0.4.0",
+ "@firebase/util": "1.9.3",
+ "faye-websocket": "0.11.4",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/database-compat": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-1.0.1.tgz",
+ "integrity": "sha512-ky82yLIboLxtAIWyW/52a6HLMVTzD2kpZlEilVDok73pNPLjkJYowj8iaIWK5nTy7+6Gxt7d00zfjL6zckGdXQ==",
+ "requires": {
+ "@firebase/component": "0.6.4",
+ "@firebase/database": "1.0.1",
+ "@firebase/database-types": "1.0.0",
+ "@firebase/logger": "0.4.0",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/database-types": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.0.tgz",
+ "integrity": "sha512-SjnXStoE0Q56HcFgNQ+9SsmJc0c8TqGARdI/T44KXy+Ets3r6x/ivhQozT66bMnCEjJRywYoxNurRTMlZF8VNg==",
+ "requires": {
+ "@firebase/app-types": "0.9.0",
+ "@firebase/util": "1.9.3"
+ }
+ },
+ "@firebase/firestore": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.2.0.tgz",
+ "integrity": "sha512-iKZqIdOBJpJUcwY5airLX0W04TLrQSJuActOP1HG5WoIY5oyGTQE4Ml7hl5GW7mBqFieT4ojtUuDXj6MLrn1lA==",
+ "requires": {
+ "@firebase/component": "0.6.4",
+ "@firebase/logger": "0.4.0",
+ "@firebase/util": "1.9.3",
+ "@firebase/webchannel-wrapper": "0.10.3",
+ "@grpc/grpc-js": "~1.9.0",
+ "@grpc/proto-loader": "^0.7.8",
+ "node-fetch": "2.6.7",
+ "tslib": "^2.1.0"
+ },
+ "dependencies": {
+ "node-fetch": {
+ "version": "2.6.7",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
+ "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
+ "requires": {
+ "whatwg-url": "^5.0.0"
+ }
+ }
+ }
+ },
+ "@firebase/firestore-compat": {
+ "version": "0.3.18",
+ "resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.18.tgz",
+ "integrity": "sha512-hkqv4mb1oScKbEtzfcK8Go8c0VpDWmbAvbD6B6XnphLqi27pkXgo9Rp+aSKlD7cBL29VMEekP5bEm9lSVfZpNw==",
+ "requires": {
+ "@firebase/component": "0.6.4",
+ "@firebase/firestore": "4.2.0",
+ "@firebase/firestore-types": "3.0.0",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/firestore-types": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-3.0.0.tgz",
+ "integrity": "sha512-Meg4cIezHo9zLamw0ymFYBD4SMjLb+ZXIbuN7T7ddXN6MGoICmOTq3/ltdCGoDCS2u+H1XJs2u/cYp75jsX9Qw==",
+ "requires": {}
+ },
+ "@firebase/functions": {
+ "version": "0.10.0",
+ "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.10.0.tgz",
+ "integrity": "sha512-2U+fMNxTYhtwSpkkR6WbBcuNMOVaI7MaH3cZ6UAeNfj7AgEwHwMIFLPpC13YNZhno219F0lfxzTAA0N62ndWzA==",
+ "requires": {
+ "@firebase/app-check-interop-types": "0.3.0",
+ "@firebase/auth-interop-types": "0.2.1",
+ "@firebase/component": "0.6.4",
+ "@firebase/messaging-interop-types": "0.2.0",
+ "@firebase/util": "1.9.3",
+ "node-fetch": "2.6.7",
+ "tslib": "^2.1.0"
+ },
+ "dependencies": {
+ "node-fetch": {
+ "version": "2.6.7",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
+ "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
+ "requires": {
+ "whatwg-url": "^5.0.0"
+ }
+ }
+ }
+ },
+ "@firebase/functions-compat": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.3.5.tgz",
+ "integrity": "sha512-uD4jwgwVqdWf6uc3NRKF8cSZ0JwGqSlyhPgackyUPe+GAtnERpS4+Vr66g0b3Gge0ezG4iyHo/EXW/Hjx7QhHw==",
+ "requires": {
+ "@firebase/component": "0.6.4",
+ "@firebase/functions": "0.10.0",
+ "@firebase/functions-types": "0.6.0",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/functions-types": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.6.0.tgz",
+ "integrity": "sha512-hfEw5VJtgWXIRf92ImLkgENqpL6IWpYaXVYiRkFY1jJ9+6tIhWM7IzzwbevwIIud/jaxKVdRzD7QBWfPmkwCYw=="
+ },
+ "@firebase/installations": {
+ "version": "0.6.4",
+ "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.4.tgz",
+ "integrity": "sha512-u5y88rtsp7NYkCHC3ElbFBrPtieUybZluXyzl7+4BsIz4sqb4vSAuwHEUgCgCeaQhvsnxDEU6icly8U9zsJigA==",
+ "requires": {
+ "@firebase/component": "0.6.4",
+ "@firebase/util": "1.9.3",
+ "idb": "7.0.1",
+ "tslib": "^2.1.0"
+ },
+ "dependencies": {
+ "idb": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/idb/-/idb-7.0.1.tgz",
+ "integrity": "sha512-UUxlE7vGWK5RfB/fDwEGgRf84DY/ieqNha6msMV99UsEMQhJ1RwbCd8AYBj3QMgnE3VZnfQvm4oKVCJTYlqIgg=="
+ }
+ }
+ },
+ "@firebase/installations-compat": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.4.tgz",
+ "integrity": "sha512-LI9dYjp0aT9Njkn9U4JRrDqQ6KXeAmFbRC0E7jI7+hxl5YmRWysq5qgQl22hcWpTk+cm3es66d/apoDU/A9n6Q==",
+ "requires": {
+ "@firebase/component": "0.6.4",
+ "@firebase/installations": "0.6.4",
+ "@firebase/installations-types": "0.5.0",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/installations-types": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.5.0.tgz",
+ "integrity": "sha512-9DP+RGfzoI2jH7gY4SlzqvZ+hr7gYzPODrbzVD82Y12kScZ6ZpRg/i3j6rleto8vTFC8n6Len4560FnV1w2IRg==",
+ "requires": {}
+ },
+ "@firebase/logger": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.0.tgz",
+ "integrity": "sha512-eRKSeykumZ5+cJPdxxJRgAC3G5NknY2GwEbKfymdnXtnT0Ucm4pspfR6GT4MUQEDuJwRVbVcSx85kgJulMoFFA==",
+ "requires": {
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/messaging": {
+ "version": "0.12.4",
+ "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.4.tgz",
+ "integrity": "sha512-6JLZct6zUaex4g7HI3QbzeUrg9xcnmDAPTWpkoMpd/GoSVWH98zDoWXMGrcvHeCAIsLpFMe4MPoZkJbrPhaASw==",
+ "requires": {
+ "@firebase/component": "0.6.4",
+ "@firebase/installations": "0.6.4",
+ "@firebase/messaging-interop-types": "0.2.0",
+ "@firebase/util": "1.9.3",
+ "idb": "7.0.1",
+ "tslib": "^2.1.0"
+ },
+ "dependencies": {
+ "idb": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/idb/-/idb-7.0.1.tgz",
+ "integrity": "sha512-UUxlE7vGWK5RfB/fDwEGgRf84DY/ieqNha6msMV99UsEMQhJ1RwbCd8AYBj3QMgnE3VZnfQvm4oKVCJTYlqIgg=="
+ }
+ }
+ },
+ "@firebase/messaging-compat": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.4.tgz",
+ "integrity": "sha512-lyFjeUhIsPRYDPNIkYX1LcZMpoVbBWXX4rPl7c/rqc7G+EUea7IEtSt4MxTvh6fDfPuzLn7+FZADfscC+tNMfg==",
+ "requires": {
+ "@firebase/component": "0.6.4",
+ "@firebase/messaging": "0.12.4",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/messaging-interop-types": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.0.tgz",
+ "integrity": "sha512-ujA8dcRuVeBixGR9CtegfpU4YmZf3Lt7QYkcj693FFannwNuZgfAYaTmbJ40dtjB81SAu6tbFPL9YLNT15KmOQ=="
+ },
+ "@firebase/performance": {
+ "version": "0.6.4",
+ "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.6.4.tgz",
+ "integrity": "sha512-HfTn/bd8mfy/61vEqaBelNiNnvAbUtME2S25A67Nb34zVuCSCRIX4SseXY6zBnOFj3oLisaEqhVcJmVPAej67g==",
+ "requires": {
+ "@firebase/component": "0.6.4",
+ "@firebase/installations": "0.6.4",
+ "@firebase/logger": "0.4.0",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/performance-compat": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.4.tgz",
+ "integrity": "sha512-nnHUb8uP9G8islzcld/k6Bg5RhX62VpbAb/Anj7IXs/hp32Eb2LqFPZK4sy3pKkBUO5wcrlRWQa6wKOxqlUqsg==",
+ "requires": {
+ "@firebase/component": "0.6.4",
+ "@firebase/logger": "0.4.0",
+ "@firebase/performance": "0.6.4",
+ "@firebase/performance-types": "0.2.0",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/performance-types": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.2.0.tgz",
+ "integrity": "sha512-kYrbr8e/CYr1KLrLYZZt2noNnf+pRwDq2KK9Au9jHrBMnb0/C9X9yWSXmZkFt4UIdsQknBq8uBB7fsybZdOBTA=="
+ },
+ "@firebase/remote-config": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.4.4.tgz",
+ "integrity": "sha512-x1ioTHGX8ZwDSTOVp8PBLv2/wfwKzb4pxi0gFezS5GCJwbLlloUH4YYZHHS83IPxnua8b6l0IXUaWd0RgbWwzQ==",
+ "requires": {
+ "@firebase/component": "0.6.4",
+ "@firebase/installations": "0.6.4",
+ "@firebase/logger": "0.4.0",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/remote-config-compat": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.4.tgz",
+ "integrity": "sha512-FKiki53jZirrDFkBHglB3C07j5wBpitAaj8kLME6g8Mx+aq7u9P7qfmuSRytiOItADhWUj7O1JIv7n9q87SuwA==",
+ "requires": {
+ "@firebase/component": "0.6.4",
+ "@firebase/logger": "0.4.0",
+ "@firebase/remote-config": "0.4.4",
+ "@firebase/remote-config-types": "0.3.0",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/remote-config-types": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.3.0.tgz",
+ "integrity": "sha512-RtEH4vdcbXZuZWRZbIRmQVBNsE7VDQpet2qFvq6vwKLBIQRQR5Kh58M4ok3A3US8Sr3rubYnaGqZSurCwI8uMA=="
+ },
+ "@firebase/storage": {
+ "version": "0.11.2",
+ "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.11.2.tgz",
+ "integrity": "sha512-CtvoFaBI4hGXlXbaCHf8humajkbXhs39Nbh6MbNxtwJiCqxPy9iH3D3CCfXAvP0QvAAwmJUTK3+z9a++Kc4nkA==",
+ "requires": {
+ "@firebase/component": "0.6.4",
+ "@firebase/util": "1.9.3",
+ "node-fetch": "2.6.7",
+ "tslib": "^2.1.0"
+ },
+ "dependencies": {
+ "node-fetch": {
+ "version": "2.6.7",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
+ "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
+ "requires": {
+ "whatwg-url": "^5.0.0"
+ }
+ }
+ }
+ },
+ "@firebase/storage-compat": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.3.2.tgz",
+ "integrity": "sha512-wvsXlLa9DVOMQJckbDNhXKKxRNNewyUhhbXev3t8kSgoCotd1v3MmqhKKz93ePhDnhHnDs7bYHy+Qa8dRY6BXw==",
+ "requires": {
+ "@firebase/component": "0.6.4",
+ "@firebase/storage": "0.11.2",
+ "@firebase/storage-types": "0.8.0",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/storage-types": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.8.0.tgz",
+ "integrity": "sha512-isRHcGrTs9kITJC0AVehHfpraWFui39MPaU7Eo8QfWlqW7YPymBmRgjDrlOgFdURh6Cdeg07zmkLP5tzTKRSpg==",
+ "requires": {}
+ },
+ "@firebase/util": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz",
+ "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==",
+ "requires": {
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/webchannel-wrapper": {
+ "version": "0.10.3",
+ "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.10.3.tgz",
+ "integrity": "sha512-+ZplYUN3HOpgCfgInqgdDAbkGGVzES1cs32JJpeqoh87SkRobGXElJx+1GZSaDqzFL+bYiX18qEcBK76mYs8uA=="
+ },
+ "@grpc/grpc-js": {
+ "version": "1.9.5",
+ "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.5.tgz",
+ "integrity": "sha512-iouYNlPxRAwZ2XboDT+OfRKHuaKHiqjB5VFYZ0NFrHkbEF+AV3muIUY9olQsp8uxU4VvRCMiRk9ftzFDGb61aw==",
+ "requires": {
+ "@grpc/proto-loader": "^0.7.8",
+ "@types/node": ">=12.12.47"
+ }
+ },
+ "@grpc/proto-loader": {
+ "version": "0.7.10",
+ "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.10.tgz",
+ "integrity": "sha512-CAqDfoaQ8ykFd9zqBDn4k6iWT9loLAlc2ETmDFS9JCD70gDcnA4L3AFEo2iV7KyAtAAHFW9ftq1Fz+Vsgq80RQ==",
+ "requires": {
+ "lodash.camelcase": "^4.3.0",
+ "long": "^5.0.0",
+ "protobufjs": "^7.2.4",
+ "yargs": "^17.7.2"
+ }
+ },
"@humanwhocodes/config-array": {
"version": "0.11.10",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz",
@@ -24535,6 +25743,60 @@
"integrity": "sha512-C16M+IYz0rgRhWZdCmK+h58JMv8vijAA61gmz2rspCSwKwzBebpdcsiUmwrtJRdphuY30i6BSLEOP8ppbNLyLg==",
"dev": true
},
+ "@protobufjs/aspromise": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
+ "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ=="
+ },
+ "@protobufjs/base64": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
+ "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg=="
+ },
+ "@protobufjs/codegen": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz",
+ "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg=="
+ },
+ "@protobufjs/eventemitter": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
+ "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q=="
+ },
+ "@protobufjs/fetch": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz",
+ "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==",
+ "requires": {
+ "@protobufjs/aspromise": "^1.1.1",
+ "@protobufjs/inquire": "^1.1.0"
+ }
+ },
+ "@protobufjs/float": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
+ "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ=="
+ },
+ "@protobufjs/inquire": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz",
+ "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q=="
+ },
+ "@protobufjs/path": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
+ "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA=="
+ },
+ "@protobufjs/pool": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
+ "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw=="
+ },
+ "@protobufjs/utf8": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
+ "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="
+ },
"@remix-run/router": {
"version": "1.7.1",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.7.1.tgz",
@@ -27375,8 +28637,7 @@
"@types/node": {
"version": "20.3.3",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.3.tgz",
- "integrity": "sha512-wheIYdr4NYML61AjC8MKj/2jrR/kDQri/CIpVoZwldwhnIrD/j9jIU5bJ8yBKuB2VhpFV7Ab6G2XkBjv9r9Zzw==",
- "dev": true
+ "integrity": "sha512-wheIYdr4NYML61AjC8MKj/2jrR/kDQri/CIpVoZwldwhnIrD/j9jIU5bJ8yBKuB2VhpFV7Ab6G2XkBjv9r9Zzw=="
},
"@types/node-fetch": {
"version": "2.6.4",
@@ -28205,8 +29466,7 @@
"ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
},
"ansi-styles": {
"version": "3.2.1",
@@ -29169,7 +30429,6 @@
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
"integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
- "dev": true,
"requires": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.1",
@@ -30397,8 +31656,7 @@
"emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "dev": true
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"emojis-list": {
"version": "3.0.0",
@@ -31386,7 +32644,6 @@
"version": "0.11.4",
"resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz",
"integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==",
- "dev": true,
"requires": {
"websocket-driver": ">=0.5.1"
}
@@ -31528,6 +32785,39 @@
"path-exists": "^4.0.0"
}
},
+ "firebase": {
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/firebase/-/firebase-10.4.0.tgz",
+ "integrity": "sha512-3Z8WsNwA7kbcKGZ+nrTZ/ES518pk0K440ZJYD8nUNKN5hV6ll+unhUw30t1msedN6yIFjhsC/9OwT4Z0ohwO2w==",
+ "requires": {
+ "@firebase/analytics": "0.10.0",
+ "@firebase/analytics-compat": "0.2.6",
+ "@firebase/app": "0.9.19",
+ "@firebase/app-check": "0.8.0",
+ "@firebase/app-check-compat": "0.3.7",
+ "@firebase/app-compat": "0.2.19",
+ "@firebase/app-types": "0.9.0",
+ "@firebase/auth": "1.3.0",
+ "@firebase/auth-compat": "0.4.6",
+ "@firebase/database": "1.0.1",
+ "@firebase/database-compat": "1.0.1",
+ "@firebase/firestore": "4.2.0",
+ "@firebase/firestore-compat": "0.3.18",
+ "@firebase/functions": "0.10.0",
+ "@firebase/functions-compat": "0.3.5",
+ "@firebase/installations": "0.6.4",
+ "@firebase/installations-compat": "0.2.4",
+ "@firebase/messaging": "0.12.4",
+ "@firebase/messaging-compat": "0.2.4",
+ "@firebase/performance": "0.6.4",
+ "@firebase/performance-compat": "0.2.4",
+ "@firebase/remote-config": "0.4.4",
+ "@firebase/remote-config-compat": "0.2.4",
+ "@firebase/storage": "0.11.2",
+ "@firebase/storage-compat": "0.3.2",
+ "@firebase/util": "1.9.3"
+ }
+ },
"flat-cache": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
@@ -31818,8 +33108,7 @@
"get-caller-file": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
- "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
- "dev": true
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
},
"get-intrinsic": {
"version": "1.2.1",
@@ -32311,8 +33600,7 @@
"http-parser-js": {
"version": "0.5.8",
"resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz",
- "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==",
- "dev": true
+ "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q=="
},
"http-proxy": {
"version": "1.18.1",
@@ -32398,6 +33686,11 @@
"dev": true,
"requires": {}
},
+ "idb": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz",
+ "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ=="
+ },
"ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
@@ -32687,8 +33980,7 @@
"is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "dev": true
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
},
"is-generator-function": {
"version": "1.0.10",
@@ -33761,6 +35053,11 @@
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
},
+ "lodash.camelcase": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
+ "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA=="
+ },
"lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
@@ -33918,6 +35215,11 @@
}
}
},
+ "long": {
+ "version": "5.2.3",
+ "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz",
+ "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q=="
+ },
"loose-envify": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
@@ -35244,6 +36546,25 @@
"react-is": "^16.13.1"
}
},
+ "protobufjs": {
+ "version": "7.2.5",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.5.tgz",
+ "integrity": "sha512-gGXRSXvxQ7UiPgfw8gevrfRWcTlSbOFg+p/N+JVJEK5VhueL2miT6qTymqAmjr1Q5WbOCyJbyrk6JfWKwlFn6A==",
+ "requires": {
+ "@protobufjs/aspromise": "^1.1.2",
+ "@protobufjs/base64": "^1.1.2",
+ "@protobufjs/codegen": "^2.0.4",
+ "@protobufjs/eventemitter": "^1.1.0",
+ "@protobufjs/fetch": "^1.1.0",
+ "@protobufjs/float": "^1.0.2",
+ "@protobufjs/inquire": "^1.1.0",
+ "@protobufjs/path": "^1.1.2",
+ "@protobufjs/pool": "^1.1.0",
+ "@protobufjs/utf8": "^1.1.0",
+ "@types/node": ">=13.7.0",
+ "long": "^5.0.0"
+ }
+ },
"proxy-addr": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
@@ -35837,8 +37158,7 @@
"require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
- "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
- "dev": true
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="
},
"require-from-string": {
"version": "2.0.2",
@@ -35941,8 +37261,7 @@
"safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
- "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
- "dev": true
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
},
"safe-regex-test": {
"version": "1.0.0",
@@ -36544,7 +37863,6 @@
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "dev": true,
"requires": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
@@ -36604,7 +37922,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
"requires": {
"ansi-regex": "^5.0.1"
}
@@ -37286,8 +38603,7 @@
"tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
- "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
- "dev": true
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
},
"trim-newlines": {
"version": "4.1.1",
@@ -37861,8 +39177,7 @@
"webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
- "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
- "dev": true
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
},
"webpack": {
"version": "5.88.1",
@@ -38155,7 +39470,6 @@
"version": "0.7.4",
"resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz",
"integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==",
- "dev": true,
"requires": {
"http-parser-js": ">=0.5.1",
"safe-buffer": ">=5.1.0",
@@ -38165,14 +39479,12 @@
"websocket-extensions": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz",
- "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==",
- "dev": true
+ "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg=="
},
"whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
- "dev": true,
"requires": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
@@ -38251,7 +39563,6 @@
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
- "dev": true,
"requires": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
@@ -38262,7 +39573,6 @@
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dev": true,
"requires": {
"color-convert": "^2.0.1"
}
@@ -38271,7 +39581,6 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "dev": true,
"requires": {
"color-name": "~1.1.4"
}
@@ -38279,8 +39588,7 @@
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "dev": true
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
}
}
},
@@ -38315,8 +39623,7 @@
"y18n": {
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
- "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
- "dev": true
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="
},
"yallist": {
"version": "3.1.1",
@@ -38333,7 +39640,6 @@
"version": "17.7.2",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
"integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
- "dev": true,
"requires": {
"cliui": "^8.0.1",
"escalade": "^3.1.1",
@@ -38347,8 +39653,7 @@
"yargs-parser": {
"version": "21.1.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
- "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
- "dev": true
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="
},
"yauzl": {
"version": "2.10.0",
diff --git a/frontend/package.json b/frontend/package.json
index 7f335a959..46181db11 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -19,6 +19,7 @@
"dependencies": {
"@pium/stack-component": "^1.0.0",
"@tanstack/react-query": "^5.0.0-beta.20",
+ "firebase": "^10.4.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.14.1",
diff --git a/frontend/public/assets/android-icon-144x144.png b/frontend/public/assets/android-icon-144x144.png
index 349129863..183d8b64e 100644
Binary files a/frontend/public/assets/android-icon-144x144.png and b/frontend/public/assets/android-icon-144x144.png differ
diff --git a/frontend/public/assets/android-icon-192x192.png b/frontend/public/assets/android-icon-192x192.png
index 0b6243288..b6b320770 100644
Binary files a/frontend/public/assets/android-icon-192x192.png and b/frontend/public/assets/android-icon-192x192.png differ
diff --git a/frontend/public/assets/android-icon-48x48.png b/frontend/public/assets/android-icon-48x48.png
index bac6abfbe..20af524da 100644
Binary files a/frontend/public/assets/android-icon-48x48.png and b/frontend/public/assets/android-icon-48x48.png differ
diff --git a/frontend/public/assets/android-icon-512x512.png b/frontend/public/assets/android-icon-512x512.png
index a68af4884..41d702e48 100644
Binary files a/frontend/public/assets/android-icon-512x512.png and b/frontend/public/assets/android-icon-512x512.png differ
diff --git a/frontend/public/assets/android-icon-72x72.png b/frontend/public/assets/android-icon-72x72.png
index d7f4cef5f..00dd12c90 100644
Binary files a/frontend/public/assets/android-icon-72x72.png and b/frontend/public/assets/android-icon-72x72.png differ
diff --git a/frontend/public/assets/android-icon-96x96.png b/frontend/public/assets/android-icon-96x96.png
index 1de52cea2..ad68d9707 100644
Binary files a/frontend/public/assets/android-icon-96x96.png and b/frontend/public/assets/android-icon-96x96.png differ
diff --git a/frontend/public/assets/apple-icon-114x114.png b/frontend/public/assets/apple-icon-114x114.png
index e796761dc..5bcd7a74f 100644
Binary files a/frontend/public/assets/apple-icon-114x114.png and b/frontend/public/assets/apple-icon-114x114.png differ
diff --git a/frontend/public/assets/apple-icon-120x120.png b/frontend/public/assets/apple-icon-120x120.png
index ab14547eb..340055e5e 100644
Binary files a/frontend/public/assets/apple-icon-120x120.png and b/frontend/public/assets/apple-icon-120x120.png differ
diff --git a/frontend/public/assets/apple-icon-144x144.png b/frontend/public/assets/apple-icon-144x144.png
index 349129863..cc59fdb26 100644
Binary files a/frontend/public/assets/apple-icon-144x144.png and b/frontend/public/assets/apple-icon-144x144.png differ
diff --git a/frontend/public/assets/apple-icon-152x152.png b/frontend/public/assets/apple-icon-152x152.png
index 7e3b1bc19..c68c36b30 100644
Binary files a/frontend/public/assets/apple-icon-152x152.png and b/frontend/public/assets/apple-icon-152x152.png differ
diff --git a/frontend/public/assets/apple-icon-180x180.png b/frontend/public/assets/apple-icon-180x180.png
index 5461e7aa3..414f59bca 100644
Binary files a/frontend/public/assets/apple-icon-180x180.png and b/frontend/public/assets/apple-icon-180x180.png differ
diff --git a/frontend/public/assets/apple-icon-192x192.png b/frontend/public/assets/apple-icon-192x192.png
deleted file mode 100644
index 0b6243288..000000000
Binary files a/frontend/public/assets/apple-icon-192x192.png and /dev/null differ
diff --git a/frontend/public/assets/apple-icon-512x512.png b/frontend/public/assets/apple-icon-512x512.png
deleted file mode 100644
index a68af4884..000000000
Binary files a/frontend/public/assets/apple-icon-512x512.png and /dev/null differ
diff --git a/frontend/public/assets/apple-icon-57x57.png b/frontend/public/assets/apple-icon-57x57.png
index 19625fee2..88bbf3f0f 100644
Binary files a/frontend/public/assets/apple-icon-57x57.png and b/frontend/public/assets/apple-icon-57x57.png differ
diff --git a/frontend/public/assets/apple-icon-60x60.png b/frontend/public/assets/apple-icon-60x60.png
index 56a26f6b9..14944e51a 100644
Binary files a/frontend/public/assets/apple-icon-60x60.png and b/frontend/public/assets/apple-icon-60x60.png differ
diff --git a/frontend/public/assets/apple-icon-72x72.png b/frontend/public/assets/apple-icon-72x72.png
index d7f4cef5f..9e1c0a71b 100644
Binary files a/frontend/public/assets/apple-icon-72x72.png and b/frontend/public/assets/apple-icon-72x72.png differ
diff --git a/frontend/public/assets/apple-icon-76x76.png b/frontend/public/assets/apple-icon-76x76.png
index 8b450e4da..bb613fb19 100644
Binary files a/frontend/public/assets/apple-icon-76x76.png and b/frontend/public/assets/apple-icon-76x76.png differ
diff --git a/frontend/public/assets/apple-icon-precomposed.png b/frontend/public/assets/apple-icon-precomposed.png
index acd529094..6a36dd0ff 100644
Binary files a/frontend/public/assets/apple-icon-precomposed.png and b/frontend/public/assets/apple-icon-precomposed.png differ
diff --git a/frontend/public/assets/apple-icon.png b/frontend/public/assets/apple-icon.png
index 0b6243288..6a36dd0ff 100644
Binary files a/frontend/public/assets/apple-icon.png and b/frontend/public/assets/apple-icon.png differ
diff --git a/frontend/public/assets/favicon-16x16.png b/frontend/public/assets/favicon-16x16.png
index 960c91a62..4b31ce258 100644
Binary files a/frontend/public/assets/favicon-16x16.png and b/frontend/public/assets/favicon-16x16.png differ
diff --git a/frontend/public/assets/favicon-32x32.png b/frontend/public/assets/favicon-32x32.png
index d293e10fc..e839645ea 100644
Binary files a/frontend/public/assets/favicon-32x32.png and b/frontend/public/assets/favicon-32x32.png differ
diff --git a/frontend/public/assets/favicon-96x96.png b/frontend/public/assets/favicon-96x96.png
index a897a1650..2eec46cc2 100644
Binary files a/frontend/public/assets/favicon-96x96.png and b/frontend/public/assets/favicon-96x96.png differ
diff --git a/frontend/public/assets/favicon.ico b/frontend/public/assets/favicon.ico
index db4f185a0..bf5a2e213 100644
Binary files a/frontend/public/assets/favicon.ico and b/frontend/public/assets/favicon.ico differ
diff --git a/frontend/public/assets/manifest.json b/frontend/public/assets/manifest.json
index b3659bb12..45ca8b0cb 100644
--- a/frontend/public/assets/manifest.json
+++ b/frontend/public/assets/manifest.json
@@ -35,7 +35,7 @@
"sizes": "192x192",
"type": "image/png",
"density": "4.0",
- "purpose": "any"
+ "purpose": "maskable"
},
{
"src": "/assets/android-icon-512x512.png",
@@ -56,5 +56,5 @@
"orientation": "portrait",
"scope": "/",
"categories": ["lifestyle", "plant", "indoor-garden"],
- "display_override": ["window-controls-overlay", "standalone", "browser"]
+ "display_override": ["window-controls-overlay"]
}
diff --git a/frontend/public/assets/ms-icon-144x144.png b/frontend/public/assets/ms-icon-144x144.png
index f668cbc0b..cc59fdb26 100644
Binary files a/frontend/public/assets/ms-icon-144x144.png and b/frontend/public/assets/ms-icon-144x144.png differ
diff --git a/frontend/public/assets/ms-icon-150x150.png b/frontend/public/assets/ms-icon-150x150.png
index 702c92369..a0c9c0b3c 100644
Binary files a/frontend/public/assets/ms-icon-150x150.png and b/frontend/public/assets/ms-icon-150x150.png differ
diff --git a/frontend/public/assets/ms-icon-310x310.png b/frontend/public/assets/ms-icon-310x310.png
index a4dd775f6..6a07a1228 100644
Binary files a/frontend/public/assets/ms-icon-310x310.png and b/frontend/public/assets/ms-icon-310x310.png differ
diff --git a/frontend/public/assets/ms-icon-70x70.png b/frontend/public/assets/ms-icon-70x70.png
index fc6af9fe4..1fe2f89c3 100644
Binary files a/frontend/public/assets/ms-icon-70x70.png and b/frontend/public/assets/ms-icon-70x70.png differ
diff --git a/frontend/public/devLocalServiceWorker.js b/frontend/public/devLocalServiceWorker.js
new file mode 100644
index 000000000..5e4980e7d
--- /dev/null
+++ b/frontend/public/devLocalServiceWorker.js
@@ -0,0 +1,3 @@
+/* eslint-disable no-undef */
+importScripts('/firebase-messaging-sw.js');
+importScripts('/mockServiceWorker.js');
diff --git a/frontend/public/firebase-messaging-sw.js b/frontend/public/firebase-messaging-sw.js
new file mode 100644
index 000000000..b876acfb0
--- /dev/null
+++ b/frontend/public/firebase-messaging-sw.js
@@ -0,0 +1,117 @@
+/* eslint-disable no-undef */
+// Give the service worker access to Firebase Messaging.
+// Note that you can only use Firebase Messaging here. Other Firebase libraries
+// are not available in the service worker.
+importScripts('https://www.gstatic.com/firebasejs/8.10.1/firebase-app.js');
+importScripts('https://www.gstatic.com/firebasejs/8.10.1/firebase-messaging.js');
+
+// Initialize the Firebase app in the service worker by passing in
+// your app's Firebase config object.
+// https://firebase.google.com/docs/web/setup#config-object
+firebase.initializeApp({
+ apiKey: 'AIzaSyCNVyJ1qLPvMiuZDK97O-rmB3mz48UqC1g',
+ authDomain: 'pium-7445f.firebaseapp.com',
+ databaseURL: 'https://pium-7445f.firebaseio.com',
+ projectId: 'pium-7445f',
+ storageBucket: 'pium-7445f.appspot.com',
+ messagingSenderId: '14284052337',
+ appId: '1:14284052337:web:4ccb34224d907e73fa48d0',
+ measurementId: 'G-Z5F62MDJ8N',
+});
+
+// Retrieve an instance of Firebase Messaging so that it can handle background
+// messages.
+const messaging = firebase.messaging();
+
+const version = 1;
+const assetCacheName = `assets-${version}`;
+
+/**
+ * cache 설정
+ * TODO: 처음 파일들을 캐싱하는 것인데 파일 명이 달라져서 매번 갈아끼워 줘야 하는 문제가 있는것 같습니다.
+ * 근데, 버저닝 생각하면 괜찮을지도?
+ *
+ * 파일명이 firebase-messaging-sw인 이유는, 해당 파일명으로 serviceWorker를 하지 않으면 firebase에서 인식이 되지 않더라구여;;
+ *
+ * https://web.dev/service-worker-mindset/ 참조
+ * https://web.dev/learn/pwa/caching/
+ */
+
+self.addEventListener('install', (event) => {
+ event.waitUntil(
+ caches.open(assetCacheName).then((cache) => {
+ // 캐시로 저장할 파일을 지정. 어떤 파일을 넣을지는 차후 얘기해 보며 좋을 듯.
+ cache.addAll([
+ '/main.43e3611a6c9133f38206.bundle.js',
+ '/vendors-node_modules_react-dom_client_js-node_modules_react-router-dom_dist_index_js-node_mod-cccd04.261f3e9fe64cb376e09d.bundle.js',
+ '/assets/logo.webp',
+ '/index.html',
+ '/',
+ ]);
+ })
+ );
+
+ // 제어중인 서비스 워커가 존재해도 대기 상태 건너 뜀
+ self.skipWaiting();
+});
+
+// 기존에 있던 cache 삭제
+self.addEventListener('activate', (event) => {
+ event.waitUntil(
+ caches.keys().then((cacheNames) => {
+ return Promise.all(
+ cacheNames.map((cacheName) => {
+ if (cacheName !== assetCacheName) {
+ return caches.delete(cacheName);
+ }
+ })
+ );
+ })
+ );
+
+ // 활성화 즉시 클라이언트를 제어한다.(새로고침 불필요)
+ self.clients.claim();
+});
+
+// 오프라인 상태라면, 캐시에 저장되어 있는 파일들 fetch로 받아옴
+self.addEventListener('fetch', (event) => {
+ if (!navigator.onLine) {
+ event.respondWith(caches.match(event.request).then((result) => result && result));
+ }
+});
+
+/**
+ * self.addEventListener('push'.)를 하지 않아도 되는 이유는 messaging이라는 메서드 안에 이미 선언이 되어 있기 때문
+ * https://github.dev/firebase/firebase-js-sdk
+ *
+ *
+ */
+
+// TODO: 사용자가 forward ground인 경우에 알림을 받을 수 있도록 설정하기.
+
+messaging.onBackgroundMessage((payload) => {
+ const {
+ notification: { title, body },
+ } = payload;
+
+ // Customize notification here
+ const notificationTitle = title;
+
+ const notificationOptions = {
+ body: body,
+ icon: './assets/favicon-32x32.png',
+ badge: './assets/favicon-16x16.png',
+ data: '/reminder',
+ tag: 'reminder-alert',
+ vibrate: [200], // 짝수 인덱스는 진동 시간, 홀수 인덱스는 휴식 시간
+ };
+
+ self.registration.showNotification(notificationTitle, notificationOptions);
+});
+
+self.addEventListener('notificationclick', (event) => {
+ event.notification.close();
+ const movePath = self.location.origin + event.notification.data; // 알림 클릭시에 리마인더로 이동 가능
+
+ event.waitUntil(self.clients.openWindow(movePath));
+});
diff --git a/frontend/public/seo/sitemap.xml b/frontend/public/seo/sitemap.xml
index 1855bea6c..14b75d8ab 100644
--- a/frontend/public/seo/sitemap.xml
+++ b/frontend/public/seo/sitemap.xml
@@ -6,31 +6,31 @@
>
https://pium.life/
- 2023-10-01T11:26:30.665Z
+ 2023-10-12T00:52:27.934Z
https://pium.life/login
- 2023-10-01T11:26:30.665Z
+ 2023-10-12T00:52:27.934Z
https://pium.life/garden
- 2023-10-01T11:26:30.665Z
+ 2023-10-12T00:52:27.934Z
https://pium.life/dict
- 2023-10-01T11:26:30.665Z
+ 2023-10-12T00:52:27.934Z
https://pium.life/dict/:id
- 2023-10-01T11:26:30.665Z
+ 2023-10-12T00:52:27.934Z
https://pium.life/dict/new-plant-request
- 2023-10-01T11:26:30.665Z
+ 2023-10-12T00:52:27.934Z
diff --git a/frontend/public/serviceWorker.js b/frontend/public/serviceWorker.js
deleted file mode 100644
index 84a866f60..000000000
--- a/frontend/public/serviceWorker.js
+++ /dev/null
@@ -1,53 +0,0 @@
-const version = 1;
-const assetCacheName = `assets-${version}`;
-
-/**
- * cache 설정
- * TODO: 처음 파일들을 캐싱하는 것인데 파일 명이 달라져서 매번 갈아끼워 줘야 하는 문제가 있는것 같습니다.
- * 근데, 버저닝 생각하면 괜찮을지도?
- * https://web.dev/service-worker-mindset/ 참조
- * https://web.dev/learn/pwa/caching/
- */
-
-self.addEventListener('install', (event) => {
- event.waitUntil(
- caches.open(assetCacheName).then((cache) => {
- // 캐시로 저장할 파일을 지정. 어떤 파일을 넣을지는 차후 얘기해 보며 좋을 듯.
- cache.addAll([
- '/main.43e3611a6c9133f38206.bundle.js',
- '/vendors-node_modules_react-dom_client_js-node_modules_react-router-dom_dist_index_js-node_mod-cccd04.261f3e9fe64cb376e09d.bundle.js',
- '/assets/logo.webp',
- '/index.html',
- '/',
- ]);
- })
- );
-
- // 제어중인 서비스 워커가 존재해도 대기 상태 건너 뜀
- self.skipWaiting();
-});
-
-// 기존에 있던 cache 삭제
-self.addEventListener('activate', (event) => {
- event.waitUntil(
- caches.keys().then((cacheNames) => {
- return Promise.all(
- cacheNames.map((cacheName) => {
- if (cacheName !== assetCacheName) {
- return caches.delete(cacheName);
- }
- })
- );
- })
- );
-
- // 활성화 즉시 클라이언트를 제어한다.(새로고침 불필요)
- self.clients.claim();
-});
-
-// 오프라인 상태라면, 캐시에 저장되어 있는 파일들 fetch로 받아옴
-self.addEventListener('fetch', (event) => {
- if (!navigator.onLine) {
- event.respondWith(caches.match(event.request).then((result) => result && result));
- }
-});
diff --git a/frontend/src/apis/webPush.ts b/frontend/src/apis/webPush.ts
new file mode 100644
index 000000000..dea4f487a
--- /dev/null
+++ b/frontend/src/apis/webPush.ts
@@ -0,0 +1,40 @@
+import { BASE_URL } from 'constants/index';
+
+export const SUBSCRIBE_URL = `${BASE_URL}/members/notification`;
+
+const headers = {
+ 'Content-Type': 'application/json',
+};
+
+const subscribe = (token: string) => {
+ return fetch(SUBSCRIBE_URL, {
+ method: 'POST',
+ headers,
+ credentials: 'include',
+ body: JSON.stringify({ token }),
+ });
+};
+
+const unSubscribe = () => {
+ return fetch(SUBSCRIBE_URL, {
+ method: 'DELETE',
+ credentials: 'include',
+ headers,
+ });
+};
+
+const currentSubscribe = () => {
+ return fetch(SUBSCRIBE_URL, {
+ method: 'GET',
+ credentials: 'include',
+ headers,
+ });
+};
+
+const WebPushAPI = {
+ subscribe,
+ unSubscribe,
+ currentSubscribe,
+};
+
+export default WebPushAPI;
diff --git a/frontend/src/components/@common/InstallPrompt/InstallPrompt.style.ts b/frontend/src/components/@common/InstallPrompt/InstallPrompt.style.ts
index 56b76dae6..323a07b85 100644
--- a/frontend/src/components/@common/InstallPrompt/InstallPrompt.style.ts
+++ b/frontend/src/components/@common/InstallPrompt/InstallPrompt.style.ts
@@ -13,9 +13,10 @@ const slideDown = keyframes`
export const Wrapper = styled.div`
position: absolute;
+ z-index: ${({ theme }) => theme.zIndex.popover};
top: 0;
- display: none;
+ display: flex;
flex-direction: column;
justify-content: space-evenly;
diff --git a/frontend/src/components/@common/InstallPrompt/index.tsx b/frontend/src/components/@common/InstallPrompt/index.tsx
index 93aecc8d9..9ba93885b 100644
--- a/frontend/src/components/@common/InstallPrompt/index.tsx
+++ b/frontend/src/components/@common/InstallPrompt/index.tsx
@@ -11,40 +11,44 @@ import theme from 'style/theme.style';
import SvgFill from '../SvgIcons/SvgFill';
const InstallPrompt = () => {
- const { installApp, ignoreInstallApp, installAppRef } = useInstallApp();
+ const { installApp, ignoreInstallApp, showPrompt, closePrompt } = useInstallApp();
const isIos = /iPhone|iPod|iPad/i.test(navigator.userAgent);
return (
-
-
-
-
- 바로가기를 추가하시면 앱처럼 사용이 가능합니다. 추가하시겠습니까?
-
-
- {isIos ? (
-
- 하단 탭에 있는 아이콘에서
- "홈 화면에 추가"를 통해 바로가기를 추가 할 수 있습니다.
-
- ) : (
-
-
-
-
+ <>
+ {showPrompt && (
+
+
+
+
+ 바로가기를 추가하시면 앱처럼 사용이 가능합니다. 추가하시겠습니까?
+
+
+ {isIos ? (
+
+ 하단 탭에 있는 {' '}
+ 아이콘에서 "홈 화면에 추가"를 통해 바로가기를 추가 할 수 있습니다.
+
+ ) : (
+
+
+
+
+ )}
+
)}
-
+ >
);
};
diff --git a/frontend/src/components/@common/Toggle/Toggle.stories.tsx b/frontend/src/components/@common/Toggle/Toggle.stories.tsx
new file mode 100644
index 000000000..a18e3938e
--- /dev/null
+++ b/frontend/src/components/@common/Toggle/Toggle.stories.tsx
@@ -0,0 +1,29 @@
+import type { Meta, StoryObj } from '@storybook/react';
+import { number } from 'prop-types';
+import Toggle from '.';
+
+const meta: Meta = {
+ component: Toggle,
+ argTypes: {
+ width: {
+ control: { type: number },
+ },
+ height: {
+ control: { type: number },
+ },
+ },
+};
+
+export default meta;
+
+type Story = StoryObj;
+
+export const Default: Story = {
+ args: {
+ width: 130,
+ height: 50,
+ },
+ render: (args) => {
+ return ;
+ },
+};
diff --git a/frontend/src/components/@common/Toggle/Toggle.style.ts b/frontend/src/components/@common/Toggle/Toggle.style.ts
new file mode 100644
index 000000000..fb983b809
--- /dev/null
+++ b/frontend/src/components/@common/Toggle/Toggle.style.ts
@@ -0,0 +1,54 @@
+import { HTMLProps } from 'react';
+import styled, { css } from 'styled-components';
+
+interface ToggleParams extends HTMLProps {
+ $on: boolean;
+ width: number;
+ height: number;
+}
+
+export const Wrapper = styled.div``;
+
+export const ToggleBtn = styled.button`
+ cursor: pointer;
+
+ position: relative;
+
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
+ width: ${({ width }) => width}px;
+ height: ${({ height }) => height}px;
+
+ opacity: ${({ disabled }) => (disabled ? 0.3 : 1)};
+ background-color: ${({ $on, theme }) => (!$on ? theme.color.gray : theme.color.primary)};
+ border: none;
+ border-radius: 30px;
+
+ transition: all 0.5s ease-in-out;
+
+ :disabled {
+ cursor: not-allowed;
+ }
+`;
+export const Circle = styled.div`
+ position: absolute;
+ left: 5%;
+
+ width: ${({ height }) => height * 0.8}px;
+ height: ${({ height }) => height * 0.8}px;
+
+ ${({ $on, width, height }) =>
+ $on &&
+ css`
+ transform: translate(${width - height}px, 0);
+ transition: all 0.5s ease-in-out;
+ `}
+
+ background-color: white;
+ border-radius: ${({ height }) => height}px;
+ box-shadow: 0 2px 2px rgba(0, 0, 0, 0.3); /* 그림자 효과 추가 */
+
+ transition: all 0.5s ease-in-out;
+`;
diff --git a/frontend/src/components/@common/Toggle/index.tsx b/frontend/src/components/@common/Toggle/index.tsx
new file mode 100644
index 000000000..a9618d52e
--- /dev/null
+++ b/frontend/src/components/@common/Toggle/index.tsx
@@ -0,0 +1,44 @@
+import { useCallback } from 'react';
+import { Circle, ToggleBtn, Wrapper } from './Toggle.style';
+
+interface ToggleProps {
+ width?: number;
+ height?: number;
+ state: boolean;
+ toggleOnCallback?: () => void;
+ toggleOffCallback?: () => void;
+ disabled?: boolean;
+}
+
+const Toggle = ({
+ width = 130,
+ height = 50,
+ state,
+ toggleOnCallback,
+ toggleOffCallback,
+ disabled = false,
+}: ToggleProps) => {
+ const toggleHandler = useCallback(() => {
+ if (state) {
+ toggleOffCallback && toggleOffCallback();
+ } else {
+ toggleOnCallback && toggleOnCallback();
+ }
+ }, [state, toggleOffCallback, toggleOnCallback]);
+
+ return (
+
+
+
+
+
+ );
+};
+
+export default Toggle;
diff --git a/frontend/src/hooks/@common/useInstallApp.ts b/frontend/src/hooks/@common/useInstallApp.ts
index d45c7999c..c36bd28e2 100644
--- a/frontend/src/hooks/@common/useInstallApp.ts
+++ b/frontend/src/hooks/@common/useInstallApp.ts
@@ -1,4 +1,5 @@
-import { useEffect, useRef } from 'react';
+import { useEffect, useState } from 'react';
+import useCheckSessionId from 'hooks/queries/auth/useCheckSessionId';
import { getCookie, setCookie } from 'utils/cookie';
declare global {
@@ -16,45 +17,39 @@ interface BeforeInstallPromptEvent extends Event {
prompt(): Promise;
}
-let deferredPrompt: BeforeInstallPromptEvent | null = null;
-
const useInstallApp = () => {
- const installAppRef = useRef(null);
+ const { isSuccess: isLoggedIn } = useCheckSessionId(false);
+
+ const [deferredPrompt, setDeferredPrompt] = useState(null);
- const installApp = () => {
+ const installApp = async () => {
if (deferredPrompt) {
- deferredPrompt.prompt();
+ await deferredPrompt.prompt();
deferredPrompt.userChoice.then(() => {
- deferredPrompt = null;
- if (installAppRef.current) {
- installAppRef.current.style.display = 'none';
- }
+ setDeferredPrompt(null);
});
}
};
const ignoreInstallApp = () => {
setCookie({ key: 'PromptVisible', value: 'false' });
+ setDeferredPrompt(null);
+ };
- deferredPrompt = null;
- if (installAppRef.current) {
- installAppRef.current.style.display = 'none';
- }
+ const closePrompt = () => {
+ setDeferredPrompt(null);
};
const beforeInstallPromptHandler = (event: BeforeInstallPromptEvent) => {
event.preventDefault();
- const showPrompt = JSON.parse(getCookie('PromptVisible') || 'true');
-
+ const showPrompt = JSON.parse(getCookie('PromptVisible') ?? 'true');
if (!showPrompt) return;
- deferredPrompt = event;
- if (installAppRef.current) {
- installAppRef.current.style.display = 'flex';
- }
+ setDeferredPrompt(event);
};
+ // TODO: 왜 '/'에서만 beforeinstallprompt가 이벤트 추가가 되나? prompt가 나오고 나머지는 나오지 않는가?
useEffect(() => {
window.addEventListener('beforeinstallprompt', beforeInstallPromptHandler);
@@ -63,7 +58,7 @@ const useInstallApp = () => {
};
}, []);
- return { installApp, ignoreInstallApp, installAppRef };
+ return { showPrompt: deferredPrompt && isLoggedIn, installApp, ignoreInstallApp, closePrompt };
};
export default useInstallApp;
diff --git a/frontend/src/hooks/@common/usePushAlert.ts b/frontend/src/hooks/@common/usePushAlert.ts
new file mode 100644
index 000000000..1e50ef814
--- /dev/null
+++ b/frontend/src/hooks/@common/usePushAlert.ts
@@ -0,0 +1,42 @@
+import useWebPush from 'hooks/queries/auth/useWebPush';
+import { getCurrentToken } from 'utils/firebase';
+import { pushStatus } from 'utils/pushStatus';
+import useAddToast from './useAddToast';
+
+const usePushAlert = () => {
+ const addToast = useAddToast();
+ const { subscribe, unSubscribe, currentSubscribe } = useWebPush();
+
+ const subscribeAlert = async () => {
+ if (!pushStatus.pushSupport) {
+ addToast({ type: 'warning', message: '지원하지 않는 브라우저입니다', time: 3000 });
+ return;
+ }
+
+ // subscribe를 하지 않으려면 해당 토큰을 제거해야 한다.
+ const permission = await Notification.requestPermission();
+ pushStatus.notificationPermission = permission;
+
+ if (permission !== 'granted') {
+ addToast({ type: 'info', message: '알림을 거부했습니다', time: 3000 });
+ return;
+ }
+
+ const currentToken = await getCurrentToken(); // 여기서 새로운 토큰을 전달하면 됨.
+ subscribe(currentToken);
+ };
+
+ const unSubscribeAlert = () => {
+ unSubscribe();
+ };
+
+ return {
+ currentSubscribe, // 현재 FCM을 구독하고 있는지 아닌지
+ pushSupport: pushStatus.pushSupport, // 푸시 서비스를 지원하는지 여부
+ notificationDenied: pushStatus.notificationPermission, // 알림 구독 여부
+ subscribeAlert,
+ unSubscribeAlert,
+ };
+};
+
+export default usePushAlert;
diff --git a/frontend/src/hooks/queries/auth/useLogin.ts b/frontend/src/hooks/queries/auth/useLogin.ts
index 69e2c0575..9272e3f7c 100644
--- a/frontend/src/hooks/queries/auth/useLogin.ts
+++ b/frontend/src/hooks/queries/auth/useLogin.ts
@@ -1,12 +1,12 @@
-import { useSuspenseQuery } from '@tanstack/react-query';
+import { useMutation } from '@tanstack/react-query';
import AuthAPI from 'apis/auth';
import throwOnInvalidStatus from 'utils/throwOnInvalidStatus';
-const useLogin = (code: string) =>
- useSuspenseQuery({
- queryKey: ['getSession', code],
- queryFn: async () => {
+const useLogin = () =>
+ useMutation({
+ mutationFn: async (code: string) => {
const response = await AuthAPI.getSessionId(code);
+
throwOnInvalidStatus(response);
return null;
},
diff --git a/frontend/src/hooks/queries/auth/useWebPush.ts b/frontend/src/hooks/queries/auth/useWebPush.ts
new file mode 100644
index 000000000..03794e39b
--- /dev/null
+++ b/frontend/src/hooks/queries/auth/useWebPush.ts
@@ -0,0 +1,91 @@
+import { useMutation, useQueryClient, useSuspenseQuery } from '@tanstack/react-query';
+import useAddToast from 'hooks/@common/useAddToast';
+import WebPushSubscribeAPI, { SUBSCRIBE_URL } from 'apis/webPush';
+import noRetryIfUnauthorized from 'utils/noRetryIfUnauthorized';
+import throwOnInvalidStatus from 'utils/throwOnInvalidStatus';
+
+interface CurrentSubscribe {
+ isSubscribe: boolean;
+}
+
+const useWebPush = () => {
+ const addToast = useAddToast();
+ const queryClient = useQueryClient();
+
+ const subscribe = useMutation({
+ mutationFn: async (token: string) => {
+ const response = await WebPushSubscribeAPI.subscribe(token);
+ throwOnInvalidStatus(response);
+
+ return null;
+ },
+ onMutate: async () => {
+ await queryClient.cancelQueries({ queryKey: [SUBSCRIBE_URL] });
+
+ const prevData = queryClient.getQueryState([SUBSCRIBE_URL]);
+
+ return { prevData };
+ },
+ onSuccess: () => {
+ addToast({ type: 'success', message: '알림을 등록했습니다', time: 3000 });
+ },
+ onError: (_, __, context) => {
+ queryClient.setQueryData([SUBSCRIBE_URL], context?.prevData);
+ addToast({ type: 'error', message: '알림 등록에 실패했습니다', time: 3000 });
+ },
+ onSettled: () => {
+ queryClient.invalidateQueries({ queryKey: [SUBSCRIBE_URL] });
+ },
+ });
+
+ const unSubscribe = useMutation({
+ mutationFn: async () => {
+ const response = await WebPushSubscribeAPI.unSubscribe();
+ throwOnInvalidStatus(response);
+ if (response.status === 407) {
+ throw new Error('랜덤 실패');
+ }
+
+ return null;
+ },
+ onMutate: async () => {
+ await queryClient.cancelQueries({ queryKey: [SUBSCRIBE_URL] });
+
+ const prevData = queryClient.getQueryState([SUBSCRIBE_URL]);
+
+ return { prevData };
+ },
+ onSuccess: () => {
+ addToast({ type: 'success', message: '알림을 해제했습니다', time: 3000 });
+ },
+ onError: (_, __, context) => {
+ // 업데이트에 실패한 경우 이전 값으로 반환
+ queryClient.setQueryData([SUBSCRIBE_URL], context?.prevData);
+ addToast({ type: 'error', message: '알림 해제에 실패했습니다', time: 3000 });
+ },
+
+ onSettled: () => {
+ queryClient.invalidateQueries({ queryKey: [SUBSCRIBE_URL] });
+ },
+ });
+
+ const currentSubscribe = useSuspenseQuery({
+ queryKey: [SUBSCRIBE_URL],
+ queryFn: async () => {
+ const response = await WebPushSubscribeAPI.currentSubscribe();
+ throwOnInvalidStatus(response);
+
+ const data = await response.json();
+ return data;
+ },
+ retry: noRetryIfUnauthorized,
+ });
+
+ return {
+ subscribe: subscribe.mutate,
+ unSubscribe: unSubscribe.mutate,
+ currentSubscribe: currentSubscribe.data.isSubscribe,
+ };
+};
+
+export default useWebPush;
diff --git a/frontend/src/hooks/queries/petPlant/useRegisterPetPlant.ts b/frontend/src/hooks/queries/petPlant/useRegisterPetPlant.ts
index 237328a65..b9d32ecae 100644
--- a/frontend/src/hooks/queries/petPlant/useRegisterPetPlant.ts
+++ b/frontend/src/hooks/queries/petPlant/useRegisterPetPlant.ts
@@ -18,6 +18,7 @@ const useRegisterPetPlant = () => {
throwOnInvalidStatus(response);
},
+ // TODO: 첫 식물 등록시에 navigate로 반환하고 알림 설정하겠냐고 물어보기
onSuccess: () => {
addToast({ type: 'success', message: '반려 식물 등록에 성공했어요' });
navigate(URL_PATH.petList, { replace: true });
diff --git a/frontend/src/index.tsx b/frontend/src/index.tsx
index 1a1754b2a..d1c78ff07 100644
--- a/frontend/src/index.tsx
+++ b/frontend/src/index.tsx
@@ -1,20 +1,24 @@
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';
-import swDev from './swDev';
+import registerServiceWork from './registerServiceWork';
if (process.env.NODE_ENV === 'development') {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { worker } = require('./mocks/browser');
+ registerServiceWork('/devLocalServiceWorker.js');
worker.start({
serviceWorker: {
- url: 'http://localhost:8282/mockServiceWorker.js',
+ url: 'http://localhost:8282/devLocalServiceWorker.js',
},
});
-} else {
- swDev();
}
+
+if (process.env.NODE_ENV === 'production') {
+ registerServiceWork('/firebase-messaging-sw.js');
+}
+
const root = createRoot(document.getElementById('root') as HTMLElement);
root.render(
diff --git a/frontend/src/mocks/handlers.ts b/frontend/src/mocks/handlers.ts
index d255b0b60..b2fac8e9d 100644
--- a/frontend/src/mocks/handlers.ts
+++ b/frontend/src/mocks/handlers.ts
@@ -241,5 +241,41 @@ export const makeHandler = (delay = 0, failRate = 0) => {
// 쿠키 갱신
return res(ctx.delay(delay), ctx.cookie('JSESSION', JSESSION));
}),
+
+ rest.get('/members/notification', (req, res, ctx) => {
+ const { JSESSION } = req.cookies;
+
+ if (JSESSION === undefined) {
+ return res(ctx.delay(delay), ctx.status(401), ctx.json({ message: '만료된 세션입니다.' }));
+ }
+
+ const token = JSON.parse(sessionStorage.getItem('FCM_TOKEN') ?? 'false');
+ let isSubscribe = false;
+ if (token) isSubscribe = true;
+
+ return res(ctx.delay(delay), ctx.json({ isSubscribe }));
+ }),
+
+ rest.post('/members/notification', async (req, res, ctx) => {
+ const { token } = await req.json();
+
+ if (Math.random() < failRate) {
+ return res(ctx.delay(delay), ctx.status(407));
+ }
+
+ sessionStorage.setItem('FCM_TOKEN', JSON.stringify(token));
+
+ return res(ctx.delay(delay), ctx.status(204));
+ }),
+
+ rest.delete('/members/notification', (req, res, ctx) => {
+ if (Math.random() < failRate) {
+ return res(ctx.delay(delay), ctx.status(407));
+ }
+
+ sessionStorage.removeItem('FCM_TOKEN');
+
+ return res(ctx.delay(delay), ctx.status(204));
+ }),
];
};
diff --git a/frontend/src/pages/@common/Main/index.tsx b/frontend/src/pages/@common/Main/index.tsx
index a4075ca86..a3ee79517 100644
--- a/frontend/src/pages/@common/Main/index.tsx
+++ b/frontend/src/pages/@common/Main/index.tsx
@@ -14,7 +14,6 @@ const Main = () => {
return (
<>
-
식물을 쉽게
diff --git a/frontend/src/pages/auth/Login/Authorization.tsx b/frontend/src/pages/auth/Login/Authorization.tsx
index 935ef34a5..2ce0665ab 100644
--- a/frontend/src/pages/auth/Login/Authorization.tsx
+++ b/frontend/src/pages/auth/Login/Authorization.tsx
@@ -1,3 +1,4 @@
+import { useEffect } from 'react';
import { Navigate, useSearchParams } from 'react-router-dom';
import useLogin from 'hooks/queries/auth/useLogin';
import { URL_PATH } from 'constants/index';
@@ -5,8 +6,11 @@ import { URL_PATH } from 'constants/index';
const Authorization = () => {
const [searchParams] = useSearchParams();
const code = searchParams.get('code');
+ const { mutate: login } = useLogin();
- useLogin(code ?? '');
+ useEffect(() => {
+ login(code ?? '');
+ }, [code, login]);
return ;
};
diff --git a/frontend/src/pages/auth/MyPage/MyPage.style.ts b/frontend/src/pages/auth/MyPage/MyPage.style.ts
index 04f1f41c3..c68b0a32f 100644
--- a/frontend/src/pages/auth/MyPage/MyPage.style.ts
+++ b/frontend/src/pages/auth/MyPage/MyPage.style.ts
@@ -3,9 +3,12 @@ import styled from 'styled-components';
export const Wrapper = styled.main`
position: relative;
+
display: flex;
flex-direction: column;
+
height: calc(100% - 68px);
+ padding: 16px 0;
`;
export const ButtonBox = styled.section`
@@ -24,6 +27,32 @@ export const ButtonBox = styled.section`
}
`;
+export const PushAlertWrapper = styled.div`
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+ justify-content: space-around;
+
+ width: 80%;
+ margin: 0 auto;
+`;
+
+export const WarnParagraph = styled.p`
+ font: 400 1.2rem/1.6rem NanumSquareRound;
+ color: ${({ theme }) => theme.color.accent};
+ text-align: right;
+`;
+
+export const PushAlertContent = styled.div`
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ width: 100%;
+ p {
+ font: 600 1.6rem/2rem NanumSquareRound;
+ }
+`;
+
export const Button = styled.button`
height: 45px;
color: ${({ theme: { color } }) => color.gray};
diff --git a/frontend/src/pages/auth/MyPage/index.tsx b/frontend/src/pages/auth/MyPage/index.tsx
index cd0fb4dfc..75b8cd092 100644
--- a/frontend/src/pages/auth/MyPage/index.tsx
+++ b/frontend/src/pages/auth/MyPage/index.tsx
@@ -2,9 +2,19 @@ import { FixedButtonArea } from 'pages/garden/GardenPostList/GardenPostList.styl
import ContentHeader from 'components/@common/ContentHeader';
import Navbar from 'components/@common/Navbar';
import SvgFill from 'components/@common/SvgIcons/SvgFill';
+import Toggle from 'components/@common/Toggle';
import VerticalDivider from 'components/@common/VerticalDivider/VerticalDivider.style';
-import { BottomSheet, Button, ButtonBox, Wrapper } from './MyPage.style';
+import {
+ BottomSheet,
+ Button,
+ ButtonBox,
+ PushAlertContent,
+ PushAlertWrapper,
+ WarnParagraph,
+ Wrapper,
+} from './MyPage.style';
import useConfirm from 'hooks/@common/useConfirm';
+import usePushAlert from 'hooks/@common/usePushAlert';
import useCheckSessionId from 'hooks/queries/auth/useCheckSessionId';
import useLogout from 'hooks/queries/auth/useLogout';
import useWithdraw from 'hooks/queries/auth/useWithdraw';
@@ -14,6 +24,10 @@ const MyPage = () => {
useCheckSessionId();
const { mutate: logoutMutate } = useLogout();
const { mutate: withdrawMutate } = useWithdraw();
+
+ const { currentSubscribe, pushSupport, notificationDenied, subscribeAlert, unSubscribeAlert } =
+ usePushAlert();
+
const confirm = useConfirm();
const handleLogout: React.MouseEventHandler = () => {
@@ -32,6 +46,25 @@ const MyPage = () => {
<>
+
+
+ 리마인더 알림 받기
+
+
+ {!pushSupport && 지원하지 않는 브라우저 또는 os입니다.}
+ {notificationDenied === 'denied' && (
+
+ 브라우저 알림을 허용하지 않았습니다. 허용하기 위해서는 설정 {'>'} 알림 허용을 해주세요
+
+ )}
+