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:
dadaloop82
2026-04-29 16:27:05 +00:00
parent 67f58172e5
commit 9c1346019c
5 changed files with 41 additions and 46 deletions
+8
View File
@@ -499,6 +499,14 @@ body {
}
.aw-cmp-legend-you { color: #16a34a; }
.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 */
.aw-status-inline {
font-size: 0.75rem;
+18 -31
View File
@@ -2076,9 +2076,9 @@ function showPage(pageId, param = null) {
// ===== ANTI-WASTE SECTION =====
const WASTE_BENCHMARKS = {
it: { avgWasteRate: 22, avgKgMonth: 5.4, costPerKg: 8.2, currency: '€', countryKey: 'antiwaste.country_it' },
de: { avgWasteRate: 20, avgKgMonth: 6.5, costPerKg: 7.7, currency: '€', countryKey: 'antiwaste.country_de' },
en: { avgWasteRate: 30, avgKgMonth: 9.2, costPerKg: 8.5, currency: '$', countryKey: 'antiwaste.country_en' },
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', rangeMin: 7, rangeMax: 34 },
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;
let _awRefreshTimer = null;
@@ -2291,7 +2291,6 @@ function _renderAntiWasteSection(used30, wasted30, usedP30, wastedP30, usedP60,
const savedEvents = Math.max(0, avgWastedEvents - wasted30);
const savedKg = +(savedEvents * _AW_KG_PER_EVENT).toFixed(1);
const savedMoney = Math.round(savedKg * bm.costPerKg);
const savedMeals = Math.round(savedKg * 2.5);
const savedCO2 = +(savedKg * 2.5).toFixed(1);
// Status
@@ -2313,21 +2312,16 @@ function _renderAntiWasteSection(used30, wasted30, usedP30, wastedP30, usedP60,
const youPct = +((myRate / scale) * 88).toFixed(1); // your bar, same scale
const youLabel = t('antiwaste.you').split(' ')[0]; // "Tu" / "You" / "Du"
// Trend cards
const totals = [usedP60 + wastedP60, usedP30 + wastedP30, total30];
const rates = totals.map((tot, i) => {
const w = [wastedP60, wastedP30, wasted30][i];
return tot > 0 ? Math.round((w / tot) * 100) : null;
});
const labels = [t('antiwaste.months_ago_2'), t('antiwaste.months_ago_1'), t('antiwaste.this_month')];
const maxTrend = Math.max(...rates.filter(r => r !== null), 5);
const hasTrend = rates[0] !== null || rates[1] !== null;
// Annual totals for comparison bar
const myAnnualKg = Math.round(wasted30 * _AW_KG_PER_EVENT * 12);
const avgAnnualKg = Math.round(bm.avgKgMonth * 12);
const annualInfo = t('antiwaste.annual_info')
.replace('{you}', myAnnualKg)
.replace('{avg}', avgAnnualKg)
.replace('{min}', bm.rangeMin)
.replace('{max}', bm.rangeMax);
const arr1 = _awTrendArrow(rates[0], rates[1]);
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)
// Build all badge objects (shown 4 at a time, rotated every 5 min)
const diffPct = avgRate - myRate;
const allBadges = [];
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-body"><b>${bm.currency}${savedMoney}/m</b><small>${t('antiwaste.badge_saved_money')}</small></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">
<span class="aw-badge-icon">🌍</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-avg">${country} <strong>${avgRate}%</strong> </span>
</div>
<p class="aw-cmp-range">${annualInfo}</p>
<p class="aw-status-inline ${statusCls}">${statusMsg}</p>
</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">
<span class="aw-fact-icon">💡</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.classList.remove('aw-fact-fade');
}, 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
if (facts.length === 0) {
return `${greeting}! La tua Dispensa ti aspetta.`;
+5 -5
View File
@@ -683,8 +683,8 @@
"grade_label": "Note",
"you": "Du",
"avg_label": "Ø",
"better": "🎉 Du verschwendest {diff}% weniger als der {country}!",
"worse": "⚠️ Du verschwendest mehr als der {country}. Verbesserungspotenzial!",
"better": "🎉 Du verlierst {diff}% weniger als der {country}!",
"worse": "⚠️ Du verlierst mehr als der {country}. Verbesserungspotenzial!",
"on_par": "→ Du liegst beim {country}. Du kannst noch besser werden!",
"saved_money": "~{amount}/Monat gespart",
"saved_meals": "~{n} Mahlzeiten gerettet",
@@ -700,10 +700,10 @@
"live_on": "Live-Daten",
"live_off": "Offline",
"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_meals": "Mahlzeiten gerettet",
"badge_wasted": "verschwendet",
"badge_wasted": "verloren",
"badge_better": "weniger als Ø"
},
"error": {
+5 -5
View File
@@ -682,8 +682,8 @@
"grade_label": "Grade",
"you": "You",
"avg_label": "Avg",
"better": "🎉 You waste {diff}% less than the {country}!",
"worse": "⚠️ You waste more than the {country}. Let's improve!",
"better": "🎉 You lose {diff}% less than the {country}!",
"worse": "⚠️ You lose more than the {country}. Room for improvement!",
"on_par": "→ You're at the {country}. You can do better!",
"saved_money": "~{amount}/month saved",
"saved_meals": "~{n} meals saved",
@@ -699,10 +699,10 @@
"live_on": "Live data",
"live_off": "Offline",
"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_meals": "meals saved",
"badge_wasted": "items wasted",
"badge_wasted": "items lost",
"badge_better": "less than avg"
},
"error": {
+5 -5
View File
@@ -682,8 +682,8 @@
"grade_label": "Voto",
"you": "Tu",
"avg_label": "Media",
"better": "🎉 Sprechi il {diff}% in meno della {country}!",
"worse": "⚠️ Sprechi più della media {country}. Puoi migliorare!",
"better": "🎉 Perdi il {diff}% in meno della {country}!",
"worse": "⚠️ Perdi più della media {country}. Puoi migliorare!",
"on_par": "→ Sei nella media {country}. Prova a fare ancora meglio!",
"saved_money": "~{amount}/mese risparmiati",
"saved_meals": "~{n} pasti salvati",
@@ -699,10 +699,10 @@
"live_on": "Dati in tempo reale",
"live_off": "Offline",
"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_meals": "pasti salvati",
"badge_wasted": "prod. sprecati",
"badge_wasted": "prod. persi",
"badge_better": "in meno vs media"
},
"error": {