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-19 16:32:41 +00:00
parent 726d371d26
commit 833afb3cfd
+28 -4
View File
@@ -1426,9 +1426,10 @@ function renderRecipeTagsConfigList(tags) {
return;
}
container.innerHTML = tags.map(tag => `
<div class="loc-row" style="display:flex;align-items:center;gap:8px;padding:8px 0;border-bottom:1px solid var(--border,#e2e8f0)">
<div class="loc-row" style="display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:8px 0;border-bottom:1px solid var(--border,#e2e8f0)">
<input type="text" class="form-input" style="max-width:60px;text-align:center" value="${escapeHtml(tag.icon)}" id="rtag-icon-${tag.key}" maxlength="4">
<input type="text" class="form-input" style="flex:1" value="${escapeHtml(tag.label)}" id="rtag-label-${tag.key}">
<input type="text" class="form-input" style="flex:1;min-width:120px" value="${escapeHtml(tag.label)}" id="rtag-label-${tag.key}">
<input type="text" class="form-input" style="flex:2;min-width:160px" value="${escapeHtml(tag.keywords || '')}" id="rtag-keywords-${tag.key}" placeholder="Mots-clés (ex: citron, lime)">
<button class="btn btn-small btn-primary" onclick="updateRecipeTagConfig('${tag.key}')" title="Enregistrer">💾</button>
<button class="btn btn-small btn-secondary" onclick="removeRecipeTagConfig('${tag.key}')" title="Supprimer">🗑</button>
</div>
@@ -1438,8 +1439,10 @@ function renderRecipeTagsConfigList(tags) {
async function addRecipeTagConfig() {
const iconInput = document.getElementById('new-recipe-tag-icon');
const labelInput = document.getElementById('new-recipe-tag-label');
const keywordsInput = document.getElementById('new-recipe-tag-keywords');
const icon = iconInput.value.trim() || '🏷️';
const label = labelInput.value.trim();
const keywords = keywordsInput ? keywordsInput.value.trim() : '';
if (!label) {
showToast('Indique un nom pour le nouveau tag', 'warning');
@@ -1448,12 +1451,13 @@ async function addRecipeTagConfig() {
showLoading(true);
try {
const result = await api('recipe_tags_add', {}, 'POST', { label, icon });
const result = await api('recipe_tags_add', {}, 'POST', { label, icon, keywords });
showLoading(false);
if (result.success) {
showToast(`Tag "${label}" ajouté`, 'success');
iconInput.value = '';
labelInput.value = '';
if (keywordsInput) keywordsInput.value = '';
_loadRecipeTagsConfigSection();
} else {
showToast(result.error || 'Erreur lors de l\'ajout', 'error');
@@ -1467,6 +1471,8 @@ async function addRecipeTagConfig() {
async function updateRecipeTagConfig(key) {
const icon = document.getElementById(`rtag-icon-${key}`).value.trim() || '🏷️';
const label = document.getElementById(`rtag-label-${key}`).value.trim();
const keywordsEl = document.getElementById(`rtag-keywords-${key}`);
const keywords = keywordsEl ? keywordsEl.value.trim() : '';
if (!label) {
showToast('Le nom ne peut pas être vide', 'warning');
@@ -1475,7 +1481,7 @@ async function updateRecipeTagConfig(key) {
showLoading(true);
try {
const result = await api('recipe_tags_update', {}, 'POST', { key, label, icon });
const result = await api('recipe_tags_update', {}, 'POST', { key, label, icon, keywords });
showLoading(false);
if (result.success) {
showToast('Tag mis à jour', 'success');
@@ -15428,10 +15434,28 @@ Ingrédients :
document.getElementById('modal-overlay').style.display = 'flex';
}
function _normalizeForMatch(s) {
return (s || '').toString().toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '');
}
function matchRecipeTagsFromIngredients(ingredients) {
const norm = _normalizeForMatch(ingredients.map(i => i.name).join(' '));
const matched = [];
(RECIPE_TAGS || []).forEach(tag => {
const raw = (tag.keywords && tag.keywords.trim()) ? tag.keywords : tag.key;
const kws = raw.split(',').map(k => _normalizeForMatch(k.trim())).filter(Boolean);
if (kws.some(kw => kw.length > 1 && norm.includes(kw))) {
matched.push(tag.key);
}
});
return matched;
}
function analyzeRawRecipeText() {
const raw = document.getElementById('rl-import-raw').value;
if (!raw.trim()) { showToast('Colle un texte de recette', 'warning'); return; }
const parsed = parseRawRecipeText(raw);
parsed.tags = matchRecipeTagsFromIngredients(parsed.ingredients);
openRecipeLibraryForm(null, parsed);
}