feat: screensaver shopping panel with item count and estimated total
This commit is contained in:
@@ -5767,6 +5767,47 @@ body.cooking-mode-active .app-header {
|
|||||||
backdrop-filter: blur(8px);
|
backdrop-filter: blur(8px);
|
||||||
-webkit-backdrop-filter: blur(8px);
|
-webkit-backdrop-filter: blur(8px);
|
||||||
}
|
}
|
||||||
|
.screensaver-shopping {
|
||||||
|
text-align: center;
|
||||||
|
user-select: none;
|
||||||
|
margin: -8px 0 0;
|
||||||
|
}
|
||||||
|
.screensaver-shopping-card {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 18px;
|
||||||
|
background: rgba(255,255,255,0.07);
|
||||||
|
border: 1px solid rgba(255,255,255,0.13);
|
||||||
|
border-radius: 20px;
|
||||||
|
padding: 14px 32px;
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
-webkit-backdrop-filter: blur(10px);
|
||||||
|
}
|
||||||
|
.ss-shop-col {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 2px;
|
||||||
|
}
|
||||||
|
.ss-shop-sep {
|
||||||
|
width: 1px;
|
||||||
|
height: 36px;
|
||||||
|
background: rgba(255,255,255,0.18);
|
||||||
|
}
|
||||||
|
.ss-shop-value {
|
||||||
|
color: rgba(255,255,255,0.92);
|
||||||
|
font-size: 1.9rem;
|
||||||
|
font-weight: 300;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
.ss-shop-label {
|
||||||
|
color: rgba(255,255,255,0.38);
|
||||||
|
font-size: 0.8rem;
|
||||||
|
font-weight: 400;
|
||||||
|
letter-spacing: 0.8px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
.screensaver-shortcuts {
|
.screensaver-shortcuts {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: max(32px, env(safe-area-inset-bottom, 32px));
|
bottom: max(32px, env(safe-area-inset-bottom, 32px));
|
||||||
|
|||||||
+34
-13
@@ -12448,6 +12448,7 @@ function activateScreensaver() {
|
|||||||
requestAnimationFrame(() => overlay.classList.add('visible'));
|
requestAnimationFrame(() => overlay.classList.add('visible'));
|
||||||
updateScreensaverClock();
|
updateScreensaverClock();
|
||||||
_screensaverClockInterval = setInterval(updateScreensaverClock, 1000);
|
_screensaverClockInterval = setInterval(updateScreensaverClock, 1000);
|
||||||
|
updateScreensaverShopping();
|
||||||
// Load data and start fact/nutrition rotation
|
// Load data and start fact/nutrition rotation
|
||||||
loadScreensaverData().then(() => {
|
loadScreensaverData().then(() => {
|
||||||
_startScreensaverRotation();
|
_startScreensaverRotation();
|
||||||
@@ -12465,6 +12466,34 @@ function updateScreensaverClock() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Show/hide the planned meal type badge on the screensaver based on current time slot. */
|
/** Show/hide the planned meal type badge on the screensaver based on current time slot. */
|
||||||
|
function updateScreensaverShopping() {
|
||||||
|
const el = document.getElementById('screensaver-shopping');
|
||||||
|
if (!el) return;
|
||||||
|
const s = getSettings();
|
||||||
|
const itemCount = shoppingItems.length;
|
||||||
|
if (itemCount === 0) { el.style.display = 'none'; return; }
|
||||||
|
|
||||||
|
const countCol = `<div class="ss-shop-col">
|
||||||
|
<div class="ss-shop-value">${itemCount}</div>
|
||||||
|
<div class="ss-shop-label">🛒 articoli</div>
|
||||||
|
</div>`;
|
||||||
|
|
||||||
|
let priceCol = '';
|
||||||
|
if (s.price_enabled) {
|
||||||
|
const saved = sessionStorage.getItem('_pricetotal');
|
||||||
|
if (saved) {
|
||||||
|
priceCol = `<div class="ss-shop-sep"></div>
|
||||||
|
<div class="ss-shop-col">
|
||||||
|
<div class="ss-shop-value">${saved.replace('ca. ', '')}</div>
|
||||||
|
<div class="ss-shop-label">💰 spesa stimata</div>
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
el.innerHTML = `<div class="screensaver-shopping-card">${countCol}${priceCol}</div>`;
|
||||||
|
el.style.display = 'block';
|
||||||
|
}
|
||||||
|
|
||||||
function updateScreensaverMealPlan() {
|
function updateScreensaverMealPlan() {
|
||||||
const el = document.getElementById('screensaver-mealplan');
|
const el = document.getElementById('screensaver-mealplan');
|
||||||
if (!el) return;
|
if (!el) return;
|
||||||
@@ -12759,36 +12788,29 @@ function generateScreensaverFact() {
|
|||||||
facts.push(() => `In questo mese scadranno ${expiringThisMonth.length} prodotti.`);
|
facts.push(() => `In questo mese scadranno ${expiringThisMonth.length} prodotti.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Shopping list facts ---
|
// --- Shopping list facts (skip count/names — already shown in the shopping panel) ---
|
||||||
if (shop.length > 0) {
|
if (shop.length > 0) {
|
||||||
facts.push(() => `Hai ${shop.length} ${shop.length === 1 ? 'prodotto' : 'prodotti'} nella lista della spesa.`);
|
const names = shop.slice(0, 3).map(i => i.name).join(', ');
|
||||||
facts.push(() => {
|
const extra = shop.length > 3 ? ` e altri ${shop.length - 3}` : '';
|
||||||
const names = shop.slice(0, 4).map(i => i.name);
|
facts.push(() => `Metti in lista: ${names}${extra} 🛒`);
|
||||||
return `Nella spesa: ${names.join(', ')}${shop.length > 4 ? '...' : ''}`;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
if (shop.length === 0) {
|
if (shop.length === 0) {
|
||||||
facts.push(() => `La lista della spesa è vuota. Tutto a posto!`);
|
facts.push(() => `Lista della spesa vuota. Tutto rifornito! ✅`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Location-based facts ---
|
// --- Location-based facts ---
|
||||||
if (inFrigo.length > 0) {
|
if (inFrigo.length > 0) {
|
||||||
facts.push(() => `Hai ${inFrigo.length} prodotti in frigo.`);
|
|
||||||
facts.push(() => {
|
facts.push(() => {
|
||||||
const item = rItem(inFrigo);
|
const item = rItem(inFrigo);
|
||||||
return `In frigo c'è: ${item.name}${item.brand ? ' (' + item.brand + ')' : ''}.`;
|
return `In frigo c'è: ${item.name}${item.brand ? ' (' + item.brand + ')' : ''}.`;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (inFreezer.length > 0) {
|
if (inFreezer.length > 0) {
|
||||||
facts.push(() => `Hai ${inFreezer.length} prodotti nel freezer.`);
|
|
||||||
facts.push(() => {
|
facts.push(() => {
|
||||||
const item = rItem(inFreezer);
|
const item = rItem(inFreezer);
|
||||||
return `Nel freezer c'è: ${item.name}. Non dimenticartelo!`;
|
return `Nel freezer c'è: ${item.name}. Non dimenticartelo!`;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (inDispensa.length > 0) {
|
|
||||||
facts.push(() => `In dispensa ci sono ${inDispensa.length} prodotti.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- Category-based facts ---
|
// --- Category-based facts ---
|
||||||
const catEntries = Object.entries(byCategory);
|
const catEntries = Object.entries(byCategory);
|
||||||
@@ -12834,7 +12856,6 @@ function generateScreensaverFact() {
|
|||||||
|
|
||||||
// --- General inventory facts ---
|
// --- General inventory facts ---
|
||||||
if (inv.length > 0) {
|
if (inv.length > 0) {
|
||||||
facts.push(() => `Hai ${totalProducts} prodotti diversi in casa per un totale di ${Math.round(totalItems)} pezzi.`);
|
|
||||||
facts.push(() => {
|
facts.push(() => {
|
||||||
const item = rItem(inv);
|
const item = rItem(inv);
|
||||||
return `Lo sapevi? Hai ${item.name} in ${LOCATIONS[item.location]?.label || item.location}.`;
|
return `Lo sapevi? Hai ${item.name} in ${LOCATIONS[item.location]?.label || item.location}.`;
|
||||||
|
|||||||
+3
-2
@@ -11,7 +11,7 @@
|
|||||||
<title>EverShelf</title>
|
<title>EverShelf</title>
|
||||||
<link rel="manifest" href="manifest.json">
|
<link rel="manifest" href="manifest.json">
|
||||||
<link rel="icon" type="image/png" href="assets/img/logo/logo_icon.png">
|
<link rel="icon" type="image/png" href="assets/img/logo/logo_icon.png">
|
||||||
<link rel="stylesheet" href="assets/css/style.css?v=20260507d">
|
<link rel="stylesheet" href="assets/css/style.css?v=20260507e">
|
||||||
<!-- QuaggaJS for barcode scanning -->
|
<!-- QuaggaJS for barcode scanning -->
|
||||||
<script src="https://cdn.jsdelivr.net/npm/@ericblade/quagga2@1.8.4/dist/quagga.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/@ericblade/quagga2@1.8.4/dist/quagga.min.js"></script>
|
||||||
<!-- @xenova/transformers: ES-module bootstrap that exposes a lazy category-classifier as window._categoryPipelinePromise -->
|
<!-- @xenova/transformers: ES-module bootstrap that exposes a lazy category-classifier as window._categoryPipelinePromise -->
|
||||||
@@ -1416,6 +1416,7 @@
|
|||||||
<div id="screensaver" class="screensaver-overlay" style="display:none">
|
<div id="screensaver" class="screensaver-overlay" style="display:none">
|
||||||
<div class="screensaver-content">
|
<div class="screensaver-content">
|
||||||
<div class="screensaver-clock" id="screensaver-clock"></div>
|
<div class="screensaver-clock" id="screensaver-clock"></div>
|
||||||
|
<div id="screensaver-shopping" class="screensaver-shopping" style="display:none"></div>
|
||||||
<div id="screensaver-mealplan" class="screensaver-mealplan" style="display:none"></div>
|
<div id="screensaver-mealplan" class="screensaver-mealplan" style="display:none"></div>
|
||||||
<!-- Nutrition pie charts panel (shown alternately with fact) -->
|
<!-- Nutrition pie charts panel (shown alternately with fact) -->
|
||||||
<div id="screensaver-nutrition" class="screensaver-nutrition" style="display:none"></div>
|
<div id="screensaver-nutrition" class="screensaver-nutrition" style="display:none"></div>
|
||||||
@@ -1461,6 +1462,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="assets/js/app.js?v=20260507i"></script>
|
<script src="assets/js/app.js?v=20260507j"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user