diff --git a/assets/js/app.js b/assets/js/app.js
index d2322b6..dbd71e3 100644
--- a/assets/js/app.js
+++ b/assets/js/app.js
@@ -5991,10 +5991,6 @@ function setReviewConfirmed(inventoryId) {
api('app_settings_save', {}, 'POST', { settings: { review_confirmed: c } }).catch(() => {});
}
-/** Return map of product IDs the user has marked as "no expiry needed". */
-function _getNoExpiryDismissed() {
- return _noExpiryDismissedCache || {};
-}
/** Permanently mark a product as "no expiry needed" for this browser. */
function _dismissNoExpiry(productId) {
const m = Object.assign({}, _noExpiryDismissedCache || {});
@@ -6002,6 +5998,31 @@ function _dismissNoExpiry(productId) {
_noExpiryDismissedCache = m;
_saveToServer('no_expiry_dismissed', m);
}
+/** Remove the "no expiry needed" mark for a product (e.g. user unchecks the box). */
+function _undismissNoExpiry(productId) {
+ const m = Object.assign({}, _noExpiryDismissedCache || {});
+ delete m[String(productId)];
+ _noExpiryDismissedCache = m;
+ _saveToServer('no_expiry_dismissed', m);
+}
+/** Build the "Ne se périme pas" toggle HTML for an expiry date input. */
+function _noExpiryCheckboxHtml(expiryInputId, checked = false) {
+ return `
+
+ ♾️ Ne se périme pas
+
+
+
+
+
+ `;
+}
+function toggleNoExpiryField(expiryInputId, isChecked) {
+ const input = document.getElementById(expiryInputId);
+ if (!input) return;
+ input.disabled = isChecked;
+ if (isChecked) input.value = '';
+}
// === ALERT BANNER SYSTEM (replaces old review table) ===
let _bannerQueue = []; // array of { type, data } — 'review' or 'prediction'
@@ -7704,7 +7725,8 @@ window._editingProduct = {
${t('inventory.label_expiry')}
-
+
+ ${_noExpiryCheckboxHtml('edit-expiry', !item.expiry_date && !!_getNoExpiryDismissed()[String(item.product_id)])}
@@ -7763,7 +7785,9 @@ async function submitEditInventory(e, id, productId) {
}
const qty = parseFloat(document.getElementById('edit-qty').value);
const loc = document.getElementById('edit-loc').value;
- const expiry = document.getElementById('edit-expiry').value || null;
+ const noExpiryChecked = document.getElementById('edit-expiry-no-expiry')?.checked || false;
+ if (noExpiryChecked) _dismissNoExpiry(productId); else _undismissNoExpiry(productId);
+ const expiry = noExpiryChecked ? null : (document.getElementById('edit-expiry').value || null);
const unit = document.getElementById('edit-unit').value;
if (unit === 'conf') {
@@ -9657,7 +9681,8 @@ function editActionInventoryItem(inventoryId) {
${t('inventory.label_expiry')}
-
+
+ ${_noExpiryCheckboxHtml('action-edit-expiry', !item.expiry_date && !!_getNoExpiryDismissed()[String(item.product_id)])}
@@ -9690,7 +9715,9 @@ async function submitActionEditInventory(e, id, productId) {
e.preventDefault();
const qty = parseFloat(document.getElementById('action-edit-qty').value);
const loc = document.getElementById('action-edit-loc').value;
- const expiry = document.getElementById('action-edit-expiry').value || null;
+ const noExpiryChecked = document.getElementById('action-edit-expiry-no-expiry')?.checked || false;
+ if (noExpiryChecked) _dismissNoExpiry(productId); else _undismissNoExpiry(productId);
+ const expiry = noExpiryChecked ? null : (document.getElementById('action-edit-expiry').value || null);
const unit = document.getElementById('action-edit-unit').value;
const payload = { id, quantity: qty, location: loc, expiry_date: expiry, unit, product_id: productId,
@@ -10089,6 +10116,7 @@ function showAddForm() {
📷
${t('add.hint_modify')}
+ ${_noExpiryCheckboxHtml('add-expiry')}
@@ -10400,6 +10428,7 @@ function selectPurchaseType(btn, type) {
📷
${t('add.hint_modify')}
+ ${_noExpiryCheckboxHtml('add-expiry')}
`;
// Restore quantity - switching purchase type should NOT change it
document.getElementById('add-quantity').value = currentQty;
@@ -10416,6 +10445,7 @@ function selectPurchaseType(btn, type) {
📷
${t('product.expiry_hint')}
+ ${_noExpiryCheckboxHtml('add-expiry')}
${t('add.remaining_label')}
@@ -10586,11 +10616,13 @@ async function submitAdd(e) {
showLoading(true);
try {
+ const noExpiryChecked = document.getElementById('add-expiry-no-expiry')?.checked || false;
+ if (noExpiryChecked) _dismissNoExpiry(currentProduct.id);
const result = await api('inventory_add', {}, 'POST', {
product_id: currentProduct.id,
quantity: parseFloat(document.getElementById('add-quantity').value) || 1,
location: document.getElementById('add-location').value,
- expiry_date: document.getElementById('add-expiry').value || null,
+ expiry_date: noExpiryChecked ? null : (document.getElementById('add-expiry').value || null),
expiry_user_set: _expiryUserSetPayload('add-expiry'),
unit: selectedUnit !== productUnit ? selectedUnit : null,
package_unit: selectedUnit === 'conf' ? (document.getElementById('add-conf-unit')?.value || null) : null,