From 7a2cae810b1e4c2e5f7c8f71edea968b20d88ccc Mon Sep 17 00:00:00 2001 From: boludedaniel Date: Thu, 29 May 2025 20:32:46 +0100 Subject: [PATCH 1/7] feat/implement analytics page --- package.json | 6 +- pnpm-lock.yaml | 626 +++++++++++++++++++- src/app/dashboard/analytics/page.tsx | 833 ++++++++++++++++++++++++++- src/components/ui/badge.tsx | 46 ++ src/components/ui/card.tsx | 92 +++ src/components/ui/dialog.tsx | 122 ++++ src/components/ui/select.tsx | 159 +++++ src/components/ui/table.tsx | 120 ++++ 8 files changed, 1996 insertions(+), 8 deletions(-) create mode 100644 src/components/ui/badge.tsx create mode 100644 src/components/ui/card.tsx create mode 100644 src/components/ui/dialog.tsx create mode 100644 src/components/ui/select.tsx create mode 100644 src/components/ui/table.tsx diff --git a/package.json b/package.json index d11cd1a..670f9b3 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,8 @@ "@headlessui/react": "^2.2.0", "@mui/material": "^7.0.2", "@radix-ui/react-checkbox": "^1.2.3", - "@radix-ui/react-dialog": "^1.1.6", + "@radix-ui/react-dialog": "^1.1.14", + "@radix-ui/react-select": "^2.2.5", "@radix-ui/react-slot": "^1.2.0", "@splidejs/react-splide": "^0.7.12", "@splidejs/splide": "^4.1.4", @@ -25,15 +26,18 @@ "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "framer-motion": "^12.5.0", + "install": "^0.13.0", "keen-slider": "^6.8.6", "lodash": "^4.17.21", "lucide-react": "^0.474.0", + "lunpm": "^1.0.1", "next": "^14.2.25", "react": "^18.3.1", "react-datepicker": "^8.2.1", "react-dom": "^18.3.1", "react-hot-toast": "^2.5.2", "react-icons": "^5.5.0", + "recharts": "^2.15.3", "sharp": "^0.33.5", "starknet": "^6.23.1", "tailwind-merge": "^2.6.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index aef69be..8275429 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,9 +8,18 @@ importers: .: dependencies: + '@emotion/react': + specifier: ^11.14.0 + version: 11.14.0(@types/react@19.1.2)(react@18.3.1) + '@emotion/styled': + specifier: ^11.14.0 + version: 11.14.0(@emotion/react@11.14.0(@types/react@19.1.2)(react@18.3.1))(@types/react@19.1.2)(react@18.3.1) '@headlessui/react': specifier: ^2.2.0 version: 2.2.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@mui/material': + specifier: ^7.0.2 + version: 7.1.0(@emotion/react@11.14.0(@types/react@19.1.2)(react@18.3.1))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.2)(react@18.3.1))(@types/react@19.1.2)(react@18.3.1))(@types/react@19.1.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-checkbox': specifier: ^1.2.3 version: 1.2.3(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -20,6 +29,12 @@ importers: '@radix-ui/react-slot': specifier: ^1.2.0 version: 1.2.0(@types/react@19.1.2)(react@18.3.1) + '@splidejs/react-splide': + specifier: ^0.7.12 + version: 0.7.12 + '@splidejs/splide': + specifier: ^4.1.4 + version: 4.1.4 '@starknet-react/chains': specifier: ^3.1.2 version: 3.1.3 @@ -37,7 +52,10 @@ importers: version: 2.1.1 framer-motion: specifier: ^12.5.0 - version: 12.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 12.9.1(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + keen-slider: + specifier: ^6.8.6 + version: 6.8.6 lodash: specifier: ^4.17.21 version: 4.17.21 @@ -115,6 +133,47 @@ packages: resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} + '@babel/code-frame@7.27.1': + resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.27.3': + resolution: {integrity: sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.27.1': + resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.27.1': + resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.27.3': + resolution: {integrity: sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/runtime@7.27.3': + resolution: {integrity: sha512-7EYtGezsdiDMyY80+65EzwiGmcJqpmcZCojSXaRgdrBaGtWTgDZKq69cPIVped6MkIM78cTQ2GOiEYjwOlG4xw==} + engines: {node: '>=6.9.0'} + + '@babel/template@7.27.2': + resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.27.3': + resolution: {integrity: sha512-lId/IfN/Ye1CIu8xG7oKBHXd2iNb2aW1ilPszzGcJug6M8RCKfVNcYhpI5+bMvFYjK7lXIM0R+a+6r8xhHp2FQ==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.27.3': + resolution: {integrity: sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw==} + engines: {node: '>=6.9.0'} + '@emnapi/core@1.4.3': resolution: {integrity: sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==} @@ -124,6 +183,60 @@ packages: '@emnapi/wasi-threads@1.0.2': resolution: {integrity: sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==} + '@emotion/babel-plugin@11.13.5': + resolution: {integrity: sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==} + + '@emotion/cache@11.14.0': + resolution: {integrity: sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==} + + '@emotion/hash@0.9.2': + resolution: {integrity: sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==} + + '@emotion/is-prop-valid@1.3.1': + resolution: {integrity: sha512-/ACwoqx7XQi9knQs/G0qKvv5teDMhD7bXYns9N/wM8ah8iNb8jZ2uNO0YOgiq2o2poIvVtJS2YALasQuMSQ7Kw==} + + '@emotion/memoize@0.9.0': + resolution: {integrity: sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==} + + '@emotion/react@11.14.0': + resolution: {integrity: sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==} + peerDependencies: + '@types/react': '*' + react: '>=16.8.0' + peerDependenciesMeta: + '@types/react': + optional: true + + '@emotion/serialize@1.3.3': + resolution: {integrity: sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==} + + '@emotion/sheet@1.4.0': + resolution: {integrity: sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==} + + '@emotion/styled@11.14.0': + resolution: {integrity: sha512-XxfOnXFffatap2IyCeJyNov3kiDQWoR08gPUQxvbL7fxKryGBKUZUkG6Hz48DZwVrJSVh9sJboyV1Ds4OW6SgA==} + peerDependencies: + '@emotion/react': ^11.0.0-rc.0 + '@types/react': '*' + react: '>=16.8.0' + peerDependenciesMeta: + '@types/react': + optional: true + + '@emotion/unitless@0.10.0': + resolution: {integrity: sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==} + + '@emotion/use-insertion-effect-with-fallbacks@1.2.0': + resolution: {integrity: sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==} + peerDependencies: + react: '>=16.8.0' + + '@emotion/utils@1.4.2': + resolution: {integrity: sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==} + + '@emotion/weak-memoize@0.4.0': + resolution: {integrity: sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==} + '@eslint-community/eslint-utils@4.6.1': resolution: {integrity: sha512-KTsJMmobmbrFLe3LDh0PC2FXpcSYJt/MLjlkh/9LEnmKYLSYmT/0EW9JWANjeoemiuZrmogti0tW5Ch+qNUYDw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -321,6 +434,104 @@ packages: cpu: [x64] os: [win32] + '@jridgewell/gen-mapping@0.3.8': + resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} + engines: {node: '>=6.0.0'} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/set-array@1.2.1': + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + + '@jridgewell/trace-mapping@0.3.25': + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + + '@mui/core-downloads-tracker@7.1.0': + resolution: {integrity: sha512-E0OqhZv548Qdc0PwWhLVA2zmjJZSTvaL4ZhoswmI8NJEC1tpW2js6LLP827jrW9MEiXYdz3QS6+hask83w74yQ==} + + '@mui/material@7.1.0': + resolution: {integrity: sha512-ahUJdrhEv+mCp4XHW+tHIEYzZMSRLg8z4AjUOsj44QpD1ZaMxQoVOG2xiHvLFdcsIPbgSRx1bg1eQSheHBgvtg==} + engines: {node: '>=14.0.0'} + peerDependencies: + '@emotion/react': ^11.5.0 + '@emotion/styled': ^11.3.0 + '@mui/material-pigment-css': ^7.1.0 + '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 + react: ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@emotion/react': + optional: true + '@emotion/styled': + optional: true + '@mui/material-pigment-css': + optional: true + '@types/react': + optional: true + + '@mui/private-theming@7.1.0': + resolution: {integrity: sha512-4Kck4jxhqF6YxNwJdSae1WgDfXVg0lIH6JVJ7gtuFfuKcQCgomJxPvUEOySTFRPz1IZzwz5OAcToskRdffElDA==} + engines: {node: '>=14.0.0'} + peerDependencies: + '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 + react: ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + + '@mui/styled-engine@7.1.0': + resolution: {integrity: sha512-m0mJ0c6iRC+f9hMeRe0W7zZX1wme3oUX0+XTVHjPG7DJz6OdQ6K/ggEOq7ZdwilcpdsDUwwMfOmvO71qDkYd2w==} + engines: {node: '>=14.0.0'} + peerDependencies: + '@emotion/react': ^11.4.1 + '@emotion/styled': ^11.3.0 + react: ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@emotion/react': + optional: true + '@emotion/styled': + optional: true + + '@mui/system@7.1.0': + resolution: {integrity: sha512-iedAWgRJMCxeMHvkEhsDlbvkK+qKf9me6ofsf7twk/jfT4P1ImVf7Rwb5VubEA0sikrVL+1SkoZM41M4+LNAVA==} + engines: {node: '>=14.0.0'} + peerDependencies: + '@emotion/react': ^11.5.0 + '@emotion/styled': ^11.3.0 + '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 + react: ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@emotion/react': + optional: true + '@emotion/styled': + optional: true + '@types/react': + optional: true + + '@mui/types@7.4.2': + resolution: {integrity: sha512-edRc5JcLPsrlNFYyTPxds+d5oUovuUxnnDtpJUbP6WMeV4+6eaX/mqai1ZIWT62lCOe0nlrON0s9HDiv5en5bA==} + peerDependencies: + '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + + '@mui/utils@7.1.0': + resolution: {integrity: sha512-/OM3S8kSHHmWNOP+NH9xEtpYSG10upXeQ0wLZnfDgmgadTAk5F4MQfFLyZ5FCRJENB3eRzltMmaNl6UtDnPovw==} + engines: {node: '>=14.0.0'} + peerDependencies: + '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 + react: ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@napi-rs/wasm-runtime@0.2.9': resolution: {integrity: sha512-OKRBiajrrxB9ATokgEQoG87Z25c67pCpYcCwmXYX8PBftC9pBfN18gnm/fh1wurSLEKIAt+QRFLFCQISrb66Jg==} @@ -416,6 +627,9 @@ packages: resolution: {integrity: sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==} engines: {node: '>=12.4.0'} + '@popperjs/core@2.11.8': + resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} + '@radix-ui/primitive@1.1.2': resolution: {integrity: sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==} @@ -676,6 +890,12 @@ packages: '@scure/starknet@1.1.0': resolution: {integrity: sha512-83g3M6Ix2qRsPN4wqLDqiRZ2GBNbjVWfboJE/9UjfG+MHr6oDSu/CWgy8hsBSJejr09DkkL+l0Ze4KVrlCIdtQ==} + '@splidejs/react-splide@0.7.12': + resolution: {integrity: sha512-UfXH+j47jsMc4x5HA/aOwuuHPqn6y9+ZTNYPWDRD8iLKvIVMZlzq2unjUEvyDAU+TTVPZOXkG2Ojeoz0P4AkZw==} + + '@splidejs/splide@4.1.4': + resolution: {integrity: sha512-5I30evTJcAJQXt6vJ26g2xEkG+l1nXcpEw4xpKh0/FWQ8ozmAeTbtniVtVmz2sH1Es3vgfC4SS8B2X4o5JMptA==} + '@starknet-io/types-js@0.7.10': resolution: {integrity: sha512-1VtCqX4AHWJlRRSYGSn+4X1mqolI1Tdq62IwzoU2vUuEE72S1OlEeGhpvd6XsdqXcfHmVzYfj8k1XtKBQqwo9w==} @@ -821,11 +1041,22 @@ packages: '@types/node@20.17.31': resolution: {integrity: sha512-quODOCNXQAbNf1Q7V+fI8WyErOCh0D5Yd31vHnKu4GkSztGQ7rlltAaqXhHhLl33tlVyUXs2386MkANSwgDn6A==} + '@types/parse-json@4.0.2': + resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} + + '@types/prop-types@15.7.14': + resolution: {integrity: sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==} + '@types/react-dom@19.1.2': resolution: {integrity: sha512-XGJkWF41Qq305SKWEILa1O8vzhb3aOo3ogBlSmiqNko/WmRb6QIaweuZCXjKygVDXpzXb5wyxKTSOsmkuqj+Qw==} peerDependencies: '@types/react': ^19.0.0 + '@types/react-transition-group@4.4.12': + resolution: {integrity: sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==} + peerDependencies: + '@types/react': '*' + '@types/react@19.1.2': resolution: {integrity: sha512-oxLPMytKchWGbnQM9O7D67uPa9paTNxO7jVoNMXgkkErULBPhPARCfkKL9ytcIJJRGjbsVwW4ugJzyFFvm/Tiw==} @@ -1062,6 +1293,10 @@ packages: resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} engines: {node: '>= 0.4'} + babel-plugin-macros@3.1.0: + resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} + engines: {node: '>=10', npm: '>=6'} + balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -1137,6 +1372,13 @@ packages: concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + convert-source-map@1.9.0: + resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} + + cosmiconfig@7.1.0: + resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} + engines: {node: '>=10'} + cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -1201,6 +1443,9 @@ packages: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} engines: {node: '>=0.10.0'} + dom-helpers@5.2.1: + resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} + dunder-proto@1.0.1: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} @@ -1215,6 +1460,9 @@ packages: resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==} engines: {node: '>=10.13.0'} + error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + es-abstract@1.23.9: resolution: {integrity: sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==} engines: {node: '>= 0.4'} @@ -1418,6 +1666,9 @@ packages: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} + find-root@1.1.0: + resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==} + find-up@5.0.0: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} @@ -1496,6 +1747,10 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} + globals@11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + globals@14.0.0: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} @@ -1546,6 +1801,9 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} + hoist-non-react-statics@3.3.2: + resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} + ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} @@ -1566,6 +1824,9 @@ packages: resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} engines: {node: '>= 0.4'} + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + is-arrayish@0.3.2: resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} @@ -1697,9 +1958,17 @@ packages: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} @@ -1717,6 +1986,9 @@ packages: resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} engines: {node: '>=4.0'} + keen-slider@6.8.6: + resolution: {integrity: sha512-dcEQ7GDBpCjUQA8XZeWh3oBBLLmyn8aoeIQFGL/NTVkoEOsmlnXqA4QykUm/SncolAZYGsEk/PfUhLZ7mwMM2w==} + keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} @@ -1795,6 +2067,9 @@ packages: resolution: {integrity: sha512-6b6gd/RUXKaw5keVdSEtqFVdzWnU5jMxTUjA2bVcMNPLwSQ08Sv/UodBVtETLCn7k4S1Ibxwh7k68IwLZPgKaA==} engines: {node: '>= 12.0.0'} + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} @@ -1951,6 +2226,10 @@ packages: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} @@ -1962,6 +2241,10 @@ packages: path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -2031,6 +2314,9 @@ packages: react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + react-is@19.1.0: + resolution: {integrity: sha512-Oe56aUPnkHyyDxxkvqtd7KkdQP5uIUfHxd5XTb3wE9d/kRnZLmKbDB0GWk919tdQ+mxxPtG6EAs6RMT6i1qtHg==} + react-remove-scroll-bar@2.3.8: resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==} engines: {node: '>=10'} @@ -2061,6 +2347,12 @@ packages: '@types/react': optional: true + react-transition-group@4.4.5: + resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==} + peerDependencies: + react: '>=16.6.0' + react-dom: '>=16.6.0' + react@18.3.1: resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} engines: {node: '>=0.10.0'} @@ -2180,6 +2472,10 @@ packages: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} + source-map@0.5.7: + resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} + engines: {node: '>=0.10.0'} + stable-hash@0.0.5: resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==} @@ -2242,6 +2538,9 @@ packages: babel-plugin-macros: optional: true + stylis@4.2.0: + resolution: {integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==} + supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} @@ -2437,6 +2736,10 @@ packages: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} + yaml@1.10.2: + resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} + engines: {node: '>= 6'} + yargs-parser@21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} @@ -2458,6 +2761,60 @@ snapshots: '@alloc/quick-lru@5.2.0': {} + '@babel/code-frame@7.27.1': + dependencies: + '@babel/helper-validator-identifier': 7.27.1 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/generator@7.27.3': + dependencies: + '@babel/parser': 7.27.3 + '@babel/types': 7.27.3 + '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/trace-mapping': 0.3.25 + jsesc: 3.1.0 + + '@babel/helper-module-imports@7.27.1': + dependencies: + '@babel/traverse': 7.27.3 + '@babel/types': 7.27.3 + transitivePeerDependencies: + - supports-color + + '@babel/helper-string-parser@7.27.1': {} + + '@babel/helper-validator-identifier@7.27.1': {} + + '@babel/parser@7.27.3': + dependencies: + '@babel/types': 7.27.3 + + '@babel/runtime@7.27.3': {} + + '@babel/template@7.27.2': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/parser': 7.27.3 + '@babel/types': 7.27.3 + + '@babel/traverse@7.27.3': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.27.3 + '@babel/parser': 7.27.3 + '@babel/template': 7.27.2 + '@babel/types': 7.27.3 + debug: 4.4.0 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.27.3': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + '@emnapi/core@1.4.3': dependencies: '@emnapi/wasi-threads': 1.0.2 @@ -2474,6 +2831,89 @@ snapshots: tslib: 2.8.1 optional: true + '@emotion/babel-plugin@11.13.5': + dependencies: + '@babel/helper-module-imports': 7.27.1 + '@babel/runtime': 7.27.3 + '@emotion/hash': 0.9.2 + '@emotion/memoize': 0.9.0 + '@emotion/serialize': 1.3.3 + babel-plugin-macros: 3.1.0 + convert-source-map: 1.9.0 + escape-string-regexp: 4.0.0 + find-root: 1.1.0 + source-map: 0.5.7 + stylis: 4.2.0 + transitivePeerDependencies: + - supports-color + + '@emotion/cache@11.14.0': + dependencies: + '@emotion/memoize': 0.9.0 + '@emotion/sheet': 1.4.0 + '@emotion/utils': 1.4.2 + '@emotion/weak-memoize': 0.4.0 + stylis: 4.2.0 + + '@emotion/hash@0.9.2': {} + + '@emotion/is-prop-valid@1.3.1': + dependencies: + '@emotion/memoize': 0.9.0 + + '@emotion/memoize@0.9.0': {} + + '@emotion/react@11.14.0(@types/react@19.1.2)(react@18.3.1)': + dependencies: + '@babel/runtime': 7.27.3 + '@emotion/babel-plugin': 11.13.5 + '@emotion/cache': 11.14.0 + '@emotion/serialize': 1.3.3 + '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@18.3.1) + '@emotion/utils': 1.4.2 + '@emotion/weak-memoize': 0.4.0 + hoist-non-react-statics: 3.3.2 + react: 18.3.1 + optionalDependencies: + '@types/react': 19.1.2 + transitivePeerDependencies: + - supports-color + + '@emotion/serialize@1.3.3': + dependencies: + '@emotion/hash': 0.9.2 + '@emotion/memoize': 0.9.0 + '@emotion/unitless': 0.10.0 + '@emotion/utils': 1.4.2 + csstype: 3.1.3 + + '@emotion/sheet@1.4.0': {} + + '@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.2)(react@18.3.1))(@types/react@19.1.2)(react@18.3.1)': + dependencies: + '@babel/runtime': 7.27.3 + '@emotion/babel-plugin': 11.13.5 + '@emotion/is-prop-valid': 1.3.1 + '@emotion/react': 11.14.0(@types/react@19.1.2)(react@18.3.1) + '@emotion/serialize': 1.3.3 + '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@18.3.1) + '@emotion/utils': 1.4.2 + react: 18.3.1 + optionalDependencies: + '@types/react': 19.1.2 + transitivePeerDependencies: + - supports-color + + '@emotion/unitless@0.10.0': {} + + '@emotion/use-insertion-effect-with-fallbacks@1.2.0(react@18.3.1)': + dependencies: + react: 18.3.1 + + '@emotion/utils@1.4.2': {} + + '@emotion/weak-memoize@0.4.0': {} + '@eslint-community/eslint-utils@4.6.1(eslint@9.25.1(jiti@2.4.2))': dependencies: eslint: 9.25.1(jiti@2.4.2) @@ -2649,6 +3089,102 @@ snapshots: '@img/sharp-win32-x64@0.33.5': optional: true + '@jridgewell/gen-mapping@0.3.8': + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping': 0.3.25 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/set-array@1.2.1': {} + + '@jridgewell/sourcemap-codec@1.5.0': {} + + '@jridgewell/trace-mapping@0.3.25': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + + '@mui/core-downloads-tracker@7.1.0': {} + + '@mui/material@7.1.0(@emotion/react@11.14.0(@types/react@19.1.2)(react@18.3.1))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.2)(react@18.3.1))(@types/react@19.1.2)(react@18.3.1))(@types/react@19.1.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@babel/runtime': 7.27.3 + '@mui/core-downloads-tracker': 7.1.0 + '@mui/system': 7.1.0(@emotion/react@11.14.0(@types/react@19.1.2)(react@18.3.1))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.2)(react@18.3.1))(@types/react@19.1.2)(react@18.3.1))(@types/react@19.1.2)(react@18.3.1) + '@mui/types': 7.4.2(@types/react@19.1.2) + '@mui/utils': 7.1.0(@types/react@19.1.2)(react@18.3.1) + '@popperjs/core': 2.11.8 + '@types/react-transition-group': 4.4.12(@types/react@19.1.2) + clsx: 2.1.1 + csstype: 3.1.3 + prop-types: 15.8.1 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-is: 19.1.0 + react-transition-group: 4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + optionalDependencies: + '@emotion/react': 11.14.0(@types/react@19.1.2)(react@18.3.1) + '@emotion/styled': 11.14.0(@emotion/react@11.14.0(@types/react@19.1.2)(react@18.3.1))(@types/react@19.1.2)(react@18.3.1) + '@types/react': 19.1.2 + + '@mui/private-theming@7.1.0(@types/react@19.1.2)(react@18.3.1)': + dependencies: + '@babel/runtime': 7.27.3 + '@mui/utils': 7.1.0(@types/react@19.1.2)(react@18.3.1) + prop-types: 15.8.1 + react: 18.3.1 + optionalDependencies: + '@types/react': 19.1.2 + + '@mui/styled-engine@7.1.0(@emotion/react@11.14.0(@types/react@19.1.2)(react@18.3.1))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.2)(react@18.3.1))(@types/react@19.1.2)(react@18.3.1))(react@18.3.1)': + dependencies: + '@babel/runtime': 7.27.3 + '@emotion/cache': 11.14.0 + '@emotion/serialize': 1.3.3 + '@emotion/sheet': 1.4.0 + csstype: 3.1.3 + prop-types: 15.8.1 + react: 18.3.1 + optionalDependencies: + '@emotion/react': 11.14.0(@types/react@19.1.2)(react@18.3.1) + '@emotion/styled': 11.14.0(@emotion/react@11.14.0(@types/react@19.1.2)(react@18.3.1))(@types/react@19.1.2)(react@18.3.1) + + '@mui/system@7.1.0(@emotion/react@11.14.0(@types/react@19.1.2)(react@18.3.1))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.2)(react@18.3.1))(@types/react@19.1.2)(react@18.3.1))(@types/react@19.1.2)(react@18.3.1)': + dependencies: + '@babel/runtime': 7.27.3 + '@mui/private-theming': 7.1.0(@types/react@19.1.2)(react@18.3.1) + '@mui/styled-engine': 7.1.0(@emotion/react@11.14.0(@types/react@19.1.2)(react@18.3.1))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.2)(react@18.3.1))(@types/react@19.1.2)(react@18.3.1))(react@18.3.1) + '@mui/types': 7.4.2(@types/react@19.1.2) + '@mui/utils': 7.1.0(@types/react@19.1.2)(react@18.3.1) + clsx: 2.1.1 + csstype: 3.1.3 + prop-types: 15.8.1 + react: 18.3.1 + optionalDependencies: + '@emotion/react': 11.14.0(@types/react@19.1.2)(react@18.3.1) + '@emotion/styled': 11.14.0(@emotion/react@11.14.0(@types/react@19.1.2)(react@18.3.1))(@types/react@19.1.2)(react@18.3.1) + '@types/react': 19.1.2 + + '@mui/types@7.4.2(@types/react@19.1.2)': + dependencies: + '@babel/runtime': 7.27.3 + optionalDependencies: + '@types/react': 19.1.2 + + '@mui/utils@7.1.0(@types/react@19.1.2)(react@18.3.1)': + dependencies: + '@babel/runtime': 7.27.3 + '@mui/types': 7.4.2(@types/react@19.1.2) + '@types/prop-types': 15.7.14 + clsx: 2.1.1 + prop-types: 15.8.1 + react: 18.3.1 + react-is: 19.1.0 + optionalDependencies: + '@types/react': 19.1.2 + '@napi-rs/wasm-runtime@0.2.9': dependencies: '@emnapi/core': 1.4.3 @@ -2715,6 +3251,8 @@ snapshots: '@nolyfill/is-core-module@1.0.39': {} + '@popperjs/core@2.11.8': {} + '@radix-ui/primitive@1.1.2': {} '@radix-ui/react-checkbox@1.2.3(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': @@ -2960,6 +3498,12 @@ snapshots: '@noble/curves': 1.7.0 '@noble/hashes': 1.6.0 + '@splidejs/react-splide@0.7.12': + dependencies: + '@splidejs/splide': 4.1.4 + + '@splidejs/splide@4.1.4': {} + '@starknet-io/types-js@0.7.10': {} '@starknet-react/chains@3.1.3': {} @@ -3090,10 +3634,18 @@ snapshots: dependencies: undici-types: 6.19.8 + '@types/parse-json@4.0.2': {} + + '@types/prop-types@15.7.14': {} + '@types/react-dom@19.1.2(@types/react@19.1.2)': dependencies: '@types/react': 19.1.2 + '@types/react-transition-group@4.4.12(@types/react@19.1.2)': + dependencies: + '@types/react': 19.1.2 + '@types/react@19.1.2': dependencies: csstype: 3.1.3 @@ -3346,6 +3898,12 @@ snapshots: axobject-query@4.1.0: {} + babel-plugin-macros@3.1.0: + dependencies: + '@babel/runtime': 7.27.3 + cosmiconfig: 7.1.0 + resolve: 1.22.10 + balanced-match@1.0.2: {} brace-expansion@1.1.11: @@ -3428,6 +3986,16 @@ snapshots: concat-map@0.0.1: {} + convert-source-map@1.9.0: {} + + cosmiconfig@7.1.0: + dependencies: + '@types/parse-json': 4.0.2 + import-fresh: 3.3.1 + parse-json: 5.2.0 + path-type: 4.0.0 + yaml: 1.10.2 + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 @@ -3488,6 +4056,11 @@ snapshots: dependencies: esutils: 2.0.3 + dom-helpers@5.2.1: + dependencies: + '@babel/runtime': 7.27.3 + csstype: 3.1.3 + dunder-proto@1.0.1: dependencies: call-bind-apply-helpers: 1.0.2 @@ -3503,6 +4076,10 @@ snapshots: graceful-fs: 4.2.11 tapable: 2.2.1 + error-ex@1.3.2: + dependencies: + is-arrayish: 0.2.1 + es-abstract@1.23.9: dependencies: array-buffer-byte-length: 1.0.2 @@ -3849,6 +4426,8 @@ snapshots: dependencies: to-regex-range: 5.0.1 + find-root@1.1.0: {} + find-up@5.0.0: dependencies: locate-path: 6.0.0 @@ -3865,12 +4444,13 @@ snapshots: dependencies: is-callable: 1.2.7 - framer-motion@12.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + framer-motion@12.9.1(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: motion-dom: 12.9.1 motion-utils: 12.8.3 tslib: 2.8.1 optionalDependencies: + '@emotion/is-prop-valid': 1.3.1 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -3937,6 +4517,8 @@ snapshots: dependencies: is-glob: 4.0.3 + globals@11.12.0: {} + globals@14.0.0: {} globalthis@1.0.4: @@ -3976,6 +4558,10 @@ snapshots: dependencies: function-bind: 1.1.2 + hoist-non-react-statics@3.3.2: + dependencies: + react-is: 16.13.1 + ignore@5.3.2: {} import-fresh@3.3.1: @@ -3997,6 +4583,8 @@ snapshots: call-bound: 1.0.4 get-intrinsic: 1.3.0 + is-arrayish@0.2.1: {} + is-arrayish@0.3.2: {} is-async-function@2.1.1: @@ -4136,8 +4724,12 @@ snapshots: dependencies: argparse: 2.0.1 + jsesc@3.1.0: {} + json-buffer@3.0.1: {} + json-parse-even-better-errors@2.3.1: {} + json-schema-traverse@0.4.1: {} json-stable-stringify-without-jsonify@1.0.1: {} @@ -4159,6 +4751,8 @@ snapshots: object.assign: 4.1.7 object.values: 1.2.1 + keen-slider@6.8.6: {} + keyv@4.5.4: dependencies: json-buffer: 3.0.1 @@ -4219,6 +4813,8 @@ snapshots: lightningcss-win32-arm64-msvc: 1.29.2 lightningcss-win32-x64-msvc: 1.29.2 + lines-and-columns@1.2.4: {} + locate-path@6.0.0: dependencies: p-locate: 5.0.0 @@ -4384,12 +4980,21 @@ snapshots: dependencies: callsites: 3.1.0 + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.27.1 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + path-exists@4.0.0: {} path-key@3.1.1: {} path-parse@1.0.7: {} + path-type@4.0.0: {} + picocolors@1.1.1: {} picomatch@2.3.1: {} @@ -4455,6 +5060,8 @@ snapshots: react-is@16.13.1: {} + react-is@19.1.0: {} + react-remove-scroll-bar@2.3.8(@types/react@19.1.2)(react@18.3.1): dependencies: react: 18.3.1 @@ -4482,6 +5089,15 @@ snapshots: optionalDependencies: '@types/react': 19.1.2 + react-transition-group@4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + '@babel/runtime': 7.27.3 + dom-helpers: 5.2.1 + loose-envify: 1.4.0 + prop-types: 15.8.1 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react@18.3.1: dependencies: loose-envify: 1.4.0 @@ -4653,6 +5269,8 @@ snapshots: source-map-js@1.2.1: {} + source-map@0.5.7: {} + stable-hash@0.0.5: {} starknet@6.24.1: @@ -4742,6 +5360,8 @@ snapshots: client-only: 0.0.1 react: 18.3.1 + stylis@4.2.0: {} + supports-color@7.2.0: dependencies: has-flag: 4.0.0 @@ -4980,6 +5600,8 @@ snapshots: y18n@5.0.8: {} + yaml@1.10.2: {} + yargs-parser@21.1.1: {} yargs@17.7.2: diff --git a/src/app/dashboard/analytics/page.tsx b/src/app/dashboard/analytics/page.tsx index 9aef32b..0546a7a 100644 --- a/src/app/dashboard/analytics/page.tsx +++ b/src/app/dashboard/analytics/page.tsx @@ -1,13 +1,836 @@ +"use client"; - +import { useState } from "react"; +import { Button } from "@/components/ui/button"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { Badge } from "@/components/ui/badge"; +import { Input } from "@/components/ui/input"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table"; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; +import { + ChevronLeft, + ChevronRight, + Menu, + Bell, + Copy, + Wallet, + X, + ArrowLeft, +} from "lucide-react"; +import { + BarChart, + Bar, + XAxis, + YAxis, + CartesianGrid, + Tooltip, + ResponsiveContainer, + Cell, +} from "recharts"; function AnalyticsPage() { + const [currentPage, setCurrentPage] = useState(1); + const [showTransactionDetails, setShowTransactionDetails] = useState(false); + const [showRequestPayment, setShowRequestPayment] = useState(false); + const [showConfirmDetails, setShowConfirmDetails] = useState(false); + const [selectedTransaction, setSelectedTransaction] = useState(null); + const [paymentAmount, setPaymentAmount] = useState(""); + const totalPages = 12; + + const metrics = [ + { title: "Current Balance", value: "$3150.00", color: "text-blue-600" }, + { title: "Pending Payout", value: "$100.06", color: "text-blue-600" }, + { title: "Total Payout", value: "$2500.01", color: "text-blue-600" }, + { title: "Total Earned", value: "$2730.19", color: "text-blue-600" }, + ]; + + const transactions = [ + { + id: "Tran-1248", + type: "Monthly Payment", + amount: "10.99 STRK", + status: "Successful", + date: "26 April", + details: { + title: "99 Laws of Power", + subtitle: "NFT Edition", + amountPaid: "8.00 USDC", + royaltyEarned: "7.00 USDC", + platformCommission: "1.00 USDC", + nftId: "90002", + buyer: "USER-0001", + transactionId: "TRANS-00112", + transactionHash: "0x5a9f79...d9c7f9g", + confirmationStatus: "12/12", + time: "16:32", + }, + }, + { + id: "Tran-1248", + type: "Book Purchase", + amount: "76.09 STRK", + status: "Successful", + date: "25 April", + details: { + title: "99 Laws of Power", + subtitle: "NFT Edition", + amountPaid: "800.00 STRK", + royaltyEarned: "50.00 STRK", + platformCommission: "30.00 STRK", + nftId: "90002", + buyer: "USER-0001", + transactionId: "TRANS-00112", + transactionHash: "0x5a9f79...d9c7f9g", + confirmationStatus: "12/12", + time: "16:32", + }, + }, + { + id: "Tran-1248", + type: "Withdraw", + amount: "1560.00 STRK", + status: "Failed", + date: "20 April", + details: { + title: "Withdrawal Request", + subtitle: "Failed Transaction", + amountPaid: "1560.00 STRK", + royaltyEarned: "0.00 STRK", + platformCommission: "5.00 STRK", + nftId: "N/A", + buyer: "N/A", + transactionId: "TRANS-00110", + transactionHash: "0x5a9f79...d9c7f9g", + confirmationStatus: "0/12", + time: "14:22", + }, + }, + { + id: "Tran-1248", + type: "NFT Royalties", + amount: "7.02 STRK", + status: "Successful", + date: "18 April", + details: { + title: "NFT Royalty Payment", + subtitle: "Collection Royalty", + amountPaid: "7.02 STRK", + royaltyEarned: "7.02 STRK", + platformCommission: "0.50 STRK", + nftId: "90001", + buyer: "USER-0003", + transactionId: "TRANS-00109", + transactionHash: "0x5a9f79...d9c7f9g", + confirmationStatus: "12/12", + time: "10:15", + }, + }, + { + id: "Tran-1248", + type: "NFT Royalties", + amount: "8.09 STRK", + status: "Successful", + date: "18 April", + details: { + title: "NFT Royalty Payment", + subtitle: "Collection Royalty", + amountPaid: "8.09 STRK", + royaltyEarned: "8.09 STRK", + platformCommission: "0.60 STRK", + nftId: "90003", + buyer: "USER-0004", + transactionId: "TRANS-00108", + transactionHash: "0x5a9f79...d9c7f9g", + confirmationStatus: "12/12", + time: "09:45", + }, + }, + ]; + + const revenueData = [ + { + name: "Monthly Subscription", + value: 40, + amount: 121, + color: "#3B82F6", + label: "Monthly Subscription Payment", + }, + { + name: "NFT Royalty", + value: 10, + amount: 101, + color: "#EAB308", + label: "NFT Royalty", + }, + { + name: "NFT", + value: 22, + amount: 121, + color: "#A855F7", + label: "NFT", + }, + { + name: "Book Purchase", + value: 28, + amount: 101, + color: "#10B981", + label: "Book Purchase", + }, + ]; + + const handleViewDetails = (transaction: any) => { + setSelectedTransaction(transaction); + setShowTransactionDetails(true); + }; + + const handleRequestPayment = () => { + setShowRequestPayment(true); + }; + + const handleProceedPayment = () => { + setShowRequestPayment(false); + setShowConfirmDetails(true); + }; + + const handleConfirmPayment = () => { + setShowConfirmDetails(false); + setPaymentAmount(""); + // Handle payment confirmation logic here + }; + + const CustomTooltip = ({ active, payload, label }: any) => { + if (active && payload && payload.length) { + return ( +
+

{`${label}`}

+

+ {`${payload[0].dataKey === "value" ? "Percentage" : "Amount"}: ${ + payload[0].value + }${ + payload[0].dataKey === "value" + ? "%" + : payload[0].dataKey === "amount" + ? " STRK" + : "" + }`} +

+
+ ); + } + return null; + }; + + const PieTooltip = ({ active, payload }: any) => { + if (active && payload && payload.length) { + return ( +
+

{payload[0].payload.label}

+

{`${payload[0].value}% ($${payload[0].payload.amount})`}

+
+ ); + } + return null; + }; + return ( -
-

Analytics

-

Analytics page content goes here.

+
+ {/* Mobile Header */} +
+
+ +
+
+ C +
+ ChainLab +
+
+
+ +
+
+
+ +
+ {/* Earnings Section */} +
+

Earnings

+
+ {metrics.map((metric, index) => ( + + +
+ {metric.title} +
+
+ {metric.value} +
+
+
+ ))} +
+ + +
+ + {/* Revenue Breakdown */} + + + + Revenue Breakdown + + + +
+ {/* Chart - 50% width on desktop */} +
+ + + + + + } /> + + {revenueData.map((entry, index) => ( + + ))} + + + +
+ + {/* Legend - 50% width on desktop */} +
+ {revenueData.map((item, index) => ( +
+
+
+
{item.label}
+
+ {item.value}% (${item.amount}) +
+
+
+ ))} +
+
+
+
+ + {/* Transaction History */} + + + + Transaction History + +
+
+ + + +
+
+ + + +
+
+
+ + {/* Desktop Table */} +
+ + + + Transaction ID + Transaction Type + Amount (STRK) + Status + Date + + + + + {transactions.map((transaction, index) => ( + + + {transaction.id} + + {transaction.type} + {transaction.amount} + + + {transaction.status} + + + {transaction.date} + + + + + ))} + +
+
+ + {/* Mobile List */} +
+ {transactions.map((transaction, index) => ( +
+
+
+
+ {transaction.type} +
+
+ {transaction.id} +
+
+ + {transaction.status} + +
+
+
{transaction.amount}
+
+ {transaction.date} +
+
+ +
+ ))} + +
+ + {/* Pagination */} +
+
Showing 1 to 5 of 12
+
+ + {[1, 2, 3, "...", 10, 11, 12].map((page, index) => ( + + ))} + +
+
+
+
+ + {/* Link Wallet */} + + + Link Wallet + + + +
+
+
+ +
+
+
Braavos
+
(Starknet)
+
+
+ +
+ +
+
+
+ A +
+
+
Argent
+
(Starknet)
+
+
+ +
+
+
+
+ + {/* Transaction Details Modal */} + + + + + + Transaction Details + + + + + {selectedTransaction && ( +
+ {/* NFT/Item Info */} +
+
+
+

+ {selectedTransaction.details.title} +

+

+ {selectedTransaction.details.subtitle} +

+

eBook

+
+
+ + {/* Transaction Details */} +
+
+ Amount Paid + + {selectedTransaction.details.amountPaid} + +
+
+ Royalty Earned + + {selectedTransaction.details.royaltyEarned} + +
+
+ Platform Commission + + {selectedTransaction.details.platformCommission} + +
+
+ +
+ + {/* Additional Details */} +
+
+ Transaction Type + {selectedTransaction.type} +
+
+ Status + + {selectedTransaction.status} + +
+
+ Date + 12 March, 2025 +
+
+ Time + {selectedTransaction.details.time} +
+
+ NFT ID + {selectedTransaction.details.nftId} +
+
+ Buyer + {selectedTransaction.details.buyer} +
+
+ Transaction ID + {selectedTransaction.details.transactionId} +
+
+ Transaction Hash + + {selectedTransaction.details.transactionHash} + +
+
+ Confirmation Status + {selectedTransaction.details.confirmationStatus} +
+
+ + {/* Action Buttons */} +
+ + +
+
+ )} +
+
+ + {/* Request Payment Modal */} + + + + + Request Payment + + + + +
+ {/* Current Balance */} +
+ +
793 STRK
+
+ + {/* Enter Amount */} +
+ +
+ setPaymentAmount(e.target.value)} + className="pr-16" + /> + +
+
+ + {/* Destination Wallet */} +
+ +
+
+ +
+
+
Braavos
+
0x5a9f...c8b0
+
+
+
+ + {/* Proceed Button */} + +
+
+
+ + {/* Confirm Details Modal */} + + + + + Confirm Details + + + + +
+ {/* Amount to be sent */} +
+ Amount to be sent +
+
19.3 STRK
+
Tax (20%)
+
+
+ + {/* Destination wallet */} +
+ Destination wallet address + 0x5a9f...c8b0 +
+ + {/* Gas fees */} +
+ Gas fees + 5 STRK +
+ + {/* Estimated time */} +
+ Estimated time of delivery + 24-48 hours +
+ + {/* Confirm Button */} + +
+
+
); } -export default AnalyticsPage \ No newline at end of file +export default AnalyticsPage; diff --git a/src/components/ui/badge.tsx b/src/components/ui/badge.tsx new file mode 100644 index 0000000..0205413 --- /dev/null +++ b/src/components/ui/badge.tsx @@ -0,0 +1,46 @@ +import * as React from "react" +import { Slot } from "@radix-ui/react-slot" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const badgeVariants = cva( + "inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden", + { + variants: { + variant: { + default: + "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90", + secondary: + "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90", + destructive: + "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", + outline: + "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground", + }, + }, + defaultVariants: { + variant: "default", + }, + } +) + +function Badge({ + className, + variant, + asChild = false, + ...props +}: React.ComponentProps<"span"> & + VariantProps & { asChild?: boolean }) { + const Comp = asChild ? Slot : "span" + + return ( + + ) +} + +export { Badge, badgeVariants } diff --git a/src/components/ui/card.tsx b/src/components/ui/card.tsx new file mode 100644 index 0000000..d05bbc6 --- /dev/null +++ b/src/components/ui/card.tsx @@ -0,0 +1,92 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +function Card({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function CardHeader({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function CardTitle({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function CardDescription({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function CardAction({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function CardContent({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function CardFooter({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +export { + Card, + CardHeader, + CardFooter, + CardTitle, + CardAction, + CardDescription, + CardContent, +} diff --git a/src/components/ui/dialog.tsx b/src/components/ui/dialog.tsx new file mode 100644 index 0000000..1647513 --- /dev/null +++ b/src/components/ui/dialog.tsx @@ -0,0 +1,122 @@ +"use client" + +import * as React from "react" +import * as DialogPrimitive from "@radix-ui/react-dialog" +import { X } from "lucide-react" + +import { cn } from "@/lib/utils" + +const Dialog = DialogPrimitive.Root + +const DialogTrigger = DialogPrimitive.Trigger + +const DialogPortal = DialogPrimitive.Portal + +const DialogClose = DialogPrimitive.Close + +const DialogOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogOverlay.displayName = DialogPrimitive.Overlay.displayName + +const DialogContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + {children} + + + Close + + + +)) +DialogContent.displayName = DialogPrimitive.Content.displayName + +const DialogHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +DialogHeader.displayName = "DialogHeader" + +const DialogFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +DialogFooter.displayName = "DialogFooter" + +const DialogTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogTitle.displayName = DialogPrimitive.Title.displayName + +const DialogDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogDescription.displayName = DialogPrimitive.Description.displayName + +export { + Dialog, + DialogPortal, + DialogOverlay, + DialogTrigger, + DialogClose, + DialogContent, + DialogHeader, + DialogFooter, + DialogTitle, + DialogDescription, +} diff --git a/src/components/ui/select.tsx b/src/components/ui/select.tsx new file mode 100644 index 0000000..6e637f7 --- /dev/null +++ b/src/components/ui/select.tsx @@ -0,0 +1,159 @@ +"use client" + +import * as React from "react" +import * as SelectPrimitive from "@radix-ui/react-select" +import { Check, ChevronDown, ChevronUp } from "lucide-react" + +import { cn } from "@/lib/utils" + +const Select = SelectPrimitive.Root + +const SelectGroup = SelectPrimitive.Group + +const SelectValue = SelectPrimitive.Value + +const SelectTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + span]:line-clamp-1", + className + )} + {...props} + > + {children} + + + + +)) +SelectTrigger.displayName = SelectPrimitive.Trigger.displayName + +const SelectScrollUpButton = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)) +SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName + +const SelectScrollDownButton = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)) +SelectScrollDownButton.displayName = + SelectPrimitive.ScrollDownButton.displayName + +const SelectContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, position = "popper", ...props }, ref) => ( + + + + + {children} + + + + +)) +SelectContent.displayName = SelectPrimitive.Content.displayName + +const SelectLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +SelectLabel.displayName = SelectPrimitive.Label.displayName + +const SelectItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + {children} + +)) +SelectItem.displayName = SelectPrimitive.Item.displayName + +const SelectSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +SelectSeparator.displayName = SelectPrimitive.Separator.displayName + +export { + Select, + SelectGroup, + SelectValue, + SelectTrigger, + SelectContent, + SelectLabel, + SelectItem, + SelectSeparator, + SelectScrollUpButton, + SelectScrollDownButton, +} diff --git a/src/components/ui/table.tsx b/src/components/ui/table.tsx new file mode 100644 index 0000000..c0df655 --- /dev/null +++ b/src/components/ui/table.tsx @@ -0,0 +1,120 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +const Table = React.forwardRef< + HTMLTableElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+ + +)) +Table.displayName = "Table" + +const TableHeader = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableHeader.displayName = "TableHeader" + +const TableBody = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableBody.displayName = "TableBody" + +const TableFooter = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + tr]:last:border-b-0", + className + )} + {...props} + /> +)) +TableFooter.displayName = "TableFooter" + +const TableRow = React.forwardRef< + HTMLTableRowElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableRow.displayName = "TableRow" + +const TableHead = React.forwardRef< + HTMLTableCellElement, + React.ThHTMLAttributes +>(({ className, ...props }, ref) => ( +
[role=checkbox]]:translate-y-[2px]", + className + )} + {...props} + /> +)) +TableHead.displayName = "TableHead" + +const TableCell = React.forwardRef< + HTMLTableCellElement, + React.TdHTMLAttributes +>(({ className, ...props }, ref) => ( + [role=checkbox]]:translate-y-[2px]", + className + )} + {...props} + /> +)) +TableCell.displayName = "TableCell" + +const TableCaption = React.forwardRef< + HTMLTableCaptionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +TableCaption.displayName = "TableCaption" + +export { + Table, + TableHeader, + TableBody, + TableFooter, + TableHead, + TableRow, + TableCell, + TableCaption, +} From c0b4ded582282eca367c5f79d66e945a8782cb5a Mon Sep 17 00:00:00 2001 From: boludedaniel Date: Fri, 30 May 2025 10:02:21 +0100 Subject: [PATCH 2/7] feat/implement analytics page --- package.json | 1 + public/starknet.png | Bin 0 -> 3100 bytes src/app/dashboard/analytics/page.tsx | 942 +++--------------- src/app/dashboard/earnings/page.tsx | 5 +- .../dashboard/transaction-table.tsx | 113 +++ src/components/ui/tabs.tsx | 55 + 6 files changed, 314 insertions(+), 802 deletions(-) create mode 100644 public/starknet.png create mode 100644 src/components/dashboard/transaction-table.tsx create mode 100644 src/components/ui/tabs.tsx diff --git a/package.json b/package.json index 670f9b3..31383a9 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "@radix-ui/react-dialog": "^1.1.14", "@radix-ui/react-select": "^2.2.5", "@radix-ui/react-slot": "^1.2.0", + "@radix-ui/react-tabs": "^1.1.12", "@splidejs/react-splide": "^0.7.12", "@splidejs/splide": "^4.1.4", "@starknet-react/chains": "^3.1.2", diff --git a/public/starknet.png b/public/starknet.png new file mode 100644 index 0000000000000000000000000000000000000000..9a47a266b8d777826e912ba3f05e39620392ffd9 GIT binary patch literal 3100 zcmV+%4CC{OP)`u|S~`v3nXCT;&w03aZ09UW-^0AVB~Y#JJ9A|h)50ABzASrrv#tgOJ<+2U(! zlMxYR|3U!a;ppq@@c&Byg@vU6CUWud^vKB7va-a(!_qoBcT!S>2nb`DnX^kve_C3I zkdUlJMSL|1|*n>E#$FaPLhTQ!i!wub=$Lz359J03&u` zF=73Ubj?OJqdiJMENOQ&T8B7Q``p<5rj-1;t^3Z${%uSDWj+0nfB#G!|5Pm4NG)+< zhBXOUv_L}PxVD*4V{9{Cgww1gQAZy zttPeFW~18IyA-gl-mf;yc1x;hN4=Ix4%8V`^{yxgvdD9J7DBOkju&M?5W9MH&`A!K z45~J5aAiT{iZ)Bw*diwi7hGdn`&&@zc-9qU42};?6uPsqdU~i@MZYj`0-+=`F7(Qw zdL0HORl5Qg7sxeE=vJjuL21)rnUAfJPcObaoF3r!v7xleP(D~Bk6iMw!lVqvR45^z z9LbhT7{$ek2i5AyMIvx~ zK@+0eFanA(c|KhxisJbwvB*&Btduqqw94az~X>>$F z5Z|~FdeA{asiPBxf}rsuq*f@XTKBK$1dZ#W{0afZoZiRxR_G!6U>Hi%{~{Bh(!=p8 z3^g(SCKHHPlW3^HNrqsOl|my<5ULetmYJ@xa&UAGK&hu2g9%ikN`hi$Ck;?6Ce-jV zh5%)r)S=i>71OaxCLXGF+CVOvOcnD9d1>*7s^a|-V!i&1V%6l z(~$%d4JDm;#FHB|L-%nX!bwOdoEN5LB?&-PaII0OqM%yk(=z3|D#I`;)JD-K|1XS@c!SIw}yutUuUHAR54VtLlC z1z+gAwAP-Ljab#a66OtvVOE~{poZZ_mPd^m;&uDCYGyA^0ff`XaH+=kx0=*Ig?4V} zg_1%sioX~Tklc57^cbzk3H;2Ib}s`FvC%WoU9c>9pn`)pD@>x0oDYzyg*a-7!l>i) zzKUTKaP7`l_fWO2pPPpvBO1y1zlWtbzEu=jcAV;vYB}t78b~4Hf!x<(B5kqSLrg*v zPys%zA-vaP+o)he>AnZc4dwtQ#*T+EYT9f8j(s(9Zp-N|lzQR)d7*L`l8q(xqQw&0 zAWJX}@ArTYAnnsms*u09*JY6f! zwou-_2c{Ltn4o8kBAQTa)9t8S#O{9pYP#=xVk0pVpkfB(Cgf)=Y&N_zVQND)cJu{3 zIg*Vv7KtvyQPI-?kjXNey}o*SUM!ddU~r^J78`^%W!gT;j`mDIoX4x% z7iB(Ipv{%nx2Hr{9U)N>PBy9S$S1q4m(4C7-+tGXdOfqVx}vo2WO98<&)Z)$I?G(W;D{Wo_2I5X*Q#;EV)?S(p(l12$?KFII|~hZu|_qU-<02n zdls0$MT;d<6F4{C#&NdmNH@63D7jn&6A!@kS4BeSwcj;Rs?it>wdYB$o1)BxGr38I@)gMc_(qx=T-y&CFUi zKff~(So7P%plE`yKU>q+R zr4cMTdIz_EY?}`_x*jZ$O`xhL$@`E@i~7p_NH`hYP1|uz_(7slu2P}O-hR6tWl!68!yuOG0S^U}h7{aA z`=osCpzH!iCu-rp`AJF~l&_=RJBh-Fr zEwBiQH}-~@V!^rU`;WM4WtsK7p2_4Myh804A@Tc%!dS#kxK-;aPDwJGef*k(=Y2iT zw_F>q|Jim!?u0hh{OvJ9t}OHX1!V#b<^P{O3)`VB00gs^QB=U?>t9z3tX|+3PhW~+ zKbc#39m=-_0I^wuKt;~ocXGX6JugDVW$^vt`Bs^`MJJz=2R2Kfww2(i*oe8R%T<5< zTK`z=O5YIhdHwb3hy-=I_cQsol^{3Z;H~*djH7!lAlQ8V{_=JE_I7&V?=XWKYZRdA+pKWJ&&7p1QcOm4~YSRXLaaLDnI>u}-87&1a q87;^{>Hl-dsB7WtSSM**$NE1-gcrldVQI4f0000(null); - const [paymentAmount, setPaymentAmount] = useState(""); - const totalPages = 12; - - const metrics = [ - { title: "Current Balance", value: "$3150.00", color: "text-blue-600" }, - { title: "Pending Payout", value: "$100.06", color: "text-blue-600" }, - { title: "Total Payout", value: "$2500.01", color: "text-blue-600" }, - { title: "Total Earned", value: "$2730.19", color: "text-blue-600" }, - ]; - - const transactions = [ - { - id: "Tran-1248", - type: "Monthly Payment", - amount: "10.99 STRK", - status: "Successful", - date: "26 April", - details: { - title: "99 Laws of Power", - subtitle: "NFT Edition", - amountPaid: "8.00 USDC", - royaltyEarned: "7.00 USDC", - platformCommission: "1.00 USDC", - nftId: "90002", - buyer: "USER-0001", - transactionId: "TRANS-00112", - transactionHash: "0x5a9f79...d9c7f9g", - confirmationStatus: "12/12", - time: "16:32", - }, - }, - { - id: "Tran-1248", - type: "Book Purchase", - amount: "76.09 STRK", - status: "Successful", - date: "25 April", - details: { - title: "99 Laws of Power", - subtitle: "NFT Edition", - amountPaid: "800.00 STRK", - royaltyEarned: "50.00 STRK", - platformCommission: "30.00 STRK", - nftId: "90002", - buyer: "USER-0001", - transactionId: "TRANS-00112", - transactionHash: "0x5a9f79...d9c7f9g", - confirmationStatus: "12/12", - time: "16:32", - }, - }, - { - id: "Tran-1248", - type: "Withdraw", - amount: "1560.00 STRK", - status: "Failed", - date: "20 April", - details: { - title: "Withdrawal Request", - subtitle: "Failed Transaction", - amountPaid: "1560.00 STRK", - royaltyEarned: "0.00 STRK", - platformCommission: "5.00 STRK", - nftId: "N/A", - buyer: "N/A", - transactionId: "TRANS-00110", - transactionHash: "0x5a9f79...d9c7f9g", - confirmationStatus: "0/12", - time: "14:22", - }, - }, - { - id: "Tran-1248", - type: "NFT Royalties", - amount: "7.02 STRK", - status: "Successful", - date: "18 April", - details: { - title: "NFT Royalty Payment", - subtitle: "Collection Royalty", - amountPaid: "7.02 STRK", - royaltyEarned: "7.02 STRK", - platformCommission: "0.50 STRK", - nftId: "90001", - buyer: "USER-0003", - transactionId: "TRANS-00109", - transactionHash: "0x5a9f79...d9c7f9g", - confirmationStatus: "12/12", - time: "10:15", - }, - }, - { - id: "Tran-1248", - type: "NFT Royalties", - amount: "8.09 STRK", - status: "Successful", - date: "18 April", - details: { - title: "NFT Royalty Payment", - subtitle: "Collection Royalty", - amountPaid: "8.09 STRK", - royaltyEarned: "8.09 STRK", - platformCommission: "0.60 STRK", - nftId: "90003", - buyer: "USER-0004", - transactionId: "TRANS-00108", - transactionHash: "0x5a9f79...d9c7f9g", - confirmationStatus: "12/12", - time: "09:45", - }, - }, - ]; - - const revenueData = [ - { - name: "Monthly Subscription", - value: 40, - amount: 121, - color: "#3B82F6", - label: "Monthly Subscription Payment", - }, - { - name: "NFT Royalty", - value: 10, - amount: 101, - color: "#EAB308", - label: "NFT Royalty", - }, - { - name: "NFT", - value: 22, - amount: 121, - color: "#A855F7", - label: "NFT", - }, - { - name: "Book Purchase", - value: 28, - amount: 101, - color: "#10B981", - label: "Book Purchase", - }, +import { Star } from "lucide-react"; +import Image from "next/image"; + +export default function AnalyticsDashboard() { + const books = [ + { rank: 1, title: "The Act" }, + { rank: 2, title: "Live at Night" }, + { rank: 3, title: "Prince of Peace" }, + { rank: 4, title: "Late Every Night" }, + { rank: 5, title: "The 91 Law of Power" }, ]; - const handleViewDetails = (transaction: any) => { - setSelectedTransaction(transaction); - setShowTransactionDetails(true); - }; - - const handleRequestPayment = () => { - setShowRequestPayment(true); - }; + return ( +
+
+ {/* Top Stats Grid */} +
+
+
Total Read
+
192
+
- const handleProceedPayment = () => { - setShowRequestPayment(false); - setShowConfirmDetails(true); - }; +
+
Subscribers
+
70
+
- const handleConfirmPayment = () => { - setShowConfirmDetails(false); - setPaymentAmount(""); - // Handle payment confirmation logic here - }; +
+
Followers
+
2071
+
- const CustomTooltip = ({ active, payload, label }: any) => { - if (active && payload && payload.length) { - return ( -
-

{`${label}`}

-

- {`${payload[0].dataKey === "value" ? "Percentage" : "Amount"}: ${ - payload[0].value - }${ - payload[0].dataKey === "value" - ? "%" - : payload[0].dataKey === "amount" - ? " STRK" - : "" - }`} -

-
- ); - } - return null; - }; +
+
Total Purchase
+
25
+
- const PieTooltip = ({ active, payload }: any) => { - if (active && payload && payload.length) { - return ( -
-

{payload[0].payload.label}

-

{`${payload[0].value}% ($${payload[0].payload.amount})`}

-
- ); - } - return null; - }; +
+
NFT Minted
+
18
+
- return ( -
- {/* Mobile Header */} -
-
- -
-
- C +
+
+ Read Completion Rate
- ChainLab +
70%
-
-
- -
-
-
-
- {/* Earnings Section */} -
-

Earnings

-
- {metrics.map((metric, index) => ( - - -
- {metric.title} -
-
- {metric.value} -
-
-
- ))} +
+
Average Rating
+
4.0
- -
- {/* Revenue Breakdown */} - - - - Revenue Breakdown - - - -
- {/* Chart - 50% width on desktop */} -
- - - - - - } /> - - {revenueData.map((entry, index) => ( - - ))} - - - -
- - {/* Legend - 50% width on desktop */} -
- {revenueData.map((item, index) => ( -
-
-
-
{item.label}
-
- {item.value}% (${item.amount}) -
-
-
- ))} -
-
-
-
- - {/* Transaction History */} - - - - Transaction History - -
-
- - - -
-
- - - -
-
-
- - {/* Desktop Table */} -
- - - - Transaction ID - Transaction Type - Amount (STRK) - Status - Date - - - - - {transactions.map((transaction, index) => ( - - - {transaction.id} - - {transaction.type} - {transaction.amount} - - - {transaction.status} - - - {transaction.date} - - - - - ))} - -
+
+ {/* Book Performance Stats */} +
+

+ Book Performance Stats +

+
+ + + +
+
- {/* Mobile List */} -
- {transactions.map((transaction, index) => ( -
-
-
-
- {transaction.type} -
-
- {transaction.id} -
-
- - {transaction.status} - -
-
-
{transaction.amount}
-
- {transaction.date} -
+ {/* Two Column Layout */} +
+ {/* Stats for Act */} +
+

+ Stats for Act +

+ +
+
+
Read
+
+ + 192 + + + -20% +
- -
- ))} - -
- - {/* Pagination */} -
-
Showing 1 to 5 of 12
-
- - {[1, 2, 3, "...", 10, 11, 12].map((page, index) => ( - - ))} - -
-
- - - - {/* Link Wallet */} - - - Link Wallet - - - -
-
-
- -
-
-
Braavos
-
(Starknet)
-
- -
-
-
-
- A -
-
-
Argent
-
(Starknet)
+
+
+ Read Compl Rate +
+
+ + 75% + + + +16% + +
-
- -
- - -
- - {/* Transaction Details Modal */} - - - - - - Transaction Details - - - - {selectedTransaction && ( -
- {/* NFT/Item Info */} -
-
-
-

- {selectedTransaction.details.title} -

-

- {selectedTransaction.details.subtitle} -

-

eBook

+
+
Sale
+
+ + 62 + + + +20% + +
-
- {/* Transaction Details */} -
-
- Amount Paid - - {selectedTransaction.details.amountPaid} - -
-
- Royalty Earned - - {selectedTransaction.details.royaltyEarned} - -
-
- Platform Commission - - {selectedTransaction.details.platformCommission} - +
+
+ Total Earning +
+
+ Indian Rupee + 3150.00 +
-
-
- - {/* Additional Details */} -
-
- Transaction Type - {selectedTransaction.type} -
-
- Status - - {selectedTransaction.status} - -
-
- Date - 12 March, 2025 -
-
- Time - {selectedTransaction.details.time} -
-
- NFT ID - {selectedTransaction.details.nftId} -
-
- Buyer - {selectedTransaction.details.buyer} -
-
- Transaction ID - {selectedTransaction.details.transactionId} -
-
- Transaction Hash - - {selectedTransaction.details.transactionHash} - -
-
- Confirmation Status - {selectedTransaction.details.confirmationStatus} +
+
+ Average Rating +
+
+ + + 3.5 + +
- - {/* Action Buttons */} -
- - -
-
- )} - -
- - {/* Request Payment Modal */} - - - - - Request Payment - - - - -
- {/* Current Balance */} -
- -
793 STRK
- {/* Enter Amount */} -
- -
- setPaymentAmount(e.target.value)} - className="pr-16" - /> -
-
- - {/* Destination Wallet */} -
- -
-
- -
-
-
Braavos
-
0x5a9f...c8b0
-
-
-
- {/* Proceed Button */} - -
-
-
- - {/* Confirm Details Modal */} - - - - - Confirm Details - - - - -
- {/* Amount to be sent */} -
- Amount to be sent -
-
19.3 STRK
-
Tax (20%)
+
+ {books.map((book) => ( +
+ + {book.rank}. + +
+
+
+ {book.title} +
+
+ +
+ ))}
- - {/* Destination wallet */} -
- Destination wallet address - 0x5a9f...c8b0 -
- - {/* Gas fees */} -
- Gas fees - 5 STRK -
- - {/* Estimated time */} -
- Estimated time of delivery - 24-48 hours -
- - {/* Confirm Button */} -
- -
+
+
); } - -export default AnalyticsPage; diff --git a/src/app/dashboard/earnings/page.tsx b/src/app/dashboard/earnings/page.tsx index ee55de9..34a4e59 100644 --- a/src/app/dashboard/earnings/page.tsx +++ b/src/app/dashboard/earnings/page.tsx @@ -1,6 +1,3 @@ - - - function EarningsPage() { return (
@@ -12,4 +9,4 @@ function EarningsPage() { ); } -export default EarningsPage; \ No newline at end of file +export default EarningsPage; diff --git a/src/components/dashboard/transaction-table.tsx b/src/components/dashboard/transaction-table.tsx new file mode 100644 index 0000000..020d8d8 --- /dev/null +++ b/src/components/dashboard/transaction-table.tsx @@ -0,0 +1,113 @@ +"use client"; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table"; +// Transaction Table Component +import { Badge } from "@/components/ui/badge"; +import { Button } from "@/components/ui/button"; +function TransactionTable({ + transactions, + onViewDetails, +}: { + transactions: any[]; + onViewDetails: (transaction: any) => void; +}) { + return ( + <> + {/* Desktop Table */} +
+ + + + Transaction ID + Transaction Type + Amount (STRK) + Status + Date + + + + + {transactions.map((transaction, index) => ( + + {transaction.id} + {transaction.type} + {transaction.amount} + + + {transaction.status} + + + {transaction.date} + + + + + ))} + +
+
+ + {/* Mobile List */} +
+ {transactions.map((transaction, index) => ( +
+
+
+
{transaction.type}
+
{transaction.id}
+
+ + {transaction.status} + +
+
+
{transaction.amount}
+
{transaction.date}
+
+ +
+ ))} +
+ + ); +} diff --git a/src/components/ui/tabs.tsx b/src/components/ui/tabs.tsx new file mode 100644 index 0000000..35f66dd --- /dev/null +++ b/src/components/ui/tabs.tsx @@ -0,0 +1,55 @@ +"use client"; + +import * as React from "react"; +import * as TabsPrimitive from "@radix-ui/react-tabs"; + +import { cn } from "@/lib/utils"; + +const Tabs = TabsPrimitive.Root; + +const TabsList = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +TabsList.displayName = TabsPrimitive.List.displayName; + +const TabsTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +TabsTrigger.displayName = TabsPrimitive.Trigger.displayName; + +const TabsContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +TabsContent.displayName = TabsPrimitive.Content.displayName; + +export { Tabs, TabsList, TabsTrigger, TabsContent }; From ac5066de73301502115c3c32c6cf9b4b57327b12 Mon Sep 17 00:00:00 2001 From: boludedaniel Date: Fri, 30 May 2025 10:14:13 +0100 Subject: [PATCH 3/7] feat/added tabs to toggle between timeframes --- src/app/dashboard/analytics/page.tsx | 567 ++++++++++++++++++++++----- 1 file changed, 469 insertions(+), 98 deletions(-) diff --git a/src/app/dashboard/analytics/page.tsx b/src/app/dashboard/analytics/page.tsx index bd98c8d..2df991d 100644 --- a/src/app/dashboard/analytics/page.tsx +++ b/src/app/dashboard/analytics/page.tsx @@ -1,6 +1,7 @@ import { Button } from "@/components/ui/button"; import { Star } from "lucide-react"; import Image from "next/image"; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; export default function AnalyticsDashboard() { const books = [ @@ -56,124 +57,494 @@ export default function AnalyticsDashboard() {
{/* Book Performance Stats */} -
-

+
+

Book Performance Stats

-
- - - - -
-
+ + + This Week + This Month + This Year + All Time + + + {/* Two Column Layout */} +
+ {/* Stats for Act */} +
+

+ Stats for Act +

- {/* Two Column Layout */} -
- {/* Stats for Act */} -
-

- Stats for Act -

- -
-
-
Read
-
- - 192 - - - -20% - -
-
+
+
+
Read
+
+ + 192 + + + -20% + +
+
-
-
- Read Compl Rate -
-
- - 75% - - - +16% - +
+
+ Read Compl Rate +
+
+ + 75% + + + +16% + +
+
+ +
+
Sale
+
+ + 62 + + + +20% + +
+
+ +
+
+ Total Earning +
+
+ Indian Rupee + 3150.00 +
+
+ +
+
+ Average Rating +
+
+ + + 3.5 + +
+
+
-
-
-
Sale
-
- - 62 - - - +20% - + {/* Top Performing Books */} +
+
+

+ Top Performing Books +

+ +
+ +
+ {books.map((book) => ( +
+ + {book.rank}. + +
+
+
+ {book.title} +
+
+ +
+ ))} +
+ + + {/* Two Column Layout */} +
+ {/* Stats for Act */} +
+

+ Stats for Act +

+ +
+
+
Read
+
+ + 192 + + + -20% + +
+
+ +
+
+ Read Compl Rate +
+
+ + 75% + + + +16% + +
+
+ +
+
Sale
+
+ + 62 + + + +20% + +
+
-
-
- Total Earning +
+
+ Total Earning +
+
+ Indian Rupee + 3150.00 +
+
+ +
+
+ Average Rating +
+
+ + + 3.5 + +
+
+
-
- Indian Rupee - 3150.00 + + {/* Top Performing Books */} +
+
+

+ Top Performing Books +

+ +
+ +
+ {books.map((book) => ( +
+ + {book.rank}. + +
+
+
+ {book.title} +
+
+ +
+ ))} +
+ + + {/* Two Column Layout */} +
+ {/* Stats for Act */} +
+

+ Stats for Act +

+ +
+
+
Read
+
+ + 192 + + + -20% + +
+
+ +
+
+ Read Compl Rate +
+
+ + 75% + + + +16% + +
+
+ +
+
Sale
+
+ + 62 + + + +20% + +
+
+ +
+
+ Total Earning +
+
+ Indian Rupee + 3150.00 +
+
-
-
- Average Rating +
+
+ Average Rating +
+
+ + + 3.5 + +
+
+
-
- - - 3.5 - + + {/* Top Performing Books */} +
+
+

+ Top Performing Books +

+ +
+ +
+ {books.map((book) => ( +
+ + {book.rank}. + +
+
+
+ {book.title} +
+
+ +
+ ))} +
-
-
+ + + {/* Two Column Layout */} +
+ {/* Stats for Act */} +
+

+ Stats for Act +

- {/* Top Performing Books */} -
-
-

- Top Performing Books -

- -
- -
- {books.map((book) => ( -
- - {book.rank}. - -
-
-
- {book.title} +
+
+
Read
+
+ + 192 + + + -20% + +
+
+ +
+
+ Read Compl Rate +
+
+ + 75% + + + +16% + +
+
+ +
+
Sale
+
+ + 62 + + + +20% + +
+
+ +
+
+ Total Earning +
+
+ Indian Rupee + 3150.00 +
+
+ +
+
+ Average Rating +
+
+ + + 3.5 + +
-
- ))} -
-
+ + {/* Top Performing Books */} +
+
+

+ Top Performing Books +

+ +
+ +
+ {books.map((book) => ( +
+ + {book.rank}. + +
+
+
+ {book.title} +
+
+ +
+ ))} +
+
+
+ +
From 7253617331aeca7eed53dc145d11a95b389c7f89 Mon Sep 17 00:00:00 2001 From: boludedaniel Date: Fri, 30 May 2025 10:17:17 +0100 Subject: [PATCH 4/7] fix/fixed alignment issues --- src/app/dashboard/analytics/page.tsx | 4 ++-- src/components/ui/tabs.tsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/dashboard/analytics/page.tsx b/src/app/dashboard/analytics/page.tsx index 2df991d..1d95311 100644 --- a/src/app/dashboard/analytics/page.tsx +++ b/src/app/dashboard/analytics/page.tsx @@ -58,11 +58,11 @@ export default function AnalyticsDashboard() {
{/* Book Performance Stats */}
-

+

Book Performance Stats

- + This Week This Month This Year diff --git a/src/components/ui/tabs.tsx b/src/components/ui/tabs.tsx index 35f66dd..baa3740 100644 --- a/src/components/ui/tabs.tsx +++ b/src/components/ui/tabs.tsx @@ -29,7 +29,7 @@ const TabsTrigger = React.forwardRef< Date: Fri, 30 May 2025 10:22:05 +0100 Subject: [PATCH 5/7] corrected height issues --- src/app/dashboard/analytics/page.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/dashboard/analytics/page.tsx b/src/app/dashboard/analytics/page.tsx index 1d95311..3e17947 100644 --- a/src/app/dashboard/analytics/page.tsx +++ b/src/app/dashboard/analytics/page.tsx @@ -77,7 +77,7 @@ export default function AnalyticsDashboard() { Stats for Act

-
+
Read
@@ -146,7 +146,7 @@ export default function AnalyticsDashboard() {
{/* Top Performing Books */} -
+

Top Performing Books From f7c36679b3b5173eb3e7343a23c9507e1c5e3265 Mon Sep 17 00:00:00 2001 From: boludedaniel Date: Fri, 30 May 2025 10:27:21 +0100 Subject: [PATCH 6/7] fix/added links for navigating back --- src/app/dashboard/analytics/page.tsx | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/app/dashboard/analytics/page.tsx b/src/app/dashboard/analytics/page.tsx index 3e17947..ddcde54 100644 --- a/src/app/dashboard/analytics/page.tsx +++ b/src/app/dashboard/analytics/page.tsx @@ -1,7 +1,8 @@ import { Button } from "@/components/ui/button"; -import { Star } from "lucide-react"; +import { Star, ArrowLeft } from "lucide-react"; import Image from "next/image"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; +import Link from "next/link"; export default function AnalyticsDashboard() { const books = [ @@ -15,6 +16,14 @@ export default function AnalyticsDashboard() { return (
+ {/* Header with back button */} +
+ + + +

Analytics

+
+ {/* Top Stats Grid */}
From 8d4e0bdf45e66c565350c4a81a439c36323b52ac Mon Sep 17 00:00:00 2001 From: boludedaniel Date: Fri, 30 May 2025 10:39:23 +0100 Subject: [PATCH 7/7] fix/created modular components for analytics page --- src/app/dashboard/analytics/page.tsx | 548 +----------------- src/components/analytics/analytics-header.tsx | 16 + .../analytics/analytics-stats-grid.tsx | 44 ++ src/components/analytics/analytics-tabs.tsx | 446 ++++++++++++++ 4 files changed, 512 insertions(+), 542 deletions(-) create mode 100644 src/components/analytics/analytics-header.tsx create mode 100644 src/components/analytics/analytics-stats-grid.tsx create mode 100644 src/components/analytics/analytics-tabs.tsx diff --git a/src/app/dashboard/analytics/page.tsx b/src/app/dashboard/analytics/page.tsx index ddcde54..0e421a2 100644 --- a/src/app/dashboard/analytics/page.tsx +++ b/src/app/dashboard/analytics/page.tsx @@ -1,68 +1,15 @@ -import { Button } from "@/components/ui/button"; -import { Star, ArrowLeft } from "lucide-react"; -import Image from "next/image"; -import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; -import Link from "next/link"; +import AnalyticsHeader from "@/components/analytics/analytics-header"; +import AnalyticsStatsGrid from "@/components/analytics/analytics-stats-grid"; +import AnalyticsTabs from "@/components/analytics/analytics-tabs"; export default function AnalyticsDashboard() { - const books = [ - { rank: 1, title: "The Act" }, - { rank: 2, title: "Live at Night" }, - { rank: 3, title: "Prince of Peace" }, - { rank: 4, title: "Late Every Night" }, - { rank: 5, title: "The 91 Law of Power" }, - ]; - return (
{/* Header with back button */} -
- - - -

Analytics

-
- + {/* Top Stats Grid */} -
-
-
Total Read
-
192
-
- -
-
Subscribers
-
70
-
- -
-
Followers
-
2071
-
- -
-
Total Purchase
-
25
-
- -
-
NFT Minted
-
18
-
- -
-
- Read Completion Rate -
-
70%
-
- -
-
Average Rating
-
4.0
-
-
+
{/* Book Performance Stats */} @@ -70,490 +17,7 @@ export default function AnalyticsDashboard() {

Book Performance Stats

- - - This Week - This Month - This Year - All Time - - - {/* Two Column Layout */} -
- {/* Stats for Act */} -
-

- Stats for Act -

- -
-
-
Read
-
- - 192 - - - -20% - -
-
- -
-
- Read Compl Rate -
-
- - 75% - - - +16% - -
-
- -
-
Sale
-
- - 62 - - - +20% - -
-
- -
-
- Total Earning -
-
- Indian Rupee - 3150.00 -
-
- -
-
- Average Rating -
-
- - - 3.5 - -
-
-
-
- - {/* Top Performing Books */} -
-
-

- Top Performing Books -

- -
- -
- {books.map((book) => ( -
- - {book.rank}. - -
-
-
- {book.title} -
-
- -
- ))} -
-
-
-
- - {/* Two Column Layout */} -
- {/* Stats for Act */} -
-

- Stats for Act -

- -
-
-
Read
-
- - 192 - - - -20% - -
-
- -
-
- Read Compl Rate -
-
- - 75% - - - +16% - -
-
- -
-
Sale
-
- - 62 - - - +20% - -
-
- -
-
- Total Earning -
-
- Indian Rupee - 3150.00 -
-
- -
-
- Average Rating -
-
- - - 3.5 - -
-
-
-
- - {/* Top Performing Books */} -
-
-

- Top Performing Books -

- -
- -
- {books.map((book) => ( -
- - {book.rank}. - -
-
-
- {book.title} -
-
- -
- ))} -
-
-
-
- - {/* Two Column Layout */} -
- {/* Stats for Act */} -
-

- Stats for Act -

- -
-
-
Read
-
- - 192 - - - -20% - -
-
- -
-
- Read Compl Rate -
-
- - 75% - - - +16% - -
-
- -
-
Sale
-
- - 62 - - - +20% - -
-
- -
-
- Total Earning -
-
- Indian Rupee - 3150.00 -
-
- -
-
- Average Rating -
-
- - - 3.5 - -
-
-
-
- - {/* Top Performing Books */} -
-
-

- Top Performing Books -

- -
- -
- {books.map((book) => ( -
- - {book.rank}. - -
-
-
- {book.title} -
-
- -
- ))} -
-
-
-
- - {/* Two Column Layout */} -
- {/* Stats for Act */} -
-

- Stats for Act -

- -
-
-
Read
-
- - 192 - - - -20% - -
-
- -
-
- Read Compl Rate -
-
- - 75% - - - +16% - -
-
- -
-
Sale
-
- - 62 - - - +20% - -
-
- -
-
- Total Earning -
-
- Indian Rupee - 3150.00 -
-
- -
-
- Average Rating -
-
- - - 3.5 - -
-
-
-
- - {/* Top Performing Books */} -
-
-

- Top Performing Books -

- -
- -
- {books.map((book) => ( -
- - {book.rank}. - -
-
-
- {book.title} -
-
- -
- ))} -
-
-
-
-
+
diff --git a/src/components/analytics/analytics-header.tsx b/src/components/analytics/analytics-header.tsx new file mode 100644 index 0000000..24258c9 --- /dev/null +++ b/src/components/analytics/analytics-header.tsx @@ -0,0 +1,16 @@ +import React from "react"; + +import Link from "next/link"; +import { ArrowLeft } from "lucide-react"; +const AnalyticsHeader = () => { + return ( +
+ + + +

Analytics

+
+ ); +}; + +export default AnalyticsHeader; diff --git a/src/components/analytics/analytics-stats-grid.tsx b/src/components/analytics/analytics-stats-grid.tsx new file mode 100644 index 0000000..9098d45 --- /dev/null +++ b/src/components/analytics/analytics-stats-grid.tsx @@ -0,0 +1,44 @@ +import React from "react"; + +const AnalyticsStatsGrid = () => { + return ( +
+
+
Total Read
+
192
+
+ +
+
Subscribers
+
70
+
+ +
+
Followers
+
2071
+
+ +
+
Total Purchase
+
25
+
+ +
+
NFT Minted
+
18
+
+ +
+
Read Completion Rate
+
70%
+
+ +
+
Average Rating
+
4.0
+
+
+ ); +}; + +export default AnalyticsStatsGrid; diff --git a/src/components/analytics/analytics-tabs.tsx b/src/components/analytics/analytics-tabs.tsx new file mode 100644 index 0000000..6b907e1 --- /dev/null +++ b/src/components/analytics/analytics-tabs.tsx @@ -0,0 +1,446 @@ +import React from "react"; +import { Button } from "@/components/ui/button"; +import { Star } from "lucide-react"; +import Image from "next/image"; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; +const AnalyticsTabs = () => { + const books = [ + { rank: 1, title: "The Act" }, + { rank: 2, title: "Live at Night" }, + { rank: 3, title: "Prince of Peace" }, + { rank: 4, title: "Late Every Night" }, + { rank: 5, title: "The 91 Law of Power" }, + ]; + return ( + + + This Week + This Month + This Year + All Time + + + {/* Two Column Layout */} +
+ {/* Stats for Act */} +
+

+ Stats for Act +

+ +
+
+
Read
+
+ + 192 + + + -20% + +
+
+ +
+
+ Read Compl Rate +
+
+ + 75% + + + +16% + +
+
+ +
+
Sale
+
+ + 62 + + + +20% + +
+
+ +
+
Total Earning
+
+ Indian Rupee + 3150.00 +
+
+ +
+
Average Rating
+
+ + + 3.5 + +
+
+
+
+ + {/* Top Performing Books */} +
+
+

+ Top Performing Books +

+ +
+ +
+ {books.map((book) => ( +
+ + {book.rank}. + +
+
+
+ {book.title} +
+
+ +
+ ))} +
+
+
+
+ + {/* Two Column Layout */} +
+ {/* Stats for Act */} +
+

+ Stats for Act +

+ +
+
+
Read
+
+ + 192 + + + -20% + +
+
+ +
+
+ Read Compl Rate +
+
+ + 75% + + + +16% + +
+
+ +
+
Sale
+
+ + 62 + + + +20% + +
+
+ +
+
Total Earning
+
+ Indian Rupee + 3150.00 +
+
+ +
+
Average Rating
+
+ + + 3.5 + +
+
+
+
+ + {/* Top Performing Books */} +
+
+

+ Top Performing Books +

+ +
+ +
+ {books.map((book) => ( +
+ + {book.rank}. + +
+
+
+ {book.title} +
+
+ +
+ ))} +
+
+
+
+ + {/* Two Column Layout */} +
+ {/* Stats for Act */} +
+

+ Stats for Act +

+ +
+
+
Read
+
+ + 192 + + + -20% + +
+
+ +
+
+ Read Compl Rate +
+
+ + 75% + + + +16% + +
+
+ +
+
Sale
+
+ + 62 + + + +20% + +
+
+ +
+
Total Earning
+
+ Indian Rupee + 3150.00 +
+
+ +
+
Average Rating
+
+ + + 3.5 + +
+
+
+
+ + {/* Top Performing Books */} +
+
+

+ Top Performing Books +

+ +
+ +
+ {books.map((book) => ( +
+ + {book.rank}. + +
+
+
+ {book.title} +
+
+ +
+ ))} +
+
+
+
+ + {/* Two Column Layout */} +
+ {/* Stats for Act */} +
+

+ Stats for Act +

+ +
+
+
Read
+
+ + 192 + + + -20% + +
+
+ +
+
+ Read Compl Rate +
+
+ + 75% + + + +16% + +
+
+ +
+
Sale
+
+ + 62 + + + +20% + +
+
+ +
+
Total Earning
+
+ Indian Rupee + 3150.00 +
+
+ +
+
Average Rating
+
+ + + 3.5 + +
+
+
+
+ + {/* Top Performing Books */} +
+
+

+ Top Performing Books +

+ +
+ +
+ {books.map((book) => ( +
+ + {book.rank}. + +
+
+
+ {book.title} +
+
+ +
+ ))} +
+
+
+
+
+ ); +}; + +export default AnalyticsTabs;