Waste section: neutral terminology, drop trend-cards & meals badge, annual/range in bar, 5-min facts, AW facts in screensaver
This commit is contained in:
@@ -499,6 +499,14 @@ body {
|
|||||||
}
|
}
|
||||||
.aw-cmp-legend-you { color: #16a34a; }
|
.aw-cmp-legend-you { color: #16a34a; }
|
||||||
.aw-cmp-legend-avg { color: #f97316; }
|
.aw-cmp-legend-avg { color: #f97316; }
|
||||||
|
/* Annual totals + range note */
|
||||||
|
.aw-cmp-range {
|
||||||
|
font-size: 0.67rem;
|
||||||
|
color: #6b7280;
|
||||||
|
margin: 1px 0 4px;
|
||||||
|
padding: 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
/* Inline status below bars */
|
/* Inline status below bars */
|
||||||
.aw-status-inline {
|
.aw-status-inline {
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
|
|||||||
+18
-31
@@ -2076,9 +2076,9 @@ function showPage(pageId, param = null) {
|
|||||||
// ===== ANTI-WASTE SECTION =====
|
// ===== ANTI-WASTE SECTION =====
|
||||||
|
|
||||||
const WASTE_BENCHMARKS = {
|
const WASTE_BENCHMARKS = {
|
||||||
it: { avgWasteRate: 22, avgKgMonth: 5.4, costPerKg: 8.2, currency: '€', countryKey: 'antiwaste.country_it' },
|
it: { avgWasteRate: 22, avgKgMonth: 5.4, costPerKg: 8.2, currency: '€', countryKey: 'antiwaste.country_it', rangeMin: 8, rangeMax: 36 },
|
||||||
de: { avgWasteRate: 20, avgKgMonth: 6.5, costPerKg: 7.7, currency: '€', countryKey: 'antiwaste.country_de' },
|
de: { avgWasteRate: 20, avgKgMonth: 6.5, costPerKg: 7.7, currency: '€', countryKey: 'antiwaste.country_de', rangeMin: 7, rangeMax: 34 },
|
||||||
en: { avgWasteRate: 30, avgKgMonth: 9.2, costPerKg: 8.5, currency: '$', countryKey: 'antiwaste.country_en' },
|
en: { avgWasteRate: 30, avgKgMonth: 9.2, costPerKg: 8.5, currency: '$', countryKey: 'antiwaste.country_en', rangeMin: 12, rangeMax: 50 },
|
||||||
};
|
};
|
||||||
const _AW_KG_PER_EVENT = 0.5;
|
const _AW_KG_PER_EVENT = 0.5;
|
||||||
let _awRefreshTimer = null;
|
let _awRefreshTimer = null;
|
||||||
@@ -2291,7 +2291,6 @@ function _renderAntiWasteSection(used30, wasted30, usedP30, wastedP30, usedP60,
|
|||||||
const savedEvents = Math.max(0, avgWastedEvents - wasted30);
|
const savedEvents = Math.max(0, avgWastedEvents - wasted30);
|
||||||
const savedKg = +(savedEvents * _AW_KG_PER_EVENT).toFixed(1);
|
const savedKg = +(savedEvents * _AW_KG_PER_EVENT).toFixed(1);
|
||||||
const savedMoney = Math.round(savedKg * bm.costPerKg);
|
const savedMoney = Math.round(savedKg * bm.costPerKg);
|
||||||
const savedMeals = Math.round(savedKg * 2.5);
|
|
||||||
const savedCO2 = +(savedKg * 2.5).toFixed(1);
|
const savedCO2 = +(savedKg * 2.5).toFixed(1);
|
||||||
|
|
||||||
// Status
|
// Status
|
||||||
@@ -2313,21 +2312,16 @@ function _renderAntiWasteSection(used30, wasted30, usedP30, wastedP30, usedP60,
|
|||||||
const youPct = +((myRate / scale) * 88).toFixed(1); // your bar, same scale
|
const youPct = +((myRate / scale) * 88).toFixed(1); // your bar, same scale
|
||||||
const youLabel = t('antiwaste.you').split(' ')[0]; // "Tu" / "You" / "Du"
|
const youLabel = t('antiwaste.you').split(' ')[0]; // "Tu" / "You" / "Du"
|
||||||
|
|
||||||
// Trend cards
|
// Annual totals for comparison bar
|
||||||
const totals = [usedP60 + wastedP60, usedP30 + wastedP30, total30];
|
const myAnnualKg = Math.round(wasted30 * _AW_KG_PER_EVENT * 12);
|
||||||
const rates = totals.map((tot, i) => {
|
const avgAnnualKg = Math.round(bm.avgKgMonth * 12);
|
||||||
const w = [wastedP60, wastedP30, wasted30][i];
|
const annualInfo = t('antiwaste.annual_info')
|
||||||
return tot > 0 ? Math.round((w / tot) * 100) : null;
|
.replace('{you}', myAnnualKg)
|
||||||
});
|
.replace('{avg}', avgAnnualKg)
|
||||||
const labels = [t('antiwaste.months_ago_2'), t('antiwaste.months_ago_1'), t('antiwaste.this_month')];
|
.replace('{min}', bm.rangeMin)
|
||||||
const maxTrend = Math.max(...rates.filter(r => r !== null), 5);
|
.replace('{max}', bm.rangeMax);
|
||||||
const hasTrend = rates[0] !== null || rates[1] !== null;
|
|
||||||
|
|
||||||
const arr1 = _awTrendArrow(rates[0], rates[1]);
|
// Build all badge objects (shown 4 at a time, rotated every 5 min)
|
||||||
const arr2 = _awTrendArrow(rates[1], rates[2]);
|
|
||||||
const arrowHtml = a => a ? `<span class="aw-tc-arrow ${a.cls}">${a.sym}</span>` : '';
|
|
||||||
|
|
||||||
// Build all badge objects (shown 4 at a time, rotated every hour)
|
|
||||||
const diffPct = avgRate - myRate;
|
const diffPct = avgRate - myRate;
|
||||||
const allBadges = [];
|
const allBadges = [];
|
||||||
allBadges.push(`<span class="aw-badge aw-badge-rate">
|
allBadges.push(`<span class="aw-badge aw-badge-rate">
|
||||||
@@ -2342,10 +2336,6 @@ function _renderAntiWasteSection(used30, wasted30, usedP30, wastedP30, usedP60,
|
|||||||
<span class="aw-badge-icon">💰</span>
|
<span class="aw-badge-icon">💰</span>
|
||||||
<span class="aw-badge-body"><b>${bm.currency}${savedMoney}/m</b><small>${t('antiwaste.badge_saved_money')}</small></span>
|
<span class="aw-badge-body"><b>${bm.currency}${savedMoney}/m</b><small>${t('antiwaste.badge_saved_money')}</small></span>
|
||||||
</span>`);
|
</span>`);
|
||||||
if (savedMeals > 0) allBadges.push(`<span class="aw-badge aw-badge-meals">
|
|
||||||
<span class="aw-badge-icon">🥗</span>
|
|
||||||
<span class="aw-badge-body"><b>${savedMeals}</b><small>${t('antiwaste.badge_meals')}</small></span>
|
|
||||||
</span>`);
|
|
||||||
if (savedCO2 > 0) allBadges.push(`<span class="aw-badge aw-badge-co2">
|
if (savedCO2 > 0) allBadges.push(`<span class="aw-badge aw-badge-co2">
|
||||||
<span class="aw-badge-icon">🌍</span>
|
<span class="aw-badge-icon">🌍</span>
|
||||||
<span class="aw-badge-body"><b>−${savedCO2} kg</b><small>CO₂</small></span>
|
<span class="aw-badge-body"><b>−${savedCO2} kg</b><small>CO₂</small></span>
|
||||||
@@ -2384,19 +2374,12 @@ function _renderAntiWasteSection(used30, wasted30, usedP30, wastedP30, usedP60,
|
|||||||
<span class="aw-cmp-legend-you">▮ ${youLabel} <strong>${myRate}%</strong></span>
|
<span class="aw-cmp-legend-you">▮ ${youLabel} <strong>${myRate}%</strong></span>
|
||||||
<span class="aw-cmp-legend-avg">${country} <strong>${avgRate}%</strong> ▮</span>
|
<span class="aw-cmp-legend-avg">${country} <strong>${avgRate}%</strong> ▮</span>
|
||||||
</div>
|
</div>
|
||||||
|
<p class="aw-cmp-range">${annualInfo}</p>
|
||||||
<p class="aw-status-inline ${statusCls}">${statusMsg}</p>
|
<p class="aw-status-inline ${statusCls}">${statusMsg}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
${allBadges.length > 0 ? `<div id="aw-badges-row" class="aw-savings-row">${initBadges}</div>` : ''}
|
${allBadges.length > 0 ? `<div id="aw-badges-row" class="aw-savings-row">${initBadges}</div>` : ''}
|
||||||
|
|
||||||
${hasTrend ? `<div class="aw-trend-cards">
|
|
||||||
${_awTrendCard(rates[0], labels[0], maxTrend)}
|
|
||||||
${arrowHtml(arr1)}
|
|
||||||
${_awTrendCard(rates[1], labels[1], maxTrend)}
|
|
||||||
${arrowHtml(arr2)}
|
|
||||||
${_awTrendCard(rates[2], labels[2], maxTrend)}
|
|
||||||
</div>` : ''}
|
|
||||||
|
|
||||||
<div class="aw-fact-rotator">
|
<div class="aw-fact-rotator">
|
||||||
<span class="aw-fact-icon">💡</span>
|
<span class="aw-fact-icon">💡</span>
|
||||||
<span id="aw-fact-text" class="aw-fact-text">${facts[factIdx]}</span>
|
<span id="aw-fact-text" class="aw-fact-text">${facts[factIdx]}</span>
|
||||||
@@ -2453,7 +2436,7 @@ function _renderAntiWasteSection(used30, wasted30, usedP30, wastedP30, usedP60,
|
|||||||
el.textContent = facts[idx];
|
el.textContent = facts[idx];
|
||||||
el.classList.remove('aw-fact-fade');
|
el.classList.remove('aw-fact-fade');
|
||||||
}, 420);
|
}, 420);
|
||||||
}, 6000);
|
}, 5 * 60_000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -11178,6 +11161,10 @@ function generateScreensaverFact() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- Anti-waste knowledge facts ---
|
||||||
|
const awFacts = _awGetFacts();
|
||||||
|
for (const f of awFacts) { facts.push(() => f); }
|
||||||
|
|
||||||
// Pick a random fact
|
// Pick a random fact
|
||||||
if (facts.length === 0) {
|
if (facts.length === 0) {
|
||||||
return `${greeting}! La tua Dispensa ti aspetta.`;
|
return `${greeting}! La tua Dispensa ti aspetta.`;
|
||||||
|
|||||||
@@ -683,8 +683,8 @@
|
|||||||
"grade_label": "Note",
|
"grade_label": "Note",
|
||||||
"you": "Du",
|
"you": "Du",
|
||||||
"avg_label": "Ø",
|
"avg_label": "Ø",
|
||||||
"better": "🎉 Du verschwendest {diff}% weniger als der {country}!",
|
"better": "🎉 Du verlierst {diff}% weniger als der {country}!",
|
||||||
"worse": "⚠️ Du verschwendest mehr als der {country}. Verbesserungspotenzial!",
|
"worse": "⚠️ Du verlierst mehr als der {country}. Verbesserungspotenzial!",
|
||||||
"on_par": "→ Du liegst beim {country}. Du kannst noch besser werden!",
|
"on_par": "→ Du liegst beim {country}. Du kannst noch besser werden!",
|
||||||
"saved_money": "~{amount}/Monat gespart",
|
"saved_money": "~{amount}/Monat gespart",
|
||||||
"saved_meals": "~{n} Mahlzeiten gerettet",
|
"saved_meals": "~{n} Mahlzeiten gerettet",
|
||||||
@@ -700,10 +700,10 @@
|
|||||||
"live_on": "Live-Daten",
|
"live_on": "Live-Daten",
|
||||||
"live_off": "Offline",
|
"live_off": "Offline",
|
||||||
"meals": "Mahlzeiten",
|
"meals": "Mahlzeiten",
|
||||||
"badge_rate": "Abfallquote",
|
"annual_info": "📅 Du ~{you} kg/Jahr · Ø ~{avg} kg/Jahr · Spanne {min}–{max}%",
|
||||||
|
"badge_rate": "Verlustquote",
|
||||||
"badge_saved_money": "gespart vs Ø",
|
"badge_saved_money": "gespart vs Ø",
|
||||||
"badge_meals": "Mahlzeiten gerettet",
|
"badge_wasted": "verloren",
|
||||||
"badge_wasted": "verschwendet",
|
|
||||||
"badge_better": "weniger als Ø"
|
"badge_better": "weniger als Ø"
|
||||||
},
|
},
|
||||||
"error": {
|
"error": {
|
||||||
|
|||||||
@@ -682,8 +682,8 @@
|
|||||||
"grade_label": "Grade",
|
"grade_label": "Grade",
|
||||||
"you": "You",
|
"you": "You",
|
||||||
"avg_label": "Avg",
|
"avg_label": "Avg",
|
||||||
"better": "🎉 You waste {diff}% less than the {country}!",
|
"better": "🎉 You lose {diff}% less than the {country}!",
|
||||||
"worse": "⚠️ You waste more than the {country}. Let's improve!",
|
"worse": "⚠️ You lose more than the {country}. Room for improvement!",
|
||||||
"on_par": "→ You're at the {country}. You can do better!",
|
"on_par": "→ You're at the {country}. You can do better!",
|
||||||
"saved_money": "~{amount}/month saved",
|
"saved_money": "~{amount}/month saved",
|
||||||
"saved_meals": "~{n} meals saved",
|
"saved_meals": "~{n} meals saved",
|
||||||
@@ -699,10 +699,10 @@
|
|||||||
"live_on": "Live data",
|
"live_on": "Live data",
|
||||||
"live_off": "Offline",
|
"live_off": "Offline",
|
||||||
"meals": "meals",
|
"meals": "meals",
|
||||||
"badge_rate": "waste rate",
|
"annual_info": "📅 You ~{you} kg/yr · avg ~{avg} kg/yr · range {min}–{max}%",
|
||||||
|
"badge_rate": "loss rate",
|
||||||
"badge_saved_money": "saved vs avg",
|
"badge_saved_money": "saved vs avg",
|
||||||
"badge_meals": "meals saved",
|
"badge_wasted": "items lost",
|
||||||
"badge_wasted": "items wasted",
|
|
||||||
"badge_better": "less than avg"
|
"badge_better": "less than avg"
|
||||||
},
|
},
|
||||||
"error": {
|
"error": {
|
||||||
|
|||||||
@@ -682,8 +682,8 @@
|
|||||||
"grade_label": "Voto",
|
"grade_label": "Voto",
|
||||||
"you": "Tu",
|
"you": "Tu",
|
||||||
"avg_label": "Media",
|
"avg_label": "Media",
|
||||||
"better": "🎉 Sprechi il {diff}% in meno della {country}!",
|
"better": "🎉 Perdi il {diff}% in meno della {country}!",
|
||||||
"worse": "⚠️ Sprechi più della media {country}. Puoi migliorare!",
|
"worse": "⚠️ Perdi più della media {country}. Puoi migliorare!",
|
||||||
"on_par": "→ Sei nella media {country}. Prova a fare ancora meglio!",
|
"on_par": "→ Sei nella media {country}. Prova a fare ancora meglio!",
|
||||||
"saved_money": "~{amount}/mese risparmiati",
|
"saved_money": "~{amount}/mese risparmiati",
|
||||||
"saved_meals": "~{n} pasti salvati",
|
"saved_meals": "~{n} pasti salvati",
|
||||||
@@ -699,10 +699,10 @@
|
|||||||
"live_on": "Dati in tempo reale",
|
"live_on": "Dati in tempo reale",
|
||||||
"live_off": "Offline",
|
"live_off": "Offline",
|
||||||
"meals": "pasti",
|
"meals": "pasti",
|
||||||
"badge_rate": "tasso spreco",
|
"annual_info": "📅 Tu ~{you} kg/anno · media ~{avg} kg/anno · intervallo {min}–{max}%",
|
||||||
|
"badge_rate": "tasso perdita",
|
||||||
"badge_saved_money": "risparmio vs media",
|
"badge_saved_money": "risparmio vs media",
|
||||||
"badge_meals": "pasti salvati",
|
"badge_wasted": "prod. persi",
|
||||||
"badge_wasted": "prod. sprecati",
|
|
||||||
"badge_better": "in meno vs media"
|
"badge_better": "in meno vs media"
|
||||||
},
|
},
|
||||||
"error": {
|
"error": {
|
||||||
|
|||||||
Reference in New Issue
Block a user