diff --git a/package-lock.json b/package-lock.json index de8c13d..866ee8f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,7 @@ "next": "15.3.1", "react": "^19.0.0", "react-dom": "^19.0.0", + "recharts": "^3.8.1", "sonner": "^2.0.7", "tailwind-merge": "^3.3.1", "zod": "^3.25.76" @@ -456,6 +457,21 @@ "node": ">=10" } }, + "node_modules/@creit.tech/stellar-wallets-kit/node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, "node_modules/@creit.tech/xbull-wallet-connect": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/@creit.tech/xbull-wallet-connect/-/xbull-wallet-connect-0.4.0.tgz", @@ -2971,6 +2987,42 @@ "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==", "license": "MIT" }, + "node_modules/@reduxjs/toolkit": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.12.0.tgz", + "integrity": "sha512-KiT+RzZbp6mQET+Mg+h2c97+9j1sNflUxQkIHI7Yuzf6Peu+OYpmkn6nbHWmLLWj+1ZODUJFwGZ7gx3L9R9EOw==", + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "@standard-schema/utils": "^0.3.0", + "immer": "^11.0.0", + "redux": "^5.0.1", + "redux-thunk": "^3.1.0", + "reselect": "^5.1.0" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17.0.0 || ^18 || ^19", + "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-redux": { + "optional": true + } + } + }, + "node_modules/@reduxjs/toolkit/node_modules/immer": { + "version": "11.1.8", + "resolved": "https://registry.npmjs.org/immer/-/immer-11.1.8.tgz", + "integrity": "sha512-/tbkHMW7y10Lx6i1crLjD4/OhNkRG+Fo7byZHtah0547nIeXYcpIXaUh0IAQY6gO5459qpGGYapcEOHtFXkIuA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, "node_modules/@reown/appkit": { "version": "1.8.19", "resolved": "https://registry.npmjs.org/@reown/appkit/-/appkit-1.8.19.tgz", @@ -4663,7 +4715,12 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", - "dev": true, + "license": "MIT" + }, + "node_modules/@standard-schema/utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz", + "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==", "license": "MIT" }, "node_modules/@stellar/freighter-api": { @@ -8106,6 +8163,69 @@ "@types/node": "*" } }, + "node_modules/@types/d3-array": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz", + "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==", + "license": "MIT" + }, + "node_modules/@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", + "license": "MIT" + }, + "node_modules/@types/d3-ease": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", + "license": "MIT" + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "license": "MIT", + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", + "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==", + "license": "MIT" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", + "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", + "license": "MIT", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-shape": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.8.tgz", + "integrity": "sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==", + "license": "MIT", + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", + "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", + "license": "MIT" + }, + "node_modules/@types/d3-timer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", + "license": "MIT" + }, "node_modules/@types/deep-eql": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", @@ -8174,6 +8294,12 @@ "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", "license": "MIT" }, + "node_modules/@types/use-sync-external-store": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", + "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==", + "license": "MIT" + }, "node_modules/@types/uuid": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", @@ -9133,6 +9259,21 @@ "ws": "^7.5.1" } }, + "node_modules/@walletconnect/jsonrpc-ws-connection/node_modules/utf-8-validate": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", + "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, "node_modules/@walletconnect/jsonrpc-ws-connection/node_modules/ws": { "version": "7.5.11", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.11.tgz", @@ -10580,6 +10721,20 @@ "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", "license": "MIT" }, + "node_modules/bufferutil": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.1.0.tgz", + "integrity": "sha512-ZMANVnAixE6AWWnPzlW2KpUrxhm9woycYvPOo67jWHyFowASTEd9s+QN1EIMsSDtwhIxN4sWE1jotpuDUIgyIw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, "node_modules/busboy": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", @@ -10995,6 +11150,127 @@ "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", "license": "MIT" }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "license": "ISC", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz", + "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "license": "ISC", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "license": "ISC", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "license": "ISC", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "license": "ISC", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", @@ -11147,6 +11423,12 @@ "dev": true, "license": "MIT" }, + "node_modules/decimal.js-light": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", + "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==", + "license": "MIT" + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -12862,6 +13144,16 @@ "node": ">= 4" } }, + "node_modules/immer": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.2.0.tgz", + "integrity": "sha512-d/+XTN3zfODyjr89gM3mPq1WNX2B8pYsu7eORitdwyA2sBubnTl3laYlBk4sXY5FUa5qTZGBDPJICVbvqzjlbw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, "node_modules/import-fresh": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", @@ -12926,6 +13218,15 @@ "node": ">= 0.4" } }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/ip-address": { "version": "10.2.0", "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz", @@ -13521,6 +13822,21 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "license": "MIT" }, + "node_modules/jayson/node_modules/utf-8-validate": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", + "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, "node_modules/jayson/node_modules/ws": { "version": "7.5.11", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.11.tgz", @@ -15392,9 +15708,31 @@ "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true, "license": "MIT" }, + "node_modules/react-redux": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.3.0.tgz", + "integrity": "sha512-KQopgqFo/p/fgmAs5qz6p5RWaNAzq40WAu7fJIXnQpYxFPbJYtsJPWvGeF2rOBaY/kEuV77AVsX8TsQzKm+A/g==", + "license": "MIT", + "dependencies": { + "@types/use-sync-external-store": "^0.0.6", + "use-sync-external-store": "^1.4.0" + }, + "peerDependencies": { + "@types/react": "^18.2.25 || ^19", + "react": "^18.0 || ^19", + "redux": "^5.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "redux": { + "optional": true + } + } + }, "node_modules/react-remove-scroll": { "version": "2.7.2", "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.2.tgz", @@ -15500,6 +15838,36 @@ "node": ">= 12.13.0" } }, + "node_modules/recharts": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/recharts/-/recharts-3.8.1.tgz", + "integrity": "sha512-mwzmO1s9sFL0TduUpwndxCUNoXsBw3u3E/0+A+cLcrSfQitSG62L32N69GhqUrrT5qKcAE3pCGVINC6pqkBBQg==", + "license": "MIT", + "workspaces": [ + "www" + ], + "dependencies": { + "@reduxjs/toolkit": "^1.9.0 || 2.x.x", + "clsx": "^2.1.1", + "decimal.js-light": "^2.5.1", + "es-toolkit": "^1.39.3", + "eventemitter3": "^5.0.1", + "immer": "^10.1.1", + "react-redux": "8.x.x || 9.x.x", + "reselect": "5.1.1", + "tiny-invariant": "^1.3.3", + "use-sync-external-store": "^1.2.2", + "victory-vendor": "^37.0.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-is": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/redent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", @@ -15514,6 +15882,21 @@ "node": ">=8" } }, + "node_modules/redux": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", + "license": "MIT" + }, + "node_modules/redux-thunk": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz", + "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==", + "license": "MIT", + "peerDependencies": { + "redux": "^5.0.0" + } + }, "node_modules/reflect.getprototypeof": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", @@ -15597,6 +15980,12 @@ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "license": "ISC" }, + "node_modules/reselect": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", + "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==", + "license": "MIT" + }, "node_modules/resolve": { "version": "2.0.0-next.7", "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz", @@ -15772,9 +16161,6 @@ "@types/node": "*" } }, - "node_modules/rpc-websockets/node_modules/bufferutil": { - "optional": true - }, "node_modules/rpc-websockets/node_modules/uuid": { "version": "14.0.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.0.tgz", @@ -16678,6 +17064,12 @@ "real-require": "^0.2.0" } }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "license": "MIT" + }, "node_modules/tiny-secp256k1": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-1.1.7.tgz", @@ -17360,6 +17752,15 @@ } } }, + "node_modules/use-sync-external-store": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/utf-8-validate": { "version": "6.0.6", "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-6.0.6.tgz", @@ -17429,6 +17830,28 @@ "uint8array-tools": "^0.0.8" } }, + "node_modules/victory-vendor": { + "version": "37.3.6", + "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-37.3.6.tgz", + "integrity": "sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ==", + "license": "MIT AND ISC", + "dependencies": { + "@types/d3-array": "^3.0.3", + "@types/d3-ease": "^3.0.0", + "@types/d3-interpolate": "^3.0.1", + "@types/d3-scale": "^4.0.2", + "@types/d3-shape": "^3.1.0", + "@types/d3-time": "^3.0.0", + "@types/d3-timer": "^3.0.0", + "d3-array": "^3.1.6", + "d3-ease": "^3.0.1", + "d3-interpolate": "^3.0.1", + "d3-scale": "^4.0.2", + "d3-shape": "^3.1.0", + "d3-time": "^3.0.0", + "d3-timer": "^3.0.1" + } + }, "node_modules/viem": { "version": "2.51.3", "resolved": "https://registry.npmjs.org/viem/-/viem-2.51.3.tgz", diff --git a/package.json b/package.json index 1792235..d787467 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "next": "15.3.1", "react": "^19.0.0", "react-dom": "^19.0.0", + "recharts": "^3.8.1", "sonner": "^2.0.7", "tailwind-merge": "^3.3.1", "zod": "^3.25.76" diff --git a/src/app/(dashboard)/dashboard/layout.tsx b/src/app/(dashboard)/dashboard/layout.tsx index 5ee4ee8..449ec6c 100644 --- a/src/app/(dashboard)/dashboard/layout.tsx +++ b/src/app/(dashboard)/dashboard/layout.tsx @@ -1,9 +1,7 @@ -import { DashboardShell } from "@/components/layout/DashboardShell"; - export default function DashboardLayout({ children, }: { children: React.ReactNode; }) { - return {children}; + return children; } diff --git a/src/app/(dashboard)/dashboard/page.tsx b/src/app/(dashboard)/dashboard/page.tsx index 02587b3..4c42da3 100644 --- a/src/app/(dashboard)/dashboard/page.tsx +++ b/src/app/(dashboard)/dashboard/page.tsx @@ -1,7 +1,10 @@ import { DollarSign, FileText, TrendingUp, Users } from "lucide-react"; +import RecentActivity from "@/components/RecentActivity"; +import RevenueChart from "@/components/RevenueChart"; import { ApiKeyManagement } from "@/components/dashboard/api-key-management"; import { StatCard } from "@/components/StatCard"; +import type { ActivityEvent } from "@/lib/activity"; import { DashboardActions } from "./dashboard-actions"; export const metadata = { @@ -9,6 +12,39 @@ export const metadata = { description: "Shade merchant dashboard.", }; +const RECENT_ACTIVITY_EVENTS: ActivityEvent[] = [ + { + id: "evt_1", + type: "invoice_paid", + description: "Invoice INV-1042 was paid", + amount: 1840, + currency: "USD", + timestamp: "2026-06-23T10:15:00Z", + }, + { + id: "evt_2", + type: "invoice_created", + description: "New invoice INV-1043 was created", + amount: 620, + currency: "USD", + timestamp: "2026-06-23T08:40:00Z", + }, + { + id: "evt_3", + type: "customer_added", + description: "Acme Labs was added as a customer", + timestamp: "2026-06-22T16:20:00Z", + }, + { + id: "evt_4", + type: "payout_sent", + description: "Weekly payout sent to connected wallet", + amount: 3120, + currency: "USD", + timestamp: "2026-06-21T12:00:00Z", + }, +]; + export default function DashboardPage() { return (
@@ -46,6 +82,13 @@ export default function DashboardPage() { />
+
+
+ +
+ +
+ diff --git a/src/app/(dashboard)/invoice-tools/invoice-tools-client.tsx b/src/app/(dashboard)/invoice-tools/invoice-tools-client.tsx index 51a7b08..03587e9 100644 --- a/src/app/(dashboard)/invoice-tools/invoice-tools-client.tsx +++ b/src/app/(dashboard)/invoice-tools/invoice-tools-client.tsx @@ -36,7 +36,9 @@ export function InvoiceToolsClient() { return (
-

Create invoice (with validation)

+

+ Create invoice (with validation) +

{ console.log("Draft saved:", draft); diff --git a/src/app/(dashboard)/invoices/invoices-client.tsx b/src/app/(dashboard)/invoices/invoices-client.tsx index d92e23c..5e46b60 100644 --- a/src/app/(dashboard)/invoices/invoices-client.tsx +++ b/src/app/(dashboard)/invoices/invoices-client.tsx @@ -47,10 +47,14 @@ export function InvoicesClient() { }) .sort((a, b) => { if (sortBy === "newest") { - return new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(); + return ( + new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime() + ); } if (sortBy === "oldest") { - return new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime(); + return ( + new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime() + ); } if (sortBy === "amount-high") { return Number(b.amount) - Number(a.amount); @@ -80,9 +84,7 @@ export function InvoicesClient() { return (
- setInvoices((current) => [invoice, ...current]) - } + onSubmit={(invoice) => setInvoices((current) => [invoice, ...current])} />

Your invoices

@@ -109,4 +111,3 @@ export function InvoicesClient() {
); } - diff --git a/src/app/(dashboard)/settings/api-keys/page.tsx b/src/app/(dashboard)/settings/api-keys/page.tsx index 2fa59f5..762ce8b 100644 --- a/src/app/(dashboard)/settings/api-keys/page.tsx +++ b/src/app/(dashboard)/settings/api-keys/page.tsx @@ -18,4 +18,3 @@ export default function ApiKeysSettingsPage() {
); } - diff --git a/src/app/pay/page.tsx b/src/app/pay/page.tsx index bb10dd1..f7118be 100644 --- a/src/app/pay/page.tsx +++ b/src/app/pay/page.tsx @@ -10,9 +10,7 @@ export default function PayPage() {
-

- Shade -

+

Shade

Pay invoice

Choose how you want to settle this invoice. diff --git a/src/app/payment/[id]/page.tsx b/src/app/payment/[id]/page.tsx index c853056..de410ff 100644 --- a/src/app/payment/[id]/page.tsx +++ b/src/app/payment/[id]/page.tsx @@ -80,7 +80,9 @@ export default function PublicPaymentPage() { Loading invoice details...

- ) : !invoice || invoice.status === "invalid" || invoice.status === "expired" ? ( + ) : !invoice || + invoice.status === "invalid" || + invoice.status === "expired" ? (
    {navItems.map(({ href, label, icon: Icon }) => { - const active = pathname === href || pathname.startsWith(href + "/"); + const active = + pathname === href || pathname.startsWith(href + "/"); return (
  • ); } - diff --git a/src/components/RevenueChart.tsx b/src/components/RevenueChart.tsx index 7a980f7..3f9403c 100644 --- a/src/components/RevenueChart.tsx +++ b/src/components/RevenueChart.tsx @@ -16,21 +16,29 @@ export interface RevenueDataPoint { } interface TooltipPayload { - value?: number; + value?: number | string | readonly (number | string)[]; } interface CustomTooltipProps { active?: boolean; - payload?: TooltipPayload[]; + payload?: readonly TooltipPayload[]; label?: string; } function CustomTooltip({ active, payload, label }: CustomTooltipProps) { if (!active || !payload?.length) return null; + + const value = payload[0].value; + const formattedValue = Array.isArray(value) + ? value.join(", ") + : typeof value === "number" + ? value.toLocaleString() + : value; + return (

    {label}

    -

    {payload[0].value?.toLocaleString()} XLM

    +

    {formattedValue} XLM

    ); } @@ -51,9 +59,14 @@ interface RevenueChartProps { export default function RevenueChart({ data = MOCK_DATA }: RevenueChartProps) { return (
    -

    Revenue Over Time

    +

    + Revenue Over Time +

    - + @@ -73,7 +86,15 @@ export default function RevenueChart({ data = MOCK_DATA }: RevenueChartProps) { tickLine={false} width={48} /> - } /> + ( + + )} + />
      {navItems.map(({ href, label, icon: Icon }) => { - const active = - pathname === href || pathname.startsWith(href + "/"); + const active = pathname === href || pathname.startsWith(href + "/"); return (
    • { const stored = localStorage.getItem("shade:theme"); - const systemDark = window.matchMedia("(prefers-color-scheme: dark)").matches; + const systemDark = window.matchMedia( + "(prefers-color-scheme: dark)", + ).matches; const dark = stored === "dark" || (stored !== "light" && systemDark); setIsDark(dark); document.documentElement.classList.toggle("dark", dark); diff --git a/src/components/avatar/avatar-upload.tsx b/src/components/avatar/avatar-upload.tsx index 5db03be..cf40d92 100644 --- a/src/components/avatar/avatar-upload.tsx +++ b/src/components/avatar/avatar-upload.tsx @@ -1,12 +1,6 @@ "use client"; -import { - ChangeEvent, - KeyboardEvent, - useEffect, - useRef, - useState, -} from "react"; +import { ChangeEvent, KeyboardEvent, useEffect, useRef, useState } from "react"; import { ImagePlus } from "lucide-react"; import { cn } from "@/lib/utils"; diff --git a/src/components/billing/billing-plan-form.test.tsx b/src/components/billing/billing-plan-form.test.tsx index 54e41b3..a8ffd86 100644 --- a/src/components/billing/billing-plan-form.test.tsx +++ b/src/components/billing/billing-plan-form.test.tsx @@ -46,7 +46,9 @@ describe("BillingPlanForm", () => { await user.click(screen.getByRole("button", { name: /create plan/i })); - expect(await screen.findByText(/plan name is required/i)).toBeInTheDocument(); + expect( + await screen.findByText(/plan name is required/i), + ).toBeInTheDocument(); expect(screen.getByText(/description is required/i)).toBeInTheDocument(); expect(screen.getByText(/amount must be/i)).toBeInTheDocument(); expect(handleSubmit).not.toHaveBeenCalled(); @@ -61,10 +63,7 @@ describe("BillingPlanForm", () => { await user.type(screen.getByLabelText(/plan name/i), "Starter"); await user.type(screen.getByLabelText(/description/i), "Entry tier"); await user.type(screen.getByLabelText(/^amount$/i), "0"); - await user.type( - screen.getByLabelText(/customer email/i), - "not-an-email", - ); + await user.type(screen.getByLabelText(/customer email/i), "not-an-email"); await user.click(screen.getByRole("button", { name: /create plan/i })); @@ -86,6 +85,8 @@ describe("BillingPlanForm", () => { ).toBeInTheDocument(); await user.type(screen.getByLabelText(/plan name/i), "Pro"); - expect(screen.queryByText(/plan name is required/i)).not.toBeInTheDocument(); + expect( + screen.queryByText(/plan name is required/i), + ).not.toBeInTheDocument(); }); }); diff --git a/src/components/billing/billing-plan-form.tsx b/src/components/billing/billing-plan-form.tsx index fbccf73..455cc4e 100644 --- a/src/components/billing/billing-plan-form.tsx +++ b/src/components/billing/billing-plan-form.tsx @@ -77,8 +77,8 @@ export function BillingPlanForm({ onSubmit }: BillingPlanFormProps) {

      Create billing plan

      - Define a recurring charge. Validate every field before activating - the plan. + Define a recurring charge. Validate every field before activating the + plan.

      @@ -145,9 +145,7 @@ export function BillingPlanForm({ onSubmit }: BillingPlanFormProps) { id="plan-interval" required aria-invalid={Boolean(errors.interval)} - aria-describedby={ - errors.interval ? "plan-interval-error" : undefined - } + aria-describedby={errors.interval ? "plan-interval-error" : undefined} value={draft.interval} onChange={(event) => updateField("interval", event.target.value)} disabled={isSubmitting} @@ -175,9 +173,7 @@ export function BillingPlanForm({ onSubmit }: BillingPlanFormProps) { errors.customerEmail ? "plan-customer-email-error" : undefined } value={draft.customerEmail} - onChange={(event) => - updateField("customerEmail", event.target.value) - } + onChange={(event) => updateField("customerEmail", event.target.value)} disabled={isSubmitting} className={inputClass(Boolean(errors.customerEmail))} placeholder="customer@example.com" diff --git a/src/components/invoice/invoice-controls.tsx b/src/components/invoice/invoice-controls.tsx index 04bafc6..82f75b6 100644 --- a/src/components/invoice/invoice-controls.tsx +++ b/src/components/invoice/invoice-controls.tsx @@ -48,7 +48,10 @@ export function InvoiceControls({
      {/* Status Dropdown */}
      -