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:
+14
-1
@@ -3926,11 +3926,12 @@ async function loadBannerAlerts() {
|
||||
if (!banner) { _bannerLoading = false; console.warn('[Banner] #alert-banner not found'); return; }
|
||||
|
||||
try {
|
||||
const [invData, predData, anomalyData, finishedData] = await Promise.all([
|
||||
const [invData, predData, anomalyData, finishedData, statsData] = await Promise.all([
|
||||
api('inventory_list'),
|
||||
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_finished_items').catch(err => { console.warn('[Banner] finished_items fetch failed:', err); return { finished: [] }; }),
|
||||
api('stats').catch(() => ({ opened: [] })),
|
||||
]);
|
||||
const items = invData.inventory || [];
|
||||
const confirmed = getReviewConfirmed();
|
||||
@@ -3971,6 +3972,18 @@ async function loadBannerAlerts() {
|
||||
_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)
|
||||
// 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
|
||||
|
||||
Reference in New Issue
Block a user