Merge branch 'develop'
This commit is contained in:
@@ -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
@@ -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.`;
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -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": {
|
||||
|
||||
Reference in New Issue
Block a user