fix: opened-but-not-edible items missing from banner + remove confusing strikethrough
- Banner (loadBannerAlerts): add step 1b — any item from statsData.opened with is_edible=false is queued as expired even when client-side getExpiredSafety would consider it 'ok' (e.g. conserve <30d past expiry). Applies to all product types, not just conserve. Requires fetching stats in the same Promise.all (no extra round-trip since loadDashboard already calls stats separately). - CSS: remove text-decoration:line-through from .alert-item-spoiled .alert-item-name. The badge (⛔/⚠️) already communicates the state; strikethrough added no information and confused users into thinking the item had been deleted.
This commit is contained in:
@@ -5751,7 +5751,6 @@ body.cooking-mode-active .app-header {
|
|||||||
opacity: 0.75;
|
opacity: 0.75;
|
||||||
}
|
}
|
||||||
.alert-item-spoiled .alert-item-name {
|
.alert-item-spoiled .alert-item-name {
|
||||||
text-decoration: line-through;
|
|
||||||
color: var(--text-light);
|
color: var(--text-light);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+14
-1
@@ -3926,11 +3926,12 @@ async function loadBannerAlerts() {
|
|||||||
if (!banner) { _bannerLoading = false; console.warn('[Banner] #alert-banner not found'); return; }
|
if (!banner) { _bannerLoading = false; console.warn('[Banner] #alert-banner not found'); return; }
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const [invData, predData, anomalyData, finishedData] = await Promise.all([
|
const [invData, predData, anomalyData, finishedData, statsData] = await Promise.all([
|
||||||
api('inventory_list'),
|
api('inventory_list'),
|
||||||
api('consumption_predictions').catch(err => { console.warn('[Banner] predictions fetch failed:', err); return { predictions: [] }; }),
|
api('consumption_predictions').catch(err => { console.warn('[Banner] predictions fetch failed:', err); return { predictions: [] }; }),
|
||||||
api('inventory_anomalies').catch(err => { console.warn('[Banner] anomalies fetch failed:', err); return { anomalies: [] }; }),
|
api('inventory_anomalies').catch(err => { console.warn('[Banner] anomalies fetch failed:', err); return { anomalies: [] }; }),
|
||||||
api('inventory_finished_items').catch(err => { console.warn('[Banner] finished_items fetch failed:', err); return { finished: [] }; }),
|
api('inventory_finished_items').catch(err => { console.warn('[Banner] finished_items fetch failed:', err); return { finished: [] }; }),
|
||||||
|
api('stats').catch(() => ({ opened: [] })),
|
||||||
]);
|
]);
|
||||||
const items = invData.inventory || [];
|
const items = invData.inventory || [];
|
||||||
const confirmed = getReviewConfirmed();
|
const confirmed = getReviewConfirmed();
|
||||||
@@ -3971,6 +3972,18 @@ async function loadBannerAlerts() {
|
|||||||
_queuedItemIds.add(item.id);
|
_queuedItemIds.add(item.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 1b. Opened items the SERVER considers not edible (is_edible=false from stats).
|
||||||
|
// The client-side getExpiredSafety check above uses conservative thresholds (e.g.
|
||||||
|
// conserve are 'ok' for 30 days past), but the server uses product-specific AI shelf
|
||||||
|
// life. Trust the server: any opened item with is_edible=false that isn't already
|
||||||
|
// queued goes into the banner as expired.
|
||||||
|
const openedNotEdible = (statsData.opened || []).filter(oi => !oi.is_edible && !_queuedItemIds.has(oi.id) && !confirmed['exp_' + oi.id]);
|
||||||
|
openedNotEdible.forEach(oi => {
|
||||||
|
const daysOI = Math.abs(oi.days_to_expiry ?? 0);
|
||||||
|
_bannerQueue.push({ type: 'expired', data: { ...oi, days_expired: daysOI } });
|
||||||
|
_queuedItemIds.add(oi.id);
|
||||||
|
});
|
||||||
|
|
||||||
// 2. Suspicious quantities ("expiring soon" shown only in dashboard sections, not in banner)
|
// 2. Suspicious quantities ("expiring soon" shown only in dashboard sections, not in banner)
|
||||||
// Group items by product identity to detect sibling entries in other locations.
|
// Group items by product identity to detect sibling entries in other locations.
|
||||||
// A "low quantity" alert is suppressed when other stock of the same product exists
|
// A "low quantity" alert is suppressed when other stock of the same product exists
|
||||||
|
|||||||
Reference in New Issue
Block a user