Fixed properties queries.

This commit is contained in:
Mike Cao 2025-07-15 01:31:08 -07:00
parent 465a03f987
commit 5e6799a715
38 changed files with 139 additions and 499 deletions

View file

@ -82,7 +82,7 @@
"@react-spring/web": "^9.7.3", "@react-spring/web": "^9.7.3",
"@svgr/cli": "^8.1.0", "@svgr/cli": "^8.1.0",
"@tanstack/react-query": "^5.80.10", "@tanstack/react-query": "^5.80.10",
"@umami/react-zen": "^0.145.0", "@umami/react-zen": "^0.147.0",
"@umami/redis-client": "^0.27.0", "@umami/redis-client": "^0.27.0",
"bcryptjs": "^2.4.3", "bcryptjs": "^2.4.3",
"chalk": "^4.1.1", "chalk": "^4.1.1",

402
pnpm-lock.yaml generated
View file

@ -45,8 +45,8 @@ importers:
specifier: ^5.80.10 specifier: ^5.80.10
version: 5.80.10(react@19.1.0) version: 5.80.10(react@19.1.0)
'@umami/react-zen': '@umami/react-zen':
specifier: ^0.145.0 specifier: ^0.147.0
version: 0.145.0(@babel/core@7.27.1)(@types/react@19.1.8)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0)) version: 0.147.0(@babel/core@7.27.1)(@types/react@19.1.8)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0))
'@umami/redis-client': '@umami/redis-client':
specifier: ^0.27.0 specifier: ^0.27.0
version: 0.27.0 version: 0.27.0
@ -355,45 +355,6 @@ importers:
specifier: ^5.5.3 specifier: ^5.5.3
version: 5.8.3 version: 5.8.3
dist:
dependencies:
'@tanstack/react-query':
specifier: ^4.33.0
version: 4.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
classnames:
specifier: ^2.3.1
version: 2.5.1
colord:
specifier: ^2.9.2
version: 2.9.3
date-fns-tz:
specifier: ^1.1.4
version: 1.3.8(date-fns@2.30.0)
immer:
specifier: ^9.0.12
version: 9.0.21
moment-timezone:
specifier: ^0.5.35
version: 0.5.48
next:
specifier: ^13.4.0
version: 13.5.11(@babel/core@7.27.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
next-basics:
specifier: ^0.36.0
version: 0.36.0(next@13.5.11(@babel/core@7.27.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
react:
specifier: ^18.2.0
version: 18.3.1
react-dom:
specifier: ^18.2.0
version: 18.3.1(react@18.3.1)
react-intl:
specifier: ^5.24.7
version: 5.25.1(react@18.3.1)(typescript@4.9.5)
zustand:
specifier: ^4.3.8
version: 4.5.7(@types/react@19.1.8)(immer@9.0.21)(react@18.3.1)
packages: packages:
'@ampproject/remapping@2.3.0': '@ampproject/remapping@2.3.0':
@ -1095,9 +1056,6 @@ packages:
'@formatjs/ecma402-abstract@2.3.4': '@formatjs/ecma402-abstract@2.3.4':
resolution: {integrity: sha512-qrycXDeaORzIqNhBOx0btnhpD1c+/qFIHAN9znofuMJX6QBwtbrmlpWfD4oiUUD2vJUOIYFA/gYtg2KAMGG7sA==} resolution: {integrity: sha512-qrycXDeaORzIqNhBOx0btnhpD1c+/qFIHAN9znofuMJX6QBwtbrmlpWfD4oiUUD2vJUOIYFA/gYtg2KAMGG7sA==}
'@formatjs/fast-memoize@1.2.1':
resolution: {integrity: sha512-Rg0e76nomkz3vF9IPlKeV+Qynok0r7YZjL6syLz4/urSg0IbjPZCB/iYUMNsYA643gh4mgrX3T7KEIFIxJBQeg==}
'@formatjs/fast-memoize@2.2.3': '@formatjs/fast-memoize@2.2.3':
resolution: {integrity: sha512-3jeJ+HyOfu8osl3GNSL4vVHUuWFXR03Iz9jjgI7RwjG6ysu/Ymdr0JRCPHfF5yGbTE6JCrd63EpvX1/WybYRbA==} resolution: {integrity: sha512-3jeJ+HyOfu8osl3GNSL4vVHUuWFXR03Iz9jjgI7RwjG6ysu/Ymdr0JRCPHfF5yGbTE6JCrd63EpvX1/WybYRbA==}
@ -1122,15 +1080,9 @@ packages:
'@formatjs/icu-skeleton-parser@1.8.8': '@formatjs/icu-skeleton-parser@1.8.8':
resolution: {integrity: sha512-vHwK3piXwamFcx5YQdCdJxUQ1WdTl6ANclt5xba5zLGDv5Bsur7qz8AD7BevaKxITwpgDeU0u8My3AIibW9ywA==} resolution: {integrity: sha512-vHwK3piXwamFcx5YQdCdJxUQ1WdTl6ANclt5xba5zLGDv5Bsur7qz8AD7BevaKxITwpgDeU0u8My3AIibW9ywA==}
'@formatjs/intl-displaynames@5.4.3':
resolution: {integrity: sha512-4r12A3mS5dp5hnSaQCWBuBNfi9Amgx2dzhU4lTFfhSxgb5DOAiAbMpg6+7gpWZgl4ahsj3l2r/iHIjdmdXOE2Q==}
'@formatjs/intl-displaynames@6.8.5': '@formatjs/intl-displaynames@6.8.5':
resolution: {integrity: sha512-85b+GdAKCsleS6cqVxf/Aw/uBd+20EM0wDpgaxzHo3RIR3bxF4xCJqH/Grbzx8CXurTgDDZHPdPdwJC+May41w==} resolution: {integrity: sha512-85b+GdAKCsleS6cqVxf/Aw/uBd+20EM0wDpgaxzHo3RIR3bxF4xCJqH/Grbzx8CXurTgDDZHPdPdwJC+May41w==}
'@formatjs/intl-listformat@6.5.3':
resolution: {integrity: sha512-ozpz515F/+3CU+HnLi5DYPsLa6JoCfBggBSSg/8nOB5LYSFW9+ZgNQJxJ8tdhKYeODT+4qVHX27EeJLoxLGLNg==}
'@formatjs/intl-listformat@7.7.5': '@formatjs/intl-listformat@7.7.5':
resolution: {integrity: sha512-Wzes10SMNeYgnxYiKsda4rnHP3Q3II4XT2tZyOgnH5fWuHDtIkceuWlRQNsvrI3uiwP4hLqp2XdQTCsfkhXulg==} resolution: {integrity: sha512-Wzes10SMNeYgnxYiKsda4rnHP3Q3II4XT2tZyOgnH5fWuHDtIkceuWlRQNsvrI3uiwP4hLqp2XdQTCsfkhXulg==}
@ -1154,14 +1106,6 @@ packages:
typescript: typescript:
optional: true optional: true
'@formatjs/intl@2.2.1':
resolution: {integrity: sha512-vgvyUOOrzqVaOFYzTf2d3+ToSkH2JpR7x/4U1RyoHQLmvEaTQvXJ7A2qm1Iy3brGNXC/+/7bUlc3lpH+h/LOJA==}
peerDependencies:
typescript: ^4.5
peerDependenciesMeta:
typescript:
optional: true
'@formatjs/ts-transformer@2.13.0': '@formatjs/ts-transformer@2.13.0':
resolution: {integrity: sha512-mu7sHXZk1NWZrQ3eUqugpSYo8x5/tXkrI4uIbFqCEC0eNgQaIcoKgVeDFgDAcgG+cEme2atAUYSFF+DFWC4org==} resolution: {integrity: sha512-mu7sHXZk1NWZrQ3eUqugpSYo8x5/tXkrI4uIbFqCEC0eNgQaIcoKgVeDFgDAcgG+cEme2atAUYSFF+DFWC4org==}
peerDependencies: peerDependencies:
@ -1437,111 +1381,54 @@ packages:
resolution: {integrity: sha512-SCF2UPT+mDrfO3DDeUb7eTRqHycBEx4aJ8vACm17Nyn2b2ueaLlS5u/2V42SSZF/F6LydI7R78fv3xPW7HHdWw==} resolution: {integrity: sha512-SCF2UPT+mDrfO3DDeUb7eTRqHycBEx4aJ8vACm17Nyn2b2ueaLlS5u/2V42SSZF/F6LydI7R78fv3xPW7HHdWw==}
engines: {node: '>=18.0.0'} engines: {node: '>=18.0.0'}
'@next/env@13.5.11':
resolution: {integrity: sha512-fbb2C7HChgM7CemdCY+y3N1n8pcTKdqtQLbC7/EQtPdLvlMUT9JX/dBYl8MMZAtYG4uVMyPFHXckb68q/NRwqg==}
'@next/env@15.3.4': '@next/env@15.3.4':
resolution: {integrity: sha512-ZkdYzBseS6UjYzz6ylVKPOK+//zLWvD6Ta+vpoye8cW11AjiQjGYVibF0xuvT4L0iJfAPfZLFidaEzAOywyOAQ==} resolution: {integrity: sha512-ZkdYzBseS6UjYzz6ylVKPOK+//zLWvD6Ta+vpoye8cW11AjiQjGYVibF0xuvT4L0iJfAPfZLFidaEzAOywyOAQ==}
'@next/eslint-plugin-next@14.2.30': '@next/eslint-plugin-next@14.2.30':
resolution: {integrity: sha512-mvVsMIutMxQ4NGZEMZ1kiBNc+la8Xmlk30bKUmCPQz2eFkmsLv54Mha8QZarMaCtSPkkFA1TMD+FIZk0l/PpzA==} resolution: {integrity: sha512-mvVsMIutMxQ4NGZEMZ1kiBNc+la8Xmlk30bKUmCPQz2eFkmsLv54Mha8QZarMaCtSPkkFA1TMD+FIZk0l/PpzA==}
'@next/swc-darwin-arm64@13.5.9':
resolution: {integrity: sha512-pVyd8/1y1l5atQRvOaLOvfbmRwefxLhqQOzYo/M7FQ5eaRwA1+wuCn7t39VwEgDd7Aw1+AIWwd+MURXUeXhwDw==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [darwin]
'@next/swc-darwin-arm64@15.3.4': '@next/swc-darwin-arm64@15.3.4':
resolution: {integrity: sha512-z0qIYTONmPRbwHWvpyrFXJd5F9YWLCsw3Sjrzj2ZvMYy9NPQMPZ1NjOJh4ojr4oQzcGYwgJKfidzehaNa1BpEg==} resolution: {integrity: sha512-z0qIYTONmPRbwHWvpyrFXJd5F9YWLCsw3Sjrzj2ZvMYy9NPQMPZ1NjOJh4ojr4oQzcGYwgJKfidzehaNa1BpEg==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [arm64] cpu: [arm64]
os: [darwin] os: [darwin]
'@next/swc-darwin-x64@13.5.9':
resolution: {integrity: sha512-DwdeJqP7v8wmoyTWPbPVodTwCybBZa02xjSJ6YQFIFZFZ7dFgrieKW4Eo0GoIcOJq5+JxkQyejmI+8zwDp3pwA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [darwin]
'@next/swc-darwin-x64@15.3.4': '@next/swc-darwin-x64@15.3.4':
resolution: {integrity: sha512-Z0FYJM8lritw5Wq+vpHYuCIzIlEMjewG2aRkc3Hi2rcbULknYL/xqfpBL23jQnCSrDUGAo/AEv0Z+s2bff9Zkw==} resolution: {integrity: sha512-Z0FYJM8lritw5Wq+vpHYuCIzIlEMjewG2aRkc3Hi2rcbULknYL/xqfpBL23jQnCSrDUGAo/AEv0Z+s2bff9Zkw==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [x64] cpu: [x64]
os: [darwin] os: [darwin]
'@next/swc-linux-arm64-gnu@13.5.9':
resolution: {integrity: sha512-wdQsKsIsGSNdFojvjW3Ozrh8Q00+GqL3wTaMjDkQxVtRbAqfFBtrLPO0IuWChVUP2UeuQcHpVeUvu0YgOP00+g==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
'@next/swc-linux-arm64-gnu@15.3.4': '@next/swc-linux-arm64-gnu@15.3.4':
resolution: {integrity: sha512-l8ZQOCCg7adwmsnFm8m5q9eIPAHdaB2F3cxhufYtVo84pymwKuWfpYTKcUiFcutJdp9xGHC+F1Uq3xnFU1B/7g==} resolution: {integrity: sha512-l8ZQOCCg7adwmsnFm8m5q9eIPAHdaB2F3cxhufYtVo84pymwKuWfpYTKcUiFcutJdp9xGHC+F1Uq3xnFU1B/7g==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
'@next/swc-linux-arm64-musl@13.5.9':
resolution: {integrity: sha512-6VpS+bodQqzOeCwGxoimlRoosiWlSc0C224I7SQWJZoyJuT1ChNCo+45QQH+/GtbR/s7nhaUqmiHdzZC9TXnXA==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
'@next/swc-linux-arm64-musl@15.3.4': '@next/swc-linux-arm64-musl@15.3.4':
resolution: {integrity: sha512-wFyZ7X470YJQtpKot4xCY3gpdn8lE9nTlldG07/kJYexCUpX1piX+MBfZdvulo+t1yADFVEuzFfVHfklfEx8kw==} resolution: {integrity: sha512-wFyZ7X470YJQtpKot4xCY3gpdn8lE9nTlldG07/kJYexCUpX1piX+MBfZdvulo+t1yADFVEuzFfVHfklfEx8kw==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
'@next/swc-linux-x64-gnu@13.5.9':
resolution: {integrity: sha512-XxG3yj61WDd28NA8gFASIR+2viQaYZEFQagEodhI/R49gXWnYhiflTeeEmCn7Vgnxa/OfK81h1gvhUZ66lozpw==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
'@next/swc-linux-x64-gnu@15.3.4': '@next/swc-linux-x64-gnu@15.3.4':
resolution: {integrity: sha512-gEbH9rv9o7I12qPyvZNVTyP/PWKqOp8clvnoYZQiX800KkqsaJZuOXkWgMa7ANCCh/oEN2ZQheh3yH8/kWPSEg==} resolution: {integrity: sha512-gEbH9rv9o7I12qPyvZNVTyP/PWKqOp8clvnoYZQiX800KkqsaJZuOXkWgMa7ANCCh/oEN2ZQheh3yH8/kWPSEg==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
'@next/swc-linux-x64-musl@13.5.9':
resolution: {integrity: sha512-/dnscWqfO3+U8asd+Fc6dwL2l9AZDl7eKtPNKW8mKLh4Y4wOpjJiamhe8Dx+D+Oq0GYVjuW0WwjIxYWVozt2bA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
'@next/swc-linux-x64-musl@15.3.4': '@next/swc-linux-x64-musl@15.3.4':
resolution: {integrity: sha512-Cf8sr0ufuC/nu/yQ76AnarbSAXcwG/wj+1xFPNbyNo8ltA6kw5d5YqO8kQuwVIxk13SBdtgXrNyom3ZosHAy4A==} resolution: {integrity: sha512-Cf8sr0ufuC/nu/yQ76AnarbSAXcwG/wj+1xFPNbyNo8ltA6kw5d5YqO8kQuwVIxk13SBdtgXrNyom3ZosHAy4A==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
'@next/swc-win32-arm64-msvc@13.5.9':
resolution: {integrity: sha512-T/iPnyurOK5a4HRUcxAlss8uzoEf5h9tkd+W2dSWAfzxv8WLKlUgbfk+DH43JY3Gc2xK5URLuXrxDZ2mGfk/jw==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [win32]
'@next/swc-win32-arm64-msvc@15.3.4': '@next/swc-win32-arm64-msvc@15.3.4':
resolution: {integrity: sha512-ay5+qADDN3rwRbRpEhTOreOn1OyJIXS60tg9WMYTWCy3fB6rGoyjLVxc4dR9PYjEdR2iDYsaF5h03NA+XuYPQQ==} resolution: {integrity: sha512-ay5+qADDN3rwRbRpEhTOreOn1OyJIXS60tg9WMYTWCy3fB6rGoyjLVxc4dR9PYjEdR2iDYsaF5h03NA+XuYPQQ==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [arm64] cpu: [arm64]
os: [win32] os: [win32]
'@next/swc-win32-ia32-msvc@13.5.9':
resolution: {integrity: sha512-BLiPKJomaPrTAb7ykjA0LPcuuNMLDVK177Z1xe0nAem33+9FIayU4k/OWrtSn9SAJW/U60+1hoey5z+KCHdRLQ==}
engines: {node: '>= 10'}
cpu: [ia32]
os: [win32]
'@next/swc-win32-x64-msvc@13.5.9':
resolution: {integrity: sha512-/72/dZfjXXNY/u+n8gqZDjI6rxKMpYsgBBYNZKWOQw0BpBF7WCnPflRy3ZtvQ2+IYI3ZH2bPyj7K+6a6wNk90Q==}
engines: {node: '>= 10'}
cpu: [x64]
os: [win32]
'@next/swc-win32-x64-msvc@15.3.4': '@next/swc-win32-x64-msvc@15.3.4':
resolution: {integrity: sha512-4kDt31Bc9DGyYs41FTL1/kNpDeHyha2TC0j5sRRoKCyrhNcfZ/nRQkAUlF27mETwm8QyHqIjHJitfcza2Iykfg==} resolution: {integrity: sha512-4kDt31Bc9DGyYs41FTL1/kNpDeHyha2TC0j5sRRoKCyrhNcfZ/nRQkAUlF27mETwm8QyHqIjHJitfcza2Iykfg==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
@ -2429,27 +2316,9 @@ packages:
'@swc/helpers@0.5.17': '@swc/helpers@0.5.17':
resolution: {integrity: sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==} resolution: {integrity: sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==}
'@swc/helpers@0.5.2':
resolution: {integrity: sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==}
'@tanstack/query-core@4.40.0':
resolution: {integrity: sha512-7MJTtZkCSuehMC7IxMOCGsLvHS3jHx4WjveSrGsG1Nc1UQLjaFwwkpLA2LmPfvOAxnH4mszMOBFD6LlZE+aB+Q==}
'@tanstack/query-core@5.80.10': '@tanstack/query-core@5.80.10':
resolution: {integrity: sha512-mUNQOtzxkjL6jLbyChZoSBP6A5gQDVRUiPvW+/zw/9ftOAz+H754zCj3D8PwnzPKyHzGkQ9JbH48ukhym9LK1Q==} resolution: {integrity: sha512-mUNQOtzxkjL6jLbyChZoSBP6A5gQDVRUiPvW+/zw/9ftOAz+H754zCj3D8PwnzPKyHzGkQ9JbH48ukhym9LK1Q==}
'@tanstack/react-query@4.40.1':
resolution: {integrity: sha512-mgD07S5N8e5v81CArKDWrHE4LM7HxZ9k/KLeD3+NUD9WimGZgKIqojUZf/rXkfAMYZU9p0Chzj2jOXm7xpgHHQ==}
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
react-native: '*'
peerDependenciesMeta:
react-dom:
optional: true
react-native:
optional: true
'@tanstack/react-query@5.80.10': '@tanstack/react-query@5.80.10':
resolution: {integrity: sha512-6zM098J8sLy9oU60XAdzUlAH4wVzoMVsWUWiiE/Iz4fd67PplxeyL4sw/MPcVJJVhbwGGXCsHn9GrQt2mlAzig==} resolution: {integrity: sha512-6zM098J8sLy9oU60XAdzUlAH4wVzoMVsWUWiiE/Iz4fd67PplxeyL4sw/MPcVJJVhbwGGXCsHn9GrQt2mlAzig==}
peerDependencies: peerDependencies:
@ -2678,8 +2547,8 @@ packages:
resolution: {integrity: sha512-xoh5rJ+tgsRKoXnkBPFRLZ7rjKM0AfVbC68UZ/ECXoDbfggb9RbEySN359acY1vS3qZ0jVTVWzbtfapwm5ztxw==} resolution: {integrity: sha512-xoh5rJ+tgsRKoXnkBPFRLZ7rjKM0AfVbC68UZ/ECXoDbfggb9RbEySN359acY1vS3qZ0jVTVWzbtfapwm5ztxw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@umami/react-zen@0.145.0': '@umami/react-zen@0.147.0':
resolution: {integrity: sha512-bbbdgWDwW0MIXfSc3JJPDOcmATZpwDsbrDdj37LEvP6rdtUgwAarnATjJa9l3133LGhhEAdYitZqwrDfHHPI5g==} resolution: {integrity: sha512-29A4IxHX/IC4w2v9cCXg8uU8lZ3VPVUrlJH9mngTKSSaCcMzlkgNjKosrQ2xV+wEsMWHl1zV3JRmLL0sgJ9TxA==}
'@umami/redis-client@0.27.0': '@umami/redis-client@0.27.0':
resolution: {integrity: sha512-SbHTpxhgeZyTBUSp2zdZM+XUtpsaSL4Tad8QXIEhEtjWhvvfoornyT5kLuyYCVtzSAT4daALeGmOO1z6EE1KcA==} resolution: {integrity: sha512-SbHTpxhgeZyTBUSp2zdZM+XUtpsaSL4Tad8QXIEhEtjWhvvfoornyT5kLuyYCVtzSAT4daALeGmOO1z6EE1KcA==}
@ -4186,9 +4055,6 @@ packages:
resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
engines: {node: '>=10.13.0'} engines: {node: '>=10.13.0'}
glob-to-regexp@0.4.1:
resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==}
glob@10.3.10: glob@10.3.10:
resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==} resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==}
engines: {node: '>=16 || 14 >=14.17'} engines: {node: '>=16 || 14 >=14.17'}
@ -4425,9 +4291,6 @@ packages:
intl-messageformat@10.7.7: intl-messageformat@10.7.7:
resolution: {integrity: sha512-F134jIoeYMro/3I0h08D0Yt4N9o9pjddU/4IIxMMURqbAtI2wu70X8hvG1V48W49zXHXv3RKSF/po+0fDfsGjA==} resolution: {integrity: sha512-F134jIoeYMro/3I0h08D0Yt4N9o9pjddU/4IIxMMURqbAtI2wu70X8hvG1V48W49zXHXv3RKSF/po+0fDfsGjA==}
intl-messageformat@9.13.0:
resolution: {integrity: sha512-7sGC7QnSQGa5LZP7bXLDhVDtQOeKGeBFGHF2Y8LVBwYZoQZCgWeKoPGTa5GMG8g/TzDgeXuYJQis7Ggiw2xTOw==}
ipaddr.js@2.2.0: ipaddr.js@2.2.0:
resolution: {integrity: sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==} resolution: {integrity: sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
@ -5219,12 +5082,6 @@ packages:
resolution: {integrity: sha512-DXO4L9W+08T+A7h5+xdT32l7IMot8z7WOH+7C1Maol571PnktQ8un7Ni4CyPFp4H+vht/FDA5/tpjRvWMFQDMw==} resolution: {integrity: sha512-DXO4L9W+08T+A7h5+xdT32l7IMot8z7WOH+7C1Maol571PnktQ8un7Ni4CyPFp4H+vht/FDA5/tpjRvWMFQDMw==}
engines: {node: '>=10', npm: '>=6'} engines: {node: '>=10', npm: '>=6'}
moment-timezone@0.5.48:
resolution: {integrity: sha512-f22b8LV1gbTO2ms2j2z13MuPogNoh5UzxL3nzNAYKGraILnbGc9NEE6dyiiiLv46DGRb8A4kg8UKWLjPthxBHw==}
moment@2.30.1:
resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==}
ms@2.1.2: ms@2.1.2:
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
@ -5244,28 +5101,6 @@ packages:
natural-compare@1.4.0: natural-compare@1.4.0:
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
next-basics@0.36.0:
resolution: {integrity: sha512-Nwou8pCjFuoD/ZxUw9iKC7hhZeWbo/ng0ze74yck3W89MNc/CepwCDziflAHY5XcmIVNmpXOCu9OfmzTdVRPWQ==}
peerDependencies:
next: ^13.4.0
react: ^18.2.0
react-dom: ^18.2.0
next@13.5.11:
resolution: {integrity: sha512-WUPJ6WbAX9tdC86kGTu92qkrRdgRqVrY++nwM+shmWQwmyxt4zhZfR59moXSI4N8GDYCBY3lIAqhzjDd4rTC8Q==}
engines: {node: '>=16.14.0'}
hasBin: true
peerDependencies:
'@opentelemetry/api': ^1.1.0
react: ^18.2.0
react-dom: ^18.2.0
sass: ^1.3.0
peerDependenciesMeta:
'@opentelemetry/api':
optional: true
sass:
optional: true
next@15.3.4: next@15.3.4:
resolution: {integrity: sha512-mHKd50C+mCjam/gcnwqL1T1vPx/XQNFlXqFIVdgQdVAFY9iIQtY0IfaVflEYzKiqjeA7B0cYYMaCrmAYFjs4rA==} resolution: {integrity: sha512-mHKd50C+mCjam/gcnwqL1T1vPx/XQNFlXqFIVdgQdVAFY9iIQtY0IfaVflEYzKiqjeA7B0cYYMaCrmAYFjs4rA==}
engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0}
@ -6101,11 +5936,6 @@ packages:
react: ^18.2.0 react: ^18.2.0
react-dom: ^18.2.0 react-dom: ^18.2.0
react-dom@18.3.1:
resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==}
peerDependencies:
react: ^18.3.1
react-dom@19.1.0: react-dom@19.1.0:
resolution: {integrity: sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==} resolution: {integrity: sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==}
peerDependencies: peerDependencies:
@ -6133,15 +5963,6 @@ packages:
peerDependencies: peerDependencies:
react: '*' react: '*'
react-intl@5.25.1:
resolution: {integrity: sha512-pkjdQDvpJROoXLMltkP/5mZb0/XqrqLoPGKUCfbdkP8m6U9xbK40K51Wu+a4aQqTEvEK5lHBk0fWzUV72SJ3Hg==}
peerDependencies:
react: ^16.3.0 || 17 || 18
typescript: ^4.5
peerDependenciesMeta:
typescript:
optional: true
react-intl@6.8.9: react-intl@6.8.9:
resolution: {integrity: sha512-TUfj5E7lyUDvz/GtovC9OMh441kBr08rtIbgh3p0R8iF3hVY+V2W9Am7rb8BpJ/29BH1utJOqOOhmvEVh3GfZg==} resolution: {integrity: sha512-TUfj5E7lyUDvz/GtovC9OMh441kBr08rtIbgh3p0R8iF3hVY+V2W9Am7rb8BpJ/29BH1utJOqOOhmvEVh3GfZg==}
peerDependencies: peerDependencies:
@ -6197,10 +6018,6 @@ packages:
react: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
react-dom: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
react@18.3.1:
resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==}
engines: {node: '>=0.10.0'}
react@19.1.0: react@19.1.0:
resolution: {integrity: sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==} resolution: {integrity: sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
@ -6387,9 +6204,6 @@ packages:
safer-buffer@2.1.2: safer-buffer@2.1.2:
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
scheduler@0.23.2:
resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==}
scheduler@0.26.0: scheduler@0.26.0:
resolution: {integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==} resolution: {integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==}
@ -6649,19 +6463,6 @@ packages:
style-search@0.1.0: style-search@0.1.0:
resolution: {integrity: sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==} resolution: {integrity: sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==}
styled-jsx@5.1.1:
resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==}
engines: {node: '>= 12.0.0'}
peerDependencies:
'@babel/core': '*'
babel-plugin-macros: '*'
react: '>= 16.8.0 || 17.x.x || ^18.0.0-0'
peerDependenciesMeta:
'@babel/core':
optional: true
babel-plugin-macros:
optional: true
styled-jsx@5.1.6: styled-jsx@5.1.6:
resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==} resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==}
engines: {node: '>= 12.0.0'} engines: {node: '>= 12.0.0'}
@ -7038,10 +6839,6 @@ packages:
walker@1.0.8: walker@1.0.8:
resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==}
watchpack@2.4.0:
resolution: {integrity: sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==}
engines: {node: '>=10.13.0'}
web-streams-polyfill@3.3.3: web-streams-polyfill@3.3.3:
resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==}
engines: {node: '>= 8'} engines: {node: '>= 8'}
@ -7157,21 +6954,6 @@ packages:
zod@3.25.67: zod@3.25.67:
resolution: {integrity: sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==} resolution: {integrity: sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==}
zustand@4.5.7:
resolution: {integrity: sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw==}
engines: {node: '>=12.7.0'}
peerDependencies:
'@types/react': '>=16.8'
immer: '>=9.0.6'
react: '>=16.8'
peerDependenciesMeta:
'@types/react':
optional: true
immer:
optional: true
react:
optional: true
zustand@5.0.5: zustand@5.0.5:
resolution: {integrity: sha512-mILtRfKW9xM47hqxGIxCv12gXusoY/xTSHBYApXozR0HmQv299whhBeeAcRy+KrPPybzosvJBCOmVjq6x12fCg==} resolution: {integrity: sha512-mILtRfKW9xM47hqxGIxCv12gXusoY/xTSHBYApXozR0HmQv299whhBeeAcRy+KrPPybzosvJBCOmVjq6x12fCg==}
engines: {node: '>=12.20.0'} engines: {node: '>=12.20.0'}
@ -7845,10 +7627,6 @@ snapshots:
decimal.js: 10.6.0 decimal.js: 10.6.0
tslib: 2.8.1 tslib: 2.8.1
'@formatjs/fast-memoize@1.2.1':
dependencies:
tslib: 2.8.1
'@formatjs/fast-memoize@2.2.3': '@formatjs/fast-memoize@2.2.3':
dependencies: dependencies:
tslib: 2.8.1 tslib: 2.8.1
@ -7890,24 +7668,12 @@ snapshots:
'@formatjs/ecma402-abstract': 2.2.4 '@formatjs/ecma402-abstract': 2.2.4
tslib: 2.8.1 tslib: 2.8.1
'@formatjs/intl-displaynames@5.4.3':
dependencies:
'@formatjs/ecma402-abstract': 1.11.4
'@formatjs/intl-localematcher': 0.2.25
tslib: 2.8.1
'@formatjs/intl-displaynames@6.8.5': '@formatjs/intl-displaynames@6.8.5':
dependencies: dependencies:
'@formatjs/ecma402-abstract': 2.2.4 '@formatjs/ecma402-abstract': 2.2.4
'@formatjs/intl-localematcher': 0.5.8 '@formatjs/intl-localematcher': 0.5.8
tslib: 2.8.1 tslib: 2.8.1
'@formatjs/intl-listformat@6.5.3':
dependencies:
'@formatjs/ecma402-abstract': 1.11.4
'@formatjs/intl-localematcher': 0.2.25
tslib: 2.8.1
'@formatjs/intl-listformat@7.7.5': '@formatjs/intl-listformat@7.7.5':
dependencies: dependencies:
'@formatjs/ecma402-abstract': 2.2.4 '@formatjs/ecma402-abstract': 2.2.4
@ -7943,18 +7709,6 @@ snapshots:
optionalDependencies: optionalDependencies:
typescript: 5.8.3 typescript: 5.8.3
'@formatjs/intl@2.2.1(typescript@4.9.5)':
dependencies:
'@formatjs/ecma402-abstract': 1.11.4
'@formatjs/fast-memoize': 1.2.1
'@formatjs/icu-messageformat-parser': 2.1.0
'@formatjs/intl-displaynames': 5.4.3
'@formatjs/intl-listformat': 6.5.3
intl-messageformat: 9.13.0
tslib: 2.8.1
optionalDependencies:
typescript: 4.9.5
'@formatjs/ts-transformer@2.13.0(ts-jest@29.4.0(@babel/core@7.27.1)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.1))(esbuild@0.25.5)(jest-util@29.7.0)(jest@29.7.0(@types/node@22.15.32)(ts-node@10.9.2(@types/node@22.15.32)(typescript@5.8.3)))(typescript@5.8.3))': '@formatjs/ts-transformer@2.13.0(ts-jest@29.4.0(@babel/core@7.27.1)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.1))(esbuild@0.25.5)(jest-util@29.7.0)(jest@29.7.0(@types/node@22.15.32)(ts-node@10.9.2(@types/node@22.15.32)(typescript@5.8.3)))(typescript@5.8.3))':
dependencies: dependencies:
intl-messageformat-parser: 6.1.2 intl-messageformat-parser: 6.1.2
@ -8316,62 +8070,33 @@ snapshots:
'@netlify/plugin-nextjs@5.11.3': {} '@netlify/plugin-nextjs@5.11.3': {}
'@next/env@13.5.11': {}
'@next/env@15.3.4': {} '@next/env@15.3.4': {}
'@next/eslint-plugin-next@14.2.30': '@next/eslint-plugin-next@14.2.30':
dependencies: dependencies:
glob: 10.3.10 glob: 10.3.10
'@next/swc-darwin-arm64@13.5.9':
optional: true
'@next/swc-darwin-arm64@15.3.4': '@next/swc-darwin-arm64@15.3.4':
optional: true optional: true
'@next/swc-darwin-x64@13.5.9':
optional: true
'@next/swc-darwin-x64@15.3.4': '@next/swc-darwin-x64@15.3.4':
optional: true optional: true
'@next/swc-linux-arm64-gnu@13.5.9':
optional: true
'@next/swc-linux-arm64-gnu@15.3.4': '@next/swc-linux-arm64-gnu@15.3.4':
optional: true optional: true
'@next/swc-linux-arm64-musl@13.5.9':
optional: true
'@next/swc-linux-arm64-musl@15.3.4': '@next/swc-linux-arm64-musl@15.3.4':
optional: true optional: true
'@next/swc-linux-x64-gnu@13.5.9':
optional: true
'@next/swc-linux-x64-gnu@15.3.4': '@next/swc-linux-x64-gnu@15.3.4':
optional: true optional: true
'@next/swc-linux-x64-musl@13.5.9':
optional: true
'@next/swc-linux-x64-musl@15.3.4': '@next/swc-linux-x64-musl@15.3.4':
optional: true optional: true
'@next/swc-win32-arm64-msvc@13.5.9':
optional: true
'@next/swc-win32-arm64-msvc@15.3.4': '@next/swc-win32-arm64-msvc@15.3.4':
optional: true optional: true
'@next/swc-win32-ia32-msvc@13.5.9':
optional: true
'@next/swc-win32-x64-msvc@13.5.9':
optional: true
'@next/swc-win32-x64-msvc@15.3.4': '@next/swc-win32-x64-msvc@15.3.4':
optional: true optional: true
@ -9728,22 +9453,8 @@ snapshots:
dependencies: dependencies:
tslib: 2.8.1 tslib: 2.8.1
'@swc/helpers@0.5.2':
dependencies:
tslib: 2.8.1
'@tanstack/query-core@4.40.0': {}
'@tanstack/query-core@5.80.10': {} '@tanstack/query-core@5.80.10': {}
'@tanstack/react-query@4.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@tanstack/query-core': 4.40.0
react: 18.3.1
use-sync-external-store: 1.5.0(react@18.3.1)
optionalDependencies:
react-dom: 18.3.1(react@18.3.1)
'@tanstack/react-query@5.80.10(react@19.1.0)': '@tanstack/react-query@5.80.10(react@19.1.0)':
dependencies: dependencies:
'@tanstack/query-core': 5.80.10 '@tanstack/query-core': 5.80.10
@ -10025,7 +9736,7 @@ snapshots:
'@typescript-eslint/types': 8.34.1 '@typescript-eslint/types': 8.34.1
eslint-visitor-keys: 4.2.1 eslint-visitor-keys: 4.2.1
'@umami/react-zen@0.145.0(@babel/core@7.27.1)(@types/react@19.1.8)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0))': '@umami/react-zen@0.147.0(@babel/core@7.27.1)(@types/react@19.1.8)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0))':
dependencies: dependencies:
'@fontsource/jetbrains-mono': 5.2.6 '@fontsource/jetbrains-mono': 5.2.6
'@internationalized/date': 3.8.2 '@internationalized/date': 3.8.2
@ -11848,8 +11559,6 @@ snapshots:
dependencies: dependencies:
is-glob: 4.0.3 is-glob: 4.0.3
glob-to-regexp@0.4.1: {}
glob@10.3.10: glob@10.3.10:
dependencies: dependencies:
foreground-child: 3.3.1 foreground-child: 3.3.1
@ -12079,13 +11788,6 @@ snapshots:
'@formatjs/icu-messageformat-parser': 2.9.4 '@formatjs/icu-messageformat-parser': 2.9.4
tslib: 2.8.1 tslib: 2.8.1
intl-messageformat@9.13.0:
dependencies:
'@formatjs/ecma402-abstract': 1.11.4
'@formatjs/fast-memoize': 1.2.1
'@formatjs/icu-messageformat-parser': 2.1.0
tslib: 2.8.1
ipaddr.js@2.2.0: {} ipaddr.js@2.2.0: {}
is-array-buffer@3.0.5: is-array-buffer@3.0.5:
@ -13062,12 +12764,6 @@ snapshots:
mmdb-lib@2.2.1: {} mmdb-lib@2.2.1: {}
moment-timezone@0.5.48:
dependencies:
moment: 2.30.1
moment@2.30.1: {}
ms@2.1.2: {} ms@2.1.2: {}
ms@2.1.3: {} ms@2.1.3: {}
@ -13078,40 +12774,6 @@ snapshots:
natural-compare@1.4.0: {} natural-compare@1.4.0: {}
next-basics@0.36.0(next@13.5.11(@babel/core@7.27.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
dependencies:
bcryptjs: 2.4.3
jsonwebtoken: 9.0.2
next: 13.5.11(@babel/core@7.27.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
pure-rand: 6.1.0
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
next@13.5.11(@babel/core@7.27.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
dependencies:
'@next/env': 13.5.11
'@swc/helpers': 0.5.2
busboy: 1.6.0
caniuse-lite: 1.0.30001727
postcss: 8.4.31
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
styled-jsx: 5.1.1(@babel/core@7.27.1)(react@18.3.1)
watchpack: 2.4.0
optionalDependencies:
'@next/swc-darwin-arm64': 13.5.9
'@next/swc-darwin-x64': 13.5.9
'@next/swc-linux-arm64-gnu': 13.5.9
'@next/swc-linux-arm64-musl': 13.5.9
'@next/swc-linux-x64-gnu': 13.5.9
'@next/swc-linux-x64-musl': 13.5.9
'@next/swc-win32-arm64-msvc': 13.5.9
'@next/swc-win32-ia32-msvc': 13.5.9
'@next/swc-win32-x64-msvc': 13.5.9
transitivePeerDependencies:
- '@babel/core'
- babel-plugin-macros
next@15.3.4(@babel/core@7.27.1)(babel-plugin-react-compiler@19.1.0-rc.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0): next@15.3.4(@babel/core@7.27.1)(babel-plugin-react-compiler@19.1.0-rc.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
dependencies: dependencies:
'@next/env': 15.3.4 '@next/env': 15.3.4
@ -13997,12 +13659,6 @@ snapshots:
react-hook-form: 7.56.4(react@19.1.0) react-hook-form: 7.56.4(react@19.1.0)
react-window: 1.8.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0) react-window: 1.8.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
react-dom@18.3.1(react@18.3.1):
dependencies:
loose-envify: 1.4.0
react: 18.3.1
scheduler: 0.23.2
react-dom@19.1.0(react@19.1.0): react-dom@19.1.0(react@19.1.0):
dependencies: dependencies:
react: 19.1.0 react: 19.1.0
@ -14025,22 +13681,6 @@ snapshots:
dependencies: dependencies:
react: 19.1.0 react: 19.1.0
react-intl@5.25.1(react@18.3.1)(typescript@4.9.5):
dependencies:
'@formatjs/ecma402-abstract': 1.11.4
'@formatjs/icu-messageformat-parser': 2.1.0
'@formatjs/intl': 2.2.1(typescript@4.9.5)
'@formatjs/intl-displaynames': 5.4.3
'@formatjs/intl-listformat': 6.5.3
'@types/hoist-non-react-statics': 3.3.6
'@types/react': 18.3.23
hoist-non-react-statics: 3.3.2
intl-messageformat: 9.13.0
react: 18.3.1
tslib: 2.8.1
optionalDependencies:
typescript: 4.9.5
react-intl@6.8.9(react@19.1.0)(typescript@5.8.3): react-intl@6.8.9(react@19.1.0)(typescript@5.8.3):
dependencies: dependencies:
'@formatjs/ecma402-abstract': 2.2.4 '@formatjs/ecma402-abstract': 2.2.4
@ -14123,10 +13763,6 @@ snapshots:
react: 19.1.0 react: 19.1.0
react-dom: 19.1.0(react@19.1.0) react-dom: 19.1.0(react@19.1.0)
react@18.3.1:
dependencies:
loose-envify: 1.4.0
react@19.1.0: {} react@19.1.0: {}
read-babelrc-up@1.1.0: read-babelrc-up@1.1.0:
@ -14360,10 +13996,6 @@ snapshots:
safer-buffer@2.1.2: {} safer-buffer@2.1.2: {}
scheduler@0.23.2:
dependencies:
loose-envify: 1.4.0
scheduler@0.26.0: {} scheduler@0.26.0: {}
schema-utils@2.7.1: schema-utils@2.7.1:
@ -14682,13 +14314,6 @@ snapshots:
style-search@0.1.0: {} style-search@0.1.0: {}
styled-jsx@5.1.1(@babel/core@7.27.1)(react@18.3.1):
dependencies:
client-only: 0.0.1
react: 18.3.1
optionalDependencies:
'@babel/core': 7.27.1
styled-jsx@5.1.6(@babel/core@7.27.1)(react@19.1.0): styled-jsx@5.1.6(@babel/core@7.27.1)(react@19.1.0):
dependencies: dependencies:
client-only: 0.0.1 client-only: 0.0.1
@ -15070,10 +14695,6 @@ snapshots:
dependencies: dependencies:
react: 19.1.0 react: 19.1.0
use-sync-external-store@1.5.0(react@18.3.1):
dependencies:
react: 18.3.1
use-sync-external-store@1.5.0(react@19.1.0): use-sync-external-store@1.5.0(react@19.1.0):
dependencies: dependencies:
react: 19.1.0 react: 19.1.0
@ -15119,11 +14740,6 @@ snapshots:
dependencies: dependencies:
makeerror: 1.0.12 makeerror: 1.0.12
watchpack@2.4.0:
dependencies:
glob-to-regexp: 0.4.1
graceful-fs: 4.2.11
web-streams-polyfill@3.3.3: {} web-streams-polyfill@3.3.3: {}
which-boxed-primitive@1.1.1: which-boxed-primitive@1.1.1:
@ -15265,14 +14881,6 @@ snapshots:
zod@3.25.67: {} zod@3.25.67: {}
zustand@4.5.7(@types/react@19.1.8)(immer@9.0.21)(react@18.3.1):
dependencies:
use-sync-external-store: 1.5.0(react@18.3.1)
optionalDependencies:
'@types/react': 19.1.8
immer: 9.0.21
react: 18.3.1
zustand@5.0.5(@types/react@19.1.8)(immer@9.0.21)(react@19.1.0)(use-sync-external-store@1.5.0(react@19.1.0)): zustand@5.0.5(@types/react@19.1.8)(immer@9.0.21)(react@19.1.0)(use-sync-external-store@1.5.0(react@19.1.0)):
optionalDependencies: optionalDependencies:
'@types/react': 19.1.8 '@types/react': 19.1.8

View file

@ -1,14 +1,5 @@
import { useMessages, useModified } from '@/components/hooks'; import { useMessages, useModified } from '@/components/hooks';
import { import { Button, Icon, Modal, Dialog, DialogTrigger, Text, useToast } from '@umami/react-zen';
Button,
Icon,
Modal,
Dialog,
DialogTrigger,
Text,
Column,
useToast,
} from '@umami/react-zen';
import { Plus } from '@/components/icons'; import { Plus } from '@/components/icons';
import { WebsiteAddForm } from './WebsiteAddForm'; import { WebsiteAddForm } from './WebsiteAddForm';
@ -33,11 +24,7 @@ export function WebsiteAddButton({ teamId, onSave }: { teamId: string; onSave?:
</Button> </Button>
<Modal> <Modal>
<Dialog title={formatMessage(labels.addWebsite)} style={{ width: 400 }}> <Dialog title={formatMessage(labels.addWebsite)} style={{ width: 400 }}>
{({ close }) => ( {({ close }) => <WebsiteAddForm teamId={teamId} onSave={handleSave} onClose={close} />}
<Column width="300px">
<WebsiteAddForm teamId={teamId} onSave={handleSave} onClose={close} />
</Column>
)}
</Dialog> </Dialog>
</Modal> </Modal>
</DialogTrigger> </DialogTrigger>

View file

@ -1,21 +1,15 @@
'use client'; 'use client';
import { Column } from '@umami/react-zen'; import { Column } from '@umami/react-zen';
import { useLoginQuery, useMessages } from '@/components/hooks'; import { useMessages } from '@/components/hooks';
import { WebsitesDataTable } from './WebsitesDataTable'; import { WebsitesDataTable } from './WebsitesDataTable';
import { ROLES } from '@/lib/constants';
import { SectionHeader } from '@/components/common/SectionHeader'; import { SectionHeader } from '@/components/common/SectionHeader';
import { WebsiteAddButton } from './WebsiteAddButton';
export function WebsitesSettingsPage({ teamId }: { teamId: string }) { export function WebsitesSettingsPage({ teamId }: { teamId: string }) {
const { user } = useLoginQuery();
const canCreate = user.role !== ROLES.viewOnly;
const { formatMessage, labels } = useMessages(); const { formatMessage, labels } = useMessages();
return ( return (
<Column gap> <Column gap>
<SectionHeader title={formatMessage(labels.websites)}> <SectionHeader title={formatMessage(labels.websites)} />
{canCreate && <WebsiteAddButton teamId={teamId} />}
</SectionHeader>
<WebsitesDataTable teamId={teamId} /> <WebsitesDataTable teamId={teamId} />
</Column> </Column>
); );

View file

@ -4,14 +4,12 @@ import { Column } from '@umami/react-zen';
import { WebsiteProvider } from './WebsiteProvider'; import { WebsiteProvider } from './WebsiteProvider';
import { PageBody } from '@/components/common/PageBody'; import { PageBody } from '@/components/common/PageBody';
import { WebsiteHeader } from './WebsiteHeader'; import { WebsiteHeader } from './WebsiteHeader';
import { WebsiteTabs } from './WebsiteTabs';
export function WebsiteLayout({ websiteId, children }: { websiteId: string; children: ReactNode }) { export function WebsiteLayout({ websiteId, children }: { websiteId: string; children: ReactNode }) {
return ( return (
<WebsiteProvider websiteId={websiteId}> <WebsiteProvider websiteId={websiteId}>
<PageBody> <PageBody>
<WebsiteHeader /> <WebsiteHeader />
<WebsiteTabs />
<Column>{children}</Column> <Column>{children}</Column>
</PageBody> </PageBody>
</WebsiteProvider> </WebsiteProvider>

View file

@ -13,8 +13,8 @@ export function EventsDataTable({
children?: ReactNode; children?: ReactNode;
}) { }) {
const { formatMessage, labels } = useMessages(); const { formatMessage, labels } = useMessages();
const query = useWebsiteEventsQuery(websiteId);
const [view, setView] = useState('all'); const [view, setView] = useState('all');
const query = useWebsiteEventsQuery(websiteId);
const buttons = [ const buttons = [
{ {

View file

@ -1,5 +1,5 @@
import { DataTable, DataColumn, Icon, Row } from '@umami/react-zen'; import { DataTable, DataColumn, Icon, Row } from '@umami/react-zen';
import { useMessages, useNavigation } from '@/components/hooks'; import { useFormat, useMessages, useNavigation } from '@/components/hooks';
import { Empty } from '@/components/common/Empty'; import { Empty } from '@/components/common/Empty';
import { Avatar } from '@/components/common/Avatar'; import { Avatar } from '@/components/common/Avatar';
import Link from 'next/link'; import Link from 'next/link';
@ -10,6 +10,7 @@ import { TypeIcon } from '@/components/common/TypeIcon';
export function EventsTable({ data = [] }) { export function EventsTable({ data = [] }) {
const { formatMessage, labels } = useMessages(); const { formatMessage, labels } = useMessages();
const { renderUrl } = useNavigation(); const { renderUrl } = useNavigation();
const { formatValue } = useFormat();
if (data.length === 0) { if (data.length === 0) {
return <Empty />; return <Empty />;
@ -20,7 +21,10 @@ export function EventsTable({ data = [] }) {
<DataColumn id="event" label={formatMessage(labels.event)} width="2fr"> <DataColumn id="event" label={formatMessage(labels.event)} width="2fr">
{(row: any) => { {(row: any) => {
return ( return (
<Row alignItems="center" gap="2"> <Row alignItems="center" gap>
<Link href={renderUrl(`/websites/${row.websiteId}/sessions/${row.sessionId}`)}>
<Avatar seed={row.sessionId} size={32} />
</Link>
<Icon>{row.eventName ? <Bolt /> : <Eye />}</Icon> <Icon>{row.eventName ? <Bolt /> : <Eye />}</Icon>
{formatMessage(row.eventName ? labels.triggeredEvent : labels.viewedPage)} {formatMessage(row.eventName ? labels.triggeredEvent : labels.viewedPage)}
<strong>{row.eventName || row.urlPath}</strong> <strong>{row.eventName || row.urlPath}</strong>
@ -28,22 +32,30 @@ export function EventsTable({ data = [] }) {
); );
}} }}
</DataColumn> </DataColumn>
<DataColumn id="created" width="1fr" align="end"> <DataColumn id="location" label={formatMessage(labels.location)}>
{(row: any) => ( {(row: any) => (
<Row alignItems="center" gap> <TypeIcon type="country" value={row.country}>
<DateDistance date={new Date(row.createdAt)} /> {row.city ? `${row.city}, ` : ''} {formatValue(row.country, 'country')}
<Link href={renderUrl(`/websites/${row.websiteId}/sessions/${row.sessionId}`)}> </TypeIcon>
<Avatar seed={row.sessionId} size={32} />
</Link>
<Row alignItems="center" gap="1">
<TypeIcon type="country" value={row.country} />
<TypeIcon type="browser" value={row.browser} />
<TypeIcon type="os" value={row.os} />
<TypeIcon type="device" value={row.device} />
</Row>
</Row>
)} )}
</DataColumn> </DataColumn>
<DataColumn id="browser" label={formatMessage(labels.browser)}>
{(row: any) => (
<TypeIcon type="browser" value={row.browser}>
{formatValue(row.browser, 'browser')}
</TypeIcon>
)}
</DataColumn>
<DataColumn id="device" label={formatMessage(labels.device)}>
{(row: any) => (
<TypeIcon type="device" value={row.device}>
{formatValue(row.device, 'device')}
</TypeIcon>
)}
</DataColumn>
<DataColumn id="created" width="160px" align="end">
{(row: any) => <DateDistance date={new Date(row.createdAt)} />}
</DataColumn>
</DataTable> </DataTable>
); );
} }

View file

@ -14,7 +14,7 @@ export function SessionsTable({ data = [] }: { data: any[]; showDomain?: boolean
<DataColumn id="id" label={formatMessage(labels.session)} width="100px"> <DataColumn id="id" label={formatMessage(labels.session)} width="100px">
{(row: any) => ( {(row: any) => (
<Link href={`sessions/${row.id}`}> <Link href={`sessions/${row.id}`}>
<Avatar seed={row.id} size={48} /> <Avatar seed={row.id} size={32} />
</Link> </Link>
)} )}
</DataColumn> </DataColumn>

View file

@ -13,7 +13,7 @@ import {
} from '@umami/react-zen'; } from '@umami/react-zen';
import { LoadingPanel } from '@/components/common/LoadingPanel'; import { LoadingPanel } from '@/components/common/LoadingPanel';
import { Bolt, Eye, FileText } from '@/components/icons'; import { Bolt, Eye, FileText } from '@/components/icons';
import { useSessionActivityQuery, useTimezone } from '@/components/hooks'; import { useMessages, useSessionActivityQuery, useTimezone } from '@/components/hooks';
import { EventData } from '@/components/metrics/EventData'; import { EventData } from '@/components/metrics/EventData';
export function SessionActivity({ export function SessionActivity({
@ -27,6 +27,7 @@ export function SessionActivity({
startDate: Date; startDate: Date;
endDate: Date; endDate: Date;
}) { }) {
const { formatMessage, labels } = useMessages();
const { formatTimezoneDate } = useTimezone(); const { formatTimezoneDate } = useTimezone();
const { data, isLoading, error } = useSessionActivityQuery( const { data, isLoading, error } = useSessionActivityQuery(
websiteId, websiteId,
@ -50,9 +51,14 @@ export function SessionActivity({
<StatusLight color={`#${visitId?.substring(0, 6)}`}> <StatusLight color={`#${visitId?.substring(0, 6)}`}>
{formatTimezoneDate(createdAt, 'pp')} {formatTimezoneDate(createdAt, 'pp')}
</StatusLight> </StatusLight>
<Row alignItems="center" gap> <Row alignItems="center" gap="2">
<Icon>{eventName ? <Bolt /> : <Eye />}</Icon> <Icon>{eventName ? <Bolt /> : <Eye />}</Icon>
<Text>{eventName || urlPath}</Text> <Text>
{eventName
? formatMessage(labels.triggeredEvent)
: formatMessage(labels.viewedPage)}
</Text>
<Text weight="bold">{eventName || urlPath}</Text>
{hasData > 0 && <PropertiesButton websiteId={websiteId} eventId={eventId} />} {hasData > 0 && <PropertiesButton websiteId={websiteId} eventId={eventId} />}
</Row> </Row>
</Row> </Row>

View file

@ -44,6 +44,13 @@ export function SessionInfo({ data }) {
{data?.city} {data?.city}
</Info> </Info>
<Info
label={formatMessage(labels.browser)}
icon={<TypeIcon type="browser" value={data?.browser} />}
>
{formatValue(data?.browser, 'browser')}
</Info>
<Info <Info
label={formatMessage(labels.os)} label={formatMessage(labels.os)}
icon={<TypeIcon type="os" value={data?.os?.toLowerCase()?.replaceAll(/\W/g, '-')} />} icon={<TypeIcon type="os" value={data?.os?.toLowerCase()?.replaceAll(/\W/g, '-')} />}
@ -57,13 +64,6 @@ export function SessionInfo({ data }) {
> >
{formatValue(data?.device, 'device')} {formatValue(data?.device, 'device')}
</Info> </Info>
<Info
label={formatMessage(labels.browser)}
icon={<TypeIcon type="browser" value={data?.browser} />}
>
{formatValue(data?.browser, 'browser')}
</Info>
</Column> </Column>
); );
} }

View file

@ -21,12 +21,14 @@ export async function GET(
return unauthorized(); return unauthorized();
} }
const filters = await getQueryFilters({ const filters = await getQueryFilters(
...query, {
...query,
startAt: subMinutes(startOfMinute(new Date()), REALTIME_RANGE).getTime(),
endAt: Date.now(),
},
websiteId, websiteId,
startAt: subMinutes(startOfMinute(new Date()), REALTIME_RANGE).getTime(), );
endAt: Date.now(),
});
const data = await getRealtimeData(websiteId, filters); const data = await getRealtimeData(websiteId, filters);

View file

@ -18,7 +18,7 @@ export async function POST(request: Request) {
} }
const parameters = await setWebsiteDate(websiteId, body.parameters); const parameters = await setWebsiteDate(websiteId, body.parameters);
const filters = await getQueryFilters(body.filters); const filters = await getQueryFilters(body.filters, websiteId);
const data = await getAttribution(websiteId, parameters as AttributionParameters, filters); const data = await getAttribution(websiteId, parameters as AttributionParameters, filters);

View file

@ -18,7 +18,7 @@ export async function POST(request: Request) {
} }
const parameters = await setWebsiteDate(websiteId, body.parameters); const parameters = await setWebsiteDate(websiteId, body.parameters);
const filters = await getQueryFilters(body.filters); const filters = await getQueryFilters(body.filters, websiteId);
const data = await getBreakdown(websiteId, parameters as BreakdownParameters, filters); const data = await getBreakdown(websiteId, parameters as BreakdownParameters, filters);

View file

@ -18,7 +18,7 @@ export async function POST(request: Request) {
} }
const parameters = await setWebsiteDate(websiteId, body.parameters); const parameters = await setWebsiteDate(websiteId, body.parameters);
const filters = await getQueryFilters(body.filters); const filters = await getQueryFilters(body.filters, websiteId);
const data = await getFunnel(websiteId, parameters as FunnelParameters, filters); const data = await getFunnel(websiteId, parameters as FunnelParameters, filters);

View file

@ -18,7 +18,7 @@ export async function POST(request: Request) {
} }
const parameters = await setWebsiteDate(websiteId, body.parameters); const parameters = await setWebsiteDate(websiteId, body.parameters);
const filters = await getQueryFilters(body.filters); const filters = await getQueryFilters(body.filters, websiteId);
const data = await getGoal(websiteId, parameters as GoalParameters, filters); const data = await getGoal(websiteId, parameters as GoalParameters, filters);

View file

@ -1,6 +1,6 @@
import { canViewWebsite } from '@/lib/auth'; import { canViewWebsite } from '@/lib/auth';
import { unauthorized, json } from '@/lib/response'; import { unauthorized, json } from '@/lib/response';
import { getQueryFilters, parseRequest, setWebsiteDate } from '@/lib/request'; import { getQueryFilters, parseRequest } from '@/lib/request';
import { getJourney } from '@/queries'; import { getJourney } from '@/queries';
import { reportResultSchema } from '@/lib/schema'; import { reportResultSchema } from '@/lib/schema';
@ -17,7 +17,7 @@ export async function POST(request: Request) {
return unauthorized(); return unauthorized();
} }
const queryFilters = await setWebsiteDate(websiteId, await getQueryFilters(filters)); const queryFilters = await getQueryFilters(filters, websiteId);
const data = await getJourney(websiteId, parameters, queryFilters); const data = await getJourney(websiteId, parameters, queryFilters);

View file

@ -17,7 +17,7 @@ export async function POST(request: Request) {
return unauthorized(); return unauthorized();
} }
const filters = await getQueryFilters(body.filters); const filters = await getQueryFilters(body.filters, websiteId);
const parameters = await setWebsiteDate(websiteId, body.parameters); const parameters = await setWebsiteDate(websiteId, body.parameters);
const data = await getRetention(websiteId, parameters as RetentionParameters, filters); const data = await getRetention(websiteId, parameters as RetentionParameters, filters);

View file

@ -18,7 +18,7 @@ export async function POST(request: Request) {
} }
const parameters = await setWebsiteDate(websiteId, body.parameters); const parameters = await setWebsiteDate(websiteId, body.parameters);
const filters = await getQueryFilters(body.filters); const filters = await getQueryFilters(body.filters, websiteId);
const data = await getRevenue(websiteId, parameters as RevenuParameters, filters); const data = await getRevenue(websiteId, parameters as RevenuParameters, filters);

View file

@ -18,7 +18,7 @@ export async function POST(request: Request) {
} }
const parameters = await setWebsiteDate(websiteId, body.parameters); const parameters = await setWebsiteDate(websiteId, body.parameters);
const filters = await getQueryFilters(body.filters); const filters = await getQueryFilters(body.filters, websiteId);
const data = await getUTM(websiteId, parameters as UTMParameters, filters); const data = await getUTM(websiteId, parameters as UTMParameters, filters);

View file

@ -26,7 +26,7 @@ export async function GET(
} }
const { event } = query; const { event } = query;
const filters = await getQueryFilters(query); const filters = await getQueryFilters(query, websiteId);
const data = await getEventDataEvents(websiteId, { const data = await getEventDataEvents(websiteId, {
...filters, ...filters,

View file

@ -25,7 +25,7 @@ export async function GET(
return unauthorized(); return unauthorized();
} }
const filters = await getQueryFilters(query); const filters = await getQueryFilters(query, websiteId);
const data = await getEventDataFields(websiteId, filters); const data = await getEventDataFields(websiteId, filters);

View file

@ -27,7 +27,7 @@ export async function GET(
} }
const { propertyName } = query; const { propertyName } = query;
const filters = await getQueryFilters(query); const filters = await getQueryFilters(query, websiteId);
const data = await getEventDataProperties(websiteId, { ...filters, propertyName }); const data = await getEventDataProperties(websiteId, { ...filters, propertyName });

View file

@ -26,7 +26,7 @@ export async function GET(
return unauthorized(); return unauthorized();
} }
const filters = await getQueryFilters(query); const filters = await getQueryFilters(query, websiteId);
const data = await getEventDataStats(websiteId, filters); const data = await getEventDataStats(websiteId, filters);

View file

@ -28,7 +28,7 @@ export async function GET(
} }
const { eventName, propertyName } = query; const { eventName, propertyName } = query;
const filters = await getQueryFilters(query); const filters = await getQueryFilters(query, websiteId);
const data = await getEventDataValues(websiteId, { const data = await getEventDataValues(websiteId, {
...filters, ...filters,

View file

@ -21,13 +21,14 @@ export async function GET(
} }
const { websiteId } = await params; const { websiteId } = await params;
const { propertyName } = query;
const filters = await getQueryFilters(query);
if (!(await canViewWebsite(auth, websiteId))) { if (!(await canViewWebsite(auth, websiteId))) {
return unauthorized(); return unauthorized();
} }
const { propertyName } = query;
const filters = await getQueryFilters(query, websiteId);
const data = await getSessionDataProperties(websiteId, { ...filters, propertyName }); const data = await getSessionDataProperties(websiteId, { ...filters, propertyName });
return json(data); return json(data);

View file

@ -1,5 +1,5 @@
import { canViewWebsite } from '@/lib/auth'; import { canViewWebsite } from '@/lib/auth';
import { getQueryFilters, parseRequest, setWebsiteDate } from '@/lib/request'; import { getQueryFilters, parseRequest } from '@/lib/request';
import { json, unauthorized } from '@/lib/response'; import { json, unauthorized } from '@/lib/response';
import { getSessionDataValues } from '@/queries'; import { getSessionDataValues } from '@/queries';
import { z } from 'zod'; import { z } from 'zod';
@ -20,14 +20,15 @@ export async function GET(
return error(); return error();
} }
const { propertyName } = query;
const { websiteId } = await params; const { websiteId } = await params;
const filters = await setWebsiteDate(websiteId, await getQueryFilters(query));
if (!(await canViewWebsite(auth, websiteId))) { if (!(await canViewWebsite(auth, websiteId))) {
return unauthorized(); return unauthorized();
} }
const { propertyName } = query;
const filters = await getQueryFilters(query, websiteId);
const data = await getSessionDataValues(websiteId, { const data = await getSessionDataValues(websiteId, {
...filters, ...filters,
propertyName, propertyName,

View file

@ -25,7 +25,7 @@ export async function GET(
return unauthorized(); return unauthorized();
} }
const filters = await getQueryFilters(query); const filters = await getQueryFilters(query, websiteId);
const data = await getSessionActivity(websiteId, sessionId, filters); const data = await getSessionActivity(websiteId, sessionId, filters);

View file

@ -1,5 +1,5 @@
import { z } from 'zod'; import { z } from 'zod';
import { getQueryFilters, parseRequest, setWebsiteDate } from '@/lib/request'; import { getQueryFilters, parseRequest } from '@/lib/request';
import { unauthorized, json } from '@/lib/response'; import { unauthorized, json } from '@/lib/response';
import { canViewWebsite } from '@/lib/auth'; import { canViewWebsite } from '@/lib/auth';
import { dateRangeParams, filterParams, pagingParams } from '@/lib/schema'; import { dateRangeParams, filterParams, pagingParams } from '@/lib/schema';
@ -27,7 +27,7 @@ export async function GET(
return unauthorized(); return unauthorized();
} }
const filters = await setWebsiteDate(websiteId, await getQueryFilters(query)); const filters = await getQueryFilters(query, websiteId);
const data = await getWebsiteSessions(websiteId, filters); const data = await getWebsiteSessions(websiteId, filters);

View file

@ -1,5 +1,5 @@
import { z } from 'zod'; import { z } from 'zod';
import { parseRequest, getQueryFilters, setWebsiteDate } from '@/lib/request'; import { parseRequest, getQueryFilters } from '@/lib/request';
import { unauthorized, json } from '@/lib/response'; import { unauthorized, json } from '@/lib/response';
import { canViewWebsite } from '@/lib/auth'; import { canViewWebsite } from '@/lib/auth';
import { filterParams } from '@/lib/schema'; import { filterParams } from '@/lib/schema';
@ -27,7 +27,7 @@ export async function GET(
return unauthorized(); return unauthorized();
} }
const filters = await setWebsiteDate(websiteId, await getQueryFilters(query)); const filters = await getQueryFilters(query, websiteId);
const metrics = await getWebsiteSessionStats(websiteId, filters); const metrics = await getWebsiteSessionStats(websiteId, filters);

View file

@ -28,7 +28,7 @@ export async function GET(
return unauthorized(); return unauthorized();
} }
const filters = await getQueryFilters(query); const filters = await getQueryFilters(query, websiteId);
const data = await getWebsiteSessionsWeekly(websiteId, filters); const data = await getWebsiteSessionsWeekly(websiteId, filters);

View file

@ -39,7 +39,7 @@ export async function GET(
if (FILTER_GROUPS[type]) { if (FILTER_GROUPS[type]) {
values = (await getWebsiteSegments(websiteId, type)).map(segment => ({ value: segment.name })); values = (await getWebsiteSegments(websiteId, type)).map(segment => ({ value: segment.name }));
} else { } else {
const filters = await getQueryFilters(query); const filters = await getQueryFilters(query, websiteId);
values = await getValues(websiteId, FILTER_COLUMNS[type], filters); values = await getValues(websiteId, FILTER_COLUMNS[type], filters);
} }

View file

@ -4,15 +4,24 @@ import { useDateParameters } from '../useDateParameters';
import { usePagedQuery } from '../usePagedQuery'; import { usePagedQuery } from '../usePagedQuery';
import { ReactQueryOptions } from '@/lib/types'; import { ReactQueryOptions } from '@/lib/types';
export function useWebsiteEventsQuery(websiteId: string, options?: ReactQueryOptions<any>) { export function useWebsiteEventsQuery(
websiteId: string,
params?: Record<string, any>,
options?: ReactQueryOptions<any>,
) {
const { get } = useApi(); const { get } = useApi();
const date = useDateParameters(websiteId); const date = useDateParameters(websiteId);
const filters = useFilterParameters(); const filters = useFilterParameters();
return usePagedQuery({ return usePagedQuery({
queryKey: ['websites:events', { websiteId, ...date, ...filters }], queryKey: ['websites:events', { websiteId, ...date, ...filters, ...params }],
queryFn: pageParams => queryFn: pageParams =>
get(`/websites/${websiteId}/events`, { ...date, ...filters, ...pageParams, pageSize: 20 }), get(`/websites/${websiteId}/events`, {
...date,
...filters,
...pageParams,
...params,
}),
enabled: !!websiteId, enabled: !!websiteId,
...options, ...options,
}); });

View file

@ -28,6 +28,7 @@ export function WebsiteSelect({
return ( return (
<Select <Select
{...props} {...props}
placeholder=""
items={data?.['data'] || []} items={data?.['data'] || []}
value={websiteId} value={websiteId}
isLoading={isLoading} isLoading={isLoading}

View file

@ -74,6 +74,7 @@ export const labels = defineMessages({
language: { id: 'label.language', defaultMessage: 'Language' }, language: { id: 'label.language', defaultMessage: 'Language' },
theme: { id: 'label.theme', defaultMessage: 'Theme' }, theme: { id: 'label.theme', defaultMessage: 'Theme' },
profile: { id: 'label.profile', defaultMessage: 'Profile' }, profile: { id: 'label.profile', defaultMessage: 'Profile' },
profiles: { id: 'label.profiles', defaultMessage: 'Profiles' },
dashboard: { id: 'label.dashboard', defaultMessage: 'Dashboard' }, dashboard: { id: 'label.dashboard', defaultMessage: 'Dashboard' },
more: { id: 'label.more', defaultMessage: 'More' }, more: { id: 'label.more', defaultMessage: 'More' },
realtime: { id: 'label.realtime', defaultMessage: 'Realtime' }, realtime: { id: 'label.realtime', defaultMessage: 'Realtime' },
@ -335,6 +336,7 @@ export const labels = defineMessages({
lastClick: { id: 'label.last-click', defaultMessage: 'Last click' }, lastClick: { id: 'label.last-click', defaultMessage: 'Last click' },
online: { id: 'label.online', defaultMessage: 'Online' }, online: { id: 'label.online', defaultMessage: 'Online' },
preferences: { id: 'label.preferences', defaultMessage: 'Preferences' }, preferences: { id: 'label.preferences', defaultMessage: 'Preferences' },
location: { id: 'label.location', defaultMessage: 'Location' },
}); });
export const messages = defineMessages({ export const messages = defineMessages({

View file

@ -105,16 +105,16 @@ export async function getQueryFilters(
): Promise<QueryFilters> { ): Promise<QueryFilters> {
const dateRange = getRequestDateRange(params); const dateRange = getRequestDateRange(params);
const filters = getRequestFilters(params); const filters = getRequestFilters(params);
const segments = websiteId ? await getRequestSegments(websiteId, params) : null;
if (websiteId) { if (websiteId) {
await setWebsiteDate(websiteId, dateRange); await setWebsiteDate(websiteId, dateRange);
Object.assign(filters, await getRequestSegments(websiteId, params));
} }
return { return {
...dateRange, ...dateRange,
...filters, ...filters,
...segments,
page: params?.page, page: params?.page,
pageSize: params?.page ? params?.pageSize || DEFAULT_PAGE_SIZE : undefined, pageSize: params?.page ? params?.pageSize || DEFAULT_PAGE_SIZE : undefined,
orderBy: params?.orderBy, orderBy: params?.orderBy,

View file

@ -17,9 +17,12 @@ async function relationalQuery(
filters: QueryFilters & { propertyName?: string }, filters: QueryFilters & { propertyName?: string },
) { ) {
const { rawQuery, parseFilters } = prisma; const { rawQuery, parseFilters } = prisma;
const { filterQuery, cohortQuery, queryParams } = parseFilters(filters, { const { filterQuery, cohortQuery, queryParams } = parseFilters(
columns: { propertyName: 'data_key' }, { ...filters, websiteId },
}); {
columns: { propertyName: 'data_key' },
},
);
return rawQuery( return rawQuery(
` `
@ -48,9 +51,12 @@ async function clickhouseQuery(
filters: QueryFilters & { propertyName?: string }, filters: QueryFilters & { propertyName?: string },
): Promise<{ eventName: string; propertyName: string; total: number }[]> { ): Promise<{ eventName: string; propertyName: string; total: number }[]> {
const { rawQuery, parseFilters } = clickhouse; const { rawQuery, parseFilters } = clickhouse;
const { filterQuery, cohortQuery, queryParams } = parseFilters(filters, { const { filterQuery, cohortQuery, queryParams } = parseFilters(
columns: { propertyName: 'data_key' }, { ...filters, websiteId },
}); {
columns: { propertyName: 'data_key' },
},
);
return rawQuery( return rawQuery(
` `

View file

@ -36,6 +36,11 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) {
referrer_path as "referrerPath", referrer_path as "referrerPath",
referrer_query as "referrerQuery", referrer_query as "referrerQuery",
referrer_domain as "referrerDomain", referrer_domain as "referrerDomain",
country as country,
city as city,
device as device,
os as os,
browser as browser,
page_title as "pageTitle", page_title as "pageTitle",
event_type as "eventType", event_type as "eventType",
event_name as "eventName" event_name as "eventName"
@ -77,12 +82,14 @@ async function clickhouseQuery(websiteId: string, filters: QueryFilters) {
referrer_query as referrerQuery, referrer_query as referrerQuery,
referrer_domain as referrerDomain, referrer_domain as referrerDomain,
country as country, country as country,
city as city,
device as device, device as device,
os as os, os as os,
browser as browser, browser as browser,
page_title as pageTitle, page_title as pageTitle,
event_type as eventType, event_type as eventType,
event_name as eventName event_name as eventName,
event_id IN (SELECT event_id FROM event_data) AS hasData
from website_event from website_event
${cohortQuery} ${cohortQuery}
where website_id = {websiteId:UUID} where website_id = {websiteId:UUID}

View file

@ -17,9 +17,12 @@ async function relationalQuery(
filters: QueryFilters & { propertyName?: string }, filters: QueryFilters & { propertyName?: string },
) { ) {
const { rawQuery, parseFilters } = prisma; const { rawQuery, parseFilters } = prisma;
const { filterQuery, cohortQuery, queryParams } = parseFilters(filters, { const { filterQuery, cohortQuery, queryParams } = parseFilters(
columns: { propertyName: 'data_key' }, { ...filters, websiteId },
}); {
columns: { propertyName: 'data_key' },
},
);
return rawQuery( return rawQuery(
` `
@ -46,9 +49,12 @@ async function clickhouseQuery(
filters: QueryFilters & { propertyName?: string }, filters: QueryFilters & { propertyName?: string },
): Promise<{ propertyName: string; total: number }[]> { ): Promise<{ propertyName: string; total: number }[]> {
const { rawQuery, parseFilters } = clickhouse; const { rawQuery, parseFilters } = clickhouse;
const { filterQuery, cohortQuery, queryParams } = parseFilters(filters, { const { filterQuery, cohortQuery, queryParams } = parseFilters(
columns: { propertyName: 'data_key' }, { ...filters, websiteId },
}); {
columns: { propertyName: 'data_key' },
},
);
return rawQuery( return rawQuery(
` `