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
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:
@@ -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');
|
||||
|
||||
Reference in New Issue
Block a user