From f98aa72ca03dad7f3c0c0c32b231839c7d10e912 Mon Sep 17 00:00:00 2001 From: Jukka Lampikoski Date: Sun, 8 Mar 2026 01:43:50 +0200 Subject: [PATCH] =?UTF-8?q?Alikategoriat:=20v=C3=A4lilehdet=20kategorian?= =?UTF-8?q?=20alla?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - defaultCategories(): subcategories-kenttä jokaisella kategorialla (reseptit: kasvis/vegaaniset/jälkiruuat, neulominen: aloittelijoille/ vaatteet/kodin tekstiilit) - 30 julkaisua merkitty subcategory-kentällä - script.js: currentSubFilter-tila, setSubFilter(), renderSubFilters() renderöi alafiltterit kun kategoria on valittu; filterPosts() ottaa molemmat filtterit huomioon; cards saavat data-subcategory-attribuutin - index.html: #subCategoryFilters-div kategoriafilttereiden alle - style.css: .sub-filter-btn -tyyli (pienempi, tummanharmaa aktiiviasennossa) Co-Authored-By: Claude Sonnet 4.6 --- api.php | 45 ++++++++++++++++++++++++++++----------------- index.html | 1 + script.js | 32 ++++++++++++++++++++++++++++---- style.css | 19 +++++++++++++++++++ 4 files changed, 76 insertions(+), 21 deletions(-) diff --git a/api.php b/api.php index 67c6574..1613bea 100644 --- a/api.php +++ b/api.php @@ -55,9 +55,20 @@ function isAdmin(): bool { // ─── Oletusdata ──────────────────────────────────────────────── function defaultCategories(): array { return [ - ['id' => 'recipes', 'fi' => 'Reseptit', 'en' => 'Recipes', 'emoji' => '🍳'], - ['id' => 'knitting', 'fi' => 'Neulominen', 'en' => 'Knitting', 'emoji' => '🧶'], - ['id' => 'tips', 'fi' => 'Vinkit', 'en' => 'Tips', 'emoji' => '💡'], + ['id' => 'recipes', 'fi' => 'Reseptit', 'en' => 'Recipes', 'emoji' => '🍳', + 'subcategories' => [ + ['id' => 'kasvis', 'fi' => 'Kasvis'], + ['id' => 'vegaaniset', 'fi' => 'Vegaaniset'], + ['id' => 'jalkiruuat', 'fi' => 'Jälkiruuat'], + ]], + ['id' => 'knitting', 'fi' => 'Neulominen', 'en' => 'Knitting', 'emoji' => '🧶', + 'subcategories' => [ + ['id' => 'aloittelijoille', 'fi' => 'Aloittelijoille'], + ['id' => 'vaatteet', 'fi' => 'Vaatteet'], + ['id' => 'kodin_tekstiilit','fi' => 'Kodin tekstiilit'], + ]], + ['id' => 'tips', 'fi' => 'Vinkit', 'en' => 'Tips', 'emoji' => '💡', + 'subcategories' => []], ]; } @@ -90,7 +101,7 @@ function defaultPosts(): array { ], [ 'id' => 'soup', 'emoji' => '🍲', 'title' => 'Täyttävä kasviskeitto', - 'category' => 'recipes', 'author' => 'Sinikka', + 'category' => 'recipes', 'subcategory' => 'kasvis', 'author' => 'Sinikka', 'time' => '45 min', 'servings' => '4 annosta', 'type' => 'recipe', 'desc' => 'Lämmittävä kulhollinen paksuja kasviksia rikkaassa yrttiliemessä.', 'ingredients' => ['2 rkl oliiviöljyä','1 sipuli','3 valkosipulia','3 porkkanaa, siivuina','2 perunaa, kuutioina','1 kesäkurpitsa','400 g tomaattimurskaa','1½ l kasvislientä','Timjami, rosmariini, suola, pippuri'], @@ -122,7 +133,7 @@ function defaultPosts(): array { ], [ 'id' => 'strawberry_quark', 'emoji' => '🍓', 'title' => 'Mansikkarahka', - 'category' => 'recipes', 'author' => 'Marjatta R.', + 'category' => 'recipes', 'subcategory' => 'jalkiruuat', 'author' => 'Marjatta R.', 'time' => '15 min', 'servings' => '4 annosta', 'type' => 'recipe', 'desc' => 'Helppo ja raikas jälkiruoka kesän makeimmista mansikoista. Valmistuu vartin kymmenessä minuutissa!', 'ingredients' => ['500 g tuoreita mansikoita','400 g rahkaa tai maitorahkaa','2 dl kuohukermaa','3 rkl sokeria tai hunajaa','1 tl vaniljasokeria','Mintunlehtiä koristeluun'], @@ -130,7 +141,7 @@ function defaultPosts(): array { ], [ 'id' => 'carrot_ginger_soup', 'emoji' => '🥕', 'title' => 'Porkkana-inkiväärikeitto', - 'category' => 'recipes', 'author' => 'Hannele', + 'category' => 'recipes', 'subcategory' => 'vegaaniset', 'author' => 'Hannele', 'time' => '35 min', 'servings' => '4 annosta', 'type' => 'recipe', 'desc' => 'Kirpeä inkivääri ja makea porkkana luovat täydellisen liiton tässä lämmittävässä keitossa.', 'ingredients' => ['700 g porkkanoita, siivuina','1 sipuli','3 valkosipulinkynttä','4 cm tuoretta inkivääriä, raastettuna','1 l kasvislientä','2 dl kookoskermaa','2 rkl oliiviöljyä','Suolaa, pippuria','Korianteria tai persiljaa tarjoiluun'], @@ -146,7 +157,7 @@ function defaultPosts(): array { ], [ 'id' => 'oat_blueberry_porridge', 'emoji' => '🫐', 'title' => 'Kaura-mustikkapuuro', - 'category' => 'recipes', 'author' => 'Maija-Liisa', + 'category' => 'recipes', 'subcategory' => 'vegaaniset', 'author' => 'Maija-Liisa', 'time' => '15 min', 'servings' => '2 annosta', 'type' => 'recipe', 'desc' => 'Täyttävä aamiainen, joka antaa energiaa koko aamulle. Mustikka tekee siitä erityisen.', 'ingredients' => ['2 dl kaurahiutaleita','5 dl maitoa tai kasvijuomaa','½ tl suolaa','1 rkl voita','2 dl mustikkaa (tuore tai pakaste)','Hunajaa tai vaahterasiirappia','Mantelilastuja päälle'], @@ -162,7 +173,7 @@ function defaultPosts(): array { ], [ 'id' => 'blueberry_pie', 'emoji' => '🫐', 'title' => 'Mustikkapiirakka', - 'category' => 'recipes', 'author' => 'Riitta H.', + 'category' => 'recipes', 'subcategory' => 'jalkiruuat', 'author' => 'Riitta H.', 'time' => '1 t 10 min', 'servings' => '8 palaa', 'type' => 'recipe', 'desc' => 'Mummolan klassikko — murea taikina ja täyteläinen mustikkatäyte. Parasta vaniljakastikkeen kera.', 'ingredients' => ['Pohja: 150 g voita, 1 dl sokeria, 1 muna, 3½ dl vehnäjauhoja, 1 tl leivinjauhetta','Täyte: 4 dl mustikkaa, ½ dl sokeria, 1 rkl perunajauhoja','Vaniljakastiketta tarjoiluun'], @@ -170,7 +181,7 @@ function defaultPosts(): array { ], [ 'id' => 'avocado_pasta', 'emoji' => '🥑', 'title' => 'Kermainen avokadopasta', - 'category' => 'recipes', 'author' => 'Sinikka', + 'category' => 'recipes', 'subcategory' => 'kasvis', 'author' => 'Sinikka', 'time' => '20 min', 'servings' => '2 annosta', 'type' => 'recipe', 'desc' => 'Nopea arkipäivän pasta, jonka kastike valmistuu siinä ajassa kuin pasta kiehuu.', 'ingredients' => ['200 g pastaa','2 kypsää avokadoa','1 valkosipulinkynsi','1 sitruunan mehu','2 rkl oliiviöljyä','Suolaa, pippuria','Kirsikkatomaatteja, basilikanlehtiä tarjoiluun','Parmesaania päälle'], @@ -186,7 +197,7 @@ function defaultPosts(): array { ], [ 'id' => 'cauliflower_soup', 'emoji' => '🥦', 'title' => 'Samettinen kukkakaalikeitto', - 'category' => 'recipes', 'author' => 'Pirkko', + 'category' => 'recipes', 'subcategory' => 'kasvis', 'author' => 'Pirkko', 'time' => '30 min', 'servings' => '4 annosta', 'type' => 'recipe', 'desc' => 'Silky-sileä kukkakaalikeitto — yllättävän täyteläinen ja herkullinen arki-illalliseksi.', 'ingredients' => ['1 kukkakaali, paloina','1 sipuli','2 valkosipulinkynttä','1 l kasvislientä','2 dl kermaa','2 rkl oliiviöljyä','Suolaa, valkopippuria','Paahdettuja pähkinöitä tai yrttejä tarjoiluun'], @@ -203,31 +214,31 @@ function defaultPosts(): array { // ── NEULOMINEN ─────────────────────────────────────────── [ 'id' => 'knitting_scarf', 'emoji' => '🧶', 'title' => 'Helppo huivi aloittelijalle', - 'category' => 'knitting', 'author' => 'Tuulikki', 'type' => 'post', + 'category' => 'knitting', 'subcategory' => 'aloittelijoille', 'author' => 'Tuulikki', 'type' => 'post', 'desc' => 'Neulo kaunis huivi muutamassa tunnissa — täydellinen ensimmäinen projekti!', 'body' => '

Tarvitset:

Ohje: Luo 20 silmukkaa. Neulo suoraan (edestakaisin oikein silmukoin) kunnes huivi on noin 150 cm pitkä. Päättele silmukat ja viimeistele päät. Valmis! 🎉

Vinkki: Paksuilla langoilla ja suurilla neuloilla saat huivista nopeasti valmiin, vaikka olisit aloittelija.

', ], [ 'id' => 'knitting_mittens', 'emoji' => '🧤', 'title' => 'Peukalolapaset aloittelijalle', - 'category' => 'knitting', 'author' => 'Hannele', 'type' => 'post', + 'category' => 'knitting', 'subcategory' => 'vaatteet', 'author' => 'Hannele', 'type' => 'post', 'desc' => 'Yksinkertaiset lapaset jotka valmistuvat viikonloppuna — lämpimät ja persoonalliset.', 'body' => '

Tarvitset:

Ohje:

  1. Luo 36 silmukkaa pyöröneulalle ja neulo 2×2-joustinta 8 cm.
  2. Vaihda sileään neuleeseen ja lisää peukaloreikää varten 8 silmukkaa.
  3. Neulo suora 15 cm peukaloreikään saakka.
  4. Sulje yläpää vähentämällä 8 silmukkaa joka toisella kerroksella.
  5. Neulo peukalo erillisistä silmukoista.

Vinkki: Käytä värillistä lankaa tekemään kirjoneuleraita, niin lapasista tulee yksilölliset! 🎨

', ], [ 'id' => 'knitting_hat', 'emoji' => '🎩', 'title' => 'Yksinkertainen pipo', - 'category' => 'knitting', 'author' => 'Aino S.', 'type' => 'post', + 'category' => 'knitting', 'subcategory' => 'vaatteet', 'author' => 'Aino S.', 'type' => 'post', 'desc' => 'Pipo syntyy parissa illassa — kiva lahja tai itselle talven varalle.', 'body' => '

Pipo on helppo ja nopea projekti, täydellinen aloittelijalle!

Tarvitset:

Ohje (koko S/M):

  1. Luo 88 silmukkaa ja liitä rengasneuleeksi.
  2. Neulo 2×2-joustinta 8 cm.
  3. Vaihda sileään neuleeseen ja neulo 18 cm.
  4. Pienennä: * 8 oikein, 2 yhteen * — toista koko kerrokselle.
  5. Neulo 1 kerros suoraan. Toista pienennykset kunnes jäljellä on 9 silmukkaa.
  6. Vedä lanka silmukoiden lävitse ja kiristä napakasti.
', ], [ 'id' => 'knitting_socks', 'emoji' => '🧦', 'title' => 'Ensimmäiset villasukat', - 'category' => 'knitting', 'author' => 'Maija-Liisa', 'type' => 'post', + 'category' => 'knitting', 'subcategory' => 'vaatteet', 'author' => 'Maija-Liisa', 'type' => 'post', 'desc' => 'Sukat ovat hauskempia neuloa kuin luulet — ja miten hyvältä ne tuntuivatkaan jalassa!', 'body' => '

Villasukat ovat yksi neulomisen perinteisimmistä ja palkitsevimmista projekteista.

Tarvikeet:

Rakenne:

  1. Varsi: Luo 60 silmukkaa 5 neulalle. Neulo 2×2-joustinta 15–20 cm.
  2. Kantapää: Neulo 30 silmukkaa edestakainen 30 kerrosta, tee kantapäämuoto lyhentämällä.
  3. Jalka: Nosta silmukat, neulo tasaisesti 18–20 cm tai kenkänumeron mukaan.
  4. Varvas: Pienennä symmetrisesti kunnes 16 silmukkaa jäljellä. Sulje Kitchener-ompeleella.

Ensimmäinen sukka näyttää hassulta — älä luovuta! Toinen onnistuu jo paremmin. 😄

', ], [ 'id' => 'knitting_basics', 'emoji' => '📚', 'title' => 'Neulomisen perusteet — näin aloitat', - 'category' => 'knitting', 'author' => 'Riitta H.', 'type' => 'post', + 'category' => 'knitting', 'subcategory' => 'aloittelijoille', 'author' => 'Riitta H.', 'type' => 'post', 'desc' => 'Oletko aina haaveillut neulomisesta mutta et tiedä mistä aloittaa? Tässä kaikki mitä tarvitset tietää.', 'body' => '

Neulominen on rentouttava harrastus, jonka voi aloittaa hyvin pienellä välineistöllä.

Perusvälineet

Perustekniikat

  1. Silmukoiden luominen: Tee lenkkejä peukalonympäri tai käytä puikolle-tekniikkaa.
  2. Oikea silmukka: Pistä neula silmukan läpi takaa eteen, kierrä lanka ja vedä läpi.
  3. Nurja silmukka: Pistä neula silmukan läpi edestä taakse, kierrä lanka ja vedä läpi.

Harjoittele ensin pienellä neliöllä ennen kuin alat varsinaiseen projektiin. Pian kädet muistavat liikkeet itsestään! 🧶

', ], @@ -239,7 +250,7 @@ function defaultPosts(): array { ], [ 'id' => 'knitting_dishcloth', 'emoji' => '🫧', 'title' => 'Neulottu tiskiliina', - 'category' => 'knitting', 'author' => 'Kaisa M.', 'type' => 'post', + 'category' => 'knitting', 'subcategory' => 'kodin_tekstiilit', 'author' => 'Kaisa M.', 'type' => 'post', 'desc' => 'Ekologinen vaihtoehto kertakäyttöisille tiskisienille. Valmistuu tunnissa ja kestää vuosia.', 'body' => '

Neulottu tiskiliina on täydellinen ensiprojekti — yksinkertainen, nopea ja hyödyllinen!

Tarvikeet:

Ohje:

  1. Luo 30 silmukkaa.
  2. Neulo helmineuletta: * 1 oikein, 1 nurjin * — toista joka kerros.
  3. Jatka kunnes tiskiliina on neliön muotoinen (noin 20×20 cm).
  4. Päättele silmukat löysästi.

Helmineule tarkoittaa, että molemmat puolet ovat samannäköisiä. Tee useampia eri väreissä! 🎨

', ], @@ -251,7 +262,7 @@ function defaultPosts(): array { ], [ 'id' => 'crochet_basket', 'emoji' => '🧺', 'title' => 'Virkkaa kori langantähteistä', - 'category' => 'knitting', 'author' => 'Marjatta R.', 'type' => 'post', + 'category' => 'knitting', 'subcategory' => 'kodin_tekstiilit', 'author' => 'Marjatta R.', 'type' => 'post', 'desc' => 'Käytä lankatähteet hyödyksi! Kori syntyy muutamassa tunnissa ja sopii kaikkeen säilyttämiseen.', 'body' => '

Tässä pääset eroon lankatähteistä luovasti. Yhdistä eri värejä raidalliseen koriin!

Tarvikeet:

Ohje:

  1. Pohja: Luo taikusilmukka. Virkkaa 12 pistettä ensimmäiseen kierrokseen. Lisää joka toisella kierroksella 6 pistettä. Jatka 5 kierrosta kunnes halkaisija on noin 15 cm.
  2. Reunat: Virkkaa vain jokaisen pisteen takimmaisen silmukan lävitse (pystyy korin reunan). Virkkaa suoraan ylöspäin 10–15 cm.
  3. Viimeistely: Päätä piste tiukasti ja piilota langat.

💡 Paksuilla langoilla kori kasvaa nopeasti. Kokeile tehdä eri kokoisia koreja sarjana!

', ], diff --git a/index.html b/index.html index 68ecee5..586382e 100644 --- a/index.html +++ b/index.html @@ -39,6 +39,7 @@
+
diff --git a/script.js b/script.js index 4aa5986..a3079d3 100644 --- a/script.js +++ b/script.js @@ -177,7 +177,7 @@ function renderCards() { ? `
${p.title}
` : `
${p.emoji}
`; return ` -
+
${cardImgHTML}
${getCategoryLabel(p.category)} @@ -201,25 +201,48 @@ function renderCards() { // =========================== // FILTER & SEARCH // =========================== -let currentFilter = 'all'; +let currentFilter = 'all'; +let currentSubFilter = 'all'; function setFilter(category, btn) { - currentFilter = category; + currentFilter = category; + currentSubFilter = 'all'; document.querySelectorAll('.filter-btn').forEach(b => b.classList.remove('active')); btn.classList.add('active'); + renderSubFilters(); filterPosts(); } +function setSubFilter(sub, btn) { + currentSubFilter = sub; + document.querySelectorAll('.sub-filter-btn').forEach(b => b.classList.remove('active')); + btn.classList.add('active'); + filterPosts(); +} + +function renderSubFilters() { + const container = document.getElementById('subCategoryFilters'); + if (!container) return; + if (currentFilter === 'all') { container.innerHTML = ''; return; } + const cat = APP.categories.find(c => c.id === currentFilter); + const subs = cat?.subcategories || []; + if (!subs.length) { container.innerHTML = ''; return; } + container.innerHTML = + `` + + subs.map(s => ``).join(''); +} + function filterPosts() { const query = (document.getElementById('search')?.value || '').toLowerCase(); const cards = document.querySelectorAll('.recipe-card'); let visible = 0; 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 show = matchesCat && matchesSearch; + const show = matchesCat && matchesSub && matchesSearch; card.style.display = show ? '' : 'none'; if (show) visible++; }); @@ -605,6 +628,7 @@ async function init() { } applyTranslations(); renderCategoryFilters(); + renderSubFilters(); renderCards(); } diff --git a/style.css b/style.css index ce0730f..d726c21 100644 --- a/style.css +++ b/style.css @@ -168,6 +168,25 @@ nav a:hover { color: #fff; } color: #fff; } +.sub-filters { margin-top: 6px; min-height: 0; } + +.sub-filter-btn { + padding: 5px 15px; + border: 1.5px solid var(--border); + border-radius: 20px; + background: #f5f5f5; + color: var(--text-light); + font-size: 0.78rem; + cursor: pointer; + transition: all 0.2s; +} + +.sub-filter-btn:hover, .sub-filter-btn.active { + background: #555; + border-color: #555; + color: #fff; +} + /* ===================== RECIPE GRID ===================== */