+
{{ value }}
{{ valueSm }}
@@ -155,4 +155,7 @@ export default {
user-select: none;
-webkit-user-select: none;
}
+.value {
+ font-variant-numeric: tabular-nums;
+}
diff --git a/assets/js/components/Savings.vue b/assets/js/components/Savings.vue
index cc8307eca..014ec37de 100644
--- a/assets/js/components/Savings.vue
+++ b/assets/js/components/Savings.vue
@@ -2,6 +2,7 @@
-
-
- {{
- $t("footer.savings.since", {
- since: startDate,
- })
- }}
-
-
+
+
+
+
+
+ {{ $t(`footer.savings.period.${period}`) }}
+
+
+
+
+
+ {{ $t("footer.savings.referenceLabel") }}
+
+
+ {{
+ priceConfigured
+ ? fmtPricePerKWh(referenceGrid, currency)
+ : "___"
+ }}
+ ({{ $t("footer.savings.referenceGrid") }}),
+
+
+
⌀ {{ fmtCo2Medium(region.co2) }}
+
+ ({{
+ region.name
+ }})
+
+
+
+
+
@@ -149,41 +202,91 @@ import Sponsor from "./Sponsor.vue";
import SavingsTile from "./SavingsTile.vue";
import LiveCommunity from "./LiveCommunity.vue";
import TelemetrySettings from "./TelemetrySettings.vue";
+import CustomSelect from "./CustomSelect.vue";
+import co2Reference from "../co2Reference";
+import settings from "../settings";
+import api from "../api";
export default {
name: "Savings",
- components: { Sponsor, SavingsTile, LiveCommunity, TelemetrySettings },
+ components: { Sponsor, SavingsTile, LiveCommunity, TelemetrySettings, CustomSelect },
mixins: [formatter],
props: {
- selfConsumptionPercent: Number,
- since: String,
+ stats: { type: Object, default: () => ({}) },
+ co2Configured: Boolean,
sponsor: String,
- amount: { type: Number, default: 0 },
- effectivePrice: { type: Number, default: 0 },
- totalCharged: { type: Number, default: 0 },
- gridCharged: { type: Number, default: 0 },
- selfConsumptionCharged: { type: Number, default: 0 },
- gridPrice: { type: Number },
- feedInPrice: { type: Number },
currency: String,
},
data() {
- return { communityView: false, telemetryEnabled: false };
+ return {
+ communityView: false,
+ telemetryEnabled: false,
+ period: settings.savingsPeriod || "30d",
+ selectedRegion: settings.savingsRegion || "Germany",
+ referenceGrid: undefined,
+ };
},
computed: {
percent() {
- return Math.round(this.selfConsumptionPercent) || 0;
+ return Math.round(this.solarPercentage) || 0;
},
- effectivePriceFormatted() {
- const value = this.fmtPricePerKWh(this.effectivePrice, this.currency, false, false);
+ regionOptions() {
+ return co2Reference.regions.map((r) => ({
+ value: r.name,
+ name: `${r.name} (${this.fmtCo2Short(r.co2)})`,
+ }));
+ },
+ region() {
+ // previously selected region
+ if (this.selectedRegion) {
+ const result = co2Reference.regions.find((r) => r.name === this.selectedRegion);
+ if (result) {
+ return result;
+ }
+ }
+
+ // first region
+ return co2Reference.regions[0];
+ },
+ periodOptions() {
+ return ["30d", "365d", "total"].map((p) => ({
+ value: p,
+ name: this.$t(`footer.savings.period.${p}`),
+ }));
+ },
+ avgPriceFormatted() {
+ const value = this.fmtPricePerKWh(
+ this.currentStats.avgPrice,
+ this.currency,
+ false,
+ false
+ );
const unit = this.pricePerKWhUnit(this.currency);
return { value, unit };
},
- startDate() {
- if (this.since) {
- return this.fmtDayMonthYear(new Date(this.since));
- }
- return "";
+ currentStats() {
+ return this.stats[this.period] || {};
+ },
+ totalCharged() {
+ return this.currentStats.chargedKWh;
+ },
+ solarPercentage() {
+ return this.currentStats.solarPercentage;
+ },
+ solarCharged() {
+ return (this.solarPercentage / 100) * this.totalCharged;
+ },
+ gridCharged() {
+ return this.totalCharged - this.solarCharged;
+ },
+ avgPrice() {
+ return this.currentStats.avgPrice;
+ },
+ avgCo2() {
+ return this.currentStats.avgCo2;
+ },
+ priceConfigured() {
+ return this.referenceGrid !== undefined;
},
},
methods: {
@@ -196,12 +299,31 @@ export default {
openModal() {
const modal = Modal.getOrCreateInstance(document.getElementById("savingsModal"));
modal.show();
+ this.updateReferenceGrid();
},
- fmtAnimation(number) {
- let decimals = 0;
- if (number < 100) decimals = 1;
- if (number < 10) decimals = 2;
- return this.fmtNumber(number, decimals);
+ selectPeriod(period) {
+ this.period = period;
+ settings.savingsPeriod = period;
+ },
+ selectRegion(region) {
+ this.selectedRegion = region;
+ settings.savingsRegion = region;
+ },
+ updateReferenceGrid: async function () {
+ try {
+ const res = await api.get(`tariff/grid`, {
+ validateStatus: (status) => status >= 200 && status < 500,
+ });
+ const { rates } = res.data.result;
+ this.referenceGrid =
+ rates.reduce((acc, slot) => {
+ acc += slot.price;
+ return acc;
+ }, 0) / rates.length;
+ } catch (e) {
+ this.referenceGrid = undefined;
+ console.error(e);
+ }
},
},
};
diff --git a/assets/js/components/SavingsTile.vue b/assets/js/components/SavingsTile.vue
index 4c4682ded..0ee92aa48 100644
--- a/assets/js/components/SavingsTile.vue
+++ b/assets/js/components/SavingsTile.vue
@@ -1,10 +1,10 @@
-
+ >
{{ title }}
-
+
{{ value }}
@@ -31,7 +31,7 @@