From 52e1440089af5f6bd852f0f8d4c7190ba2f35dde Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Sat, 19 Apr 2025 10:09:59 -0700 Subject: [PATCH] Custom date range select. --- package.json | 4 +- pnpm-lock.yaml | 295 +++++++++--------- src/app/actions/getConfig.ts | 1 + src/components/common/FilterButtons.tsx | 35 ++- src/components/input/WebsiteDateFilter.tsx | 6 +- .../metrics/DatePickerForm.module.css | 44 --- src/components/metrics/DatePickerForm.tsx | 78 +++-- src/components/metrics/PagesTable.tsx | 14 +- .../metrics/QueryParametersTable.tsx | 6 +- src/components/metrics/ReferrersTable.tsx | 36 +-- src/lib/__tests__/charts.test.ts | 42 +-- 11 files changed, 247 insertions(+), 314 deletions(-) delete mode 100644 src/components/metrics/DatePickerForm.module.css diff --git a/package.json b/package.json index 62287ffd..c7303a36 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,7 @@ "@react-spring/web": "^9.7.5", "@tanstack/react-query": "^5.71.10", "@umami/prisma-client": "^0.16.0", - "@umami/react-zen": "^0.83.0", + "@umami/react-zen": "^0.87.0", "@umami/redis-client": "^0.27.0", "bcryptjs": "^2.4.3", "chalk": "^4.1.2", @@ -107,7 +107,7 @@ "lucide-react": "^0.475.0", "maxmind": "^4.3.24", "md5": "^2.3.0", - "next": "15.2.4", + "next": "15.3.0", "node-fetch": "^3.3.2", "npm-run-all": "^4.1.5", "prisma": "6.5.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3dcf2de3..2588db7c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -45,8 +45,8 @@ importers: specifier: ^0.16.0 version: 0.16.0(@prisma/client@6.5.0(prisma@6.5.0(typescript@5.8.3))(typescript@5.8.3))(@prisma/extension-read-replicas@0.4.1(@prisma/client@6.5.0(prisma@6.5.0(typescript@5.8.3))(typescript@5.8.3))) '@umami/react-zen': - specifier: ^0.83.0 - version: 0.83.0(@babel/core@7.26.9)(@types/react@19.1.0)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0)) + specifier: ^0.87.0 + version: 0.87.0(@babel/core@7.26.9)(@types/react@19.1.0)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0)) '@umami/redis-client': specifier: ^0.27.0 version: 0.27.0 @@ -132,8 +132,8 @@ importers: specifier: ^2.3.0 version: 2.3.0 next: - specifier: 15.2.4 - version: 15.2.4(@babel/core@7.26.9)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + specifier: 15.3.0 + version: 15.3.0(@babel/core@7.26.9)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) node-fetch: specifier: ^3.3.2 version: 3.3.2 @@ -1314,8 +1314,8 @@ packages: peerDependencies: '@dicebear/core': ^9.0.0 - '@emnapi/runtime@1.4.0': - resolution: {integrity: sha512-64WYIf4UYcdLnbKn/umDlNjQDSS8AgZrI/R9+x5ilkUVFxXcA1Ebl+gQLc/6mERA4407Xof0R7wEyEuj091CVw==} + '@emnapi/runtime@1.4.3': + resolution: {integrity: sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==} '@esbuild/aix-ppc64@0.25.2': resolution: {integrity: sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==} @@ -1580,107 +1580,112 @@ packages: resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} deprecated: Use @eslint/object-schema instead - '@img/sharp-darwin-arm64@0.33.5': - resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==} + '@img/sharp-darwin-arm64@0.34.1': + resolution: {integrity: sha512-pn44xgBtgpEbZsu+lWf2KNb6OAf70X68k+yk69Ic2Xz11zHR/w24/U49XT7AeRwJ0Px+mhALhU5LPci1Aymk7A==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [darwin] - '@img/sharp-darwin-x64@0.33.5': - resolution: {integrity: sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==} + '@img/sharp-darwin-x64@0.34.1': + resolution: {integrity: sha512-VfuYgG2r8BpYiOUN+BfYeFo69nP/MIwAtSJ7/Zpxc5QF3KS22z8Pvg3FkrSFJBPNQ7mmcUcYQFBmEQp7eu1F8Q==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [darwin] - '@img/sharp-libvips-darwin-arm64@1.0.4': - resolution: {integrity: sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==} + '@img/sharp-libvips-darwin-arm64@1.1.0': + resolution: {integrity: sha512-HZ/JUmPwrJSoM4DIQPv/BfNh9yrOA8tlBbqbLz4JZ5uew2+o22Ik+tHQJcih7QJuSa0zo5coHTfD5J8inqj9DA==} cpu: [arm64] os: [darwin] - '@img/sharp-libvips-darwin-x64@1.0.4': - resolution: {integrity: sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==} + '@img/sharp-libvips-darwin-x64@1.1.0': + resolution: {integrity: sha512-Xzc2ToEmHN+hfvsl9wja0RlnXEgpKNmftriQp6XzY/RaSfwD9th+MSh0WQKzUreLKKINb3afirxW7A0fz2YWuQ==} cpu: [x64] os: [darwin] - '@img/sharp-libvips-linux-arm64@1.0.4': - resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==} + '@img/sharp-libvips-linux-arm64@1.1.0': + resolution: {integrity: sha512-IVfGJa7gjChDET1dK9SekxFFdflarnUB8PwW8aGwEoF3oAsSDuNUTYS+SKDOyOJxQyDC1aPFMuRYLoDInyV9Ew==} cpu: [arm64] os: [linux] - '@img/sharp-libvips-linux-arm@1.0.5': - resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==} + '@img/sharp-libvips-linux-arm@1.1.0': + resolution: {integrity: sha512-s8BAd0lwUIvYCJyRdFqvsj+BJIpDBSxs6ivrOPm/R7piTs5UIwY5OjXrP2bqXC9/moGsyRa37eYWYCOGVXxVrA==} cpu: [arm] os: [linux] - '@img/sharp-libvips-linux-s390x@1.0.4': - resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==} + '@img/sharp-libvips-linux-ppc64@1.1.0': + resolution: {integrity: sha512-tiXxFZFbhnkWE2LA8oQj7KYR+bWBkiV2nilRldT7bqoEZ4HiDOcePr9wVDAZPi/Id5fT1oY9iGnDq20cwUz8lQ==} + cpu: [ppc64] + os: [linux] + + '@img/sharp-libvips-linux-s390x@1.1.0': + resolution: {integrity: sha512-xukSwvhguw7COyzvmjydRb3x/09+21HykyapcZchiCUkTThEQEOMtBj9UhkaBRLuBrgLFzQ2wbxdeCCJW/jgJA==} cpu: [s390x] os: [linux] - '@img/sharp-libvips-linux-x64@1.0.4': - resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==} + '@img/sharp-libvips-linux-x64@1.1.0': + resolution: {integrity: sha512-yRj2+reB8iMg9W5sULM3S74jVS7zqSzHG3Ol/twnAAkAhnGQnpjj6e4ayUz7V+FpKypwgs82xbRdYtchTTUB+Q==} cpu: [x64] os: [linux] - '@img/sharp-libvips-linuxmusl-arm64@1.0.4': - resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==} + '@img/sharp-libvips-linuxmusl-arm64@1.1.0': + resolution: {integrity: sha512-jYZdG+whg0MDK+q2COKbYidaqW/WTz0cc1E+tMAusiDygrM4ypmSCjOJPmFTvHHJ8j/6cAGyeDWZOsK06tP33w==} cpu: [arm64] os: [linux] - '@img/sharp-libvips-linuxmusl-x64@1.0.4': - resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==} + '@img/sharp-libvips-linuxmusl-x64@1.1.0': + resolution: {integrity: sha512-wK7SBdwrAiycjXdkPnGCPLjYb9lD4l6Ze2gSdAGVZrEL05AOUJESWU2lhlC+Ffn5/G+VKuSm6zzbQSzFX/P65A==} cpu: [x64] os: [linux] - '@img/sharp-linux-arm64@0.33.5': - resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==} + '@img/sharp-linux-arm64@0.34.1': + resolution: {integrity: sha512-kX2c+vbvaXC6vly1RDf/IWNXxrlxLNpBVWkdpRq5Ka7OOKj6nr66etKy2IENf6FtOgklkg9ZdGpEu9kwdlcwOQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] - '@img/sharp-linux-arm@0.33.5': - resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==} + '@img/sharp-linux-arm@0.34.1': + resolution: {integrity: sha512-anKiszvACti2sGy9CirTlNyk7BjjZPiML1jt2ZkTdcvpLU1YH6CXwRAZCA2UmRXnhiIftXQ7+Oh62Ji25W72jA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm] os: [linux] - '@img/sharp-linux-s390x@0.33.5': - resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==} + '@img/sharp-linux-s390x@0.34.1': + resolution: {integrity: sha512-7s0KX2tI9mZI2buRipKIw2X1ufdTeaRgwmRabt5bi9chYfhur+/C1OXg3TKg/eag1W+6CCWLVmSauV1owmRPxA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [s390x] os: [linux] - '@img/sharp-linux-x64@0.33.5': - resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==} + '@img/sharp-linux-x64@0.34.1': + resolution: {integrity: sha512-wExv7SH9nmoBW3Wr2gvQopX1k8q2g5V5Iag8Zk6AVENsjwd+3adjwxtp3Dcu2QhOXr8W9NusBU6XcQUohBZ5MA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] - '@img/sharp-linuxmusl-arm64@0.33.5': - resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==} + '@img/sharp-linuxmusl-arm64@0.34.1': + resolution: {integrity: sha512-DfvyxzHxw4WGdPiTF0SOHnm11Xv4aQexvqhRDAoD00MzHekAj9a/jADXeXYCDFH/DzYruwHbXU7uz+H+nWmSOQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] - '@img/sharp-linuxmusl-x64@0.33.5': - resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==} + '@img/sharp-linuxmusl-x64@0.34.1': + resolution: {integrity: sha512-pax/kTR407vNb9qaSIiWVnQplPcGU8LRIJpDT5o8PdAx5aAA7AS3X9PS8Isw1/WfqgQorPotjrZL3Pqh6C5EBg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] - '@img/sharp-wasm32@0.33.5': - resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==} + '@img/sharp-wasm32@0.34.1': + resolution: {integrity: sha512-YDybQnYrLQfEpzGOQe7OKcyLUCML4YOXl428gOOzBgN6Gw0rv8dpsJ7PqTHxBnXnwXr8S1mYFSLSa727tpz0xg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [wasm32] - '@img/sharp-win32-ia32@0.33.5': - resolution: {integrity: sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==} + '@img/sharp-win32-ia32@0.34.1': + resolution: {integrity: sha512-WKf/NAZITnonBf3U1LfdjoMgNO5JYRSlhovhRhMxXVdvWYveM4kM3L8m35onYIdh75cOMCo1BexgVQcCDzyoWw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [ia32] os: [win32] - '@img/sharp-win32-x64@0.33.5': - resolution: {integrity: sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==} + '@img/sharp-win32-x64@0.34.1': + resolution: {integrity: sha512-hw1iIAHpNE8q3uMIRCgGOeDoz9KtFNarFLQclLxr/LK1VBkj8nby18RjFvr6aP7USRYAjTZW6yisnBWMX571Tw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [win32] @@ -1809,56 +1814,56 @@ packages: resolution: {integrity: sha512-0c4Y6Td2YcWjVaIwvJNNWqV8RJJ6uV/8DvKL2Czbp5Pp6KZ9TEIevexfzFSEZG1VgU6bgUUDAIPI2xFKN2Op8A==} engines: {node: '>=18.0.0'} - '@next/env@15.2.4': - resolution: {integrity: sha512-+SFtMgoiYP3WoSswuNmxJOCwi06TdWE733D+WPjpXIe4LXGULwEaofiiAy6kbS0+XjM5xF5n3lKuBwN2SnqD9g==} + '@next/env@15.3.0': + resolution: {integrity: sha512-6mDmHX24nWlHOlbwUiAOmMyY7KELimmi+ed8qWcJYjqXeC+G6JzPZ3QosOAfjNwgMIzwhXBiRiCgdh8axTTdTA==} '@next/eslint-plugin-next@14.2.26': resolution: {integrity: sha512-SPEj1O5DAVTPaWD9XPupelfT2APNIgcDYD2OzEm328BEmHaglhmYNUvxhzfJYDr12AgAfW4V3UHSV93qaeELJA==} - '@next/swc-darwin-arm64@15.2.4': - resolution: {integrity: sha512-1AnMfs655ipJEDC/FHkSr0r3lXBgpqKo4K1kiwfUf3iE68rDFXZ1TtHdMvf7D0hMItgDZ7Vuq3JgNMbt/+3bYw==} + '@next/swc-darwin-arm64@15.3.0': + resolution: {integrity: sha512-PDQcByT0ZfF2q7QR9d+PNj3wlNN4K6Q8JoHMwFyk252gWo4gKt7BF8Y2+KBgDjTFBETXZ/TkBEUY7NIIY7A/Kw==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@next/swc-darwin-x64@15.2.4': - resolution: {integrity: sha512-3qK2zb5EwCwxnO2HeO+TRqCubeI/NgCe+kL5dTJlPldV/uwCnUgC7VbEzgmxbfrkbjehL4H9BPztWOEtsoMwew==} + '@next/swc-darwin-x64@15.3.0': + resolution: {integrity: sha512-m+eO21yg80En8HJ5c49AOQpFDq+nP51nu88ZOMCorvw3g//8g1JSUsEiPSiFpJo1KCTQ+jm9H0hwXK49H/RmXg==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@next/swc-linux-arm64-gnu@15.2.4': - resolution: {integrity: sha512-HFN6GKUcrTWvem8AZN7tT95zPb0GUGv9v0d0iyuTb303vbXkkbHDp/DxufB04jNVD+IN9yHy7y/6Mqq0h0YVaQ==} + '@next/swc-linux-arm64-gnu@15.3.0': + resolution: {integrity: sha512-H0Kk04ZNzb6Aq/G6e0un4B3HekPnyy6D+eUBYPJv9Abx8KDYgNMWzKt4Qhj57HXV3sTTjsfc1Trc1SxuhQB+Tg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-arm64-musl@15.2.4': - resolution: {integrity: sha512-Oioa0SORWLwi35/kVB8aCk5Uq+5/ZIumMK1kJV+jSdazFm2NzPDztsefzdmzzpx5oGCJ6FkUC7vkaUseNTStNA==} + '@next/swc-linux-arm64-musl@15.3.0': + resolution: {integrity: sha512-k8GVkdMrh/+J9uIv/GpnHakzgDQhrprJ/FbGQvwWmstaeFG06nnAoZCJV+wO/bb603iKV1BXt4gHG+s2buJqZA==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-x64-gnu@15.2.4': - resolution: {integrity: sha512-yb5WTRaHdkgOqFOZiu6rHV1fAEK0flVpaIN2HB6kxHVSy/dIajWbThS7qON3W9/SNOH2JWkVCyulgGYekMePuw==} + '@next/swc-linux-x64-gnu@15.3.0': + resolution: {integrity: sha512-ZMQ9yzDEts/vkpFLRAqfYO1wSpIJGlQNK9gZ09PgyjBJUmg8F/bb8fw2EXKgEaHbCc4gmqMpDfh+T07qUphp9A==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-linux-x64-musl@15.2.4': - resolution: {integrity: sha512-Dcdv/ix6srhkM25fgXiyOieFUkz+fOYkHlydWCtB0xMST6X9XYI3yPDKBZt1xuhOytONsIFJFB08xXYsxUwJLw==} + '@next/swc-linux-x64-musl@15.3.0': + resolution: {integrity: sha512-RFwq5VKYTw9TMr4T3e5HRP6T4RiAzfDJ6XsxH8j/ZeYq2aLsBqCkFzwMI0FmnSsLaUbOb46Uov0VvN3UciHX5A==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-win32-arm64-msvc@15.2.4': - resolution: {integrity: sha512-dW0i7eukvDxtIhCYkMrZNQfNicPDExt2jPb9AZPpL7cfyUo7QSNl1DjsHjmmKp6qNAqUESyT8YFl/Aw91cNJJg==} + '@next/swc-win32-arm64-msvc@15.3.0': + resolution: {integrity: sha512-a7kUbqa/k09xPjfCl0RSVAvEjAkYBYxUzSVAzk2ptXiNEL+4bDBo9wNC43G/osLA/EOGzG4CuNRFnQyIHfkRgQ==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@next/swc-win32-x64-msvc@15.2.4': - resolution: {integrity: sha512-SbnWkJmkS7Xl3kre8SdMF6F/XDh1DTFEhp0jRTj/uB8iPKoU2bb2NDfcu+iifv1+mxQEd1g2vvSxcZbXSKyWiQ==} + '@next/swc-win32-x64-msvc@15.3.0': + resolution: {integrity: sha512-vHUQS4YVGJPmpjn7r5lEZuMhK5UQBNBRSB+iGDvJjaNk649pTIcRluDWNb9siunyLLiu/LDPHfvxBtNamyuLTw==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -2952,8 +2957,8 @@ packages: '@prisma/client': ^4.8.0 '@prisma/extension-read-replicas': ^0.3.0 - '@umami/react-zen@0.83.0': - resolution: {integrity: sha512-XfS46KJoPd7vKWrC2tRc7OLBfgOvDu/nmWOejqJLRSpJtg3tmwPmOYfT1vFo3T9s9Lj4qWYBX3I/fBt7u4Yv3A==} + '@umami/react-zen@0.87.0': + resolution: {integrity: sha512-zgsvY54ykQ1jW5YTmvZkNa9JNPspjcJneyhQn6YGrWHBlpr9ddPttBWAr2muQM2WrKFEYHx31WKLnBlzGg2lgg==} '@umami/redis-client@0.27.0': resolution: {integrity: sha512-SbHTpxhgeZyTBUSp2zdZM+XUtpsaSL4Tad8QXIEhEtjWhvvfoornyT5kLuyYCVtzSAT4daALeGmOO1z6EE1KcA==} @@ -3323,6 +3328,9 @@ packages: caniuse-lite@1.0.30001712: resolution: {integrity: sha512-MBqPpGYYdQ7/hfKiet9SCI+nmN5/hp4ZzveOJubl5DTAMa5oggjAuoi0Z4onBpKPFI2ePGnQuQIzF3VxDjDJig==} + caniuse-lite@1.0.30001714: + resolution: {integrity: sha512-mtgapdwDLSSBnCI3JokHM7oEQBLxiJKVRtg10AxM1AyeiKcM96f0Mkbqeq+1AbiCtvMcHRulAAEMu693JrSWqg==} + caseless@0.12.0: resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} @@ -5436,8 +5444,8 @@ packages: natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - next@15.2.4: - resolution: {integrity: sha512-VwL+LAaPSxEkd3lU2xWbgEOtrM8oedmyhBqaVNmgKB+GvZlCy9rgaEc+y2on0wv+l0oSFqLtYD6dcC1eAedUaQ==} + next@15.3.0: + resolution: {integrity: sha512-k0MgP6BsK8cZ73wRjMazl2y2UcXj49ZXLDEgx6BikWuby/CN+nh81qFFI16edgd7xYpe/jj2OZEIwCoqnzz0bQ==} engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} hasBin: true peerDependencies: @@ -6558,8 +6566,8 @@ packages: resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} engines: {node: '>= 0.4'} - sharp@0.33.5: - resolution: {integrity: sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==} + sharp@0.34.1: + resolution: {integrity: sha512-1j0w61+eVxu7DawFJtnfYcvSv6qPFvfTaqzTQ2BLknVhHTwGS8sc63ZBF4rzkWMBVKybo4S5OBtDdZahh2A1xg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} shebang-command@1.2.0: @@ -8390,7 +8398,7 @@ snapshots: dependencies: '@dicebear/core': 9.2.2 - '@emnapi/runtime@1.4.0': + '@emnapi/runtime@1.4.3': dependencies: tslib: 2.8.1 optional: true @@ -8634,79 +8642,82 @@ snapshots: '@humanwhocodes/object-schema@2.0.3': {} - '@img/sharp-darwin-arm64@0.33.5': + '@img/sharp-darwin-arm64@0.34.1': optionalDependencies: - '@img/sharp-libvips-darwin-arm64': 1.0.4 + '@img/sharp-libvips-darwin-arm64': 1.1.0 optional: true - '@img/sharp-darwin-x64@0.33.5': + '@img/sharp-darwin-x64@0.34.1': optionalDependencies: - '@img/sharp-libvips-darwin-x64': 1.0.4 + '@img/sharp-libvips-darwin-x64': 1.1.0 optional: true - '@img/sharp-libvips-darwin-arm64@1.0.4': + '@img/sharp-libvips-darwin-arm64@1.1.0': optional: true - '@img/sharp-libvips-darwin-x64@1.0.4': + '@img/sharp-libvips-darwin-x64@1.1.0': optional: true - '@img/sharp-libvips-linux-arm64@1.0.4': + '@img/sharp-libvips-linux-arm64@1.1.0': optional: true - '@img/sharp-libvips-linux-arm@1.0.5': + '@img/sharp-libvips-linux-arm@1.1.0': optional: true - '@img/sharp-libvips-linux-s390x@1.0.4': + '@img/sharp-libvips-linux-ppc64@1.1.0': optional: true - '@img/sharp-libvips-linux-x64@1.0.4': + '@img/sharp-libvips-linux-s390x@1.1.0': optional: true - '@img/sharp-libvips-linuxmusl-arm64@1.0.4': + '@img/sharp-libvips-linux-x64@1.1.0': optional: true - '@img/sharp-libvips-linuxmusl-x64@1.0.4': + '@img/sharp-libvips-linuxmusl-arm64@1.1.0': optional: true - '@img/sharp-linux-arm64@0.33.5': + '@img/sharp-libvips-linuxmusl-x64@1.1.0': + optional: true + + '@img/sharp-linux-arm64@0.34.1': optionalDependencies: - '@img/sharp-libvips-linux-arm64': 1.0.4 + '@img/sharp-libvips-linux-arm64': 1.1.0 optional: true - '@img/sharp-linux-arm@0.33.5': + '@img/sharp-linux-arm@0.34.1': optionalDependencies: - '@img/sharp-libvips-linux-arm': 1.0.5 + '@img/sharp-libvips-linux-arm': 1.1.0 optional: true - '@img/sharp-linux-s390x@0.33.5': + '@img/sharp-linux-s390x@0.34.1': optionalDependencies: - '@img/sharp-libvips-linux-s390x': 1.0.4 + '@img/sharp-libvips-linux-s390x': 1.1.0 optional: true - '@img/sharp-linux-x64@0.33.5': + '@img/sharp-linux-x64@0.34.1': optionalDependencies: - '@img/sharp-libvips-linux-x64': 1.0.4 + '@img/sharp-libvips-linux-x64': 1.1.0 optional: true - '@img/sharp-linuxmusl-arm64@0.33.5': + '@img/sharp-linuxmusl-arm64@0.34.1': optionalDependencies: - '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 + '@img/sharp-libvips-linuxmusl-arm64': 1.1.0 optional: true - '@img/sharp-linuxmusl-x64@0.33.5': + '@img/sharp-linuxmusl-x64@0.34.1': optionalDependencies: - '@img/sharp-libvips-linuxmusl-x64': 1.0.4 + '@img/sharp-libvips-linuxmusl-x64': 1.1.0 optional: true - '@img/sharp-wasm32@0.33.5': + '@img/sharp-wasm32@0.34.1': dependencies: - '@emnapi/runtime': 1.4.0 + '@emnapi/runtime': 1.4.3 optional: true - '@img/sharp-win32-ia32@0.33.5': + '@img/sharp-win32-ia32@0.34.1': optional: true - '@img/sharp-win32-x64@0.33.5': + '@img/sharp-win32-x64@0.34.1': optional: true '@internationalized/date@3.7.0': @@ -8942,34 +8953,34 @@ snapshots: '@netlify/plugin-nextjs@5.10.3': {} - '@next/env@15.2.4': {} + '@next/env@15.3.0': {} '@next/eslint-plugin-next@14.2.26': dependencies: glob: 10.3.10 - '@next/swc-darwin-arm64@15.2.4': + '@next/swc-darwin-arm64@15.3.0': optional: true - '@next/swc-darwin-x64@15.2.4': + '@next/swc-darwin-x64@15.3.0': optional: true - '@next/swc-linux-arm64-gnu@15.2.4': + '@next/swc-linux-arm64-gnu@15.3.0': optional: true - '@next/swc-linux-arm64-musl@15.2.4': + '@next/swc-linux-arm64-musl@15.3.0': optional: true - '@next/swc-linux-x64-gnu@15.2.4': + '@next/swc-linux-x64-gnu@15.3.0': optional: true - '@next/swc-linux-x64-musl@15.2.4': + '@next/swc-linux-x64-musl@15.3.0': optional: true - '@next/swc-win32-arm64-msvc@15.2.4': + '@next/swc-win32-arm64-msvc@15.3.0': optional: true - '@next/swc-win32-x64-msvc@15.2.4': + '@next/swc-win32-x64-msvc@15.3.0': optional: true '@nodelib/fs.scandir@2.1.5': @@ -10586,16 +10597,17 @@ snapshots: transitivePeerDependencies: - supports-color - '@umami/react-zen@0.83.0(@babel/core@7.26.9)(@types/react@19.1.0)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0))': + '@umami/react-zen@0.87.0(@babel/core@7.26.9)(@types/react@19.1.0)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0))': dependencies: '@fontsource/jetbrains-mono': 5.2.5 + '@internationalized/date': 3.8.0 '@react-aria/focus': 3.20.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@react-spring/web': 9.7.5(react-dom@19.1.0(react@19.1.0))(react@19.1.0) classnames: 2.5.1 glob: 10.4.5 highlight.js: 11.11.1 lucide-react: 0.479.0(react@19.1.0) - next: 15.2.4(@babel/core@7.26.9)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + next: 15.3.0(@babel/core@7.26.9)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) react: 19.1.0 react-aria-components: 1.8.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) react-dom: 19.1.0(react@19.1.0) @@ -11068,6 +11080,8 @@ snapshots: caniuse-lite@1.0.30001712: {} + caniuse-lite@1.0.30001714: {} + caseless@0.12.0: {} chalk@2.4.2: @@ -13594,27 +13608,27 @@ snapshots: natural-compare@1.4.0: {} - next@15.2.4(@babel/core@7.26.9)(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + next@15.3.0(@babel/core@7.26.9)(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: - '@next/env': 15.2.4 + '@next/env': 15.3.0 '@swc/counter': 0.1.3 '@swc/helpers': 0.5.15 busboy: 1.6.0 - caniuse-lite: 1.0.30001712 + caniuse-lite: 1.0.30001714 postcss: 8.4.31 react: 19.1.0 react-dom: 19.1.0(react@19.1.0) styled-jsx: 5.1.6(@babel/core@7.26.9)(react@19.1.0) optionalDependencies: - '@next/swc-darwin-arm64': 15.2.4 - '@next/swc-darwin-x64': 15.2.4 - '@next/swc-linux-arm64-gnu': 15.2.4 - '@next/swc-linux-arm64-musl': 15.2.4 - '@next/swc-linux-x64-gnu': 15.2.4 - '@next/swc-linux-x64-musl': 15.2.4 - '@next/swc-win32-arm64-msvc': 15.2.4 - '@next/swc-win32-x64-msvc': 15.2.4 - sharp: 0.33.5 + '@next/swc-darwin-arm64': 15.3.0 + '@next/swc-darwin-x64': 15.3.0 + '@next/swc-linux-arm64-gnu': 15.3.0 + '@next/swc-linux-arm64-musl': 15.3.0 + '@next/swc-linux-x64-gnu': 15.3.0 + '@next/swc-linux-x64-musl': 15.3.0 + '@next/swc-win32-arm64-msvc': 15.3.0 + '@next/swc-win32-x64-msvc': 15.3.0 + sharp: 0.34.1 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros @@ -14851,31 +14865,32 @@ snapshots: es-errors: 1.3.0 es-object-atoms: 1.1.1 - sharp@0.33.5: + sharp@0.34.1: dependencies: color: 4.2.3 detect-libc: 2.0.3 semver: 7.7.1 optionalDependencies: - '@img/sharp-darwin-arm64': 0.33.5 - '@img/sharp-darwin-x64': 0.33.5 - '@img/sharp-libvips-darwin-arm64': 1.0.4 - '@img/sharp-libvips-darwin-x64': 1.0.4 - '@img/sharp-libvips-linux-arm': 1.0.5 - '@img/sharp-libvips-linux-arm64': 1.0.4 - '@img/sharp-libvips-linux-s390x': 1.0.4 - '@img/sharp-libvips-linux-x64': 1.0.4 - '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 - '@img/sharp-libvips-linuxmusl-x64': 1.0.4 - '@img/sharp-linux-arm': 0.33.5 - '@img/sharp-linux-arm64': 0.33.5 - '@img/sharp-linux-s390x': 0.33.5 - '@img/sharp-linux-x64': 0.33.5 - '@img/sharp-linuxmusl-arm64': 0.33.5 - '@img/sharp-linuxmusl-x64': 0.33.5 - '@img/sharp-wasm32': 0.33.5 - '@img/sharp-win32-ia32': 0.33.5 - '@img/sharp-win32-x64': 0.33.5 + '@img/sharp-darwin-arm64': 0.34.1 + '@img/sharp-darwin-x64': 0.34.1 + '@img/sharp-libvips-darwin-arm64': 1.1.0 + '@img/sharp-libvips-darwin-x64': 1.1.0 + '@img/sharp-libvips-linux-arm': 1.1.0 + '@img/sharp-libvips-linux-arm64': 1.1.0 + '@img/sharp-libvips-linux-ppc64': 1.1.0 + '@img/sharp-libvips-linux-s390x': 1.1.0 + '@img/sharp-libvips-linux-x64': 1.1.0 + '@img/sharp-libvips-linuxmusl-arm64': 1.1.0 + '@img/sharp-libvips-linuxmusl-x64': 1.1.0 + '@img/sharp-linux-arm': 0.34.1 + '@img/sharp-linux-arm64': 0.34.1 + '@img/sharp-linux-s390x': 0.34.1 + '@img/sharp-linux-x64': 0.34.1 + '@img/sharp-linuxmusl-arm64': 0.34.1 + '@img/sharp-linuxmusl-x64': 0.34.1 + '@img/sharp-wasm32': 0.34.1 + '@img/sharp-win32-ia32': 0.34.1 + '@img/sharp-win32-x64': 0.34.1 optional: true shebang-command@1.2.0: diff --git a/src/app/actions/getConfig.ts b/src/app/actions/getConfig.ts index bb892f01..7a16a3a4 100644 --- a/src/app/actions/getConfig.ts +++ b/src/app/actions/getConfig.ts @@ -6,5 +6,6 @@ export async function getConfig() { trackerScriptName: process.env.TRACKER_SCRIPT_NAME, uiDisabled: !!process.env.DISABLE_UI, updatesDisabled: !!process.env.DISABLE_UPDATES, + loginDisabled: !!process.env.DISABLE_LOGIN, }; } diff --git a/src/components/common/FilterButtons.tsx b/src/components/common/FilterButtons.tsx index 612b350f..7f1f1a44 100644 --- a/src/components/common/FilterButtons.tsx +++ b/src/components/common/FilterButtons.tsx @@ -1,22 +1,27 @@ -import { Key } from 'react'; -import { Text, Row, Button, Flexbox } from '@umami/react-zen'; +import { useState } from 'react'; +import { ToggleGroup, ToggleGroupItem } from '@umami/react-zen'; export interface FilterButtonsProps { - items: any[]; - selectedKey?: Key; - onSelect: (key: any) => void; + items: { id: string; label: string }[]; + value: string; + onChange?: (value: string) => void; } -export function FilterButtons({ items, selectedKey, onSelect }: FilterButtonsProps) { +export function FilterButtons({ items, value, onChange }: FilterButtonsProps) { + const [selected, setSelected] = useState(value); + + const handleChange = (value: string) => { + setSelected(value); + onChange?.(value); + }; + return ( - - - {items.map(({ key, label }) => ( - - ))} - - + handleChange(e[0])}> + {items.map(({ id, label }) => ( + + {label} + + ))} + ); } diff --git a/src/components/input/WebsiteDateFilter.tsx b/src/components/input/WebsiteDateFilter.tsx index f5147eb5..a2b0bbe7 100644 --- a/src/components/input/WebsiteDateFilter.tsx +++ b/src/components/input/WebsiteDateFilter.tsx @@ -41,11 +41,13 @@ export function WebsiteDateFilter({ const disableForward = value === 'all' || isAfter(getOffsetDateRange(dateRange, 1).startDate, new Date()); - const handleChange = (value: string | DateRange) => { - saveDateRange(value); + const handleChange = (date: string | DateRange) => { + router.push(renderUrl({ date })); + saveDateRange(date); }; const handleIncrement = (increment: number) => { + router.push(renderUrl({ increment })); saveDateRange(getOffsetDateRange(dateRange, increment)); }; diff --git a/src/components/metrics/DatePickerForm.module.css b/src/components/metrics/DatePickerForm.module.css deleted file mode 100644 index 7168fa0d..00000000 --- a/src/components/metrics/DatePickerForm.module.css +++ /dev/null @@ -1,44 +0,0 @@ -.container { - display: flex; - flex-direction: column; - max-width: 100vw; -} - -.calendars { - display: flex; - justify-content: center; -} - -.calendars > div + div { - margin-inline-start: 20px; - padding-inline-start: 20px; - border-inline-start: 1px solid var(--base300); -} - -.filter { - display: flex; - justify-content: center; - align-items: center; - margin-bottom: 20px; -} - -.buttons { - display: flex; - align-items: center; - justify-content: center; - gap: 10px; - margin-top: 20px; -} - -@media only screen and (max-width: 768px) { - .calendars { - flex-direction: column; - } - - .calendars > div + div { - padding: 0; - margin-inline-start: 0; - margin-top: 20px; - border: 0; - } -} diff --git a/src/components/metrics/DatePickerForm.tsx b/src/components/metrics/DatePickerForm.tsx index 7fd127e5..a8b2fb8c 100644 --- a/src/components/metrics/DatePickerForm.tsx +++ b/src/components/metrics/DatePickerForm.tsx @@ -1,10 +1,8 @@ import { useState } from 'react'; -import { Button, Row, Calendar } from '@umami/react-zen'; +import { Button, Row, Column, Calendar, ToggleGroup, ToggleGroupItem } from '@umami/react-zen'; import { isAfter, isBefore, isSameDay, startOfDay, endOfDay } from 'date-fns'; import { FILTER_DAY, FILTER_RANGE } from '@/lib/constants'; import { useMessages } from '@/components/hooks'; -import { parseDate } from '@internationalized/date'; -import styles from './DatePickerForm.module.css'; export function DatePickerForm({ startDate: defaultStartDate, @@ -14,61 +12,61 @@ export function DatePickerForm({ onChange, onClose, }) { - const [selected, setSelected] = useState( + const [selected, setSelected] = useState([ isSameDay(defaultStartDate, defaultEndDate) ? FILTER_DAY : FILTER_RANGE, - ); - const [singleDate, setSingleDate] = useState(defaultStartDate || new Date()); + ]); + const [date, setDate] = useState(defaultStartDate || new Date()); const [startDate, setStartDate] = useState(defaultStartDate || new Date()); - const [endDate] = useState(defaultEndDate || new Date()); + const [endDate, setEndDate] = useState(defaultEndDate || new Date()); const { formatMessage, labels } = useMessages(); - const disabled = - selected === FILTER_DAY - ? isAfter(minDate, singleDate) && isBefore(maxDate, singleDate) - : isAfter(startDate, endDate); + const disabled = selected.includes(FILTER_DAY) + ? isAfter(minDate, date) && isBefore(maxDate, date) + : isAfter(startDate, endDate); const handleSave = () => { - if (selected === FILTER_DAY) { - onChange(`range:${startOfDay(singleDate).getTime()}:${endOfDay(singleDate).getTime()}`); + if (selected.includes(FILTER_DAY)) { + onChange(`range:${startOfDay(date).getTime()}:${endOfDay(date).getTime()}`); } else { onChange(`range:${startOfDay(startDate).getTime()}:${endOfDay(endDate).getTime()}`); } }; return ( -
-
- - - - -
-
- {selected === FILTER_DAY && ( - setSingleDate(d.toDate('America/Los_Angeles'))} - /> + + + + {formatMessage(labels.singleDay)} + {formatMessage(labels.dateRange)} + + + + {selected.includes(FILTER_DAY) && ( + )} - {selected === FILTER_RANGE && ( - <> + {selected.includes(FILTER_RANGE) && ( + setStartDate(d.toDate('America/Los_Angeles'))} + value={startDate} + minValue={minDate} + maxValue={endDate} + onChange={setStartDate} /> - + + )} -
-
+ + + - -
-
+ + ); } diff --git a/src/components/metrics/PagesTable.tsx b/src/components/metrics/PagesTable.tsx index ebd7bddb..cf248d67 100644 --- a/src/components/metrics/PagesTable.tsx +++ b/src/components/metrics/PagesTable.tsx @@ -19,26 +19,26 @@ export function PagesTable({ allowFilter, ...props }: PagesTableProps) { const { formatMessage, labels } = useMessages(); const { domain } = useContext(WebsiteContext); - const handleSelect = (key: any) => { - router.push(renderUrl({ view: key })); + const handleChange = (id: any) => { + router.push(renderUrl({ view: id })); }; const buttons = [ { + id: 'url', label: formatMessage(labels.path), - key: 'url', }, { + id: 'entry', label: formatMessage(labels.entry), - key: 'entry', }, { + id: 'exit', label: formatMessage(labels.exit), - key: 'exit', }, { + id: 'title', label: formatMessage(labels.title), - key: 'title', }, ]; @@ -66,7 +66,7 @@ export function PagesTable({ allowFilter, ...props }: PagesTableProps) { dataFilter={emptyFilter} renderLabel={renderLink} > - {allowFilter && } + {allowFilter && } ); } diff --git a/src/components/metrics/QueryParametersTable.tsx b/src/components/metrics/QueryParametersTable.tsx index 47f5aea5..fb641cd2 100644 --- a/src/components/metrics/QueryParametersTable.tsx +++ b/src/components/metrics/QueryParametersTable.tsx @@ -20,10 +20,10 @@ export function QueryParametersTable({ const buttons = [ { + id: FILTER_COMBINED, label: formatMessage(labels.filterCombined), - key: FILTER_COMBINED, }, - { label: formatMessage(labels.filterRaw), key: FILTER_RAW }, + { id: FILTER_RAW, label: formatMessage(labels.filterRaw) }, ]; return ( @@ -45,7 +45,7 @@ export function QueryParametersTable({ } delay={0} > - {allowFilter && } + {allowFilter && } ); } diff --git a/src/components/metrics/ReferrersTable.tsx b/src/components/metrics/ReferrersTable.tsx index 2109228e..42e81e4d 100644 --- a/src/components/metrics/ReferrersTable.tsx +++ b/src/components/metrics/ReferrersTable.tsx @@ -1,11 +1,11 @@ +import { Row } from '@umami/react-zen'; import { FilterLink } from '@/components/common/FilterLink'; import { Favicon } from '@/components/common/Favicon'; +import { FilterButtons } from '@/components/common/FilterButtons'; import { useMessages, useNavigation } from '@/components/hooks'; import { MetricsTable, MetricsTableProps } from './MetricsTable'; -import { FilterButtons } from '@/components/common/FilterButtons'; import thenby from 'thenby'; import { GROUPED_DOMAINS } from '@/lib/constants'; -import { Flexbox } from '@umami/react-zen'; export interface ReferrersTableProps extends MetricsTableProps { allowFilter?: boolean; @@ -25,12 +25,12 @@ export function ReferrersTable({ allowFilter, ...props }: ReferrersTableProps) { const buttons = [ { + id: 'referrer', label: formatMessage(labels.domain), - key: 'referrer', }, { + id: 'grouped', label: formatMessage(labels.grouped), - key: 'grouped', }, ]; @@ -40,10 +40,10 @@ export function ReferrersTable({ allowFilter, ...props }: ReferrersTableProps) { return `(${formatMessage(labels.other)})`; } else { return ( - + {GROUPED_DOMAINS.find(({ domain }) => domain === referrer)?.name} - + ); } } @@ -86,19 +86,15 @@ export function ReferrersTable({ allowFilter, ...props }: ReferrersTableProps) { }; return ( - <> - - {allowFilter && ( - - )} - - + + {allowFilter && } + ); } diff --git a/src/lib/__tests__/charts.test.ts b/src/lib/__tests__/charts.test.ts index e330fadd..601ee63d 100644 --- a/src/lib/__tests__/charts.test.ts +++ b/src/lib/__tests__/charts.test.ts @@ -1,5 +1,4 @@ -import { renderNumberLabels, renderDateLabels } from '../charts'; -import { formatDate } from '../date'; +import { renderNumberLabels } from '../charts'; // test for renderNumberLabels @@ -40,42 +39,3 @@ describe('renderNumberLabels', () => { expect(renderNumberLabels(input)).toBe(expected); }); }); - -describe('renderDateLabels', () => { - const mockValues = [{ value: '2024-03-23T10:00:00Z' }, { value: '2024-03-24T15:30:00Z' }]; - - beforeEach(() => { - // eslint-disable-next-line @typescript-eslint/no-require-imports - jest.spyOn(require('@/lib/date'), 'formatDate'); - }); - - afterEach(() => { - jest.restoreAllMocks(); // Reset spy to prevent interference - }); - - test.each([ - ['minute', 'h:mm', 'en-US'], - ['hour', 'p', 'en-US'], - ['day', 'MMM d', 'en-US'], - ['month', 'MMM', 'en-US'], - ['year', 'yyyy', 'en-US'], - ])('formats date correctly for unit: %s', (unit, expectedFormat, locale) => { - const formatLabel = renderDateLabels(unit, locale); - const formatted = formatLabel('label', 0, mockValues); - - expect(formatDate).toHaveBeenCalledWith(new Date(mockValues[0].value), expectedFormat, locale); - expect(formatted).toBe(formatDate(new Date(mockValues[0].value), expectedFormat, locale)); - }); - - test('returns label for unknown unit', () => { - const formatLabel = renderDateLabels('unknown', 'en-US'); - expect(formatLabel('original-label', 0, mockValues)).toBe('original-label'); - }); - - test('throws error for invalid date input', () => { - const invalidValues = [{ value: 'invalid-date' }]; - const formatLabel = renderDateLabels('day', 'en-US'); - - expect(() => formatLabel('label', 0, invalidValues)).toThrow(); - }); -});