Korjaa alikategoria-ongelmat

- api.php: getOrInitCategories() päivittää automaattisesti subcategories-kentän
  olemassaolevaan categories.json-tiedostoon ilman manuaalista seedausta
- index.html: alikategoria-valitsin julkaisulomakkeeseen (näkyy kun kategorialla on alikategoriat)
- script.js: subcategory tallennetaan uuteen julkaisuun
- script.js: filterPosts null-turva + hakukenttä etsii myös alikategoria-id:llä
- script.js: updateSubcategoryPicker() päivittää alikategoriat kategorian vaihtuessa

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-08 08:24:24 +02:00
parent 88e17d2b92
commit 993a137508
3 changed files with 50 additions and 12 deletions

16
api.php
View File

@@ -315,7 +315,21 @@ function getOrInitCategories(): array {
writeData('categories.json', $cats);
return $cats;
}
return readData('categories.json', []);
$cats = readData('categories.json', []);
// Merge in subcategories if existing file doesn't have them yet
$defaults = defaultCategories();
$defaultMap = [];
foreach ($defaults as $d) { $defaultMap[$d['id']] = $d; }
$changed = false;
foreach ($cats as &$cat) {
if (!isset($cat['subcategories']) && isset($defaultMap[$cat['id']]['subcategories'])) {
$cat['subcategories'] = $defaultMap[$cat['id']]['subcategories'];
$changed = true;
}
}
unset($cat);
if ($changed) writeData('categories.json', $cats);
return $cats;
}
// ─── Routing ───────────────────────────────────────────────────

View File

@@ -109,7 +109,12 @@
<div class="form-group">
<label>Kategoria</label>
<select id="sub-category"></select>
<select id="sub-category" onchange="updateSubcategoryPicker()"></select>
</div>
<div class="form-group" id="sub-subcategory-group" style="display:none">
<label>Alikategoria</label>
<select id="sub-subcategory"></select>
</div>
<div class="form-group">

View File

@@ -239,9 +239,10 @@ function filterPosts() {
cards.forEach(card => {
const matchesCat = currentFilter === 'all' || card.dataset.category === currentFilter;
const matchesSub = currentSubFilter === 'all' || card.dataset.subcategory === currentSubFilter;
const title = card.querySelector('h3').textContent.toLowerCase();
const desc = card.querySelector('p:not(.card-author)').textContent.toLowerCase();
const matchesSearch = title.includes(query) || desc.includes(query);
const title = (card.querySelector('h3')?.textContent || '').toLowerCase();
const desc = (card.querySelector('p:not(.card-author)')?.textContent || '').toLowerCase();
const subLbl = (card.dataset.subcategory || '').toLowerCase();
const matchesSearch = !query || title.includes(query) || desc.includes(query) || subLbl.includes(query);
const show = matchesCat && matchesSub && matchesSearch;
card.style.display = show ? '' : 'none';
if (show) visible++;
@@ -402,10 +403,27 @@ function setSubmitType(type) {
document.getElementById('sub-typePostBtn').classList.toggle('active', type === 'post');
}
function updateSubcategoryPicker() {
const catId = document.getElementById('sub-category').value;
const cat = APP.categories.find(c => c.id === catId);
const subs = cat?.subcategories || [];
const group = document.getElementById('sub-subcategory-group');
const sel = document.getElementById('sub-subcategory');
if (!subs.length) {
group.style.display = 'none';
sel.innerHTML = '';
} else {
sel.innerHTML = `<option value="">— Valitse alikategoria —</option>` +
subs.map(s => `<option value="${s.id}">${s.fi}</option>`).join('');
group.style.display = '';
}
}
function openSubmitModal() {
const cats = APP.categories;
const sel = document.getElementById('sub-category');
sel.innerHTML = cats.map(c => `<option value="${c.id}">${c.emoji || ''} ${c.fi}</option>`).join('');
updateSubcategoryPicker();
setSubmitType('recipe');
document.getElementById('submitOverlay').classList.add('open');
document.body.style.overflow = 'hidden';
@@ -508,6 +526,7 @@ async function submitPublicPost() {
}
const category = document.getElementById('sub-category').value;
const subcategory = document.getElementById('sub-subcategory')?.value || '';
const cat = APP.categories.find(c => c.id === category);
const emoji = cat?.emoji || '📝';
const author = document.getElementById('sub-author').value.trim() || 'Vieras';
@@ -520,7 +539,7 @@ async function submitPublicPost() {
const post = {
id: title.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g,'').replace(/\s+/g,'_').replace(/[^a-z0-9_]/g,'') + '_' + Date.now(),
title, emoji, category, author, desc, images,
title, emoji, category, subcategory, author, desc, images,
type: submitType,
};