-
+
${escapeHtml(item.brand || item.category)}
-
-
- ${expiryInfo.label}
+
+ ${isOpened ? 'Opened / In Use' : 'Full Pack'}
@@ -314,7 +314,7 @@ function renderManageQuickPicker(filterQuery = '') {
if (matched.length === 0) {
container.innerHTML = `
- No matching fridge items found. Scan barcode or add as new product!
+ No matching items found. Scan barcode or add as new product!
`;
return;
@@ -347,7 +347,6 @@ function renderManageQuickPicker(filterQuery = '') {
function handleManageSearch(val) {
renderManageQuickPicker(val);
- // If barcode entered directly (e.g. 8-14 digits) and matches an item
const clean = val.trim();
if (/^\d{8,14}$/.test(clean)) {
const found = state.items.find(i => i.barcode === clean);
@@ -368,9 +367,8 @@ function selectManageItem(item) {
state.manage.packetCount = 1;
state.manage.amountValue = item.quantity;
- // Populate Selected Product Banner
document.getElementById('manage-selected-name').textContent = item.name;
- document.getElementById('manage-selected-details').textContent = `Currently: ${item.quantity} ${item.unit} in fridge • 1 Full Pack = ${item.initial_quantity} ${item.unit}`;
+ document.getElementById('manage-selected-details').textContent = `Currently: ${item.quantity} ${item.unit} in stock • 1 Full Pack = ${item.initial_quantity} ${item.unit}`;
document.getElementById('manage-pack-size-label').textContent = `${item.initial_quantity} ${item.unit}`;
document.getElementById('manage-amount-unit').textContent = item.unit;
document.getElementById('manage-amount-val').textContent = item.quantity;
@@ -387,17 +385,13 @@ function selectManageItem(item) {
imgBox.innerHTML = `
`;
}
- // Reveal Action Card
document.getElementById('manage-action-card').classList.remove('hidden');
document.getElementById('manage-qty-type-section').classList.add('hidden');
- // Reset Action Button Styles
resetActionButtonsStyle();
-
renderManageQuickPicker();
initLucide();
- // Scroll smoothly to action card on tablet
document.getElementById('manage-action-card').scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}
@@ -427,13 +421,13 @@ function setManageAction(action) {
btnRemove.className = 'p-4 sm:p-5 rounded-2xl border-2 text-center font-extrabold transition-all active:scale-95 touch-manipulation flex flex-col items-center justify-center gap-2 min-h-[80px] bg-slate-950 border-slate-800 text-slate-400 hover:border-slate-700';
step3Title.textContent = `How much ${state.manage.selectedItem.name} to ADD?`;
confirmBtn.className = 'w-full py-4 rounded-2xl bg-emerald-500 hover:bg-emerald-400 text-white font-black text-base sm:text-lg shadow-xl shadow-emerald-500/25 active:scale-95 transition-all touch-manipulation flex items-center justify-center gap-2';
- confirmLabel.textContent = `Confirm Add to Fridge`;
+ confirmLabel.textContent = `Confirm Add to Stock`;
} else {
btnRemove.className = 'p-4 sm:p-5 rounded-2xl border-2 text-center font-extrabold transition-all active:scale-95 touch-manipulation flex flex-col items-center justify-center gap-2 min-h-[80px] bg-rose-500/20 border-rose-500 text-white shadow-lg shadow-rose-500/20 ring-2 ring-rose-500/40';
btnAdd.className = 'p-4 sm:p-5 rounded-2xl border-2 text-center font-extrabold transition-all active:scale-95 touch-manipulation flex flex-col items-center justify-center gap-2 min-h-[80px] bg-slate-950 border-slate-800 text-slate-400 hover:border-slate-700';
step3Title.textContent = `How much ${state.manage.selectedItem.name} to REMOVE?`;
confirmBtn.className = 'w-full py-4 rounded-2xl bg-rose-500 hover:bg-rose-400 text-white font-black text-base sm:text-lg shadow-xl shadow-rose-500/25 active:scale-95 transition-all touch-manipulation flex items-center justify-center gap-2';
- confirmLabel.textContent = `Confirm Remove from Fridge`;
+ confirmLabel.textContent = `Confirm Remove from Stock`;
}
qtySection.classList.remove('hidden');
@@ -473,7 +467,6 @@ function setQtyMode(mode) {
initLucide();
}
-// Packet count stepper
function changePacketCount(delta) {
state.manage.packetCount = Math.max(1, state.manage.packetCount + delta);
document.getElementById('manage-pack-count').textContent = state.manage.packetCount;
@@ -484,7 +477,6 @@ function setPacketCount(num) {
document.getElementById('manage-pack-count').textContent = num;
}
-// Specific amount slider & delta
function onManageAmountSlider(val) {
state.manage.amountValue = parseFloat(val);
document.getElementById('manage-amount-val').textContent = state.manage.amountValue;
@@ -503,10 +495,6 @@ function setManageAmountRatio(ratio) {
document.getElementById('manage-amount-val').textContent = state.manage.amountValue;
}
-// ----------------------------------------------------
-// EXECUTION: Commit Add / Remove
-// ----------------------------------------------------
-
async function confirmManageExecution() {
const item = state.manage.selectedItem;
const action = state.manage.action;
@@ -529,7 +517,7 @@ async function confirmManageExecution() {
if (res.ok) {
const updated = await res.json();
playBeepSound();
- showToast(`✓ ${action === 'add' ? 'Added' : 'Removed'} ${state.manage.packetCount} packet(s) of ${updated.name} (Now: ${updated.quantity} ${updated.unit})`, 'success');
+ showToast(`✓ ${action === 'add' ? 'Added' : 'Removed'} ${state.manage.packetCount} pack(s) of ${updated.name} (Now: ${updated.quantity} ${updated.unit})`, 'success');
clearSelectedManageItem();
await loadStats();
await loadItems();
@@ -537,7 +525,6 @@ async function confirmManageExecution() {
showToast('Failed to update packet', 'error');
}
} else {
- // Specific Grams / Amount mode
const newQty = state.manage.amountValue;
const res = await fetch(`/api/items/${item.id}/quantity`, {
method: 'PATCH',
@@ -585,7 +572,6 @@ function openItemModal(itemId = null) {
document.getElementById('modal-initial-quantity').value = item.initial_quantity || item.quantity;
document.getElementById('modal-unit').value = item.unit || 'g';
document.getElementById('modal-category').value = item.category || 'General';
- document.getElementById('modal-expiry').value = item.expiry_date || '';
document.getElementById('modal-notes').value = item.notes || '';
if (item.image_url) {
@@ -658,11 +644,6 @@ function applyProductDataToForm(data) {
}
}
-function setModalExpiryDays(days) {
- const date = new Date(Date.now() + days * 24 * 60 * 60 * 1000);
- document.getElementById('modal-expiry').value = date.toISOString().slice(0, 10);
-}
-
async function handleItemFormSubmit(event) {
event.preventDefault();
@@ -678,7 +659,6 @@ async function handleItemFormSubmit(event) {
initial_quantity: initQty,
unit: document.getElementById('modal-unit').value,
category: document.getElementById('modal-category').value,
- expiry_date: document.getElementById('modal-expiry').value || null,
notes: document.getElementById('modal-notes').value.trim(),
image_url: document.getElementById('modal-image-url').value || null
};
@@ -695,11 +675,10 @@ async function handleItemFormSubmit(event) {
if (res.ok) {
const saved = await res.json();
- showToast(itemId ? 'Product updated' : 'Product added to fridge', 'success');
+ showToast(itemId ? 'Product updated' : 'Product added', 'success');
closeItemModal();
await loadStats();
await loadItems();
- // Auto-select in manage tab
selectManageItem(saved);
switchTab('manage');
} else {
@@ -779,7 +758,6 @@ async function onBarcodeScannedSuccess(decodedText) {
stopCameraScanner();
closeScannerModal();
- // Check if item exists in fridge
const existing = state.items.find(i => i.barcode === decodedText);
if (existing) {
switchTab('manage');
@@ -788,7 +766,6 @@ async function onBarcodeScannedSuccess(decodedText) {
return;
}
- // Otherwise fetch from API / Open Food Facts
try {
const res = await fetch(`/api/barcode/${encodeURIComponent(decodedText)}`);
if (res.ok) {
@@ -832,58 +809,6 @@ function playBeepSound() {
} catch (e) {}
}
-// ----------------------------------------------------
-// Helpers
-// ----------------------------------------------------
-
-function getExpiryStatus(expiryDateStr) {
- if (!expiryDateStr) {
- return { label: 'No Expiry', badgeClass: 'bg-slate-800 text-slate-400', icon: 'calendar' };
- }
-
- const today = new Date();
- today.setHours(0, 0, 0, 0);
-
- const expDate = new Date(expiryDateStr);
- expDate.setHours(0, 0, 0, 0);
-
- const diffDays = Math.round((expDate - today) / (1000 * 60 * 60 * 24));
-
- if (diffDays < 0) {
- return {
- label: `Expired ${Math.abs(diffDays)}d ago`,
- badgeClass: 'bg-rose-500/20 text-rose-300 border border-rose-500/30',
- icon: 'alert-triangle'
- };
- }
- if (diffDays === 0) {
- return {
- label: 'Expires Today!',
- badgeClass: 'bg-rose-500/20 text-rose-300 border border-rose-500/30 font-bold',
- icon: 'alert-circle'
- };
- }
- if (diffDays === 1) {
- return {
- label: 'Expires Tomorrow',
- badgeClass: 'bg-amber-500/20 text-amber-300 border border-amber-500/30',
- icon: 'clock'
- };
- }
- if (diffDays <= 3) {
- return {
- label: `${diffDays} days left`,
- badgeClass: 'bg-amber-500/20 text-amber-300 border border-amber-500/30',
- icon: 'clock'
- };
- }
- return {
- label: `${diffDays} days left`,
- badgeClass: 'bg-emerald-500/10 text-emerald-400 border border-emerald-500/20',
- icon: 'calendar-check'
- };
-}
-
function getCategoryIcon(category) {
const cat = state.meta.categories.find(c => c.id === category);
return cat ? cat.icon : 'package';
@@ -924,16 +849,3 @@ function showToast(message, type = 'info') {
setTimeout(() => toast.remove(), 300);
}, 3000);
}
-
-async function seedDemoData() {
- try {
- const res = await fetch('/api/seed?force=true', { method: 'POST' });
- if (res.ok) {
- showToast('Loaded sample items!', 'success');
- await loadStats();
- await loadItems();
- }
- } catch (err) {
- console.error(err);
- }
-}
diff --git a/public/index.html b/public/index.html
index a474a24..d9b8e51 100644
--- a/public/index.html
+++ b/public/index.html
@@ -3,7 +3,7 @@
-
Fridger - Tablet Fridge Manager
+
Fridger - Inventory & Stock Manager
@@ -46,14 +46,14 @@