feat(dashboard): handle API errors and enhance translations
This commit is contained in:
@@ -72,7 +72,7 @@ class ZonneplanPriceClient implements PriceClient
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
throw new Exception(
|
throw new Exception(
|
||||||
"Kon energieprijzen niet ophalen voor {$path}",
|
__('errors.client_error'),
|
||||||
previous: $e,
|
previous: $e,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Authentication Language Lines
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The following language lines are used during authentication for various
|
||||||
|
| messages that we need to display to the user. You are free to modify
|
||||||
|
| these language lines according to your application's requirements.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'failed' => 'These credentials do not match our records.',
|
||||||
|
'password' => 'The provided password is incorrect.',
|
||||||
|
'throttle' => 'Too many login attempts. Please try again in :seconds seconds.',
|
||||||
|
|
||||||
|
];
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Pagination Language Lines
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The following language lines are used by the paginator library to build
|
||||||
|
| the simple pagination links. You are free to change them to anything
|
||||||
|
| you want to customize your views to better match your application.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'previous' => '« Previous',
|
||||||
|
'next' => 'Next »',
|
||||||
|
|
||||||
|
];
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Password Reset Language Lines
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The following language lines are the default lines which match reasons
|
||||||
|
| that are given by the password broker for a password update attempt
|
||||||
|
| outcome such as failure due to an invalid password / reset token.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'reset' => 'Your password has been reset.',
|
||||||
|
'sent' => 'We have emailed your password reset link.',
|
||||||
|
'throttled' => 'Please wait before retrying.',
|
||||||
|
'token' => 'This password reset token is invalid.',
|
||||||
|
'user' => "We can't find a user with that email address.",
|
||||||
|
|
||||||
|
];
|
||||||
@@ -0,0 +1,201 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Validation Language Lines
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The following language lines contain the default error messages used by
|
||||||
|
| the validator class. Some of these rules have multiple versions such
|
||||||
|
| as the size rules. Feel free to tweak each of these messages here.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'accepted' => 'The :attribute field must be accepted.',
|
||||||
|
'accepted_if' => 'The :attribute field must be accepted when :other is :value.',
|
||||||
|
'active_url' => 'The :attribute field must be a valid URL.',
|
||||||
|
'after' => 'The :attribute field must be a date after :date.',
|
||||||
|
'after_or_equal' => 'The :attribute field must be a date after or equal to :date.',
|
||||||
|
'alpha' => 'The :attribute field must only contain letters.',
|
||||||
|
'alpha_dash' => 'The :attribute field must only contain letters, numbers, dashes, and underscores.',
|
||||||
|
'alpha_num' => 'The :attribute field must only contain letters and numbers.',
|
||||||
|
'any_of' => 'The :attribute field is invalid.',
|
||||||
|
'array' => 'The :attribute field must be an array.',
|
||||||
|
'ascii' => 'The :attribute field must only contain single-byte alphanumeric characters and symbols.',
|
||||||
|
'base64' => 'The :attribute field must be a valid Base64 string.',
|
||||||
|
'before' => 'The :attribute field must be a date before :date.',
|
||||||
|
'before_or_equal' => 'The :attribute field must be a date before or equal to :date.',
|
||||||
|
'between' => [
|
||||||
|
'array' => 'The :attribute field must have between :min and :max items.',
|
||||||
|
'file' => 'The :attribute field must be between :min and :max kilobytes.',
|
||||||
|
'numeric' => 'The :attribute field must be between :min and :max.',
|
||||||
|
'string' => 'The :attribute field must be between :min and :max characters.',
|
||||||
|
],
|
||||||
|
'boolean' => 'The :attribute field must be true or false.',
|
||||||
|
'can' => 'The :attribute field contains an unauthorized value.',
|
||||||
|
'confirmed' => 'The :attribute field confirmation does not match.',
|
||||||
|
'contains' => 'The :attribute field is missing a required value.',
|
||||||
|
'current_password' => 'The password is incorrect.',
|
||||||
|
'date' => 'The :attribute field must be a valid date.',
|
||||||
|
'date_equals' => 'The :attribute field must be a date equal to :date.',
|
||||||
|
'date_format' => 'The :attribute field must match the format :format.',
|
||||||
|
'decimal' => 'The :attribute field must have :decimal decimal places.',
|
||||||
|
'declined' => 'The :attribute field must be declined.',
|
||||||
|
'declined_if' => 'The :attribute field must be declined when :other is :value.',
|
||||||
|
'different' => 'The :attribute field and :other must be different.',
|
||||||
|
'digits' => 'The :attribute field must be :digits digits.',
|
||||||
|
'digits_between' => 'The :attribute field must be between :min and :max digits.',
|
||||||
|
'dimensions' => 'The :attribute field has invalid image dimensions.',
|
||||||
|
'distinct' => 'The :attribute field has a duplicate value.',
|
||||||
|
'doesnt_contain' => 'The :attribute field must not contain any of the following: :values.',
|
||||||
|
'doesnt_end_with' => 'The :attribute field must not end with one of the following: :values.',
|
||||||
|
'doesnt_start_with' => 'The :attribute field must not start with one of the following: :values.',
|
||||||
|
'email' => 'The :attribute field must be a valid email address.',
|
||||||
|
'encoding' => 'The :attribute field must be encoded in :encoding.',
|
||||||
|
'ends_with' => 'The :attribute field must end with one of the following: :values.',
|
||||||
|
'enum' => 'The selected :attribute is invalid.',
|
||||||
|
'exists' => 'The selected :attribute is invalid.',
|
||||||
|
'extensions' => 'The :attribute field must have one of the following extensions: :values.',
|
||||||
|
'file' => 'The :attribute field must be a file.',
|
||||||
|
'filled' => 'The :attribute field must have a value.',
|
||||||
|
'gt' => [
|
||||||
|
'array' => 'The :attribute field must have more than :value items.',
|
||||||
|
'file' => 'The :attribute field must be greater than :value kilobytes.',
|
||||||
|
'numeric' => 'The :attribute field must be greater than :value.',
|
||||||
|
'string' => 'The :attribute field must be greater than :value characters.',
|
||||||
|
],
|
||||||
|
'gte' => [
|
||||||
|
'array' => 'The :attribute field must have :value items or more.',
|
||||||
|
'file' => 'The :attribute field must be greater than or equal to :value kilobytes.',
|
||||||
|
'numeric' => 'The :attribute field must be greater than or equal to :value.',
|
||||||
|
'string' => 'The :attribute field must be greater than or equal to :value characters.',
|
||||||
|
],
|
||||||
|
'hex_color' => 'The :attribute field must be a valid hexadecimal color.',
|
||||||
|
'image' => 'The :attribute field must be an image.',
|
||||||
|
'in' => 'The selected :attribute is invalid.',
|
||||||
|
'in_array' => 'The :attribute field must exist in :other.',
|
||||||
|
'in_array_keys' => 'The :attribute field must contain at least one of the following keys: :values.',
|
||||||
|
'integer' => 'The :attribute field must be an integer.',
|
||||||
|
'ip' => 'The :attribute field must be a valid IP address.',
|
||||||
|
'ipv4' => 'The :attribute field must be a valid IPv4 address.',
|
||||||
|
'ipv6' => 'The :attribute field must be a valid IPv6 address.',
|
||||||
|
'json' => 'The :attribute field must be a valid JSON string.',
|
||||||
|
'list' => 'The :attribute field must be a list.',
|
||||||
|
'lowercase' => 'The :attribute field must be lowercase.',
|
||||||
|
'lt' => [
|
||||||
|
'array' => 'The :attribute field must have less than :value items.',
|
||||||
|
'file' => 'The :attribute field must be less than :value kilobytes.',
|
||||||
|
'numeric' => 'The :attribute field must be less than :value.',
|
||||||
|
'string' => 'The :attribute field must be less than :value characters.',
|
||||||
|
],
|
||||||
|
'lte' => [
|
||||||
|
'array' => 'The :attribute field must not have more than :value items.',
|
||||||
|
'file' => 'The :attribute field must be less than or equal to :value kilobytes.',
|
||||||
|
'numeric' => 'The :attribute field must be less than or equal to :value.',
|
||||||
|
'string' => 'The :attribute field must be less than or equal to :value characters.',
|
||||||
|
],
|
||||||
|
'mac_address' => 'The :attribute field must be a valid MAC address.',
|
||||||
|
'max' => [
|
||||||
|
'array' => 'The :attribute field must not have more than :max items.',
|
||||||
|
'file' => 'The :attribute field must not be greater than :max kilobytes.',
|
||||||
|
'numeric' => 'The :attribute field must not be greater than :max.',
|
||||||
|
'string' => 'The :attribute field must not be greater than :max characters.',
|
||||||
|
],
|
||||||
|
'max_digits' => 'The :attribute field must not have more than :max digits.',
|
||||||
|
'mimes' => 'The :attribute field must be a file of type: :values.',
|
||||||
|
'mimetypes' => 'The :attribute field must be a file of type: :values.',
|
||||||
|
'min' => [
|
||||||
|
'array' => 'The :attribute field must have at least :min items.',
|
||||||
|
'file' => 'The :attribute field must be at least :min kilobytes.',
|
||||||
|
'numeric' => 'The :attribute field must be at least :min.',
|
||||||
|
'string' => 'The :attribute field must be at least :min characters.',
|
||||||
|
],
|
||||||
|
'min_digits' => 'The :attribute field must have at least :min digits.',
|
||||||
|
'missing' => 'The :attribute field must be missing.',
|
||||||
|
'missing_if' => 'The :attribute field must be missing when :other is :value.',
|
||||||
|
'missing_unless' => 'The :attribute field must be missing unless :other is :value.',
|
||||||
|
'missing_with' => 'The :attribute field must be missing when :values is present.',
|
||||||
|
'missing_with_all' => 'The :attribute field must be missing when :values are present.',
|
||||||
|
'multiple_of' => 'The :attribute field must be a multiple of :value.',
|
||||||
|
'not_in' => 'The selected :attribute is invalid.',
|
||||||
|
'not_regex' => 'The :attribute field format is invalid.',
|
||||||
|
'numeric' => 'The :attribute field must be a number.',
|
||||||
|
'password' => [
|
||||||
|
'letters' => 'The :attribute field must contain at least one letter.',
|
||||||
|
'mixed' => 'The :attribute field must contain at least one uppercase and one lowercase letter.',
|
||||||
|
'numbers' => 'The :attribute field must contain at least one number.',
|
||||||
|
'symbols' => 'The :attribute field must contain at least one symbol.',
|
||||||
|
'uncompromised' => 'The given :attribute has appeared in a data leak. Please choose a different :attribute.',
|
||||||
|
],
|
||||||
|
'present' => 'The :attribute field must be present.',
|
||||||
|
'present_if' => 'The :attribute field must be present when :other is :value.',
|
||||||
|
'present_unless' => 'The :attribute field must be present unless :other is :value.',
|
||||||
|
'present_with' => 'The :attribute field must be present when :values is present.',
|
||||||
|
'present_with_all' => 'The :attribute field must be present when :values are present.',
|
||||||
|
'prohibited' => 'The :attribute field is prohibited.',
|
||||||
|
'prohibited_if' => 'The :attribute field is prohibited when :other is :value.',
|
||||||
|
'prohibited_if_accepted' => 'The :attribute field is prohibited when :other is accepted.',
|
||||||
|
'prohibited_if_declined' => 'The :attribute field is prohibited when :other is declined.',
|
||||||
|
'prohibited_unless' => 'The :attribute field is prohibited unless :other is in :values.',
|
||||||
|
'prohibits' => 'The :attribute field prohibits :other from being present.',
|
||||||
|
'regex' => 'The :attribute field format is invalid.',
|
||||||
|
'required' => 'The :attribute field is required.',
|
||||||
|
'required_array_keys' => 'The :attribute field must contain entries for: :values.',
|
||||||
|
'required_if' => 'The :attribute field is required when :other is :value.',
|
||||||
|
'required_if_accepted' => 'The :attribute field is required when :other is accepted.',
|
||||||
|
'required_if_declined' => 'The :attribute field is required when :other is declined.',
|
||||||
|
'required_unless' => 'The :attribute field is required unless :other is in :values.',
|
||||||
|
'required_with' => 'The :attribute field is required when :values is present.',
|
||||||
|
'required_with_all' => 'The :attribute field is required when :values are present.',
|
||||||
|
'required_without' => 'The :attribute field is required when :values is not present.',
|
||||||
|
'required_without_all' => 'The :attribute field is required when none of :values are present.',
|
||||||
|
'same' => 'The :attribute field must match :other.',
|
||||||
|
'size' => [
|
||||||
|
'array' => 'The :attribute field must contain :size items.',
|
||||||
|
'file' => 'The :attribute field must be :size kilobytes.',
|
||||||
|
'numeric' => 'The :attribute field must be :size.',
|
||||||
|
'string' => 'The :attribute field must be :size characters.',
|
||||||
|
],
|
||||||
|
'starts_with' => 'The :attribute field must start with one of the following: :values.',
|
||||||
|
'string' => 'The :attribute field must be a string.',
|
||||||
|
'timezone' => 'The :attribute field must be a valid timezone.',
|
||||||
|
'unique' => 'The :attribute has already been taken.',
|
||||||
|
'uploaded' => 'The :attribute failed to upload.',
|
||||||
|
'uppercase' => 'The :attribute field must be uppercase.',
|
||||||
|
'url' => 'The :attribute field must be a valid URL.',
|
||||||
|
'ulid' => 'The :attribute field must be a valid ULID.',
|
||||||
|
'uuid' => 'The :attribute field must be a valid UUID.',
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Custom Validation Language Lines
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here you may specify custom validation messages for attributes using the
|
||||||
|
| convention "attribute.rule" to name the lines. This makes it quick to
|
||||||
|
| specify a specific custom language line for a given attribute rule.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'custom' => [
|
||||||
|
'attribute-name' => [
|
||||||
|
'rule-name' => 'custom-message',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Custom Validation Attributes
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The following language lines are used to swap our attribute placeholder
|
||||||
|
| with something more reader friendly such as "E-Mail Address" instead
|
||||||
|
| of "email". This simply helps us make our message more expressive.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'attributes' => [],
|
||||||
|
|
||||||
|
];
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'client_error' => 'Kon energieprijzen niet ophalen'
|
||||||
|
];
|
||||||
@@ -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<{
|
defineProps<{
|
||||||
label: string;
|
label: string;
|
||||||
price: number | null | undefined;
|
price: number;
|
||||||
time: moment.Moment | string;
|
time: moment.Moment | string;
|
||||||
}>();
|
}>();
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import moment from 'moment';
|
|||||||
import { onMounted } from 'vue';
|
import { onMounted } from 'vue';
|
||||||
import Price from '../components/Price.vue';
|
import Price from '../components/Price.vue';
|
||||||
import useDashboardViewModel from '../viewmodels/DashboardViewModel';
|
import useDashboardViewModel from '../viewmodels/DashboardViewModel';
|
||||||
|
import Error from '@/components/Error.vue';
|
||||||
|
|
||||||
const model = useDashboardViewModel();
|
const model = useDashboardViewModel();
|
||||||
|
|
||||||
@@ -16,12 +17,15 @@ onMounted(() => {
|
|||||||
<h1 class="mb-4 text-3xl font-black text-primary">
|
<h1 class="mb-4 text-3xl font-black text-primary">
|
||||||
{{ t('dashboard.title') }}
|
{{ t('dashboard.title') }}
|
||||||
</h1>
|
</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">
|
<h2 class="text-2xl font-black text-primary">
|
||||||
{{ t('dashboard.electricity') }}
|
{{ t('dashboard.electricity') }}
|
||||||
</h2>
|
</h2>
|
||||||
<div class="flex flex-wrap gap-4">
|
<div class="flex flex-wrap gap-4">
|
||||||
<Price
|
<Price
|
||||||
|
v-if="
|
||||||
|
model.dashboardData.value?.electricity.totalPriceTaxIncluded
|
||||||
|
"
|
||||||
:label="t('dashboard.current_electricity_price')"
|
:label="t('dashboard.current_electricity_price')"
|
||||||
:price="
|
:price="
|
||||||
model.dashboardData.value?.electricity.totalPriceTaxIncluded
|
model.dashboardData.value?.electricity.totalPriceTaxIncluded
|
||||||
@@ -29,6 +33,10 @@ onMounted(() => {
|
|||||||
:time="moment(model.dashboardData.value?.electricity.startDate)"
|
:time="moment(model.dashboardData.value?.electricity.startDate)"
|
||||||
/>
|
/>
|
||||||
<Price
|
<Price
|
||||||
|
v-if="
|
||||||
|
model.dashboardData.value?.electricityCheapest
|
||||||
|
?.totalPriceTaxIncluded
|
||||||
|
"
|
||||||
:label="t('dashboard.cheapest_electricity_price')"
|
:label="t('dashboard.cheapest_electricity_price')"
|
||||||
:price="
|
:price="
|
||||||
model.dashboardData.value?.electricityCheapest
|
model.dashboardData.value?.electricityCheapest
|
||||||
@@ -42,6 +50,10 @@ onMounted(() => {
|
|||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
<Price
|
<Price
|
||||||
|
v-if="
|
||||||
|
model.dashboardData.value?.electricityDurable
|
||||||
|
?.totalPriceTaxIncluded
|
||||||
|
"
|
||||||
:label="t('dashboard.durable_electricity_price')"
|
:label="t('dashboard.durable_electricity_price')"
|
||||||
:price="
|
:price="
|
||||||
model.dashboardData.value?.electricityDurable
|
model.dashboardData.value?.electricityDurable
|
||||||
@@ -55,6 +67,10 @@ onMounted(() => {
|
|||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
<Price
|
<Price
|
||||||
|
v-if="
|
||||||
|
model.dashboardData.value?.electricityPriciest
|
||||||
|
?.totalPriceTaxIncluded
|
||||||
|
"
|
||||||
:label="t('dashboard.priciest_electricity_price')"
|
:label="t('dashboard.priciest_electricity_price')"
|
||||||
:price="
|
:price="
|
||||||
model.dashboardData.value?.electricityPriciest
|
model.dashboardData.value?.electricityPriciest
|
||||||
@@ -69,12 +85,13 @@ onMounted(() => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</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">
|
<h2 class="text-2xl font-black text-primary">
|
||||||
{{ t('dashboard.gas') }}
|
{{ t('dashboard.gas') }}
|
||||||
</h2>
|
</h2>
|
||||||
<div class="flex flex-wrap gap-4">
|
<div class="flex flex-wrap gap-4">
|
||||||
<Price
|
<Price
|
||||||
|
v-if="model.dashboardData.value?.gas.totalPriceTaxIncluded"
|
||||||
:label="t('dashboard.current_gas_price')"
|
:label="t('dashboard.current_gas_price')"
|
||||||
:price="model.dashboardData.value?.gas.totalPriceTaxIncluded"
|
:price="model.dashboardData.value?.gas.totalPriceTaxIncluded"
|
||||||
:time="
|
:time="
|
||||||
@@ -84,6 +101,10 @@ onMounted(() => {
|
|||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
<Price
|
<Price
|
||||||
|
v-if="
|
||||||
|
model.dashboardData.value?.gasCheapest
|
||||||
|
?.totalPriceTaxIncluded
|
||||||
|
"
|
||||||
:label="t('dashboard.cheapest_gas_price')"
|
:label="t('dashboard.cheapest_gas_price')"
|
||||||
:price="
|
:price="
|
||||||
model.dashboardData.value?.gasCheapest
|
model.dashboardData.value?.gasCheapest
|
||||||
@@ -96,6 +117,10 @@ onMounted(() => {
|
|||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
<Price
|
<Price
|
||||||
|
v-if="
|
||||||
|
model.dashboardData.value?.gasPriciest
|
||||||
|
?.totalPriceTaxIncluded
|
||||||
|
"
|
||||||
:label="t('dashboard.priciest_gas_price')"
|
:label="t('dashboard.priciest_gas_price')"
|
||||||
:price="
|
:price="
|
||||||
model.dashboardData.value?.gasPriciest
|
model.dashboardData.value?.gasPriciest
|
||||||
@@ -109,4 +134,5 @@ onMounted(() => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<Error :message="model.error.value" v-if="model.error.value" />
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import DashboardData = App.Features.Dashboard.Data.DashboardData;
|
|||||||
|
|
||||||
export default function useDashboardViewModel() {
|
export default function useDashboardViewModel() {
|
||||||
const isLoading = ref<boolean>(false);
|
const isLoading = ref<boolean>(false);
|
||||||
|
const error = ref<string>();
|
||||||
const dashboardData = ref<DashboardData>();
|
const dashboardData = ref<DashboardData>();
|
||||||
|
|
||||||
function getDashboardData() {
|
function getDashboardData() {
|
||||||
@@ -15,8 +16,11 @@ export default function useDashboardViewModel() {
|
|||||||
.then((res) => {
|
.then((res) => {
|
||||||
dashboardData.value = res.data;
|
dashboardData.value = res.data;
|
||||||
})
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
error.value = err.response.data.message;
|
||||||
|
})
|
||||||
.finally(() => (isLoading.value = false));
|
.finally(() => (isLoading.value = false));
|
||||||
}
|
}
|
||||||
|
|
||||||
return { isLoading, dashboardData, getDashboardData };
|
return { isLoading, dashboardData, error, getDashboardData };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ ChartJS.register(
|
|||||||
|
|
||||||
export interface PricePoint {
|
export interface PricePoint {
|
||||||
label: string;
|
label: string;
|
||||||
value: number;
|
value: number | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import nl from "./nl";
|
import nl from './nl';
|
||||||
|
|
||||||
export default {
|
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 dashboard from './dashboard.json';
|
||||||
|
import history from './history.json';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
dashboard,
|
dashboard,
|
||||||
|
history,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,17 +2,33 @@
|
|||||||
import { t } from 'i18next';
|
import { t } from 'i18next';
|
||||||
import dashboard from '@/routes/dashboard';
|
import dashboard from '@/routes/dashboard';
|
||||||
import history from '@/routes/history';
|
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>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<nav class="fixed top-0 bottom-0 left-0 w-64 bg-primary p-4">
|
<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" />
|
<img src="/storage/logo.svg" class="mb-4 mix-blend-plus-lighter" />
|
||||||
<ul class="flex-1 gap-4">
|
<ul class="flex flex-1 flex-col gap-2">
|
||||||
<li>
|
<li v-for="item in navItems" :key="item.href">
|
||||||
<a :href="dashboard.index().url">{{ t('dashboard.title') }}</a>
|
<Link
|
||||||
</li>
|
:href="item.href"
|
||||||
<li>
|
:class="
|
||||||
<a :href="history.index().url">{{ t('history.title') }}</a>
|
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>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
Reference in New Issue
Block a user