From 9e9bcdde4fa427f5afe8fd6709c1828592ea9579 Mon Sep 17 00:00:00 2001 From: Hayden <64056131+hay-kot@users.noreply.github.com> Date: Mon, 5 Dec 2022 12:38:08 -0900 Subject: [PATCH] wip: charts.js experimental work --- frontend/components/Chart/Donut.vue | 94 ++++++++++++++++++++++++++++ frontend/components/Chart/Line.vue | 96 +++++++++++++++++++++++++++++ frontend/composables/use-css-var.ts | 38 ++++++++++++ frontend/package.json | 4 +- frontend/pages/home.vue | 77 ++++++++++++++++++++++- 5 files changed, 307 insertions(+), 2 deletions(-) create mode 100644 frontend/components/Chart/Donut.vue create mode 100644 frontend/components/Chart/Line.vue create mode 100644 frontend/composables/use-css-var.ts diff --git a/frontend/components/Chart/Donut.vue b/frontend/components/Chart/Donut.vue new file mode 100644 index 0000000..97d4113 --- /dev/null +++ b/frontend/components/Chart/Donut.vue @@ -0,0 +1,94 @@ + + + diff --git a/frontend/components/Chart/Line.vue b/frontend/components/Chart/Line.vue new file mode 100644 index 0000000..014f20c --- /dev/null +++ b/frontend/components/Chart/Line.vue @@ -0,0 +1,96 @@ + + + diff --git a/frontend/composables/use-css-var.ts b/frontend/composables/use-css-var.ts new file mode 100644 index 0000000..c92e1e9 --- /dev/null +++ b/frontend/composables/use-css-var.ts @@ -0,0 +1,38 @@ +import { ComputedRef } from "vue"; + +type ColorType = "hsla"; + +export type VarOptions = { + type: ColorType; + transparency?: number; + apply?: (value: string) => string; +}; + +export function useCssVar(name: string, options?: VarOptions): ComputedRef { + if (!options) { + options = { + type: "hsla", + transparency: 1, + apply: null, + }; + } + + switch (options.type) { + case "hsla": { + return computed(() => { + if (!document) { + return ""; + } + + let val = getComputedStyle(document.documentElement).getPropertyValue(name); + val = val.trim().split(" ").join(", "); + + if (options.transparency) { + val += `, ${options.transparency}`; + } + + return `hsla(${val})`; + }); + } + } +} diff --git a/frontend/package.json b/frontend/package.json index 973e383..93ca2a2 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -36,12 +36,14 @@ "@tailwindcss/typography": "^0.5.4", "@vueuse/nuxt": "^9.1.1", "autoprefixer": "^10.4.8", + "chart.js": "^4.0.1", "daisyui": "^2.24.0", "dompurify": "^2.4.1", "markdown-it": "^13.0.1", "pinia": "^2.0.21", "postcss": "^8.4.16", "tailwindcss": "^3.1.8", - "vue": "^3.2.38" + "vue": "^3.2.38", + "vue-chartjs": "^4.1.2" } } \ No newline at end of file diff --git a/frontend/pages/home.vue b/frontend/pages/home.vue index e8a52e7..ea93771 100644 --- a/frontend/pages/home.vue +++ b/frontend/pages/home.vue @@ -6,7 +6,6 @@ definePageMeta({ middleware: ["auth"], }); - useHead({ title: "Homebox | Home", }); @@ -87,6 +86,63 @@ eventBus.emit(EventTypes.ClearStores); } + + const { data: timeseries } = useAsyncData(async () => { + const { data } = await api.stats.totalPriceOverTime(); + return data; + }); + + const primary = useCssVar("--p"); + const secondary = useCssVar("--s"); + const accent = useCssVar("--a"); + const neutral = useCssVar("--n"); + const base = useCssVar("--b"); + + const chartData = computed(() => { + let start = timeseries.value?.valueAtStart; + + return { + labels: timeseries?.value.entries.map(t => new Date(t.date).toDateString()) || [], + datasets: [ + { + label: "Purchase Price", + data: + timeseries.value?.entries.map(t => { + start += t.value; + return start; + }) || [], + backgroundColor: primary.value, + borderColor: primary.value, + }, + ], + }; + }); + + const { data: donutSeries } = useAsyncData(async () => { + const { data } = await api.stats.locations(); + return data; + }); + + const donutData = computed(() => { + return { + labels: donutSeries.value?.map(l => l.name) || [], + datasets: [ + { + label: "Value", + data: donutSeries.value?.map(l => l.total) || [], + backgroundColor: [primary.value, secondary.value, neutral.value], + borderColor: [primary.value, secondary.value, neutral.value], + hoverOffset: 4, + }, + ], + }; + }); + + const refDonutEl = ref(null); + + const donutElWidth = computed(() => { + return refDonutEl.value?.clientWidth || 0; + });