Alikategoria-parannukset: monivalinta, Muut-kategoria, emoji pois administa

- api.php: lisätään 'Muut'-alikategoria Resepteihin, Neulomiseen ja Vinkkeihin
- api.php: getOrInitCategories() lisää puuttuvat alikategoriat automaattisesti
- admin.html: poistetaan emoji-kenttä (emoji tulee kategoriasta automaattisesti)
- admin.html: alikategoriat checkboxeina → voi valita useamman samanaikaisesti
- script.js: subcategory tallennetaan aina taulukkona
- script.js: filterPosts tukee pilkulla eroteltuja alikategorioita (postSubs.includes)
- script.js: renderCards kirjoittaa subcategory-arrayn pilkulla eroteltuna data-attribuuttiin

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-08 08:30:10 +02:00
parent 993a137508
commit 22a03c10a0
3 changed files with 64 additions and 25 deletions

View File

@@ -245,15 +245,14 @@
</div>
</div>
<div class="form-row">
<div class="form-group">
<label id="lbl_category">Kategoria</label>
<select id="postCategory"></select>
</div>
<div class="form-group">
<label id="lbl_emoji">Emoji</label>
<input type="text" id="postEmoji" placeholder="🍽️" maxlength="4" />
</div>
<div class="form-group">
<label id="lbl_category">Kategoria</label>
<select id="postCategory" onchange="updateAdminSubcategories()"></select>
</div>
<div class="form-group" id="adminSubcatGroup" style="display:none">
<label>Alikategoriat <small style="color:#7a5c3e;font-weight:normal;text-transform:none">(voit valita useamman)</small></label>
<div id="adminSubcatCheckboxes" style="display:flex;flex-wrap:wrap;gap:8px;margin-top:4px"></div>
</div>
<div class="form-group">
@@ -600,6 +599,26 @@
const current = sel.value;
sel.innerHTML = ADMIN.categories.map(c => `<option value="${c.id}">${c.emoji || ''} ${c.fi} / ${c.en}</option>`).join('');
if (current) sel.value = current;
updateAdminSubcategories();
}
function updateAdminSubcategories(checked = []) {
const catId = document.getElementById('postCategory').value;
const cat = ADMIN.categories.find(c => c.id === catId);
const subs = cat?.subcategories || [];
const group = document.getElementById('adminSubcatGroup');
const box = document.getElementById('adminSubcatCheckboxes');
if (!subs.length) { group.style.display = 'none'; box.innerHTML = ''; return; }
group.style.display = '';
box.innerHTML = subs.map(s => `
<label style="display:flex;align-items:center;gap:5px;cursor:pointer;background:#f5f0eb;padding:5px 10px;border-radius:6px;font-size:0.88rem">
<input type="checkbox" value="${s.id}" ${checked.includes(s.id) ? 'checked' : ''} style="accent-color:#8b5e3c">
${s.fi}
</label>`).join('');
}
function getCheckedSubcategories() {
return [...document.querySelectorAll('#adminSubcatCheckboxes input[type=checkbox]:checked')].map(cb => cb.value);
}
// ===========================
@@ -645,11 +664,13 @@
let editingId = null;
async function savePost() {
const title = document.getElementById('postTitle').value.trim();
const emoji = document.getElementById('postEmoji').value.trim() || '🍽️';
const category = document.getElementById('postCategory').value;
const author = document.getElementById('postAuthor').value.trim();
const desc = document.getElementById('postDesc').value.trim();
const title = document.getElementById('postTitle').value.trim();
const category = document.getElementById('postCategory').value;
const subcategory = getCheckedSubcategories();
const cat = ADMIN.categories.find(c => c.id === category);
const emoji = cat?.emoji || '📝';
const author = document.getElementById('postAuthor').value.trim();
const desc = document.getElementById('postDesc').value.trim();
if (!title) { showToast(at('no_title')); return; }
@@ -658,7 +679,7 @@
document.getElementById('postImg2').value.trim(),
document.getElementById('postImg3').value.trim(),
].filter(Boolean);
const post = { title, emoji, category, author, desc, images, type: currentType };
const post = { title, emoji, category, subcategory, author, desc, images, type: currentType };
if (currentType === 'recipe') {
post.time = document.getElementById('postTime').value.trim();
@@ -698,9 +719,11 @@
editingId = id;
document.getElementById('formTitle').textContent = at('form_edit');
document.getElementById('postTitle').value = p.title;
document.getElementById('postEmoji').value = p.emoji;
document.getElementById('postCategory').value = p.category;
document.getElementById('postAuthor').value = p.author || '';
// Load subcategory checkboxes with existing values
const existingSubs = Array.isArray(p.subcategory) ? p.subcategory : (p.subcategory ? [p.subcategory] : []);
updateAdminSubcategories(existingSubs);
document.getElementById('postDesc').value = p.desc || '';
setAdmImgPreview(1, p.images?.[0] || '');
setAdmImgPreview(2, p.images?.[1] || '');
@@ -735,8 +758,8 @@
function resetForm() {
editingId = null;
document.getElementById('postTitle').value = '';
document.getElementById('postEmoji').value = '';
document.getElementById('postAuthor').value = '';
updateAdminSubcategories([]);
document.getElementById('postDesc').value = '';
document.getElementById('postTime').value = '';
document.getElementById('postServings').value = '';