Actualiser assets/js/app.js
CI / PHP Syntax Check (push) Has been cancelled
CI / JavaScript Lint (push) Has been cancelled
CI / Docker Build Test (push) Has been cancelled
CI / Validate Translation Files (push) Has been cancelled
CI / Auto-merge develop → main (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled

This commit is contained in:
2026-06-18 16:49:19 +00:00
parent cfcc3ce49f
commit 5a4e16c30d
+142
View File
@@ -1398,6 +1398,7 @@ async function _loadConfigPage() {
await _loadCategoriesConfigSection();
await _loadSubcategoryConfigSection();
await _loadRecipeTagsConfigSection();
await _loadCustomUnitsConfigSection();
}
async function _loadRecipeTagsConfigSection() {
@@ -1507,6 +1508,134 @@ async function removeRecipeTagConfig(key) {
}
}
async function _loadCustomUnitsConfigSection() {
const container = document.getElementById('custom-units-list-container');
if (!container) return;
container.innerHTML = `<p class="settings-hint">Chargement…</p>`;
try {
const result = await api('custom_units_list', {}, 'GET');
if (!result.success) {
container.innerHTML = `<p class="settings-hint">Erreur de chargement.</p>`;
return;
}
CUSTOM_UNITS = result.units;
renderCustomUnitsConfigList(result.units);
} catch (e) {
container.innerHTML = `<p class="settings-hint">Erreur de chargement.</p>`;
}
}
function renderCustomUnitsConfigList(units) {
const container = document.getElementById('custom-units-list-container');
if (!container) return;
if (!units || units.length === 0) {
container.innerHTML = `<p class="settings-hint">Aucune unité personnalisée.</p>`;
return;
}
const baseOptionsHtml = (selected) => ['g', 'ml', 'pz'].map(b => `<option value="${b}" ${selected === b ? 'selected' : ''}>${b}</option>`).join('');
container.innerHTML = units.map(u => `
<div class="loc-row" style="display:flex;align-items:center;gap:8px;padding:8px 0;border-bottom:1px solid var(--border,#e2e8f0);flex-wrap:wrap">
<input type="text" class="form-input" style="max-width:60px;text-align:center" value="${escapeHtml(u.icon)}" id="cunit-icon-${u.key}" maxlength="4">
<span class="settings-hint" style="min-width:50px">${escapeHtml(u.key)}</span>
<input type="text" class="form-input" style="flex:1;min-width:120px" value="${escapeHtml(u.label)}" id="cunit-label-${u.key}">
<select class="form-input" style="max-width:80px" id="cunit-base-${u.key}">${baseOptionsHtml(u.base_unit)}</select>
<input type="number" class="form-input" style="max-width:100px" value="${escapeHtml(String(u.factor))}" id="cunit-factor-${u.key}" min="0.001" step="any">
<button class="btn btn-small btn-primary" onclick="updateCustomUnitConfig('${u.key}')" title="Enregistrer">💾</button>
<button class="btn btn-small btn-secondary" onclick="removeCustomUnitConfig('${u.key}')" title="Supprimer">🗑</button>
</div>
`).join('');
}
async function addCustomUnitConfig() {
const iconInput = document.getElementById('new-unit-icon');
const keyInput = document.getElementById('new-unit-key');
const labelInput = document.getElementById('new-unit-label');
const baseInput = document.getElementById('new-unit-base');
const factorInput = document.getElementById('new-unit-factor');
const icon = iconInput.value.trim() || '📏';
const key = keyInput.value.trim();
const label = labelInput.value.trim();
const base_unit = baseInput.value;
const factor = parseFloat(factorInput.value);
if (!key || !label) {
showToast('Indique une clé et un nom pour la nouvelle unité', 'warning');
return;
}
if (!factor || factor <= 0) {
showToast('Indique un facteur de conversion valide', 'warning');
return;
}
showLoading(true);
try {
const result = await api('custom_units_add', {}, 'POST', { key, label, icon, base_unit, factor });
showLoading(false);
if (result.success) {
showToast(`Unité "${label}" ajoutée`, 'success');
keyInput.value = '';
labelInput.value = '';
factorInput.value = '';
_loadCustomUnitsConfigSection();
} else {
showToast(result.error || 'Erreur lors de l\'ajout', 'error');
}
} catch (e) {
showLoading(false);
showToast('Erreur lors de l\'ajout', 'error');
}
}
async function updateCustomUnitConfig(key) {
const icon = document.getElementById(`cunit-icon-${key}`).value.trim() || '📏';
const label = document.getElementById(`cunit-label-${key}`).value.trim();
const base_unit = document.getElementById(`cunit-base-${key}`).value;
const factor = parseFloat(document.getElementById(`cunit-factor-${key}`).value);
if (!label) {
showToast('Le nom ne peut pas être vide', 'warning');
return;
}
if (!factor || factor <= 0) {
showToast('Facteur de conversion invalide', 'warning');
return;
}
showLoading(true);
try {
const result = await api('custom_units_update', {}, 'POST', { key, label, icon, base_unit, factor });
showLoading(false);
if (result.success) {
showToast('Unité mise à jour', 'success');
_loadCustomUnitsConfigSection();
} else {
showToast(result.error || 'Erreur', 'error');
}
} catch (e) {
showLoading(false);
showToast('Erreur', 'error');
}
}
async function removeCustomUnitConfig(key) {
if (!confirm(`Supprimer cette unité ?`)) return;
showLoading(true);
try {
const result = await api('custom_units_remove', {}, 'POST', { key });
showLoading(false);
if (result.success) {
showToast('Unité supprimée', 'success');
_loadCustomUnitsConfigSection();
} else {
showToast(result.error || 'Impossible de supprimer', 'error');
}
} catch (e) {
showLoading(false);
showToast('Erreur lors de la suppression', 'error');
}
}
async function _loadCategoriesConfigSection() {
const container = document.getElementById('categories-list-container');
if (!container) return;
@@ -15164,6 +15293,18 @@ async function loadRecipeTags() {
}
}
let CUSTOM_UNITS = [];
async function loadCustomUnits() {
try {
const result = await api('custom_units_list', {}, 'GET');
if (result.success && Array.isArray(result.units)) {
CUSTOM_UNITS = result.units;
}
} catch (e) {
console.warn('[EverShelf] Could not load custom units:', e);
}
}
let _recipeLibraryCache = [];
async function loadRecipeLibrary() {
@@ -20508,6 +20649,7 @@ async function _initApp() {
// Load recipe tags (used by the "Mes recettes" form and filter bar)
await loadRecipeTags();
await loadCustomUnits();
// Check for setup wizard resume (after language change)
const resumeStep = localStorage.getItem('evershelf_setup_step');