feat(dashboard): add price overview UI
This commit is contained in:
@@ -20,7 +20,7 @@ class DashboardService
|
|||||||
|
|
||||||
$eNow = $electricity->whereBetween('startDate', [$now->copy()->subHour(), $now])->first();
|
$eNow = $electricity->whereBetween('startDate', [$now->copy()->subHour(), $now])->first();
|
||||||
$eCheapest = $electricity->where('totalPriceTaxIncluded', $electricity->min('totalPriceTaxIncluded'))->first();
|
$eCheapest = $electricity->where('totalPriceTaxIncluded', $electricity->min('totalPriceTaxIncluded'))->first();
|
||||||
$eDurable = $electricity->where('sustainabilityScore', $electricity->min('sustainabilityScore'))->first();
|
$eDurable = $electricity->where('sustainabilityScore', $electricity->max('sustainabilityScore'))->first();
|
||||||
$ePriciest = $electricity->where('totalPriceTaxIncluded', $electricity->max('totalPriceTaxIncluded'))->first();
|
$ePriciest = $electricity->where('totalPriceTaxIncluded', $electricity->max('totalPriceTaxIncluded'))->first();
|
||||||
|
|
||||||
$gas = $this->repository->retrieveGas();
|
$gas = $this->repository->retrieveGas();
|
||||||
|
|||||||
Generated
+10
@@ -15,6 +15,7 @@
|
|||||||
"i18next": "^26.3.6",
|
"i18next": "^26.3.6",
|
||||||
"i18next-vue": "^5.4.0",
|
"i18next-vue": "^5.4.0",
|
||||||
"laravel-vite-plugin": "^3.1",
|
"laravel-vite-plugin": "^3.1",
|
||||||
|
"moment": "^2.30.1",
|
||||||
"tailwind-merge": "^3.2.0",
|
"tailwind-merge": "^3.2.0",
|
||||||
"tailwindcss": "^4.1.1",
|
"tailwindcss": "^4.1.1",
|
||||||
"typescript": "^5.2.2",
|
"typescript": "^5.2.2",
|
||||||
@@ -5040,6 +5041,15 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/moment": {
|
||||||
|
"version": "2.30.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
|
||||||
|
"integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ms": {
|
"node_modules/ms": {
|
||||||
"version": "2.1.3",
|
"version": "2.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
"i18next": "^26.3.6",
|
"i18next": "^26.3.6",
|
||||||
"i18next-vue": "^5.4.0",
|
"i18next-vue": "^5.4.0",
|
||||||
"laravel-vite-plugin": "^3.1",
|
"laravel-vite-plugin": "^3.1",
|
||||||
|
"moment": "^2.30.1",
|
||||||
"tailwind-merge": "^3.2.0",
|
"tailwind-merge": "^3.2.0",
|
||||||
"tailwindcss": "^4.1.1",
|
"tailwindcss": "^4.1.1",
|
||||||
"typescript": "^5.2.2",
|
"typescript": "^5.2.2",
|
||||||
|
|||||||
@@ -8,4 +8,6 @@
|
|||||||
Instrument Sans, ui-sans-serif, system-ui, sans-serif,
|
Instrument Sans, ui-sans-serif, system-ui, sans-serif,
|
||||||
'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
|
'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
|
||||||
'Noto Color Emoji';
|
'Noto Color Emoji';
|
||||||
|
|
||||||
|
--color-primary: #4ba66a;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
label: string;
|
||||||
|
price: number | null | undefined;
|
||||||
|
time: moment.Moment | string;
|
||||||
|
}>();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="flex flex-col gap-4 rounded-xl bg-primary/10 p-4 shadow-md">
|
||||||
|
<div class="font-bold text-primary uppercase">{{ label }}</div>
|
||||||
|
<div class="flex flex-col gap-2">
|
||||||
|
<div class="text-4xl font-black">
|
||||||
|
€{{ price?.toPrecision(2).toString().replace('.', ',') }}
|
||||||
|
</div>
|
||||||
|
<div class="text-sm text-black/50">
|
||||||
|
{{ moment.isMoment(time) ? time.format('DD-MM-YYYY HH:mm') : time }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -1,5 +1,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { t } from 'i18next';
|
||||||
|
import moment from 'moment';
|
||||||
import { onMounted } from 'vue';
|
import { onMounted } from 'vue';
|
||||||
|
import Price from '../components/Price.vue';
|
||||||
import useDashboardViewModel from '../viewmodels/DashboardViewModel';
|
import useDashboardViewModel from '../viewmodels/DashboardViewModel';
|
||||||
|
|
||||||
const model = useDashboardViewModel();
|
const model = useDashboardViewModel();
|
||||||
@@ -10,6 +13,100 @@ onMounted(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>{{ model.isLoading }}</div>
|
<h1 class="mb-4 text-3xl font-black text-primary">
|
||||||
<div>{{ model.dashboardData }}</div>
|
{{ t('dashboard.title') }}
|
||||||
|
</h1>
|
||||||
|
<div class="mb-4 flex flex-col gap-2">
|
||||||
|
<h2 class="text-2xl font-black text-primary">
|
||||||
|
{{ t('dashboard.electricity') }}
|
||||||
|
</h2>
|
||||||
|
<div class="flex flex-wrap gap-4">
|
||||||
|
<Price
|
||||||
|
:label="t('dashboard.current_electricity_price')"
|
||||||
|
:price="
|
||||||
|
model.dashboardData.value?.electricity.totalPriceTaxIncluded
|
||||||
|
"
|
||||||
|
:time="moment(model.dashboardData.value?.electricity.startDate)"
|
||||||
|
/>
|
||||||
|
<Price
|
||||||
|
:label="t('dashboard.cheapest_electricity_price')"
|
||||||
|
:price="
|
||||||
|
model.dashboardData.value?.electricityCheapest
|
||||||
|
?.totalPriceTaxIncluded
|
||||||
|
"
|
||||||
|
:time="
|
||||||
|
moment(
|
||||||
|
model.dashboardData.value?.electricityCheapest
|
||||||
|
?.startDate,
|
||||||
|
)
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<Price
|
||||||
|
:label="t('dashboard.durable_electricity_price')"
|
||||||
|
:price="
|
||||||
|
model.dashboardData.value?.electricityDurable
|
||||||
|
?.totalPriceTaxIncluded
|
||||||
|
"
|
||||||
|
:time="
|
||||||
|
moment(
|
||||||
|
model.dashboardData.value?.electricityDurable
|
||||||
|
?.startDate,
|
||||||
|
)
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<Price
|
||||||
|
:label="t('dashboard.priciest_electricity_price')"
|
||||||
|
:price="
|
||||||
|
model.dashboardData.value?.electricityPriciest
|
||||||
|
?.totalPriceTaxIncluded
|
||||||
|
"
|
||||||
|
:time="
|
||||||
|
moment(
|
||||||
|
model.dashboardData.value?.electricityPriciest
|
||||||
|
?.startDate,
|
||||||
|
)
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mb-4 flex flex-col gap-2">
|
||||||
|
<h2 class="text-2xl font-black text-primary">
|
||||||
|
{{ t('dashboard.gas') }}
|
||||||
|
</h2>
|
||||||
|
<div class="flex flex-wrap gap-4">
|
||||||
|
<Price
|
||||||
|
:label="t('dashboard.current_gas_price')"
|
||||||
|
:price="model.dashboardData.value?.gas.totalPriceTaxIncluded"
|
||||||
|
:time="
|
||||||
|
moment(model.dashboardData.value?.gas.startDate).format(
|
||||||
|
'DD-MM-YYYY',
|
||||||
|
)
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<Price
|
||||||
|
:label="t('dashboard.cheapest_gas_price')"
|
||||||
|
:price="
|
||||||
|
model.dashboardData.value?.gasCheapest
|
||||||
|
?.totalPriceTaxIncluded
|
||||||
|
"
|
||||||
|
:time="
|
||||||
|
moment(
|
||||||
|
model.dashboardData.value?.gasCheapest?.startDate,
|
||||||
|
).format('DD-MM-YYYY')
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<Price
|
||||||
|
:label="t('dashboard.priciest_gas_price')"
|
||||||
|
:price="
|
||||||
|
model.dashboardData.value?.gasPriciest
|
||||||
|
?.totalPriceTaxIncluded
|
||||||
|
"
|
||||||
|
:time="
|
||||||
|
moment(
|
||||||
|
model.dashboardData.value?.gasPriciest?.startDate,
|
||||||
|
).format('DD-MM-YYYY')
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
+2
-2
@@ -3,11 +3,11 @@ declare namespace App {
|
|||||||
namespace Dashboard {
|
namespace Dashboard {
|
||||||
namespace Data {
|
namespace Data {
|
||||||
export type DashboardData = {
|
export type DashboardData = {
|
||||||
electricityHistory: App.Features.Dashboard.Data.ElectricityData[];
|
electricity: App.Features.Dashboard.Data.ElectricityData;
|
||||||
electricityCheapest: App.Features.Dashboard.Data.ElectricityData | null;
|
electricityCheapest: App.Features.Dashboard.Data.ElectricityData | null;
|
||||||
electricityDurable: App.Features.Dashboard.Data.ElectricityData | null;
|
electricityDurable: App.Features.Dashboard.Data.ElectricityData | null;
|
||||||
electricityPriciest: App.Features.Dashboard.Data.ElectricityData | null;
|
electricityPriciest: App.Features.Dashboard.Data.ElectricityData | null;
|
||||||
gasHistory: App.Features.Dashboard.Data.ElectricityData[];
|
gas: App.Features.Dashboard.Data.GasData;
|
||||||
gasCheapest: App.Features.Dashboard.Data.GasData | null;
|
gasCheapest: App.Features.Dashboard.Data.GasData | null;
|
||||||
gasPriciest: App.Features.Dashboard.Data.GasData | null;
|
gasPriciest: App.Features.Dashboard.Data.GasData | null;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"generated.d.ts": "63b1a5a3410956e9dfd29ea3c90abc71"
|
"generated.d.ts": "f593095f6f419a96a4c39c2b93719f9a"
|
||||||
}
|
}
|
||||||
@@ -5,8 +5,9 @@ import history from '@/routes/history';
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<nav class="fixed top-0 left-0 w-40">
|
<nav class="fixed top-0 bottom-0 left-0 w-64 bg-primary p-4">
|
||||||
<ul>
|
<img src="/storage/logo.svg" class="mb-4 mix-blend-plus-lighter" />
|
||||||
|
<ul class="flex-1 gap-4">
|
||||||
<li>
|
<li>
|
||||||
<a :href="dashboard.index().url">{{ t('dashboard.title') }}</a>
|
<a :href="dashboard.index().url">{{ t('dashboard.title') }}</a>
|
||||||
</li>
|
</li>
|
||||||
@@ -15,5 +16,5 @@ import history from '@/routes/history';
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
<div class="absolute top-0 left-40"><slot /></div>
|
<div class="absolute top-0 left-64 p-4"><slot /></div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
Reference in New Issue
Block a user