feat(chart): use tremor chart for showing log frequency Tried using D3 and while I might have been able to make charts exactly the way it would have taken too much time, so chose to go with a simple looking charts library
Brijesh ops@brijesh.dev
Wed, 03 Jul 2024 19:38:37 +0530
6 files changed,
305 insertions(+),
12 deletions(-)
M
client/package.json
→
client/package.json
@@ -9,18 +9,24 @@ "start": "next start",
"lint": "next lint" }, "dependencies": { + "@headlessui/react": "^2.1.1", + "@headlessui/tailwindcss": "^0.2.1", + "@remixicon/react": "^4.2.0", + "@tremor/react": "^3.17.4", + "next": "14.2.4", "react": "^18", "react-dom": "^18", - "next": "14.2.4" + "recharts": "^2.12.7" }, "devDependencies": { - "typescript": "^5", + "@tailwindcss/forms": "^0.5.7", "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", + "eslint": "^8", + "eslint-config-next": "14.2.4", "postcss": "^8", "tailwindcss": "^3.4.1", - "eslint": "^8", - "eslint-config-next": "14.2.4" + "typescript": "^5" } }
A
client/src/components/visualisation/Bar-Chart.tsx
@@ -0,0 +1,124 @@
+import { BarChart, Card, Divider, Switch } from "@tremor/react"; +import { useState } from "react"; + +function valueFormatter(number: any) { + return new Intl.NumberFormat("en-US", { + maximumFractionDigits: 0, + notation: "compact", + compactDisplay: "short", + style: "currency", + currency: "INR", + }).format(number); +} + +export default function BarChartExample() { + const [showComparison, setShowComparison] = useState(false); + return ( + <> + {/* <Card className="ax-w-2xl"> */} + <BarChart + data={data} + index="date" + categories={["value"]} + colors={["slate"]} + valueFormatter={valueFormatter} + showYAxis={false} + className="my-4 h-40" + showLegend={false} + showGridLines={false} + showAnimation={true} + animationDuration={100} + tickGap={30} + barCategoryGap={3} + /> + {/* </Card> */} + </> + ); +} + +const data = [ + { date: "May 23", value: 56000 }, + { date: "Jun 23", value: 30000 }, + { date: "Jul 23", value: 85390 }, + { date: "Aug 23", value: 80100 }, + { date: "Sep 23", value: 75090 }, + { date: "Oct 23", value: 71080 }, + { date: "Nov 23", value: 61210 }, + { date: "Dec 23", value: 60143 }, + { date: "Jan 24", value: 10000 }, + { date: "Feb 24", value: 10000 }, + { date: "Mar 24", value: 10000 }, + { date: "Apr 24", value: 10000 }, + { date: "May 24", value: 10000 }, + { date: "Jun 24", value: 10000 }, + { date: "Jul 24", value: 10000 }, + { date: "Aug 24", value: 10000 }, + { date: "Sep 24", value: 10000 }, + { date: "Oct 24", value: 10000 }, + { date: "Nov 24", value: 10000 }, + { date: "Dec 24", value: 10000 }, + { date: "Jan 25", value: 10000 }, + { date: "Feb 25", value: 10000 }, + { date: "Mar 25", value: 10000 }, + { date: "Apr 25", value: 10000 }, + { date: "May 25", value: 10000 }, + { date: "Jun 25", value: 10000 }, + { date: "Jul 25", value: 10000 }, + { date: "Aug 25", value: 10000 }, + { date: "Sep 25", value: 10000 }, + { date: "Oct 25", value: 10000 }, + { date: "Nov 25", value: 10000 }, + { date: "Dec 25", value: 10000 }, + { date: "Jan 26", value: 10000 }, + { date: "Feb 26", value: 10000 }, + { date: "Mar 26", value: 10000 }, + { date: "Apr 26", value: 10000 }, + { date: "May 26", value: 10000 }, + { date: "Jun 26", value: 10000 }, + { date: "Jul 26", value: 10000 }, + { date: "Aug 26", value: 10000 }, + { date: "Sep 26", value: 10000 }, + { date: "Oct 26", value: 10000 }, + { date: "Nov 26", value: 10000 }, + { date: "Dec 26", value: 10000 }, + { date: "Jan 27", value: 10000 }, + { date: "Feb 27", value: 10000 }, + { date: "Mar 27", value: 10000 }, + { date: "Apr 27", value: 10000 }, + { date: "May 27", value: 10000 }, + { date: "Jun 27", value: 10000 }, + { date: "Jul 27", value: 43523 }, + { date: "Aug 27", value: 10000 }, + { date: "Sep 27", value: 10000 }, + { date: "Oct 27", value: 10000 }, + { date: "Nov 27", value: 10000 }, + { date: "Dec 27", value: 10000 }, + { date: "Jan 28", value: 10000 }, + { date: "Feb 28", value: 10000 }, + { date: "Mar 28", value: 10000 }, + { date: "Apr 28", value: 10000 }, + { date: "May 28", value: 10000 }, + { date: "Jun 28", value: 10000 }, + { date: "Jul 28", value: 10000 }, + { date: "Aug 28", value: 10000 }, + { date: "Sep 28", value: 10000 }, + { date: "Oct 28", value: 10000 }, + { date: "Nov 28", value: 10000 }, + { date: "Dec 28", value: 10000 }, + { date: "Jan 29", value: 10000 }, + { date: "Feb 29", value: 10000 }, + { date: "Mar 29", value: 10000 }, + { date: "Apr 29", value: 10000 }, + { date: "May 29", value: 10000 }, + { date: "Jun 29", value: 10000 }, + { date: "Jul 29", value: 10000 }, + { date: "Aug 29", value: 10000 }, + { date: "Sep 29", value: 10000 }, + { date: "Oct 29", value: 10000 }, + { date: "Nov 29", value: 10000 }, + { date: "Dec 29", value: 10000 }, + { date: "Jan 30", value: 10000 }, + { date: "Feb 30", value: 10000 }, + { date: "Mar 30", value: 10000 }, + { date: "Apr 30", value: 10000 }, +];
M
client/src/pages/index.tsx
→
client/src/pages/index.tsx
@@ -1,4 +1,6 @@
import MainLayout from "@/components/MainLayout"; +import BarChartExample from "@/components/visualisation/Bar-Chart"; +import { BarChart } from "@tremor/react"; import Head from "next/head"; import Link from "next/link";@@ -16,6 +18,7 @@ <h1 className="text-xl font-medium">Homepage</h1>
<p className="my-2"> Please check this page later, as it is still under construction. </p> + <BarChartExample /> </MainLayout> ); };
A
client/src/pages/logs/index.tsx
@@ -0,0 +1,23 @@
+import MainLayout from "@/components/MainLayout"; +import Head from "next/head"; +import Link from "next/link"; + +const LogsIndexPage = () => { + return ( + <MainLayout> + <Head> + <title>Watchman</title> + <Link + rel="icon" + href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🎯</text></svg>" + /> + </Head> + <h1 className="text-xl font-medium">Logs Index Page</h1> + <p className="my-2"> + Please check this page later, as it is still under construction. + </p> + </MainLayout> + ); +}; + +export default LogsIndexPage;
M
client/tailwind.config.ts
→
client/tailwind.config.ts
@@ -1,20 +1,157 @@
+// import type { Config } from "tailwindcss"; +// +// const config: Config = { +// content: [ +// "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", +// "./src/components/**/*.{js,ts,jsx,tsx,mdx}", +// "./src/app/**/*.{js,ts,jsx,tsx,mdx}", +// ], +// theme: { +// extend: { +// backgroundImage: { +// "gradient-radial": "radial-gradient(var(--tw-gradient-stops))", +// "gradient-conic": +// "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))", +// }, +// }, +// }, +// plugins: [], +// }; +// export default config; + import type { Config } from "tailwindcss"; +import colors from "tailwindcss/colors"; const config: Config = { content: [ - "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", - "./src/components/**/*.{js,ts,jsx,tsx,mdx}", - "./src/app/**/*.{js,ts,jsx,tsx,mdx}", + "./src/**/*.{js,ts,jsx,tsx}", + + // Path to Tremor module + "./node_modules/@tremor/**/*.{js,ts,jsx,tsx}", ], theme: { + transparent: "transparent", + current: "currentColor", extend: { - backgroundImage: { - "gradient-radial": "radial-gradient(var(--tw-gradient-stops))", - "gradient-conic": - "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))", + colors: { + // light mode + tremor: { + brand: { + faint: colors.blue[50], + muted: colors.blue[200], + subtle: colors.blue[400], + DEFAULT: colors.blue[500], + emphasis: colors.blue[700], + inverted: colors.white, + }, + background: { + muted: colors.gray[50], + subtle: colors.gray[100], + DEFAULT: colors.white, + emphasis: colors.gray[700], + }, + border: { + DEFAULT: colors.gray[200], + }, + ring: { + DEFAULT: colors.gray[200], + }, + content: { + subtle: colors.gray[400], + DEFAULT: colors.gray[500], + emphasis: colors.gray[700], + strong: colors.gray[900], + inverted: colors.white, + }, + }, + // dark mode + // "dark-tremor": { + // brand: { + // faint: "#0B1229", + // muted: colors.blue[950], + // subtle: colors.blue[800], + // DEFAULT: colors.blue[500], + // emphasis: colors.blue[400], + // inverted: colors.blue[950], + // }, + // background: { + // muted: "#131A2B", + // subtle: colors.gray[800], + // DEFAULT: colors.gray[900], + // emphasis: colors.gray[300], + // }, + // border: { + // DEFAULT: colors.gray[800], + // }, + // ring: { + // DEFAULT: colors.gray[800], + // }, + // content: { + // subtle: colors.gray[600], + // DEFAULT: colors.gray[500], + // emphasis: colors.gray[200], + // strong: colors.gray[50], + // inverted: colors.gray[950], + // }, + // }, + }, + boxShadow: { + // light + "tremor-input": "0 1px 2px 0 rgb(0 0 0 / 0.05)", + "tremor-card": + "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)", + "tremor-dropdown": + "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)", + // dark + // "dark-tremor-input": "0 1px 2px 0 rgb(0 0 0 / 0.05)", + // "dark-tremor-card": + // "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)", + // "dark-tremor-dropdown": + // "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)", + }, + borderRadius: { + "tremor-small": "0.375rem", + "tremor-default": "0.2rem", + "tremor-full": "9999px", + }, + fontSize: { + "tremor-label": ["0.75rem", { lineHeight: "1rem" }], + "tremor-default": ["0.875rem", { lineHeight: "1.25rem" }], + "tremor-title": ["1.125rem", { lineHeight: "1.75rem" }], + "tremor-metric": ["1.875rem", { lineHeight: "2.25rem" }], }, }, }, - plugins: [], + safelist: [ + { + pattern: + /^(bg-(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-(?:50|100|200|300|400|500|600|700|800|900|950))$/, + variants: ["hover", "ui-selected"], + }, + { + pattern: + /^(text-(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-(?:50|100|200|300|400|500|600|700|800|900|950))$/, + variants: ["hover", "ui-selected"], + }, + { + pattern: + /^(border-(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-(?:50|100|200|300|400|500|600|700|800|900|950))$/, + variants: ["hover", "ui-selected"], + }, + { + pattern: + /^(ring-(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-(?:50|100|200|300|400|500|600|700|800|900|950))$/, + }, + { + pattern: + /^(stroke-(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-(?:50|100|200|300|400|500|600|700|800|900|950))$/, + }, + { + pattern: + /^(fill-(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-(?:50|100|200|300|400|500|600|700|800|900|950))$/, + }, + ], + plugins: [require("@headlessui/tailwindcss"), require("@tailwindcss/forms")], }; + export default config;