feat(dashboard): handle API errors and enhance translations
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
defineProps<{
|
||||
message: string;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="rounded-xl bg-red-300 p-2 font-semibold text-red-900 shadow-md">
|
||||
{{ message }}
|
||||
</div>
|
||||
</template>
|
||||
@@ -3,7 +3,7 @@ import moment from 'moment';
|
||||
|
||||
defineProps<{
|
||||
label: string;
|
||||
price: number | null | undefined;
|
||||
price: number;
|
||||
time: moment.Moment | string;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
@@ -4,6 +4,7 @@ import moment from 'moment';
|
||||
import { onMounted } from 'vue';
|
||||
import Price from '../components/Price.vue';
|
||||
import useDashboardViewModel from '../viewmodels/DashboardViewModel';
|
||||
import Error from '@/components/Error.vue';
|
||||
|
||||
const model = useDashboardViewModel();
|
||||
|
||||
@@ -16,12 +17,15 @@ onMounted(() => {
|
||||
<h1 class="mb-4 text-3xl font-black text-primary">
|
||||
{{ t('dashboard.title') }}
|
||||
</h1>
|
||||
<div class="mb-4 flex flex-col gap-2">
|
||||
<div class="mb-4 flex flex-col gap-2" v-if="model.dashboardData.value">
|
||||
<h2 class="text-2xl font-black text-primary">
|
||||
{{ t('dashboard.electricity') }}
|
||||
</h2>
|
||||
<div class="flex flex-wrap gap-4">
|
||||
<Price
|
||||
v-if="
|
||||
model.dashboardData.value?.electricity.totalPriceTaxIncluded
|
||||
"
|
||||
:label="t('dashboard.current_electricity_price')"
|
||||
:price="
|
||||
model.dashboardData.value?.electricity.totalPriceTaxIncluded
|
||||
@@ -29,6 +33,10 @@ onMounted(() => {
|
||||
:time="moment(model.dashboardData.value?.electricity.startDate)"
|
||||
/>
|
||||
<Price
|
||||
v-if="
|
||||
model.dashboardData.value?.electricityCheapest
|
||||
?.totalPriceTaxIncluded
|
||||
"
|
||||
:label="t('dashboard.cheapest_electricity_price')"
|
||||
:price="
|
||||
model.dashboardData.value?.electricityCheapest
|
||||
@@ -42,6 +50,10 @@ onMounted(() => {
|
||||
"
|
||||
/>
|
||||
<Price
|
||||
v-if="
|
||||
model.dashboardData.value?.electricityDurable
|
||||
?.totalPriceTaxIncluded
|
||||
"
|
||||
:label="t('dashboard.durable_electricity_price')"
|
||||
:price="
|
||||
model.dashboardData.value?.electricityDurable
|
||||
@@ -55,6 +67,10 @@ onMounted(() => {
|
||||
"
|
||||
/>
|
||||
<Price
|
||||
v-if="
|
||||
model.dashboardData.value?.electricityPriciest
|
||||
?.totalPriceTaxIncluded
|
||||
"
|
||||
:label="t('dashboard.priciest_electricity_price')"
|
||||
:price="
|
||||
model.dashboardData.value?.electricityPriciest
|
||||
@@ -69,12 +85,13 @@ onMounted(() => {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-4 flex flex-col gap-2">
|
||||
<div class="mb-4 flex flex-col gap-2" v-if="model.dashboardData.value">
|
||||
<h2 class="text-2xl font-black text-primary">
|
||||
{{ t('dashboard.gas') }}
|
||||
</h2>
|
||||
<div class="flex flex-wrap gap-4">
|
||||
<Price
|
||||
v-if="model.dashboardData.value?.gas.totalPriceTaxIncluded"
|
||||
:label="t('dashboard.current_gas_price')"
|
||||
:price="model.dashboardData.value?.gas.totalPriceTaxIncluded"
|
||||
:time="
|
||||
@@ -84,6 +101,10 @@ onMounted(() => {
|
||||
"
|
||||
/>
|
||||
<Price
|
||||
v-if="
|
||||
model.dashboardData.value?.gasCheapest
|
||||
?.totalPriceTaxIncluded
|
||||
"
|
||||
:label="t('dashboard.cheapest_gas_price')"
|
||||
:price="
|
||||
model.dashboardData.value?.gasCheapest
|
||||
@@ -96,6 +117,10 @@ onMounted(() => {
|
||||
"
|
||||
/>
|
||||
<Price
|
||||
v-if="
|
||||
model.dashboardData.value?.gasPriciest
|
||||
?.totalPriceTaxIncluded
|
||||
"
|
||||
:label="t('dashboard.priciest_gas_price')"
|
||||
:price="
|
||||
model.dashboardData.value?.gasPriciest
|
||||
@@ -109,4 +134,5 @@ onMounted(() => {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Error :message="model.error.value" v-if="model.error.value" />
|
||||
</template>
|
||||
|
||||
@@ -4,6 +4,7 @@ import DashboardData = App.Features.Dashboard.Data.DashboardData;
|
||||
|
||||
export default function useDashboardViewModel() {
|
||||
const isLoading = ref<boolean>(false);
|
||||
const error = ref<string>();
|
||||
const dashboardData = ref<DashboardData>();
|
||||
|
||||
function getDashboardData() {
|
||||
@@ -15,8 +16,11 @@ export default function useDashboardViewModel() {
|
||||
.then((res) => {
|
||||
dashboardData.value = res.data;
|
||||
})
|
||||
.catch((err) => {
|
||||
error.value = err.response.data.message;
|
||||
})
|
||||
.finally(() => (isLoading.value = false));
|
||||
}
|
||||
|
||||
return { isLoading, dashboardData, getDashboardData };
|
||||
return { isLoading, dashboardData, error, getDashboardData };
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ ChartJS.register(
|
||||
|
||||
export interface PricePoint {
|
||||
label: string;
|
||||
value: number;
|
||||
value: number | null;
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import nl from "./nl";
|
||||
import nl from './nl';
|
||||
|
||||
export default {
|
||||
nl
|
||||
}
|
||||
nl: { translation: nl },
|
||||
};
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
{
|
||||
"title": "Overzicht"
|
||||
"title": "Overzicht",
|
||||
"electricity": "Elektriciteit",
|
||||
"gas": "Gas",
|
||||
"current_electricity_price": "Actuele elektriciteitsprijs",
|
||||
"cheapest_electricity_price": "Goedkoopste elektriciteitsprijs",
|
||||
"durable_electricity_price": "Duurzaamste elektriciteitsprijs",
|
||||
"priciest_electricity_price": "Duurste elektriciteitsprijs",
|
||||
"current_gas_price": "Actuele gasprijs",
|
||||
"cheapest_gas_price": "Goedkoopste gasprijs",
|
||||
"priciest_gas_price": "Duurste gasprijs"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"title": "Prijshistorie"
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
import dashboard from './dashboard.json';
|
||||
import history from './history.json';
|
||||
|
||||
export default {
|
||||
dashboard,
|
||||
history,
|
||||
};
|
||||
|
||||
@@ -2,17 +2,33 @@
|
||||
import { t } from 'i18next';
|
||||
import dashboard from '@/routes/dashboard';
|
||||
import history from '@/routes/history';
|
||||
import { Link, router, usePage } from '@inertiajs/vue3';
|
||||
import { computed } from 'vue';
|
||||
|
||||
const page = usePage();
|
||||
const currentUrl = computed(() => page.url);
|
||||
|
||||
const navItems = [
|
||||
{ href: dashboard.index().url, label: 'dashboard.title' },
|
||||
{ href: history.index().url, label: 'history.title' },
|
||||
];
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<nav class="fixed top-0 bottom-0 left-0 w-64 bg-primary p-4">
|
||||
<img src="/storage/logo.svg" class="mb-4 mix-blend-plus-lighter" />
|
||||
<ul class="flex-1 gap-4">
|
||||
<li>
|
||||
<a :href="dashboard.index().url">{{ t('dashboard.title') }}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a :href="history.index().url">{{ t('history.title') }}</a>
|
||||
<ul class="flex flex-1 flex-col gap-2">
|
||||
<li v-for="item in navItems" :key="item.href">
|
||||
<Link
|
||||
:href="item.href"
|
||||
:class="
|
||||
currentUrl === item.href
|
||||
? 'block rounded-lg bg-white/10 p-2 font-semibold text-white'
|
||||
: 'block rounded-lg p-2 text-white/70 hover:bg-white/5 hover:text-white'
|
||||
"
|
||||
>
|
||||
{{ t(item.label) }}
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
Reference in New Issue
Block a user