refactor(dashboard,history): replace ViewModels with Pinia stores and improve backend

This commit is contained in:
2026-08-05 09:23:18 +02:00
parent a0387126de
commit 90930cd223
29 changed files with 1372 additions and 237 deletions
@@ -29,6 +29,7 @@ export interface PricePoint {
const props = defineProps<{
data: PricePoint[];
color?: string;
}>();
const chartData = computed(() => ({
@@ -36,8 +37,10 @@ const chartData = computed(() => ({
datasets: [
{
data: props.data.map((d) => d.value),
borderColor: '#4ba66a',
backgroundColor: 'rgba(75, 166, 106, 0.1)',
borderColor: props.color || '#4ba66a',
backgroundColor: props.color
? `${props.color}1a`
: 'rgba(75, 166, 106, 0.1)',
fill: true,
tension: 0.4,
pointRadius: 2,
+86 -15
View File
@@ -1,37 +1,108 @@
<script setup lang="ts">
import { computed, onMounted, ref, watch } from 'vue';
import useHistoryViewModel from '../viewmodels/HistoryViewModel';
import { computed, onMounted, watch } from 'vue';
import moment from 'moment';
import { useHistoryStore } from '@/stores/history';
import Chart from '../components/Chart.vue';
import Loading from '@/components/Loading.vue';
import Error from '@/components/Error.vue';
import { t } from 'i18next';
const model = useHistoryViewModel();
const date = ref<Date>();
const store = useHistoryStore();
onMounted(() => {
model.getHistoryData(moment().format('YYYY-MM-DD'));
store.fetchHistoryData(moment().format('YYYY-MM-DD'));
});
watch(date, (value) => {
model.getHistoryData(moment(value).format('YYYY-MM-DD'));
});
watch(
() => store.selectedDate,
(value) => {
if (value) {
store.fetchHistoryData(value);
}
},
);
const chartData = computed(
const electricityChartData = computed(
() =>
model.historyData.value?.electricity
store.historyData?.electricity
.filter((e) => e.totalPriceTaxIncluded != null)
.map((e) => ({
label: moment(e.startDate).format('HH:mm'),
value: e.totalPriceTaxIncluded,
})) ?? [],
);
const gasChartData = computed(
() =>
store.historyData?.gas
.filter((g) => g.totalPriceTaxIncluded != null)
.map((g) => ({
label: moment(g.startDate).format('DD-MM-YYYY'),
value: g.totalPriceTaxIncluded,
})) ?? [],
);
</script>
<template>
<input type="date" v-model="date" />
<Loading v-if="model.isLoading.value" />
<Chart :data="chartData" v-if="chartData" />
<Error v-if="model.error.value" :message="model.error.value" />
<h1 class="mb-4 text-3xl font-black text-primary">
{{ t('history.title') }}
</h1>
<div class="mb-6">
<label
for="date-select"
class="mb-2 block text-sm font-medium text-gray-700"
>
{{ t('history.select_date') }}
</label>
<input
id="date-select"
type="date"
:value="store.selectedDate"
@input="
store.selectedDate = ($event.target as HTMLInputElement).value
"
class="rounded-lg border border-gray-300 bg-white px-4 py-2 text-sm shadow-sm focus:border-primary focus:ring-1 focus:ring-primary focus:outline-none"
/>
</div>
<Loading v-if="store.isLoading" />
<template v-else-if="store.historyData">
<div class="mb-6">
<h2 class="mb-2 text-xl font-bold text-primary">
{{ t('history.electricity_prices') }}
</h2>
<Chart
v-if="electricityChartData.length > 0"
:data="electricityChartData"
/>
<div
v-else
class="rounded-xl bg-gray-100 p-8 text-center text-gray-500"
>
{{ t('history.no_electricity_data') }}
</div>
</div>
<div>
<h2 class="mb-2 text-xl font-bold text-primary">
{{ t('history.gas_prices') }}
</h2>
<Chart
v-if="gasChartData.length > 0"
:data="gasChartData"
color="#3b82f6"
/>
<div
v-else
class="rounded-xl bg-gray-100 p-8 text-center text-gray-500"
>
{{ t('history.no_gas_data') }}
</div>
</div>
</template>
<div
v-else-if="!store.isLoading && !store.historyData"
class="rounded-xl bg-gray-100 p-8 text-center text-gray-500"
>
{{ t('history.no_data') }}
</div>
<Error v-if="store.error" :message="store.error" />
</template>
@@ -1,30 +0,0 @@
import { create } from 'axios';
import { ref } from 'vue';
import HistoryData = App.Features.History.Data.HistoryData;
export default function useHistoryViewModel() {
const isLoading = ref<boolean>(false);
const error = ref<string>();
const historyData = ref<HistoryData>();
function getHistoryData(date: string) {
isLoading.value = true;
const client = create();
client
.get<HistoryData>('/api/history', {
params: {
date,
},
})
.then((res) => {
historyData.value = res.data;
})
.catch((err) => {
error.value = err.response.data.message;
})
.finally(() => (isLoading.value = false));
}
return { isLoading, historyData, error, getHistoryData };
}