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 _loadCategoriesConfigSection();
|
||||||
await _loadSubcategoryConfigSection();
|
await _loadSubcategoryConfigSection();
|
||||||
await _loadRecipeTagsConfigSection();
|
await _loadRecipeTagsConfigSection();
|
||||||
|
await _loadCustomUnitsConfigSection();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function _loadRecipeTagsConfigSection() {
|
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() {
|
async function _loadCategoriesConfigSection() {
|
||||||
const container = document.getElementById('categories-list-container');
|
const container = document.getElementById('categories-list-container');
|
||||||
if (!container) return;
|
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 = [];
|
let _recipeLibraryCache = [];
|
||||||
|
|
||||||
async function loadRecipeLibrary() {
|
async function loadRecipeLibrary() {
|
||||||
@@ -20508,6 +20649,7 @@ async function _initApp() {
|
|||||||
|
|
||||||
// Load recipe tags (used by the "Mes recettes" form and filter bar)
|
// Load recipe tags (used by the "Mes recettes" form and filter bar)
|
||||||
await loadRecipeTags();
|
await loadRecipeTags();
|
||||||
|
await loadCustomUnits();
|
||||||
|
|
||||||
// Check for setup wizard resume (after language change)
|
// Check for setup wizard resume (after language change)
|
||||||
const resumeStep = localStorage.getItem('evershelf_setup_step');
|
const resumeStep = localStorage.getItem('evershelf_setup_step');
|
||||||
|
|||||||
Reference in New Issue
Block a user