Explorar o código

usage metrics

jusrhee %!s(int64=2) %!d(string=hai) anos
pai
achega
32cb3227b8

+ 428 - 76
dashboard/package-lock.json

@@ -78,6 +78,7 @@
         "react-table": "^7.7.0",
         "react-timer-hook": "^3.0.7",
         "react-transition-group": "^4.4.2",
+        "recharts": "^2.12.5",
         "regenerator-runtime": "^0.13.9",
         "semver": "^7.3.5",
         "simple-statistics": "^7.8.0",
@@ -3264,16 +3265,34 @@
       "integrity": "sha512-hN879HLPTVqZV3FQEXy7ptt083UXwguNbnxdTGzVW4y4KjX5uyNKljrQixZcSJfLyFirbpUokxpXtvR+N5+KIg==",
       "dev": true
     },
+    "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=="
+    },
     "node_modules/@types/d3-delaunay": {
       "version": "6.0.1",
       "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.1.tgz",
       "integrity": "sha512-tLxQ2sfT0p6sxdG75c6f/ekqxjyYR0+LwPrsO1mbC9YDBzPJhs2HbJJRrn8Ez1DBoHRo2yx7YEATI+8V1nGMnQ=="
     },
+    "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=="
+    },
     "node_modules/@types/d3-format": {
       "version": "3.0.1",
       "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-3.0.1.tgz",
       "integrity": "sha512-5KY70ifCCzorkLuIkDe0Z9YTf9RR2CjBX1iaJG+rgM/cPP+sO+q9YdQ9WdhQcgPj1EQiJ2/0+yUkkziTG6Lubg=="
     },
+    "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==",
+      "dependencies": {
+        "@types/d3-color": "*"
+      }
+    },
     "node_modules/@types/d3-path": {
       "version": "1.0.9",
       "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-1.0.9.tgz",
@@ -3284,6 +3303,14 @@
       "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-2.2.1.tgz",
       "integrity": "sha512-5vvxn6//poNeOxt1ZwC7QU//dG9QqABjy1T7fP/xmFHY95GnaOw3yABf29hiu5SR1Oo34XcpyHFbzod+vemQjA=="
     },
+    "node_modules/@types/d3-scale": {
+      "version": "4.0.8",
+      "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.8.tgz",
+      "integrity": "sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==",
+      "dependencies": {
+        "@types/d3-time": "*"
+      }
+    },
     "node_modules/@types/d3-shape": {
       "version": "1.3.8",
       "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-1.3.8.tgz",
@@ -3292,12 +3319,22 @@
         "@types/d3-path": "^1"
       }
     },
+    "node_modules/@types/d3-time": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.3.tgz",
+      "integrity": "sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw=="
+    },
     "node_modules/@types/d3-time-format": {
       "version": "3.0.1",
       "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-3.0.1.tgz",
       "integrity": "sha512-5GIimz5IqaRsdnxs4YlyTZPwAMfALu/wA4jqSiuqgdbCxUZ2WjrnwANqOtoBJQgeaUTdYNfALJO0Yb0YrDqduA==",
       "dev": true
     },
+    "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=="
+    },
     "node_modules/@types/d3-voronoi": {
       "version": "1.1.9",
       "resolved": "https://registry.npmjs.org/@types/d3-voronoi/-/d3-voronoi-1.1.9.tgz",
@@ -4466,48 +4503,6 @@
         "node": ">=12"
       }
     },
-    "node_modules/@visx/vendor/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==",
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/@visx/vendor/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==",
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/@visx/vendor/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==",
-      "dependencies": {
-        "d3-color": "1 - 3"
-      },
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/@visx/vendor/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==",
-      "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/@visx/vendor/node_modules/d3-time": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz",
@@ -6933,6 +6928,14 @@
         "internmap": "^1.0.0"
       }
     },
+    "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==",
+      "engines": {
+        "node": ">=12"
+      }
+    },
     "node_modules/d3-delaunay": {
       "version": "6.0.2",
       "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.2.tgz",
@@ -6944,6 +6947,33 @@
         "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==",
+      "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==",
+      "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==",
+      "dependencies": {
+        "d3-color": "1 - 3"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
     "node_modules/d3-interpolate-path": {
       "version": "2.2.1",
       "resolved": "https://registry.npmjs.org/d3-interpolate-path/-/d3-interpolate-path-2.2.1.tgz",
@@ -6959,6 +6989,21 @@
       "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-2.2.2.tgz",
       "integrity": "sha512-0D9P8TRj6qDAtHhRQn6EfdOtHMfsUWanl3yb/84C4DqpZ+VsgfI5iTVRNRbELCfNvRfpMr8OrqqUTQ6ANGCijw=="
     },
+    "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==",
+      "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": "1.3.7",
       "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz",
@@ -6983,6 +7028,14 @@
         "d3-time": "1 - 2"
       }
     },
+    "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==",
+      "engines": {
+        "node": ">=12"
+      }
+    },
     "node_modules/d3-voronoi": {
       "version": "1.1.4",
       "resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.1.4.tgz",
@@ -7035,6 +7088,11 @@
         "node": ">=0.10.0"
       }
     },
+    "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=="
+    },
     "node_modules/decode-uri-component": {
       "version": "0.2.2",
       "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz",
@@ -8496,8 +8554,7 @@
     "node_modules/eventemitter3": {
       "version": "4.0.7",
       "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
-      "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
-      "dev": true
+      "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="
     },
     "node_modules/events": {
       "version": "3.3.0",
@@ -8815,6 +8872,14 @@
       "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
       "dev": true
     },
+    "node_modules/fast-equals": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.0.1.tgz",
+      "integrity": "sha512-WF1Wi8PwwSY7/6Kx0vKXtw8RwuSGoM1bvDaJbu7MxDlR1vovZjIAKrnzyrThgAjm6JDTu0fVgWXDlMGspodfoQ==",
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
     "node_modules/fast-glob": {
       "version": "3.3.1",
       "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz",
@@ -13892,6 +13957,20 @@
         "react": ">=15"
       }
     },
+    "node_modules/react-smooth": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.1.tgz",
+      "integrity": "sha512-OE4hm7XqR0jNOq3Qmk9mFLyd6p2+j6bvbPJ7qlB7+oo0eNcL2l7WQzG6MBnT3EXY6xzkLMUBec3AfewJdA0J8w==",
+      "dependencies": {
+        "fast-equals": "^5.0.1",
+        "prop-types": "^15.8.1",
+        "react-transition-group": "^4.4.5"
+      },
+      "peerDependencies": {
+        "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
+        "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
+      }
+    },
     "node_modules/react-table": {
       "version": "7.8.0",
       "resolved": "https://registry.npmjs.org/react-table/-/react-table-7.8.0.tgz",
@@ -13984,6 +14063,44 @@
         "node": ">=8.10.0"
       }
     },
+    "node_modules/recharts": {
+      "version": "2.12.5",
+      "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.12.5.tgz",
+      "integrity": "sha512-Cy+BkqrFIYTHJCyKHJEPvbHE2kVQEP6PKbOHJ8ztRGTAhvHuUnCwDaKVb13OwRFZ0QNUk1QvGTDdgWSMbuMtKw==",
+      "dependencies": {
+        "clsx": "^2.0.0",
+        "eventemitter3": "^4.0.1",
+        "lodash": "^4.17.21",
+        "react-is": "^16.10.2",
+        "react-smooth": "^4.0.0",
+        "recharts-scale": "^0.4.4",
+        "tiny-invariant": "^1.3.1",
+        "victory-vendor": "^36.6.8"
+      },
+      "engines": {
+        "node": ">=14"
+      },
+      "peerDependencies": {
+        "react": "^16.0.0 || ^17.0.0 || ^18.0.0",
+        "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0"
+      }
+    },
+    "node_modules/recharts-scale": {
+      "version": "0.4.5",
+      "resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.5.tgz",
+      "integrity": "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==",
+      "dependencies": {
+        "decimal.js-light": "^2.4.1"
+      }
+    },
+    "node_modules/recharts/node_modules/clsx": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz",
+      "integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==",
+      "engines": {
+        "node": ">=6"
+      }
+    },
     "node_modules/redent": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz",
@@ -16605,6 +16722,81 @@
         "node": ">= 0.8"
       }
     },
+    "node_modules/victory-vendor": {
+      "version": "36.9.2",
+      "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.9.2.tgz",
+      "integrity": "sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==",
+      "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/victory-vendor/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=="
+    },
+    "node_modules/victory-vendor/node_modules/@types/d3-shape": {
+      "version": "3.1.6",
+      "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.6.tgz",
+      "integrity": "sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA==",
+      "dependencies": {
+        "@types/d3-path": "*"
+      }
+    },
+    "node_modules/victory-vendor/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==",
+      "dependencies": {
+        "internmap": "1 - 2"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/victory-vendor/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==",
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/victory-vendor/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==",
+      "dependencies": {
+        "d3-path": "^3.1.0"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/victory-vendor/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==",
+      "dependencies": {
+        "d3-array": "2 - 3"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
     "node_modules/vm-browserify": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz",
@@ -20459,16 +20651,34 @@
       "integrity": "sha512-hN879HLPTVqZV3FQEXy7ptt083UXwguNbnxdTGzVW4y4KjX5uyNKljrQixZcSJfLyFirbpUokxpXtvR+N5+KIg==",
       "dev": true
     },
+    "@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=="
+    },
     "@types/d3-delaunay": {
       "version": "6.0.1",
       "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.1.tgz",
       "integrity": "sha512-tLxQ2sfT0p6sxdG75c6f/ekqxjyYR0+LwPrsO1mbC9YDBzPJhs2HbJJRrn8Ez1DBoHRo2yx7YEATI+8V1nGMnQ=="
     },
+    "@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=="
+    },
     "@types/d3-format": {
       "version": "3.0.1",
       "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-3.0.1.tgz",
       "integrity": "sha512-5KY70ifCCzorkLuIkDe0Z9YTf9RR2CjBX1iaJG+rgM/cPP+sO+q9YdQ9WdhQcgPj1EQiJ2/0+yUkkziTG6Lubg=="
     },
+    "@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==",
+      "requires": {
+        "@types/d3-color": "*"
+      }
+    },
     "@types/d3-path": {
       "version": "1.0.9",
       "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-1.0.9.tgz",
@@ -20479,6 +20689,14 @@
       "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-2.2.1.tgz",
       "integrity": "sha512-5vvxn6//poNeOxt1ZwC7QU//dG9QqABjy1T7fP/xmFHY95GnaOw3yABf29hiu5SR1Oo34XcpyHFbzod+vemQjA=="
     },
+    "@types/d3-scale": {
+      "version": "4.0.8",
+      "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.8.tgz",
+      "integrity": "sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==",
+      "requires": {
+        "@types/d3-time": "*"
+      }
+    },
     "@types/d3-shape": {
       "version": "1.3.8",
       "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-1.3.8.tgz",
@@ -20487,12 +20705,22 @@
         "@types/d3-path": "^1"
       }
     },
+    "@types/d3-time": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.3.tgz",
+      "integrity": "sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw=="
+    },
     "@types/d3-time-format": {
       "version": "3.0.1",
       "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-3.0.1.tgz",
       "integrity": "sha512-5GIimz5IqaRsdnxs4YlyTZPwAMfALu/wA4jqSiuqgdbCxUZ2WjrnwANqOtoBJQgeaUTdYNfALJO0Yb0YrDqduA==",
       "dev": true
     },
+    "@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=="
+    },
     "@types/d3-voronoi": {
       "version": "1.1.9",
       "resolved": "https://registry.npmjs.org/@types/d3-voronoi/-/d3-voronoi-1.1.9.tgz",
@@ -21490,36 +21718,6 @@
             "internmap": "1 - 2"
           }
         },
-        "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=="
-        },
-        "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=="
-        },
-        "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==",
-          "requires": {
-            "d3-color": "1 - 3"
-          }
-        },
-        "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==",
-          "requires": {
-            "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"
-          }
-        },
         "d3-time": {
           "version": "3.1.0",
           "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz",
@@ -23512,6 +23710,11 @@
         "internmap": "^1.0.0"
       }
     },
+    "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=="
+    },
     "d3-delaunay": {
       "version": "6.0.2",
       "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.2.tgz",
@@ -23520,6 +23723,24 @@
         "delaunator": "5"
       }
     },
+    "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=="
+    },
+    "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=="
+    },
+    "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==",
+      "requires": {
+        "d3-color": "1 - 3"
+      }
+    },
     "d3-interpolate-path": {
       "version": "2.2.1",
       "resolved": "https://registry.npmjs.org/d3-interpolate-path/-/d3-interpolate-path-2.2.1.tgz",
@@ -23535,6 +23756,18 @@
       "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-2.2.2.tgz",
       "integrity": "sha512-0D9P8TRj6qDAtHhRQn6EfdOtHMfsUWanl3yb/84C4DqpZ+VsgfI5iTVRNRbELCfNvRfpMr8OrqqUTQ6ANGCijw=="
     },
+    "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==",
+      "requires": {
+        "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"
+      }
+    },
     "d3-shape": {
       "version": "1.3.7",
       "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz",
@@ -23559,6 +23792,11 @@
         "d3-time": "1 - 2"
       }
     },
+    "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=="
+    },
     "d3-voronoi": {
       "version": "1.1.4",
       "resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.1.4.tgz",
@@ -23593,6 +23831,11 @@
       "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
       "dev": true
     },
+    "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=="
+    },
     "decode-uri-component": {
       "version": "0.2.2",
       "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz",
@@ -24715,8 +24958,7 @@
     "eventemitter3": {
       "version": "4.0.7",
       "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
-      "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
-      "dev": true
+      "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="
     },
     "events": {
       "version": "3.3.0",
@@ -24988,6 +25230,11 @@
       "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
       "dev": true
     },
+    "fast-equals": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.0.1.tgz",
+      "integrity": "sha512-WF1Wi8PwwSY7/6Kx0vKXtw8RwuSGoM1bvDaJbu7MxDlR1vovZjIAKrnzyrThgAjm6JDTu0fVgWXDlMGspodfoQ=="
+    },
     "fast-glob": {
       "version": "3.3.1",
       "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz",
@@ -28825,6 +29072,16 @@
         "tiny-warning": "^1.0.0"
       }
     },
+    "react-smooth": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.1.tgz",
+      "integrity": "sha512-OE4hm7XqR0jNOq3Qmk9mFLyd6p2+j6bvbPJ7qlB7+oo0eNcL2l7WQzG6MBnT3EXY6xzkLMUBec3AfewJdA0J8w==",
+      "requires": {
+        "fast-equals": "^5.0.1",
+        "prop-types": "^15.8.1",
+        "react-transition-group": "^4.4.5"
+      }
+    },
     "react-table": {
       "version": "7.8.0",
       "resolved": "https://registry.npmjs.org/react-table/-/react-table-7.8.0.tgz",
@@ -28898,6 +29155,36 @@
         "picomatch": "^2.2.1"
       }
     },
+    "recharts": {
+      "version": "2.12.5",
+      "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.12.5.tgz",
+      "integrity": "sha512-Cy+BkqrFIYTHJCyKHJEPvbHE2kVQEP6PKbOHJ8ztRGTAhvHuUnCwDaKVb13OwRFZ0QNUk1QvGTDdgWSMbuMtKw==",
+      "requires": {
+        "clsx": "^2.0.0",
+        "eventemitter3": "^4.0.1",
+        "lodash": "^4.17.21",
+        "react-is": "^16.10.2",
+        "react-smooth": "^4.0.0",
+        "recharts-scale": "^0.4.4",
+        "tiny-invariant": "^1.3.1",
+        "victory-vendor": "^36.6.8"
+      },
+      "dependencies": {
+        "clsx": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz",
+          "integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg=="
+        }
+      }
+    },
+    "recharts-scale": {
+      "version": "0.4.5",
+      "resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.5.tgz",
+      "integrity": "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==",
+      "requires": {
+        "decimal.js-light": "^2.4.1"
+      }
+    },
     "redent": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz",
@@ -30952,6 +31239,71 @@
       "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
       "dev": true
     },
+    "victory-vendor": {
+      "version": "36.9.2",
+      "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.9.2.tgz",
+      "integrity": "sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==",
+      "requires": {
+        "@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"
+      },
+      "dependencies": {
+        "@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=="
+        },
+        "@types/d3-shape": {
+          "version": "3.1.6",
+          "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.6.tgz",
+          "integrity": "sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA==",
+          "requires": {
+            "@types/d3-path": "*"
+          }
+        },
+        "d3-array": {
+          "version": "3.2.4",
+          "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz",
+          "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==",
+          "requires": {
+            "internmap": "1 - 2"
+          }
+        },
+        "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=="
+        },
+        "d3-shape": {
+          "version": "3.2.0",
+          "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz",
+          "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==",
+          "requires": {
+            "d3-path": "^3.1.0"
+          }
+        },
+        "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==",
+          "requires": {
+            "d3-array": "2 - 3"
+          }
+        }
+      }
+    },
     "vm-browserify": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz",

+ 1 - 0
dashboard/package.json

@@ -73,6 +73,7 @@
     "react-table": "^7.7.0",
     "react-timer-hook": "^3.0.7",
     "react-transition-group": "^4.4.2",
+    "recharts": "^2.12.5",
     "regenerator-runtime": "^0.13.9",
     "semver": "^7.3.5",
     "simple-statistics": "^7.8.0",

+ 7 - 8
dashboard/src/components/porter/Fieldset.tsx

@@ -4,12 +4,10 @@ import styled from "styled-components";
 type Props = {
   children: React.ReactNode;
   background?: string;
+  row?: boolean;
 };
 
-const Fieldset: React.FC<Props> = ({
-  children,
-  background,
-}) => {
+const Fieldset: React.FC<Props> = ({ children, background, row }) => {
   const getBackground = () => {
     switch (background) {
       case "dark":
@@ -19,7 +17,7 @@ const Fieldset: React.FC<Props> = ({
     }
   };
   return (
-    <StyledFieldset background={getBackground()}>
+    <StyledFieldset background={getBackground()} row={row}>
       {children}
     </StyledFieldset>
   );
@@ -29,11 +27,12 @@ export default Fieldset;
 
 const StyledFieldset = styled.div<{
   background?: string;
+  row?: boolean;
 }>`
   position: relative;
-  padding: 25px;
+  padding: ${(props) => (props.row ? "15px 20px" : "25px")};
   border-radius: 5px;
-  background: ${props => props.background || props.theme.fg};
+  background: ${(props) => props.background || props.theme.fg};
   border: 1px solid #494b4f;
   font-size: 13px;
-`;
+`;

+ 1 - 2
dashboard/src/lib/hooks/useStripe.tsx

@@ -8,10 +8,10 @@ import {
   PaymentMethodValidator,
   Plan,
   UsageValidator,
-  UsageList,
   type CreditGrants,
   type PaymentMethod,
   type PaymentMethodList,
+  type UsageList,
 } from "lib/billing/types";
 
 import api from "shared/api";
@@ -63,7 +63,6 @@ type TGetUsage = {
   usage: UsageList | undefined;
 };
 
-
 const embeddableDashboardColors = {
   grayDark: "Gray_dark",
   grayMedium: "Gray_medium",

+ 56 - 0
dashboard/src/main/home/project-settings/Bars.tsx

@@ -0,0 +1,56 @@
+import React, { useState } from "react";
+import {
+  Bar,
+  BarChart,
+  CartesianGrid,
+  Legend,
+  Rectangle,
+  ResponsiveContainer,
+  Tooltip,
+  XAxis,
+  YAxis,
+} from "recharts";
+import styled from "styled-components";
+
+import Text from "components/porter/Text";
+
+type Props = {
+  data: any;
+  yKey: string;
+  xKey: string;
+  fill?: string;
+  title?: string;
+};
+
+const Bars: React.FC<Props> = ({ data, yKey, xKey, fill, title }) => {
+  return (
+    <ResponsiveContainer width="100%" height="100%">
+      <BarChart
+        width={500}
+        height={300}
+        data={data}
+        margin={{
+          top: 5,
+          right: 0,
+          left: -20,
+          bottom: 5,
+        }}
+      >
+        <CartesianGrid vertical={false} stroke="#ffffff22" />
+        <XAxis dataKey={xKey} tick={{ fontSize: 13 }} />
+        <YAxis tick={{ fontSize: 13 }} />
+        <Tooltip />
+        <Bar dataKey={yKey} fill={fill || "#6A7FC4"} />
+      </BarChart>
+      <Center>
+        <Text color="helper">{title}</Text>
+      </Center>
+    </ResponsiveContainer>
+  );
+};
+
+export default Bars;
+
+const Center = styled.div`
+  text-align: center;
+`;

+ 79 - 27
dashboard/src/main/home/project-settings/BillingPage.tsx

@@ -1,5 +1,4 @@
-import React, { useContext, useState } from "react";
-import ParentSize from "@visx/responsive/lib/components/ParentSize";
+import React, { useContext, useMemo, useState } from "react";
 import styled from "styled-components";
 
 import Loading from "components/Loading";
@@ -14,7 +13,6 @@ import {
   checkIfProjectHasPayment,
   useCustomerPlan,
   useCustomerUsage,
-  useCustomeUsageDashboard,
   usePaymentMethods,
   usePorterCredits,
   useSetDefaultPaymentMethod,
@@ -26,6 +24,7 @@ import gift from "assets/gift.svg";
 import trashIcon from "assets/trash.png";
 
 import BillingModal from "../modals/BillingModal";
+import Bars from "./Bars";
 
 function BillingPage(): JSX.Element {
   const { setCurrentOverlay } = useContext(Context);
@@ -45,10 +44,33 @@ function BillingPage(): JSX.Element {
 
   const { refetchPaymentEnabled } = checkIfProjectHasPayment();
 
-  const { url: usageDashboard } = useCustomeUsageDashboard("usage");
-
   const { usage } = useCustomerUsage();
-  console.log(usage)
+
+  const processedData = useMemo(() => {
+    const before = usage;
+    const resultMap = new Map();
+
+    before?.forEach((metric) => {
+      const metricName = metric.metric_name.toLowerCase().replace(" ", "_");
+      metric.usage_metrics.forEach(({ starting_on, value }) => {
+        if (resultMap.has(starting_on)) {
+          resultMap.get(starting_on)[metricName] = value;
+        } else {
+          resultMap.set(starting_on, {
+            starting_on: new Date(starting_on).toLocaleDateString("en-US", {
+              month: "short",
+              day: "numeric",
+            }),
+            [metricName]: value,
+          });
+        }
+      });
+    });
+
+    // Convert the map to an array of values
+    const x = Array.from(resultMap.values());
+    return x;
+  }, [usage]);
 
   const formatCredits = (credits: number): string => {
     return (credits / 100).toFixed(2);
@@ -113,10 +135,10 @@ function BillingPage(): JSX.Element {
       {paymentMethodList.map((paymentMethod, idx) => {
         return (
           <div key={idx}>
-            <Fieldset>
+            <Fieldset row>
               <Container row spaced>
                 <Container row>
-                  <Icon src={cardIcon} height={"14px"} />
+                  <Icon opacity={0.5} src={cardIcon} height={"14px"} />
                   <Spacer inline x={1} />
                   <Text color="helper">
                     **** **** **** {paymentMethod.last4}
@@ -199,10 +221,10 @@ function BillingPage(): JSX.Element {
               <Spacer inline x={1} />
               <Text size={20}>
                 {creditGrants !== undefined &&
-                  creditGrants.remaining_credits > 0
+                creditGrants.remaining_credits > 0
                   ? `$${formatCredits(
-                    creditGrants.remaining_credits
-                  )}/$${formatCredits(creditGrants.granted_credits)}`
+                      creditGrants.remaining_credits
+                    )}/$${formatCredits(creditGrants.granted_credits)}`
                   : "$ 0.00"}
               </Text>
             </Container>
@@ -221,14 +243,14 @@ function BillingPage(): JSX.Element {
               <div>
                 <Text>Active Plan</Text>
                 <Spacer y={0.5} />
-                <Fieldset>
+                <Fieldset row>
                   <Container row spaced>
                     <Container row>
                       <Text color="helper">{plan.plan_name}</Text>
                     </Container>
                     <Container row>
                       {plan.trial_info !== undefined &&
-                        plan.trial_info.ending_before !== "" ? (
+                      plan.trial_info.ending_before !== "" ? (
                         <Text>
                           Free trial ends{" "}
                           {relativeTime(plan.trial_info.ending_before)}
@@ -245,20 +267,39 @@ function BillingPage(): JSX.Element {
                 <Text color="helper">
                   View the current usage of this billing period.
                 </Text>
-                <Spacer y={1} />{" "}
-                <Container row style={{ width: "100%", height: "80vh" }}>
-                  <ParentSize>
-                    {({ width, height }) => (
-                      <iframe
-                        width={width}
-                        height={height}
-                        src={usageDashboard}
-                        scrolling="no"
-                        frameBorder={0}
-                      ></iframe>
-                    )}
-                  </ParentSize>
-                </Container>
+                <Spacer y={1} />
+                {usage?.length &&
+                usage.length > 0 &&
+                usage[0].usage_metrics.length > 0 ? (
+                  <Flex>
+                    <BarWrapper>
+                      <Bars
+                        title="GiB Hours"
+                        fill="#8784D2"
+                        yKey="gib_hours"
+                        xKey="starting_on"
+                        data={processedData}
+                      />
+                    </BarWrapper>
+                    <Spacer x={1} inline />
+                    <BarWrapper>
+                      <Bars
+                        title="CPU Hours"
+                        fill="#5886E0"
+                        yKey="cpu_hours"
+                        xKey="starting_on"
+                        data={processedData}
+                      />
+                    </BarWrapper>
+                  </Flex>
+                ) : (
+                  <Fieldset>
+                    <Text color="helper">
+                      No usage data available for this billing period.
+                    </Text>
+                  </Fieldset>
+                )}
+                <Spacer y={2} />
               </div>
             ) : (
               <Text>This project does not have an active billing plan.</Text>
@@ -274,6 +315,17 @@ function BillingPage(): JSX.Element {
 
 export default BillingPage;
 
+const Flex = styled.div`
+  display: flex;
+  flex-wrap: wrap;
+`;
+
+const BarWrapper = styled.div`
+  flex: 1;
+  height: 300px;
+  min-width: 450px;
+`;
+
 const I = styled.i`
   font-size: 18px;
   margin-right: 10px;