diff --git a/package-lock.json b/package-lock.json
index 159bdb5..245be98 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -40,6 +40,7 @@
"react-intersection-observer": "^9.16.0",
"react-quill": "^2.0.0",
"react-toastify": "^11.0.5",
+ "recharts": "^3.1.2",
"sharp": "^0.33.5",
"starknet": "^6.23.1",
"starknetkit": "^2.12.1",
@@ -3214,6 +3215,32 @@
"react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
}
},
+ "node_modules/@reduxjs/toolkit": {
+ "version": "2.8.2",
+ "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.8.2.tgz",
+ "integrity": "sha512-MYlOhQ0sLdw4ud48FoC5w0dH9VfWQjtCjreKwYTT3l+r427qYC5Y8PihNutepr8XrNaBUDQo9khWUwQxZaqt5A==",
+ "license": "MIT",
+ "dependencies": {
+ "@standard-schema/spec": "^1.0.0",
+ "@standard-schema/utils": "^0.3.0",
+ "immer": "^10.0.3",
+ "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/@scure/base": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.1.tgz",
@@ -3344,6 +3371,12 @@
"@sinonjs/commons": "^3.0.0"
}
},
+ "node_modules/@standard-schema/spec": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz",
+ "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==",
+ "license": "MIT"
+ },
"node_modules/@standard-schema/utils": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz",
@@ -3535,6 +3568,69 @@
"@babel/types": "^7.20.7"
}
},
+ "node_modules/@types/d3-array": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz",
+ "integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==",
+ "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.7",
+ "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.7.tgz",
+ "integrity": "sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg==",
+ "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/graceful-fs": {
"version": "4.1.9",
"resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz",
@@ -3651,6 +3747,12 @@
"integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==",
"peer": true
},
+ "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/warning": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.3.tgz",
@@ -5294,6 +5396,127 @@
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
"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.0",
+ "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz",
+ "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==",
+ "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/dataloader": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/dataloader/-/dataloader-2.2.3.tgz",
@@ -5327,6 +5550,12 @@
}
}
},
+ "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/decode-uri-component": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz",
@@ -6542,6 +6771,16 @@
"node": ">=16.x"
}
},
+ "node_modules/immer": {
+ "version": "10.1.1",
+ "resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz",
+ "integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==",
+ "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",
@@ -6583,6 +6822,15 @@
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
+ "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/invariant": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
@@ -9214,6 +9462,29 @@
"react": "^18.3.1"
}
},
+ "node_modules/react-redux": {
+ "version": "9.2.0",
+ "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz",
+ "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+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-refresh": {
"version": "0.14.2",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz",
@@ -9544,6 +9815,33 @@
"node": ">= 12.13.0"
}
},
+ "node_modules/recharts": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/recharts/-/recharts-3.1.2.tgz",
+ "integrity": "sha512-vhNbYwaxNbk/IATK0Ki29k3qvTkGqwvCgyQAQ9MavvvBwjvKnMTswdbklJpcOAoMPN/qxF3Lyqob0zO+ZXkZ4g==",
+ "license": "MIT",
+ "dependencies": {
+ "@reduxjs/toolkit": "1.x.x || 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/redeyed": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz",
@@ -9553,6 +9851,21 @@
"esprima": "~4.0.0"
}
},
+ "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/regenerator-runtime": {
"version": "0.13.11",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
@@ -9594,6 +9907,12 @@
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
"license": "MIT"
},
+ "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/resize-observer-polyfill": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
@@ -10788,6 +11107,12 @@
"integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==",
"peer": true
},
+ "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/tmpl": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
@@ -11272,6 +11597,28 @@
"node": ">= 0.4.0"
}
},
+ "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.31.4",
"resolved": "https://registry.npmjs.org/viem/-/viem-2.31.4.tgz",
diff --git a/package.json b/package.json
index 67210e1..eb58fc9 100644
--- a/package.json
+++ b/package.json
@@ -41,6 +41,7 @@
"react-intersection-observer": "^9.16.0",
"react-quill": "^2.0.0",
"react-toastify": "^11.0.5",
+ "recharts": "^3.1.2",
"sharp": "^0.33.5",
"starknet": "^6.23.1",
"starknetkit": "^2.12.1",
diff --git a/public/wallet_icons/braavos_icon.svg b/public/wallet_icons/braavos_icon.svg
new file mode 100644
index 0000000..f66e200
--- /dev/null
+++ b/public/wallet_icons/braavos_icon.svg
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/app/dashboard/admin/blog-management/page.tsx b/src/app/dashboard/admin/blog-management/page.tsx
new file mode 100644
index 0000000..4583406
--- /dev/null
+++ b/src/app/dashboard/admin/blog-management/page.tsx
@@ -0,0 +1,7 @@
+import React from "react";
+
+function page() {
+ return
page
;
+}
+
+export default page;
diff --git a/src/app/dashboard/admin/help-center/page.tsx b/src/app/dashboard/admin/help-center/page.tsx
new file mode 100644
index 0000000..4583406
--- /dev/null
+++ b/src/app/dashboard/admin/help-center/page.tsx
@@ -0,0 +1,7 @@
+import React from "react";
+
+function page() {
+ return page
;
+}
+
+export default page;
diff --git a/src/app/dashboard/admin/layout.tsx b/src/app/dashboard/admin/layout.tsx
new file mode 100644
index 0000000..e7eb220
--- /dev/null
+++ b/src/app/dashboard/admin/layout.tsx
@@ -0,0 +1,45 @@
+import DashboardNav from "../components/resuables/DashboardNav";
+
+export default function Layout({
+ children,
+}: Readonly<{
+ children: React.ReactNode;
+}>) {
+ const nav_items = [
+ { href: "/dashboard/admin/overview", label: "Overview" },
+ {
+ href: "/dashboard/admin/projects",
+ label: "Projects",
+ },
+ {
+ href: "/dashboard/admin/researchers",
+ label: "Researchers",
+ },
+ {
+ href: "/dashboard/admin/validators",
+ label: "Validators",
+ },
+ {
+ href: "/dashboard/admin/metrics",
+ label: "Metrics",
+ },
+ {
+ href: "/dashboard/admin/blog-management",
+ label: "Blog Management",
+ },
+ {
+ href: "/dashboard/admin/help-center",
+ label: "Help Center",
+ },
+ {
+ href: "/dashboard/admin/suspension",
+ label: "Suspension",
+ },
+ ];
+ return (
+
+
+ {children}
+
+ );
+}
diff --git a/src/app/dashboard/admin/metrics/page.tsx b/src/app/dashboard/admin/metrics/page.tsx
new file mode 100644
index 0000000..4583406
--- /dev/null
+++ b/src/app/dashboard/admin/metrics/page.tsx
@@ -0,0 +1,7 @@
+import React from "react";
+
+function page() {
+ return page
;
+}
+
+export default page;
diff --git a/src/app/dashboard/admin/overview/components/AdminOverviewStats.tsx b/src/app/dashboard/admin/overview/components/AdminOverviewStats.tsx
new file mode 100644
index 0000000..f5f983c
--- /dev/null
+++ b/src/app/dashboard/admin/overview/components/AdminOverviewStats.tsx
@@ -0,0 +1,57 @@
+import StatCard from "@/app/dashboard/components/resuables/StatCard";
+import { CircleDollarSign, FileText, FolderOpen } from "lucide-react";
+
+const dummy_stats = [
+ {
+ label: "Total Projects",
+ value: "24",
+ icon: ,
+ badgeText: "+12% from last month",
+ },
+ {
+ label: "Active Validators",
+ value: "18,429",
+ icon: ,
+ badgeText: "+8% from last month",
+ },
+ {
+ label: "Active Researchers",
+ value: "247",
+ icon: ,
+ badgeText: "+5.4% from yesterday",
+ },
+ {
+ label: "Total Revenue",
+ value: "$700K",
+ icon: ,
+ badgeText: "+0.2% this quarter",
+ },
+ {
+ label: "Vulnerabilities Found",
+ value: "24",
+ icon: ,
+ badgeText: "+12% from last month",
+ },
+ {
+ label: "Avg Completion Time",
+ value: "24",
+ icon: ,
+ badgeText: "+12% from last month",
+ },
+];
+
+function AdminOverviewStats() {
+ return (
+
+ {dummy_stats.map((stat, id) => (
+
+ ))}
+
+ );
+}
+
+export default AdminOverviewStats;
diff --git a/src/app/dashboard/admin/overview/components/ProjectSeverityDist.tsx b/src/app/dashboard/admin/overview/components/ProjectSeverityDist.tsx
new file mode 100644
index 0000000..cbeaa37
--- /dev/null
+++ b/src/app/dashboard/admin/overview/components/ProjectSeverityDist.tsx
@@ -0,0 +1,101 @@
+"use client";
+import { useState } from "react";
+import { Cell, Pie, PieChart, ResponsiveContainer } from "recharts";
+
+function ProjectSeverityDist() {
+ const [totalHigh] = useState(10);
+ const [totalMedium] = useState(20);
+ const [totalLow] = useState(4);
+ return (
+
+
+ Project Severity Distribution
+
+
+
+ {/* TODO: Implement Chart */}
+
+
+
+
+
+
+ {Math.round(
+ (totalHigh / (totalHigh + totalMedium + totalLow)) * 100
+ )}
+ %
+
+
+
+
+
+ {Math.round(
+ (totalMedium / (totalHigh + totalMedium + totalLow)) * 100
+ )}
+ %
+
+
+
+
+
+ {" "}
+ {Math.round(
+ (totalLow / (totalHigh + totalMedium + totalLow)) * 100
+ )}
+ %
+
+
+
+
+
+ );
+}
+
+export default ProjectSeverityDist;
diff --git a/src/app/dashboard/admin/overview/components/RecentActivity.tsx b/src/app/dashboard/admin/overview/components/RecentActivity.tsx
new file mode 100644
index 0000000..407b985
--- /dev/null
+++ b/src/app/dashboard/admin/overview/components/RecentActivity.tsx
@@ -0,0 +1,52 @@
+import React from "react";
+
+function RecentActivity() {
+ const dummy_activity = [
+ {
+ title: "Smart contract update deployed",
+ time: "2 hours ago",
+ },
+ {
+ title: "High dispute resolution queue",
+ time: "15 mins ago",
+ },
+ {
+ title: "Token issuance completed",
+ time: "5 minutes ago",
+ },
+ {
+ title: "Scheduled maintenance planned",
+ time: "1 hour ago",
+ },
+ {
+ title: "Token issuance completed",
+ time: "5 minutes ago",
+ },
+ {
+ title: "Token issuance completed",
+ time: "5 minutes ago",
+ },
+ ];
+ return (
+
+
Recent Activity
+
+
+ {dummy_activity.map((activity, i) => (
+
+
+
+
{activity.title}
+ {activity.time}
+
+
+ ))}
+
+
+ );
+}
+
+export default RecentActivity;
diff --git a/src/app/dashboard/admin/overview/components/RevenueChart.tsx b/src/app/dashboard/admin/overview/components/RevenueChart.tsx
new file mode 100644
index 0000000..98ed26d
--- /dev/null
+++ b/src/app/dashboard/admin/overview/components/RevenueChart.tsx
@@ -0,0 +1,64 @@
+"use client";
+import {
+ LineChart,
+ Line,
+ XAxis,
+ YAxis,
+ CartesianGrid,
+ ResponsiveContainer,
+ Tooltip,
+} from "recharts";
+
+function RevenueChart() {
+ return (
+
+
+ Revenue Over Time
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export default RevenueChart;
diff --git a/src/app/dashboard/admin/overview/components/UserGrowthChart.tsx b/src/app/dashboard/admin/overview/components/UserGrowthChart.tsx
new file mode 100644
index 0000000..4d97b37
--- /dev/null
+++ b/src/app/dashboard/admin/overview/components/UserGrowthChart.tsx
@@ -0,0 +1,119 @@
+"use client";
+import {
+ XAxis,
+ YAxis,
+ ResponsiveContainer,
+ Tooltip,
+ BarChart,
+ Bar,
+} from "recharts";
+
+const dummy_users = [
+ {
+ amt: 1400,
+ month: "Jan",
+ "Project Owners": 1,
+ Researchers: 2,
+ Validators: 1,
+ },
+ {
+ amt: 1400,
+ month: "Feb",
+ "Project Owners": 1,
+ Researchers: 5,
+ Validators: 3,
+ },
+ {
+ amt: 1506,
+ month: "Mar",
+ "Project Owners": 3,
+ Researchers: 10,
+ Validators: 4,
+ },
+ {
+ amt: 989,
+ month: "Apr",
+ "Project Owners": 3,
+ Researchers: 10,
+ Validators: 4,
+ },
+ {
+ amt: 1228,
+ month: "May",
+ "Project Owners": 5,
+ Researchers: 11,
+ Validators: 4,
+ },
+ {
+ amt: 1100,
+ month: "Jun",
+ "Project Owners": 6,
+ Researchers: 8,
+ Validators: 2,
+ },
+];
+
+function UserGrowthChart() {
+ return (
+
+
User Growth
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export default UserGrowthChart;
diff --git a/src/app/dashboard/admin/overview/page.tsx b/src/app/dashboard/admin/overview/page.tsx
index eec59e2..f3bc2a5 100644
--- a/src/app/dashboard/admin/overview/page.tsx
+++ b/src/app/dashboard/admin/overview/page.tsx
@@ -1,236 +1,24 @@
-'use client'
-
import React from "react";
-import { StatCard } from "../../components/resuables/StatsCard";
-import { RecentActivity } from "../../components/resuables/RecentActivity";
-import { Animation } from "@/motion/Animation";
-import Image from "next/image";
-import adminOne from "../../../../../public/adminIcon/adminStatsOne.svg";
-import adminTwo from "../../../../../public/adminIcon/adminStatsTwo.svg";
-import adminThree from "../../../../../public/adminIcon/adminStatsThree.svg";
-
-// Example Stats Data
-const stats = [
- {
- id: 1,
- icon: ,
- value: "15",
- label: "Validators Pending KYC Review",
- },
- {
- id: 2,
- icon: ,
- value: "15",
- label: "Support Tickets Pending",
- },
- {
- id: 3,
- icon: ,
- value: "1",
- label: "Total Approved Validators",
- },
-];
-
-// Example Recent Events
-const recentEvents = [
- {
- id: 1,
- title: "New Support Ticket Submitted",
- subtitle: "Support tickets are pending replies",
- timestamp: "Today 4:55pm",
- },
- {
- id: 2,
- title: "Validators Application",
- subtitle: "Multiple validators accounts are pending review",
- timestamp: "Today 4:55pm",
- },
- {
- id: 3,
- title: "Project Submissions",
- subtitle: "Multiple project submissions have been made",
- timestamp: "Yesterday",
- },
-];
+import AdminOverviewStats from "./components/AdminOverviewStats";
+import RevenueChart from "./components/RevenueChart";
+import UserGrowthChart from "./components/UserGrowthChart";
+import RecentActivity from "./components/RecentActivity";
+import ProjectSeverityDist from "./components/ProjectSeverityDist";
-// Validators data
-const validators = [
- {
- name: "Daniel Ochoja",
- walletAddress: "0×1234...abcd",
- reviewedProjects: 4,
- proficiency: "Python, Rust, C, C#",
- status: "Approved",
- },
- {
- name: "Aisha Muritala",
- walletAddress: "0×1234...abcd",
- reviewedProjects: 0,
- proficiency: "Typescript, Solidity",
- status: "Pending",
- },
- {
- name: "Favour Stephen",
- walletAddress: "0×1234...abcd",
- reviewedProjects: 0,
- proficiency: "Cairo, Go, Python",
- status: "Pending",
- },
- {
- name: "Favour Stephen",
- walletAddress: "0×1234...abcd",
- reviewedProjects: 4,
- proficiency: "Cairo, Go, Python",
- status: "Approved",
- },
-];
-
-const ValidatorsTable = () => {
+function page() {
return (
-
-
-
Validators
-
- View All
-
-
-
- {/* Desktop Table View (hidden on mobile) */}
-
-
-
-
- Name
- Wallet Address
- Reviewed Projects
- Proficiency
- Status
- Action
-
-
-
- {validators.map((validator, index) => (
-
-
-
- {validator.name}
-
-
-
-
- {validator.walletAddress}
-
-
-
-
- {validator.reviewedProjects}
-
-
-
-
- {validator.proficiency}
-
-
-
-
-
- {validator.status}
-
-
-
-
-
-
- View Profile
-
-
-
-
- ))}
-
-
-
-
- {/* Mobile Card View (visible only on mobile) */}
-
- {validators.map((validator, index) => (
-
-
-
-
- {validator.name}
-
-
- {validator.status}
-
-
-
-
-
- Wallet Address:
- {validator.walletAddress}
-
-
-
- Reviewed Projects:
-
- {validator.reviewedProjects}
-
-
-
-
- Proficiency:
- {validator.proficiency}
-
-
-
-
-
- View Profile
-
-
-
-
- ))}
+
- );
-};
-
-const AdminDashboard = () => {
- return (
-
- {/* Stats Grid */}
-
- {stats.map((stat) => (
-
- ))}
+
-
- {/* Recent Activity */}
-
-
- {/* Validators Table */}
-
);
-};
+}
-export default AdminDashboard;
+export default page;
diff --git a/src/app/dashboard/admin/page.tsx b/src/app/dashboard/admin/page.tsx
index caef1f7..ed258f0 100644
--- a/src/app/dashboard/admin/page.tsx
+++ b/src/app/dashboard/admin/page.tsx
@@ -1,10 +1,16 @@
-import React from "react";
-import AdminDashboard from "./overview/page";
+"use client";
-const page = () => {
- return
;
+import { useEffect } from "react";
+import { useRouter } from "next/navigation";
+
+const Page = () => {
+ const router = useRouter();
+
+ useEffect(() => {
+ router.replace("/dashboard/admin/overview");
+ }, [router]);
+
+ return null;
};
-export default page;
+export default Page;
diff --git a/src/app/dashboard/admin/projects/page.tsx b/src/app/dashboard/admin/projects/page.tsx
index ef263cf..e284e67 100644
--- a/src/app/dashboard/admin/projects/page.tsx
+++ b/src/app/dashboard/admin/projects/page.tsx
@@ -2,50 +2,28 @@
import React from "react";
-import Image from "next/image";
-import { StatCard } from "../../components/resuables/StatsCard";
import ProjectTable from "@/components/dashboard/projects/project-table";
+import StatCard from "../../components/resuables/StatCard";
// Example Stats Data
const stats = [
{
- id: 1,
- icon: (
-
- ),
+ icon: "/adminIcon/project-card1icon.svg",
value: "5",
label: "Total Number of Projects",
+ progression: "",
},
{
- id: 2,
- icon: (
-
- ),
+ icon: "/adminIcon/project-card2icon.svg",
value: "5",
label: "Active bounties",
+ progression: "",
},
{
- id: 3,
- icon: (
-
- ),
+ icon: "/adminIcon/money-bag.svg",
value: "$8,232,523.34",
label: "Total Bounty Paid",
+ progression: "",
},
];
@@ -96,21 +74,16 @@ const Projects = () => {
];
return (
-
+
{/* Stats Cards */}
- {stats.map((stat) => (
+ {stats.map((stat, id) => (
-
+ {/* */}
))}
{/*
diff --git a/src/app/dashboard/admin/rankings/page.tsx b/src/app/dashboard/admin/rankings/page.tsx
new file mode 100644
index 0000000..2cb5717
--- /dev/null
+++ b/src/app/dashboard/admin/rankings/page.tsx
@@ -0,0 +1,5 @@
+function page() {
+ return
page
;
+}
+
+export default page;
diff --git a/src/app/dashboard/admin/researchers/page.tsx b/src/app/dashboard/admin/researchers/page.tsx
new file mode 100644
index 0000000..4583406
--- /dev/null
+++ b/src/app/dashboard/admin/researchers/page.tsx
@@ -0,0 +1,7 @@
+import React from "react";
+
+function page() {
+ return
page
;
+}
+
+export default page;
diff --git a/src/app/dashboard/admin/support/components/SupportCard.tsx b/src/app/dashboard/admin/support/components/SupportCard.tsx
index 000785b..cced6a0 100644
--- a/src/app/dashboard/admin/support/components/SupportCard.tsx
+++ b/src/app/dashboard/admin/support/components/SupportCard.tsx
@@ -1,14 +1,12 @@
-
import Image from "next/image";
-import { StatCard } from "../../../components/resuables/StatsCard";
+// import { StatCard } from "../../../components/resuables/StatCard";
import open from "../../../../../../public/adminIcon/open.svg";
import resolevd from "../../../../../../public/adminIcon/resolved.svg";
import Inprog from "../../../../../../public/adminIcon/progress.svg";
-export default function SupportCard () {
-
-const stats = [
+export default function SupportCard() {
+ const stats = [
{
id: 1,
icon:
,
@@ -28,29 +26,28 @@ const stats = [
label: "In Progress",
},
{
- id: 4,
- icon:
,
- value: "15",
- label: "Resolved Tickets",
- },
-];
-
- return(
-
-
+ id: 4,
+ icon:
,
+ value: "15",
+ label: "Resolved Tickets",
+ },
+ ];
-
- {stats.map((stat) => (
-
- ))}
-
-
-
+ return (
+
+
+
+ {/* {stats.map((stat) => (
+
+ ))} */}
+
+
+
);
-};
\ No newline at end of file
+}
diff --git a/src/app/dashboard/admin/suspension/page.tsx b/src/app/dashboard/admin/suspension/page.tsx
new file mode 100644
index 0000000..4583406
--- /dev/null
+++ b/src/app/dashboard/admin/suspension/page.tsx
@@ -0,0 +1,7 @@
+import React from "react";
+
+function page() {
+ return
page
;
+}
+
+export default page;
diff --git a/src/app/dashboard/components/RewardsStats.tsx b/src/app/dashboard/components/RewardsStats.tsx
index 3880adc..cd35e23 100644
--- a/src/app/dashboard/components/RewardsStats.tsx
+++ b/src/app/dashboard/components/RewardsStats.tsx
@@ -3,10 +3,10 @@
import type React from "react";
import { Animation } from "@/motion/Animation";
import { Wallet, DollarSign, ArrowRight } from "lucide-react";
-import { StatCard } from "./resuables/StatsCard";
import imgFour from "../../../../public/validatorIcons/valImgFour.svg";
import Image from "next/image";
+import StatsCard from "@/components/dashboard/projects/StatsCard";
interface RewardsStatsProps {
totalEarnings: string;
@@ -21,13 +21,13 @@ export function RewardsStats({
}: RewardsStatsProps) {
return (
-
}
value={totalEarnings}
label="Total Earnings"
/>
-
}
value={availableForWithdrawal}
label="Available for Withdrawal"
diff --git a/src/app/dashboard/components/header.tsx b/src/app/dashboard/components/header.tsx
index 5001e11..086f6d2 100644
--- a/src/app/dashboard/components/header.tsx
+++ b/src/app/dashboard/components/header.tsx
@@ -1,13 +1,16 @@
"use client";
import { usePathname } from "next/navigation";
-import { ScrollArea } from "@/components/ui/scroll-area";
import React, { useState } from "react";
-import { Bell, Copy, ChevronUp, ChevronDown } from "lucide-react";
+import { Bell } from "lucide-react";
import { Animation } from "@/motion/Animation";
-import { motion, AnimatePresence, Variants } from "framer-motion";
+import { motion } from "framer-motion";
import { ConnectButton } from "@/components/connect-button";
import NotificationModal from "./resuables/Notification-modal";
+import {
+ DropdownMenu,
+ DropdownMenuTrigger,
+} from "@/components/ui/dropdown-menu";
const Header = () => {
const pathname = usePathname();
@@ -18,62 +21,16 @@ const Header = () => {
const walletAddress = "0x04baf3f32432a21D3b2C90E998Aa5EC7817E61b3";
- // Fixed title logic to handle project detail pages and report pages
- const getPageTitle = () => {
- const pathSegments = pathname?.split("/").filter(Boolean) || [];
+ const dashboardType = pathname.split("/")[2] || "";
- // Check if we're on a report detail page
- if (pathSegments.includes("reports")) {
- const reportsIndex = pathSegments.indexOf("reports");
-
- // If there's a segment after "reports" that looks like an ID or specific route
- if (reportsIndex < pathSegments.length - 1) {
- const nextSegment = pathSegments[reportsIndex + 1];
-
- // Check for specific report routes
- if (nextSegment === "success" || nextSegment === "reject") {
- return "Report Details";
- }
-
- // If it's just a report ID (numeric or alphanumeric), show "Report Details"
- if (/^[a-zA-Z0-9-_]+$/.test(nextSegment) && nextSegment !== "new") {
- return "Report Details";
- }
- }
-
- // Default for reports page
- return "Reports";
- }
-
- // Check if we're on a project detail page (ends with a project ID)
- if (pathSegments.length >= 4 && pathSegments[2] === "projects") {
- const lastSegment = pathSegments[pathSegments.length - 1];
- // If the last segment looks like a project ID (numeric or alphanumeric ID)
- if (
- /^[a-zA-Z0-9-_]+$/.test(lastSegment) &&
- pathSegments[pathSegments.length - 2] !== "register-project"
- ) {
- return "Project Details";
- }
- }
-
- // For register project page
- if (pathSegments.includes("register-project")) {
- return "Register Project";
- }
-
- // Default behavior for other pages
- const title = pathSegments[pathSegments.length - 1] || "dashboard";
- return title.charAt(0).toUpperCase() + title.slice(1);
+ const titleMap: Record
= {
+ admin: "Admin Dashboard",
+ "project-owner": "Project Owner Dashboard",
+ researcher: "Researcher Dashboard",
+ validator: "Validator Dashboard",
};
- const capitalizedTitle = getPageTitle().replace("-", " ");
-
- const handleCopy = () => {
- navigator.clipboard.writeText(walletAddress);
- setCopied(true);
- setTimeout(() => setCopied(false), 1500);
- };
+ const capitalizedTitle = titleMap[dashboardType] || "Dashboard";
const navItemVariants = {
hidden: { opacity: 0, y: -10 },
@@ -84,104 +41,42 @@ const Header = () => {
},
};
- interface Notification {
- id: number;
- type: "urgent" | "fund release" | "Bounty Paid Out" | "New submission";
- title: string;
- description: string;
- actionText: string;
- timeAgo: string;
- imageSrc: string;
- }
-
- const notifications: Notification[] = [
- {
- id: 1,
- type: "urgent",
- title: "Vulnerability Found!",
- description:
- "A critical vulnerability has been reported in your project SecureChain. Immediate action is required!",
- actionText: "View Report",
- timeAgo: "2 mins ago",
- imageSrc: "/notification-icons/urgent.png",
- },
- {
- id: 2,
- type: "fund release",
- title: "",
- description:
- "Your escrow funds of 1,500 STRK (~$2,000) are now available for withdrawal.",
- actionText: "Withdraw Now",
- timeAgo: "10 mins ago",
- imageSrc: "/notification-icons/money-bag.png",
- },
- {
- id: 3,
- type: "Bounty Paid Out",
- title: "",
- description:
- "A researcher has received their bounty for their report on SecureChain.",
- actionText: "View Details",
- timeAgo: "1 hour ago",
- imageSrc: "/notification-icons/green-tick.png",
- },
- {
- id: 4,
- type: "New submission",
- title: "",
- description:
- "A security researcher submitted a new bug report. Please review and take action.",
- actionText: "Review Submission",
- timeAgo: "30 mins ago",
- imageSrc: "/notification-icons/file.png",
- },
- ];
-
- // --- Animation Variants ---
-
- const dropdownVariants: Variants = {
- hidden: { opacity: 0, scale: 0.95, y: -10 },
- visible: { opacity: 1, scale: 1, y: 0 },
- exit: { opacity: 0, scale: 0.95, y: -10, transition: { duration: 0.15 } },
- };
-
- const notificationItemVariants: Variants = {
- hidden: { opacity: 0, x: -20 },
- visible: { opacity: 1, x: 0 },
- };
-
- function bellActiveHandler() {
- setIsBellActive(false);
- }
-
return (
-
+
-
- {capitalizedTitle}
-
+
+
+ {pathname?.startsWith("/dashboard") && (
+
+ {capitalizedTitle}
+
+ )}
+
- {/* Notification Bell */}
-
setIsBellActive(!isBellActive)}
- className={`border border-[#6B6668] p-2 rounded-lg transition-colors ${
- isBellActive ? "bg-white" : "bg-transparent"
- }`}
- >
-
-
-
- {isBellActive && (
-
- )}
+
+
+ setIsBellActive(!isBellActive)}
+ className="flex gap-x-2 items-center p-3 lg:py-3 lg:px-6 transition-colors bg-[#101011] rounded-full"
+ >
+
+ Notification
+
+
+
+
{/* Wallet Button */}
-
+
{
{/* Wallet Dropdown */}
{walletOpen && (
-
+
Disconnect Wallet
diff --git a/src/app/dashboard/components/resuables/AnnoucmentSection.tsx b/src/app/dashboard/components/resuables/AnnoucmentSection.tsx
index 0a022ea..bdcb714 100644
--- a/src/app/dashboard/components/resuables/AnnoucmentSection.tsx
+++ b/src/app/dashboard/components/resuables/AnnoucmentSection.tsx
@@ -64,9 +64,7 @@ export const Announcements: React.FC = ({
- {showNotification && (
-
- )}
+ {showNotification && }
{announcements.map((announcement, index) => (
diff --git a/src/app/dashboard/components/resuables/DashboardNav.tsx b/src/app/dashboard/components/resuables/DashboardNav.tsx
new file mode 100644
index 0000000..6401c32
--- /dev/null
+++ b/src/app/dashboard/components/resuables/DashboardNav.tsx
@@ -0,0 +1,50 @@
+"use client";
+
+import Link from "next/link";
+import { usePathname } from "next/navigation";
+
+function DashboardNav({
+ navItems,
+}: {
+ navItems: {
+ label: string;
+ href: string;
+ }[];
+}) {
+ const pathname = usePathname();
+ console.log(pathname);
+
+ return (
+
+ {navItems.map((item, id) => {
+ const isActive = pathname === item.href;
+
+ return (
+
+
+ {item.label}
+
+
+ );
+ })}
+
+ );
+}
+
+export default DashboardNav;
diff --git a/src/app/dashboard/components/resuables/Notification-modal.tsx b/src/app/dashboard/components/resuables/Notification-modal.tsx
index 3778493..32005de 100644
--- a/src/app/dashboard/components/resuables/Notification-modal.tsx
+++ b/src/app/dashboard/components/resuables/Notification-modal.tsx
@@ -1,4 +1,4 @@
-import { ScrollArea } from "@/components/ui/scroll-area";
+import { DropdownMenuContent } from "@/components/ui/dropdown-menu";
import { motion, Variants } from "framer-motion";
type Notification = {
@@ -11,7 +11,7 @@ type Notification = {
imageSrc: string;
};
-const notifications: Notification[] = [
+const dummy_notifications: Notification[] = [
{
id: 1,
type: "urgent",
@@ -25,7 +25,7 @@ const notifications: Notification[] = [
{
id: 2,
type: "fund release",
- title: "",
+ title: "Fund Released",
description:
"Your escrow funds of 1,500 STRK (~$2,000) are now available for withdrawal.",
actionText: "Withdraw Now",
@@ -35,7 +35,7 @@ const notifications: Notification[] = [
{
id: 3,
type: "Bounty Paid Out",
- title: "",
+ title: "Bounty Paid Out",
description:
"A researcher has received their bounty for their report on SecureChain.",
actionText: "View Details",
@@ -45,7 +45,7 @@ const notifications: Notification[] = [
{
id: 4,
type: "New submission",
- title: "",
+ title: "New submission",
description:
"A security researcher submitted a new bug report. Please review and take action.",
actionText: "Review Submission",
@@ -54,108 +54,44 @@ const notifications: Notification[] = [
},
];
-export default function NotificationModal({ setIsBellActive }: { setIsBellActive:()=>void }) {
- // --- Animation Variants ---
-
- const dropdownVariants: Variants = {
- hidden: { opacity: 0, scale: 0.95, y: -10 },
- visible: { opacity: 1, scale: 1, y: 0 },
- exit: { opacity: 0, scale: 0.95, y: -10, transition: { duration: 0.15 } },
- };
-
+export default function NotificationModal() {
const notificationItemVariants: Variants = {
hidden: { opacity: 0, x: -20 },
visible: { opacity: 1, x: 0 },
};
+
return (
-
-
-
-
-
Notifications
-
setIsBellActive()}
- className="flex items-center p-2 bg-gray-600 rounded-full"
- aria-label="Close notifications panel"
- >
-
-
-
-
-
-
+
+
+
Notifications
+
+ Mark all as read
+
+
-
- {notifications.map((notification, index) => (
-
-
-
-
-
-
- [{notification.title.startsWith("[") ? "" : notification.type}
- ] {notification.title}
-
-
-
+
+ {dummy_notifications.map((notification, index) => (
+
+
+
+
+ Tuesday, July 1, 2025 - 8:00AM
+
+
+ {notification.title}
+
+
{notification.description}
-
-
- [{notification.actionText}]
-
-
- {notification.type === "urgent" ||
- notification.type === "New submission"
- ? "⏳"
- : "📅"}
- {notification.timeAgo}
-
-
-
- ))}
-
-
-
-
Load More
-
-
-
-
+
+ ))}
+
+
);
-}
\ No newline at end of file
+}
diff --git a/src/app/dashboard/components/resuables/OverviewCardExpandable.tsx b/src/app/dashboard/components/resuables/OverviewCardExpandable.tsx
new file mode 100644
index 0000000..15b98af
--- /dev/null
+++ b/src/app/dashboard/components/resuables/OverviewCardExpandable.tsx
@@ -0,0 +1,39 @@
+import React from "react";
+
+function OverviewCardExpandable({
+ stat,
+ badgeStyle = "text-[#1BC100] bg-[#153710]",
+ children,
+}: {
+ stat: {
+ label: string;
+ value: string;
+ badgeText: string;
+ icon: React.ReactNode;
+ };
+ badgeStyle: string;
+ children: React.ReactNode;
+}) {
+ return (
+
+
+
+
{stat.label}
+
+
{stat.value}
+
+
+ {stat.badgeText}
+
+
+
+
{stat.icon}
+
+ {children}
+
+ );
+}
+
+export default OverviewCardExpandable;
diff --git a/src/app/dashboard/components/resuables/StatCard.tsx b/src/app/dashboard/components/resuables/StatCard.tsx
new file mode 100644
index 0000000..fb69911
--- /dev/null
+++ b/src/app/dashboard/components/resuables/StatCard.tsx
@@ -0,0 +1,32 @@
+import React from "react";
+
+function StatCard({
+ stat,
+ badgeStyle = "bg-[#153710] text-[#1BC100]",
+}: {
+ stat: {
+ label: string;
+ value: string;
+ icon: React.ReactNode;
+ badgeText: string;
+ };
+ badgeStyle: string;
+}) {
+ return (
+
+
+
{stat.label}
+
+
{stat.value}
+
+
+ {stat.badgeText}
+
+
+
+
{stat.icon}
+
+ );
+}
+
+export default StatCard;
diff --git a/src/app/dashboard/components/resuables/StatsCard.tsx b/src/app/dashboard/components/resuables/StatsCard.tsx
deleted file mode 100644
index 65e57b7..0000000
--- a/src/app/dashboard/components/resuables/StatsCard.tsx
+++ /dev/null
@@ -1,32 +0,0 @@
-import React from "react";
-import { Animation } from "@/motion/Animation";
-
-interface StatCardProps {
- icon: React.ReactNode;
- value: string | number;
- label: string;
- iconBgColor?: string;
- className?: string;
-}
-
-export const StatCard: React.FC = ({
- icon,
- value,
- label,
- // iconBgColor = "bg-neutral-800",
-}) => {
- return (
-
-
- {icon}
-
-
- {value}
-
-
-
- {label}
-
-
- );
-};
diff --git a/src/app/dashboard/layout.tsx b/src/app/dashboard/layout.tsx
index ebceefe..f4498ec 100644
--- a/src/app/dashboard/layout.tsx
+++ b/src/app/dashboard/layout.tsx
@@ -6,10 +6,9 @@ import { ProjectsProvider } from "@/context/project-context";
const Layout: React.FC<{ children: React.ReactNode }> = ({ children }) => {
return (
-
-
-
-
+
diff --git a/src/app/dashboard/project-owner/layout.tsx b/src/app/dashboard/project-owner/layout.tsx
new file mode 100644
index 0000000..1466fea
--- /dev/null
+++ b/src/app/dashboard/project-owner/layout.tsx
@@ -0,0 +1,33 @@
+import DashboardNav from "../components/resuables/DashboardNav";
+
+export default function Layout({
+ children,
+}: Readonly<{
+ children: React.ReactNode;
+}>) {
+ const nav_items = [
+ { href: "/dashboard/project-owner/overview", label: "Overview" },
+ {
+ href: "/dashboard/project-owner/upload-project",
+ label: "Upload Project",
+ },
+ {
+ href: "/dashboard/project-owner/projects",
+ label: "View Projects",
+ },
+ {
+ href: "/dashboard/project-owner/rankings",
+ label: "Rankings",
+ },
+ {
+ href: "/dashboard/researcher/profile",
+ label: "Profile",
+ },
+ ];
+ return (
+
+
+ {children}
+
+ );
+}
diff --git a/src/app/dashboard/project-owner/overview/components/ReportHistory.tsx b/src/app/dashboard/project-owner/overview/components/ReportHistory.tsx
new file mode 100644
index 0000000..d746678
--- /dev/null
+++ b/src/app/dashboard/project-owner/overview/components/ReportHistory.tsx
@@ -0,0 +1,89 @@
+"use client";
+import {
+ XAxis,
+ YAxis,
+ ResponsiveContainer,
+ Tooltip,
+ BarChart,
+ Bar,
+} from "recharts";
+
+const dummy_users = [
+ {
+ Reports: 2,
+ Month: "Jan",
+ },
+ {
+ Reports: 4,
+ Month: "Feb",
+ },
+ {
+ Reports: 1,
+ Month: "Mar",
+ },
+ {
+ Reports: 0,
+ Month: "Apr",
+ },
+ {
+ Reports: 6,
+ Month: "May",
+ },
+ {
+ Reports: 1,
+ Month: "Jun",
+ },
+];
+
+function ReportHistory() {
+ return (
+
+
Report History
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export default ReportHistory;
diff --git a/src/app/dashboard/project-owner/overview/page.tsx b/src/app/dashboard/project-owner/overview/page.tsx
index 5e054af..201a99f 100644
--- a/src/app/dashboard/project-owner/overview/page.tsx
+++ b/src/app/dashboard/project-owner/overview/page.tsx
@@ -1,128 +1,74 @@
-import React from "react";
-import { ClipboardList, Shield, BarChart3, Wallet, Users } from "lucide-react";
-import { ActionButton } from "../../components/resuables/ActionButton";
-import { StatCard } from "../../components/resuables/StatsCard";
-import { RecentActivity } from "../../components/resuables/RecentActivity";
-import Image from "next/image";
-import infoOne from "../../../../../public/overviewIcons/infoOne.svg";
-import infoTwo from "../../../../../public/overviewIcons/infoTwo.svg";
-import infoThree from "../../../../../public/overviewIcons/infoThree.svg";
-import statsOne from "../../../../../public/overviewIcons/statsOne.svg";
-import statsTwo from "../../../../../public/overviewIcons/statsTwo.svg";
-import statsThree from "../../../../../public/overviewIcons/statsThree.svg";
-import statsFour from "../../../../../public/overviewIcons/statsFour.svg";
-import { ProjectOwnerActionButton } from "../../components/resuables/ProjectOwnerActionButton";
+import StatCard from "@/app/dashboard/components/resuables/StatCard";
+import { CircleDollarSign, FileText, FolderOpen } from "lucide-react";
+import ReportHistory from "./components/ReportHistory";
-const Overview = () => {
- const actionButtons = [
- {
- id: 1,
- icon:
,
- title: "Register Project",
- description: "Submit your smart contract for security review",
- href: "/dashboard/project-owner/projects",
- iconBgColor: "bg-[#0000FF]",
- },
- {
- id: 2,
- icon:
,
- title: "Fund Escrow",
- description: "Securely deposit bounty rewards",
- href: "/dashboard/project-owner/projects",
- iconBgColor: "bg-[#0000FF]",
- },
- {
- id: 3,
- icon:
,
- title: "View Reports",
- description: "Track vulnerability findings in real time",
- href: "/dashboard/project-owner/reports",
- iconBgColor: "bg-[#0000FF]",
- },
- ];
-
- const stats = [
- {
- id: 1,
- icon:
,
- value: 5,
- label: "Total Number of Projects",
- },
- {
- id: 2,
- icon:
,
- value: 5,
- label: "Total Vulnerabilities Found",
- },
- {
- id: 3,
- icon:
,
- value: "$2,523.34",
- label: "Total Bounties Paid",
- },
- {
- id: 4,
- icon:
,
- value: 5,
- label: "Active Bounties",
- },
- ];
- const recentEvents = [
- {
- id: 1,
- title: "Project Registered",
- subtitle: "Your Project SkillNet has been submitted for security review",
- timestamp: "Today 4:15pm",
- },
- {
- id: 2,
- title: "Reported Vulnerabilities",
- subtitle: "Security reports have been submitted by researchers",
- timestamp: "Today 2:35pm",
- },
- {
- id: 3,
- title: "Reported Vulnerabilities",
- subtitle: "Security reports have been submitted by researchers",
- timestamp: "Yesterday",
- },
- ];
+const dummy_stats = [
+ {
+ label: "Total Allocated Bounty",
+ value: "12",
+ icon:
,
+ badgeText: "+2 this month",
+ },
+ {
+ label: "In Progress Audit",
+ value: "1",
+ icon:
,
+ badgeText: "Requires attention",
+ },
+ {
+ label: "Completed Audit",
+ value: "2",
+ icon:
,
+ badgeText: "Closed",
+ },
+ {
+ label: "Active Researchers",
+ value: "2",
+ icon:
,
+ badgeText: "+1 this month",
+ },
+];
+const stat_badge_styles = [
+ "bg-[#153710] text-[#1BC100]",
+ "bg-[#373510] text-[#C1B700]",
+ "bg-[#10273E] text-[#0073E6]",
+ "bg-[#153710] text-[#1BC100]",
+];
+function page() {
return (
-
- {/* Action Buttons */}
-
- {actionButtons.map((btn) => (
-
- ))}
-
-
- {/* Stats Grid */}
-
- {stats.map((stat) => (
-
+
+
+ {dummy_stats.map((stat, id) => (
+
))}
+
+
+
+
Note:
+
Quick tips to get you started.
- {/* Recent Activity */}
-
-
+
+ Please fund the audit with USDC on Starknet chain.
+
+ Security researchers and validators can proceed with the audit
+ once there's an adequate bounty amount.
+
+
+ It would be helpful to set a reasonable timeframe for the audit.
+
+
+ After the audit is completed, reports will be shared to guide the
+ developers of the audited project in making any necessary changes.
+
+ You can download the audit certificate on successful audit
+ Make your audit smart contract github repo public
+
+
);
-};
+}
-export default Overview;
+export default page;
diff --git a/src/app/dashboard/project-owner/page.tsx b/src/app/dashboard/project-owner/page.tsx
index f0f84c4..cfaa44e 100644
--- a/src/app/dashboard/project-owner/page.tsx
+++ b/src/app/dashboard/project-owner/page.tsx
@@ -1,7 +1,16 @@
-import { redirect } from "next/navigation";
+"use client";
-const page = () => {
- redirect("/dashboard/project-owner/overview");
+import { useEffect } from "react";
+import { useRouter } from "next/navigation";
+
+const Page = () => {
+ const router = useRouter();
+
+ useEffect(() => {
+ router.replace("/dashboard/project-owner/overview");
+ }, [router]);
+
+ return null;
};
-export default page;
+export default Page;
diff --git a/src/app/dashboard/project-owner/rankings/page.tsx b/src/app/dashboard/project-owner/rankings/page.tsx
new file mode 100644
index 0000000..4583406
--- /dev/null
+++ b/src/app/dashboard/project-owner/rankings/page.tsx
@@ -0,0 +1,7 @@
+import React from "react";
+
+function page() {
+ return
page
;
+}
+
+export default page;
diff --git a/src/app/dashboard/project-owner/upload-project/page.tsx b/src/app/dashboard/project-owner/upload-project/page.tsx
new file mode 100644
index 0000000..4583406
--- /dev/null
+++ b/src/app/dashboard/project-owner/upload-project/page.tsx
@@ -0,0 +1,7 @@
+import React from "react";
+
+function page() {
+ return
page
;
+}
+
+export default page;
diff --git a/src/app/dashboard/researcher/help-center/page.tsx b/src/app/dashboard/researcher/help-center/page.tsx
deleted file mode 100644
index 95903be..0000000
--- a/src/app/dashboard/researcher/help-center/page.tsx
+++ /dev/null
@@ -1,387 +0,0 @@
-"use client";
-
-import React, { useState, useRef, useEffect } from "react";
-import * as z from "zod";
-import { useForm, Controller } from "react-hook-form";
-import { zodResolver } from "@hookform/resolvers/zod";
-import { motion, AnimatePresence, Variants } from "framer-motion";
-
-const MAX_FILE_SIZE = 5 * 1024 * 1024; // 5 MB
-const ACCEPTED_FILE_TYPES = [
- "application/pdf",
- "image/jpeg",
- "image/png",
- "image/webp",
-];
-
-const schema = z.object({
- email: z.string().email("Invalid email address"),
- subject: z.string().nonempty("Subject is required"),
- message: z.string().nonempty("Message is required"),
- document: z
- .any()
- .refine((files: FileList) => {
- if (!files?.length) return true; // optional
- return files[0].size <= MAX_FILE_SIZE;
- }, "File must be ≤ 5 MB")
- .refine((files: FileList) => {
- if (!files?.length) return true;
- return ACCEPTED_FILE_TYPES.includes(files[0].type);
- }, "Unsupported file type"),
-});
-
-type FormData = z.infer
;
-
-export default function Page() {
- const {
- register,
- handleSubmit,
- control,
- formState: { errors, isSubmitting },
- } = useForm({
- resolver: zodResolver(schema),
- });
-
- const onSubmit = (data: FormData) => {
- // data.document is a FileList; access via data.document[0]
- console.log(data);
- };
-
- // Custom dropdown state & refs
- const [open, setOpen] = useState(false);
- const ref = useRef(null);
- const options = [
- { label: "General Inquiry", value: "general" },
- { label: "Support", value: "support" },
- { label: "Feedback", value: "feedback" },
- ];
-
- // Close dropdown on outside click
- useEffect(() => {
- const onClick = (e: MouseEvent) => {
- if (ref.current && !ref.current.contains(e.target as Node)) {
- setOpen(false);
- }
- };
- document.addEventListener("mousedown", onClick);
- return () => document.removeEventListener("mousedown", onClick);
- }, []);
-
- // --- Animation Variants ---
-
- const containerVariants: Variants = {
- hidden: { opacity: 0 },
- visible: {
- opacity: 1,
- transition: {
- staggerChildren: 0.1, // Stagger animation of children
- },
- },
- };
-
- const itemVariants: Variants = {
- hidden: { opacity: 0, y: 20 },
- visible: {
- opacity: 1,
- y: 0,
- transition: {
- duration: 0.4,
- ease: "easeOut",
- },
- },
- };
-
- const dropdownVariants: Variants = {
- hidden: { opacity: 0, scale: 0.95, y: -10 },
- visible: {
- opacity: 1,
- scale: 1,
- y: 0,
- transition: { duration: 0.2, ease: "easeOut" },
- },
- exit: {
- opacity: 0,
- scale: 0.95,
- y: -10,
- transition: { duration: 0.15, ease: "easeIn" },
- },
- };
-
- const errorVariants: Variants = {
- hidden: { opacity: 0, height: 0, y: -10, marginTop: 0 },
- visible: {
- opacity: 1,
- height: "auto",
- y: 0,
- marginTop: "0.25rem",
- transition: { duration: 0.2 },
- },
- exit: {
- opacity: 0,
- height: 0,
- y: -5,
- marginTop: 0,
- transition: { duration: 0.15 },
- },
- };
-
- return (
-
-
-
- Submit a Request
-
-
-
-
- );
-}
diff --git a/src/app/dashboard/researcher/layout.tsx b/src/app/dashboard/researcher/layout.tsx
new file mode 100644
index 0000000..4982325
--- /dev/null
+++ b/src/app/dashboard/researcher/layout.tsx
@@ -0,0 +1,33 @@
+import DashboardNav from "../components/resuables/DashboardNav";
+
+export default function Layout({
+ children,
+}: Readonly<{
+ children: React.ReactNode;
+}>) {
+ const nav_items = [
+ { href: "/dashboard/researcher/overview", label: "Overview" },
+ {
+ href: "/dashboard/researcher/projects",
+ label: "Projects",
+ },
+ {
+ href: "/dashboard/researcher/my-reports",
+ label: "My Report",
+ },
+ {
+ href: "/dashboard/researcher/rankings",
+ label: "Rankings",
+ },
+ {
+ href: "/dashboard/researcher/profile",
+ label: "Profile",
+ },
+ ];
+ return (
+
+
+ {children}
+
+ );
+}
diff --git a/src/app/dashboard/researcher/my-reports/page.tsx b/src/app/dashboard/researcher/my-reports/page.tsx
new file mode 100644
index 0000000..4583406
--- /dev/null
+++ b/src/app/dashboard/researcher/my-reports/page.tsx
@@ -0,0 +1,7 @@
+import React from "react";
+
+function page() {
+ return page
;
+}
+
+export default page;
diff --git a/src/app/dashboard/researcher/overview/components/ReportsApproved.tsx b/src/app/dashboard/researcher/overview/components/ReportsApproved.tsx
new file mode 100644
index 0000000..c69130e
--- /dev/null
+++ b/src/app/dashboard/researcher/overview/components/ReportsApproved.tsx
@@ -0,0 +1,36 @@
+"use client";
+import React, { useState } from "react";
+
+function ReportsApproved() {
+ const [score] = useState("92.42");
+ return (
+
+
Report Stats
+
+
Report Score
+
+
{score}%
+
+
+
+
Total Reports
+
+
4
+
1 pending review
+
+
+
Approval Rate
+
+
3/4
+
Correct Report
+
+
+ );
+}
+
+export default ReportsApproved;
diff --git a/src/app/dashboard/researcher/overview/components/ReportsSubmitted.tsx b/src/app/dashboard/researcher/overview/components/ReportsSubmitted.tsx
new file mode 100644
index 0000000..5829475
--- /dev/null
+++ b/src/app/dashboard/researcher/overview/components/ReportsSubmitted.tsx
@@ -0,0 +1,81 @@
+import { Clock } from "lucide-react";
+import React from "react";
+
+const dummy_alerts = [
+ {
+ title: "Smart contract audit",
+ priority: "high",
+ time_passed: "30 mins ago",
+ },
+ {
+ title: "Smart contract audit",
+ priority: "medium",
+ time_passed: "1 hour ago",
+ },
+ {
+ title: "Smart contract audit",
+ priority: "low",
+ time_passed: "1 day ago",
+ },
+];
+
+function AlertCard({
+ alert,
+}: {
+ alert: {
+ title: string;
+ priority: string;
+ time_passed: string;
+ };
+}) {
+ function priority_class() {
+ if (alert.priority === "high") {
+ return "bg-[#401D1D] text-[#EF4343]";
+ }
+ if (alert.priority === "medium") {
+ return "bg-[#373510] text-[#C1B700]";
+ }
+ if (alert.priority === "low") {
+ return "bg-[#10273E] text-[#0073E6]";
+ }
+ }
+ return (
+
+
+
{alert.title}
+
+ Priority: {alert.priority}
+
+
+
+
+ {alert.time_passed}
+
+
+ );
+}
+
+function ReportsSubmitted() {
+ return (
+
+
New Project Alerts
+ {dummy_alerts.map((alert, id) => (
+
+ ))}
+
+
+ Go to Projects
+
+
+
+ );
+}
+
+export default ReportsSubmitted;
diff --git a/src/app/dashboard/researcher/overview/components/TokenEarnings.tsx b/src/app/dashboard/researcher/overview/components/TokenEarnings.tsx
new file mode 100644
index 0000000..bbb11ae
--- /dev/null
+++ b/src/app/dashboard/researcher/overview/components/TokenEarnings.tsx
@@ -0,0 +1,30 @@
+"use client";
+import React, { useState } from "react";
+
+function TokenEarnings() {
+ const [reputation] = useState("91");
+ return (
+
+
Performance Snapshot
+
+
Rank
+
+
#23
+
Out of 247 researchers
+
+
+
Reputation
+
+
{reputation}%
+
+
+
+ );
+}
+
+export default TokenEarnings;
diff --git a/src/app/dashboard/researcher/overview/page.tsx b/src/app/dashboard/researcher/overview/page.tsx
index 0b03a1c..603d019 100644
--- a/src/app/dashboard/researcher/overview/page.tsx
+++ b/src/app/dashboard/researcher/overview/page.tsx
@@ -1,148 +1,45 @@
import React from "react";
-import {
- File,
- Clock,
- CheckCircle,
- AlertTriangle,
- BadgeDollarSign,
-} from "lucide-react";
-import { StatCard } from "../../components/resuables/StatsCard";
-import { RecentReports } from "../../components/resuables/TableComponents";
-import { Announcements } from "../../components/resuables/AnnoucmentSection";
-import Image from "next/image";
-import statsOne from "../../../../../public/researcherIcon/reStatsOne.svg";
-import statsTwo from "../../../../../public/researcherIcon/reSttatsTwo.svg";
-import statsThree from "../../../../../public/researcherIcon/reStatsThree.svg";
-import statsFour from "../../../../../public/researcherIcon/reStatsFour.svg";
-import statsFive from "../../../../../public/researcherIcon/reStatsFive.svg";
-import hourglass from "../../../../../public/researcherIcon/hourGlass.svg";
-import calendar from "../../../../../public/researcherIcon/calendarImg.svg";
-
-const Overview = () => {
- // Data for stat cards
- const statCardsData = [
- {
- icon: ,
- value: "15",
- label: "Total Reports Submitted",
- },
- {
- icon: ,
- value: "15",
- label: "Pending Reviews",
- },
- {
- icon: ,
- value: "8",
- label: "Approved Reports",
- },
- {
- icon: ,
- value: "1",
- label: "Disputed Reports",
- },
- {
- icon: ,
- value: "$1,525.11",
- label: "Total Earnings",
- },
- ];
-
- // Data for recent reports table
- const reportsData = [
- {
- id: "#24084",
- projectName: "InheritX",
- primaryLanguage: "Cairo",
- severity: "Critical",
- status: "Approved",
- actionLink: "/dashboard/validator/reports",
- },
- {
- id: "#24084",
- projectName: "InheritX",
- primaryLanguage: "Cairo",
- severity: "Critical",
- status: "Rejected",
- actionLink: "/dashboard/validator/reports",
- },
- {
- id: "#24084",
- projectName: "InheritX",
- primaryLanguage: "Cairo",
- severity: "High",
- status: "Approved",
- actionLink: "/dashboard/validator/reports",
- },
- {
- id: "#24084",
- projectName: "InheritX",
- primaryLanguage: "Cairo",
- severity: "Critical",
- status: "Pending",
- actionLink: "/dashboard/validator/reports",
- },
- ];
-
- // Data for announcements section
- const announcementsData = [
- {
- type: "rejected",
- title: "[Rejected Report]",
- description:
- "The vulnerability report for Project name... that you submitted have been rejected",
- actionLink: "/view-report/1",
- authorIcon: ,
- timeAgo: "2 mins ago",
- },
- {
- type: "bounty",
- title: "[Bounty Paid Out]",
- description:
- "Project name... has been approved and your bounty has been paid",
- actionLink: "/view-bounty/1",
- authorIcon: ,
- timeAgo: "1 hour ago",
- },
- {
- type: "new",
- title: "[New Project]",
- description:
- "A new project have been created, take a look and check out vulnerabilities",
- actionLink: "/view-project/1",
- authorIcon: ,
- timeAgo: "30 mins ago",
- },
- ];
+import { CircleDollarSignIcon, DollarSign, FolderOpen } from "lucide-react";
+import OverviewCardExpandable from "../../components/resuables/OverviewCardExpandable";
+import ReportsSubmitted from "./components/ReportsSubmitted";
+import ReportsApproved from "./components/ReportsApproved";
+import TokenEarnings from "./components/TokenEarnings";
+function page() {
return (
-
- {/* Stat Cards Section */}
-
- {statCardsData.map((card, index) => (
-
- ))}
-
-
- {/* Recent Reports Section */}
-
-
-
-
- {/* Announcements Section */}
-
+
+ ,
+ }}
+ badgeStyle="text-[#1BC100] bg-[#153710]"
+ children={ }
+ />
+ ,
+ }}
+ badgeStyle="bg-[#10273E] text-[#0073E6]"
+ children={ }
+ />
+ ,
+ }}
+ badgeStyle="bg-[#320D35] text-[#BB00C1]"
+ children={ }
+ />
);
-};
+}
-export default Overview;
+export default page;
diff --git a/src/app/dashboard/researcher/page.tsx b/src/app/dashboard/researcher/page.tsx
index 8a05568..b8747aa 100644
--- a/src/app/dashboard/researcher/page.tsx
+++ b/src/app/dashboard/researcher/page.tsx
@@ -1,7 +1,16 @@
-import { redirect } from "next/navigation";
+"use client";
-const page = () => {
- redirect("/dashboard/researcher/overview");
+import { useEffect } from "react";
+import { useRouter } from "next/navigation";
+
+const Page = () => {
+ const router = useRouter();
+
+ useEffect(() => {
+ router.replace("/dashboard/researcher/overview");
+ }, [router]);
+
+ return null;
};
-export default page;
+export default Page;
diff --git a/src/app/dashboard/researcher/profile/page.tsx b/src/app/dashboard/researcher/profile/page.tsx
new file mode 100644
index 0000000..4583406
--- /dev/null
+++ b/src/app/dashboard/researcher/profile/page.tsx
@@ -0,0 +1,7 @@
+import React from "react";
+
+function page() {
+ return
page
;
+}
+
+export default page;
diff --git a/src/app/dashboard/researcher/rankings/page.tsx b/src/app/dashboard/researcher/rankings/page.tsx
new file mode 100644
index 0000000..4583406
--- /dev/null
+++ b/src/app/dashboard/researcher/rankings/page.tsx
@@ -0,0 +1,7 @@
+import React from "react";
+
+function page() {
+ return
page
;
+}
+
+export default page;
diff --git a/src/app/dashboard/researcher/reports/success/[id]/page.tsx b/src/app/dashboard/researcher/reports/success/[id]/page.tsx
index ca6c00e..71010d4 100644
--- a/src/app/dashboard/researcher/reports/success/[id]/page.tsx
+++ b/src/app/dashboard/researcher/reports/success/[id]/page.tsx
@@ -1,7 +1,5 @@
-// pages/reports/success.tsx or app/reports/success/page.tsx (depending on your Next.js version)
"use client";
-import { useState, useEffect} from 'react';
import { ReportLayout } from '../../ReportLayout';
import { useParams } from 'next/navigation';
import { ReportHeader } from '../../../../components/report/ReportHeader';
@@ -9,56 +7,17 @@ import { ReportInfoSection } from '../../../../components/report/ReportInfoSecti
import { ReportTextSection } from '../../../../components/report/ReportTextSection';
import { ImageGallery } from '../../../../components/report/ImageGallery';
import { SuccessActions } from '../../../../components/report/ActionButtons';
+import { useGetReport } from '@/hooks/useGetReport';
-const getReportData = (id: string) => {
- // This would typically be an API call
- return {
- id,
- title: "Local File Inclusion (LFI) on Home Page – https://example.com/home",
- status: "Fixed",
- severity: "High",
- cvssScore: "8.6",
- vulnerableUrl: "https://example.com/home - Home Page",
- vulnerableParam: "Broken Access Control",
- description: "Attackers can exploit the Filename parameter to access sensitive files (e.g., /etc/passwd) by sending a crafted request, exposing critical server data.",
- impact: "The vulnerability of Local File Inclusion (LFI) on the home page \"https://example.com/home\" can be attributed to the impact of the filename parameter. This vulnerability allows an attacker to manipulate the filename parameter in the URL to include arbitrary local files from the server.",
- stepsToReproduce: (
-
- Go to the Home Page (https://example.com/home).
- Select any file from the selection section.
- Intercept the request in the Burp Suite Proxy tool and send it to the request repeater tab in Burp Suite Proxy tool.
-
- ),
- mitigation: (
-
- Implement input validation and sanitize user input to prevent the inclusion of unauthorized file paths or malicious input.
- Avoid using user-supplied input directly in file inclusion functions. Instead, use a whitelist approach or predefined file mappings.
-
- ),
- pocImages: [
- { src: "/download3.svg", alt: "PoC 1" },
- { src: "/poc.svg", alt: "PoC 2" },
- { src: "/download.svg", alt: "PoC 3" }
- ]
- };
-};
const Success = () => {
const params = useParams();
const reportId = params?.id as string;
- const [loading, setLoading] = useState(true);
- const [reportData, setReportData] = useState
(null);
-
- useEffect(() => {
- if (reportId) {
- setTimeout(() => {
- const data = getReportData(reportId);
- setReportData(data);
- setLoading(false);
- }, 300);
- }
- }, [reportId]);
+ // Use the useGetReport hook to fetch full report data (blockchain + IPFS)
+ const { report, loading, error, isEmpty, refetch } = useGetReport(Number(reportId));
+
+ // Handle loading state
if (loading) {
return (
@@ -67,14 +26,65 @@ const Success = () => {
);
}
- if (!reportData) {
+ // Handle simple error state
+ if (error) {
return (
-
Report not found
+
+
Report Not Found
+
+ The report with ID {reportId} could not be found.
+
+
+ Try Again
+
+
+
+ );
+ }
+
+ // Handle empty state
+ if (isEmpty || !report) {
+ return (
+
+
+
Report Not Found
+
The report with ID {reportId} could not be found.
+
+ Try Again
+
+
);
}
-
+
+ const reportData = {
+ id: report.id,
+ title: report.title || "",
+ status: report.status || "Unknown",
+ severity: report.severity || "Medium",
+ cvssScore: report.cvssScore?.toString() || "0",
+ vulnerableUrl: report.url || report.report_uri || "",
+ vulnerableParam: report.vulnerableParameter || "",
+ description: report.vulnerabilityDescription || report.description || "",
+ impact: report.vulnerabilityImpact || "",
+ stepsToReproduce: report.stepsToReproduce && report.stepsToReproduce.length > 0 ? report.stepsToReproduce : null,
+ mitigation: report.mitigationSteps && report.mitigationSteps.length > 0 ? report.mitigationSteps : null,
+ pocImages: report.proofOfConcept && report.proofOfConcept.length > 0 ?
+ report.proofOfConcept.map((poc, index) => ({
+ src: poc,
+ alt: `PoC ${index + 1}`
+ })) : null
+ };
+
+
+
return (
}>
@@ -90,40 +100,62 @@ const Success = () => {
vulnerableParam={reportData.vulnerableParam}
/>
-
-
-
+ {reportData.description && (
+
+
+
+ )}
-
-
-
+ {reportData.impact && (
+
+
+
+ )}
-
-
-
+ {reportData.stepsToReproduce && (
+
+
+ {reportData.stepsToReproduce.map((step, index) => (
+ {step}
+ ))}
+
+ }
+ />
+
+ )}
-
- }
- />
-
+ {reportData.pocImages && (
+
+ }
+ />
+
+ )}
-
-
-
+ {reportData.mitigation && (
+
+
+ {reportData.mitigation.map((step, index) => (
+ {step}
+ ))}
+
+ }
+ />
+
+ )}
);
diff --git a/src/app/dashboard/researcher/rewards/page.tsx b/src/app/dashboard/researcher/rewards/page.tsx
index 646d298..9f8d873 100644
--- a/src/app/dashboard/researcher/rewards/page.tsx
+++ b/src/app/dashboard/researcher/rewards/page.tsx
@@ -8,7 +8,7 @@ import { TransactionSuccessModal } from "@/components/dashboard/Transaction-succ
import { WithdrawalHistory } from "@/components/dashboard/Withdrawal-history";
import { WithdrawalHistoryModal } from "@/components/dashboard/Withdrawal-history-modal";
import { WithdrawalRequest } from "@/components/dashboard/Withdrawal-request";
-import { StatCard } from "../../components/resuables/StatsCard";
+import StatsCard from "@/components/dashboard/projects/StatsCard";
export default function RewardPage() {
const [showSuccessModal, setShowSuccessModal] = useState(false);
@@ -27,7 +27,7 @@ export default function RewardPage() {
<>
- }
value="2,500 STRK"
label="Total Rewards Earned:"
@@ -35,7 +35,7 @@ export default function RewardPage() {
- }
value="150 STRK"
label="Pending Withdrawal"
diff --git a/src/app/dashboard/validator/assigned-projects/page.tsx b/src/app/dashboard/validator/assigned-projects/page.tsx
new file mode 100644
index 0000000..4583406
--- /dev/null
+++ b/src/app/dashboard/validator/assigned-projects/page.tsx
@@ -0,0 +1,7 @@
+import React from "react";
+
+function page() {
+ return page
;
+}
+
+export default page;
diff --git a/src/app/dashboard/validator/layout.tsx b/src/app/dashboard/validator/layout.tsx
new file mode 100644
index 0000000..0d3c750
--- /dev/null
+++ b/src/app/dashboard/validator/layout.tsx
@@ -0,0 +1,33 @@
+import DashboardNav from "../components/resuables/DashboardNav";
+
+export default function Layout({
+ children,
+}: Readonly<{
+ children: React.ReactNode;
+}>) {
+ const nav_items = [
+ { href: "/dashboard/validator/overview", label: "Overview" },
+ {
+ href: "/dashboard/validator/reports",
+ label: "Reports",
+ },
+ {
+ href: "/dashboard/validator/assigned-projects",
+ label: "Assigned Projects",
+ },
+ {
+ href: "/dashboard/validator/rankings",
+ label: "Rankings",
+ },
+ {
+ href: "/dashboard/validator/profile",
+ label: "Profile",
+ },
+ ];
+ return (
+
+
+ {children}
+
+ );
+}
diff --git a/src/app/dashboard/validator/overview/components/AuditStats.tsx b/src/app/dashboard/validator/overview/components/AuditStats.tsx
new file mode 100644
index 0000000..aec2d36
--- /dev/null
+++ b/src/app/dashboard/validator/overview/components/AuditStats.tsx
@@ -0,0 +1,35 @@
+"use client";
+import React, { useState } from "react";
+
+function AuditStats() {
+ const [accuracy] = useState("92.42");
+ return (
+
+
Audit Stats
+
+
Overall Accuracy
+
+
{accuracy}%
+
+
+
+
Total Votes
+
+
4
+
1 pending review
+
+
+
Success Rate
+
+ 5/5
+
+
+ );
+}
+
+export default AuditStats;
diff --git a/src/app/dashboard/validator/overview/components/PerformanceSnapshot.tsx b/src/app/dashboard/validator/overview/components/PerformanceSnapshot.tsx
new file mode 100644
index 0000000..605c9e1
--- /dev/null
+++ b/src/app/dashboard/validator/overview/components/PerformanceSnapshot.tsx
@@ -0,0 +1,30 @@
+"use client";
+import React, { useState } from "react";
+
+function PerformanceSnapshot() {
+ const [reputation] = useState("91");
+ return (
+
+
Performance Snapshot
+
+
Rank
+
+
#23
+
Out of 247 validators
+
+
+
Reputation
+
+
{reputation}%
+
+
+
+ );
+}
+
+export default PerformanceSnapshot;
diff --git a/src/app/dashboard/validator/overview/components/ReportAlerts.tsx b/src/app/dashboard/validator/overview/components/ReportAlerts.tsx
new file mode 100644
index 0000000..ecbde2e
--- /dev/null
+++ b/src/app/dashboard/validator/overview/components/ReportAlerts.tsx
@@ -0,0 +1,81 @@
+import { Clock } from "lucide-react";
+import React from "react";
+
+const dummy_alerts = [
+ {
+ title: "Smart contract audit",
+ priority: "high",
+ time_passed: "30 mins ago",
+ },
+ {
+ title: "Smart contract audit",
+ priority: "medium",
+ time_passed: "1 hour ago",
+ },
+ {
+ title: "Smart contract audit",
+ priority: "low",
+ time_passed: "1 day ago",
+ },
+];
+
+function AlertCard({
+ alert,
+}: {
+ alert: {
+ title: string;
+ priority: string;
+ time_passed: string;
+ };
+}) {
+ function priority_class() {
+ if (alert.priority === "high") {
+ return "bg-[#401D1D] text-[#EF4343]";
+ }
+ if (alert.priority === "medium") {
+ return "bg-[#373510] text-[#C1B700]";
+ }
+ if (alert.priority === "low") {
+ return "bg-[#10273E] text-[#0073E6]";
+ }
+ }
+ return (
+
+
+
{alert.title}
+
+ Priority: {alert.priority}
+
+
+
+
+ {alert.time_passed}
+
+
+ );
+}
+
+function ReportAlerts() {
+ return (
+
+
New Reports Alerts
+ {dummy_alerts.map((alert, id) => (
+
+ ))}
+
+
+ Go to Reports
+
+
+
+ );
+}
+
+export default ReportAlerts;
diff --git a/src/app/dashboard/validator/overview/page.tsx b/src/app/dashboard/validator/overview/page.tsx
index 33bc989..81fdcbc 100644
--- a/src/app/dashboard/validator/overview/page.tsx
+++ b/src/app/dashboard/validator/overview/page.tsx
@@ -1,166 +1,45 @@
import React from "react";
-// import Link from "next/link";
-import { ActionButton } from "../../components/resuables/ActionButton";
-import { StatCard } from "../../components/resuables/StatsCard";
-import {
- RecentReports,
- ValidatorRanking,
-} from "../../components/resuables/TableComponents";
-import { RecentActivity } from "../../components/resuables/RecentActivity";
-import Image from "next/image";
-import walletIcon from "../../../../../public/validatorIcons/valAction.svg";
-import imgOne from "../../../../../public/validatorIcons/valImgOne.svg";
-import imgTwo from "../../../../../public/validatorIcons/valImgTwo.svg";
-import imgThree from "../../../../../public/validatorIcons/valImgThree.svg";
-import imgFour from "../../../../../public/validatorIcons/valImgFour.svg";
-
-const Overview = () => {
- // Sample data for validator ranking
- const validatorData = [
- {
- rank: 1,
- validator: "0x1234...abcd",
- reportsValidated: 8,
- totalRewards: "$24,123.11",
- },
- {
- rank: 2,
- validator: "Daniel Ocheje",
- reportsValidated: 8,
- totalRewards: "$18,205.15",
- },
- {
- rank: 3,
- validator: "Aisha Murtala",
- reportsValidated: 7,
- totalRewards: "$16,355.11",
- },
- {
- rank: 4,
- validator: "Favour Stephen",
- reportsValidated: 7,
- totalRewards: "$12,804.78",
- },
- ];
-
- // Sample data for recent reports
- const reportsData = [
- {
- id: "#24084",
- projectName: "inheritX",
- primaryLanguage: "Cairo",
- severity: "Critical",
- status: "Approved",
- actionLink: "/dashboard/validator/reports",
- },
- {
- id: "#24084",
- projectName: "inheritX",
- primaryLanguage: "Cairo",
- severity: "Completed",
- status: "Rejected",
- actionLink: "/dashboard/validator/reports",
- },
- {
- id: "#24084",
- projectName: "inheritX",
- primaryLanguage: "Cairo",
- severity: "High",
- status: "Approved",
- actionLink: "/dashboard/validator/reports",
- },
- {
- id: "#24084",
- projectName: "inheritX",
- primaryLanguage: "Cairo",
- severity: "Completed",
- status: "Pending",
- actionLink: "/dashboard/validator/reports",
- },
- ];
-
- // Recent activity data
- const recentActivities = [
- {
- id: 1,
- title: "Account Created",
- subtitle: "Your account was successfully created",
- timestamp: "Today 4:55pm",
- },
- {
- id: 2,
- title: "Vulnerability Report Added to Bookmarks",
- subtitle: "Vulnerability report saved to Bookmark",
- timestamp: "Today 4:55pm",
- },
- {
- id: 3,
- title: "Reward Claimed",
- subtitle: "Rewards from reports claimed",
- timestamp: "Yesterday",
- },
- ];
+import { CircleDollarSignIcon, DollarSign, FolderOpen } from "lucide-react";
+import ReportAlerts from "./components/ReportAlerts";
+import AuditStats from "./components/AuditStats";
+import PerformanceSnapshot from "./components/PerformanceSnapshot";
+import OverviewCardExpandable from "../../components/resuables/OverviewCardExpandable";
+function page() {
return (
-
- {/* Top Section with Action Button and Disconnect Wallet */}
-
-
- }
- title="Withdraw Available Funds"
- description="Transfer available funds to your wallet"
- href="/withdraw"
- iconBgColor="bg-[#0000FF]"
- id={""}
- />
-
-
- {/* Stats Cards */}
-
- }
- value={15}
- label="Pending Reports"
- />
- }
- value={8}
- label="Approved Reports"
- />
- }
- value={1}
- label="Disputed Reports"
- />
- }
- value="$1,525.11"
- label="Total Earnings"
- />
-
-
- {/* Recent Activity Section */}
-
-
-
-
- {/* Table Components */}
-
+ ,
+ }}
+ badgeStyle="text-[#1BC100] bg-[#153710]"
+ children={ }
+ />
+ ,
+ }}
+ badgeStyle="text-[#1BC100] bg-[#153710]"
+ children={ }
+ />
+ ,
+ }}
+ badgeStyle="bg-[#320D35] text-[#BB00C1]"
+ children={ }
/>
-
-
-
-
);
-};
+}
-export default Overview;
+export default page;
diff --git a/src/app/dashboard/validator/page.tsx b/src/app/dashboard/validator/page.tsx
index 7affe64..8936688 100644
--- a/src/app/dashboard/validator/page.tsx
+++ b/src/app/dashboard/validator/page.tsx
@@ -1,7 +1,16 @@
-import { redirect } from "next/navigation";
+"use client";
-const page = () => {
- redirect("/dashboard/validator/overview");
+import { useEffect } from "react";
+import { useRouter } from "next/navigation";
+
+const Page = () => {
+ const router = useRouter();
+
+ useEffect(() => {
+ router.replace("/dashboard/validator/overview");
+ }, [router]);
+
+ return null;
};
-export default page;
+export default Page;
diff --git a/src/app/dashboard/validator/rankings/page.tsx b/src/app/dashboard/validator/rankings/page.tsx
new file mode 100644
index 0000000..4583406
--- /dev/null
+++ b/src/app/dashboard/validator/rankings/page.tsx
@@ -0,0 +1,7 @@
+import React from "react";
+
+function page() {
+ return page
;
+}
+
+export default page;
diff --git a/src/app/globals.css b/src/app/globals.css
index ec194ea..d666401 100644
--- a/src/app/globals.css
+++ b/src/app/globals.css
@@ -169,3 +169,7 @@ body {
.ql-toolbar button {
font-size: 20px;
}
+
+button:focus {
+ outline: none;
+}
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index b2278e6..8eecd3e 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -1,14 +1,9 @@
-
-
-
-import type React from "react"
-import type { Metadata } from "next"
-import "./globals.css"
-import { StructuredData } from "../components/metadata/structured-data"
+import type React from "react";
+import type { Metadata } from "next";
+import "./globals.css";
+import { StructuredData } from "../components/metadata/structured-data";
import ClientProviders from "@/providers/client-providers";
-
-
export const metadata: Metadata = {
title: "FortiChain - Decentralized Blockchain Security Platform",
description:
@@ -59,7 +54,8 @@ export const metadata: Metadata = {
twitter: {
card: "summary_large_image",
title: "FortiChain - Decentralized Blockchain Security Platform",
- description: "Enhance blockchain security through automated vulnerability disclosure and bug bounty processes.",
+ description:
+ "Enhance blockchain security through automated vulnerability disclosure and bug bounty processes.",
images: ["/twitter-image.png"],
creator: "@fortichain",
site: "@fortichain",
@@ -79,21 +75,21 @@ export const metadata: Metadata = {
google: "your-google-verification-code",
yandex: "your-yandex-verification-code",
},
-}
+};
export default function RootLayout({
children,
}: Readonly<{
- children: React.ReactNode
+ children: React.ReactNode;
}>) {
return (
-
- {children}
-
+
+ {children}
+
- )
+ );
}
diff --git a/src/components/address-bar.tsx b/src/components/address-bar.tsx
new file mode 100644
index 0000000..402ef99
--- /dev/null
+++ b/src/components/address-bar.tsx
@@ -0,0 +1,33 @@
+import { useAccount } from "@starknet-react/core";
+import { Ellipsis } from "lucide-react";
+import React from "react";
+
+function AddressBar() {
+ const { address } = useAccount();
+ return (
+
+
+
+
+
+ {address?.slice(0, 6)}...{address?.slice(-5)}
+
+
+
+
+
+
+
+ );
+}
+
+export default AddressBar;
diff --git a/src/components/connect-button.tsx b/src/components/connect-button.tsx
index 0ff3c6a..f08b46e 100644
--- a/src/components/connect-button.tsx
+++ b/src/components/connect-button.tsx
@@ -10,6 +10,7 @@ import { AccountTypeModal } from "./account-type-modal";
import Link from "next/link";
import { StarknetkitConnector, useStarknetkitConnectModal } from "starknetkit";
import { WebWalletConnector } from "starknetkit/webwallet";
+import AddressBar from "./address-bar";
type ConnectButtonVariant = "default" | "navbar";
@@ -102,47 +103,13 @@ export function ConnectButton({
return (
{isConnected && address ? (
-
-
setIsDropdownOpen(!isDropdownOpen)}
- className={`flex items-center gap-2 border border-[#6B6668] text-white transition-colors ${
- variant === "navbar"
- ? "rounded px-4 py-2"
- : "rounded-lg px-6 py-3 sm:px-8 sm:py-4 md:px-10 md:py-5 text-base sm:text-lg md:text-xl font-semibold"
- }`}
- aria-label="Account menu"
- >
- {truncateAddress(address)}
-
-
-
- {isDropdownOpen && (
-
-
- Disconnect Wallet
-
-
- )}
-
+
) : (