Přeskočit na obsah

Refaktor v3 — další vrstva kvality (mimo jádro v2)

Stav dokumentu: Částečně — kódové sliby v3 z roku 2026 jsou v hlavní větvi splněny (npm run verify = typecheck + ESLint + Vitest + build; CI volá verify). Otevřené zůstávají jen body závislé na regresní matici / produktové akceptaci (P2.3 SQL, volitelný PageDecor, případné další dělení DB). Archiv v2: refaktor-v2.md.

Cíl: shrnout další směry — větší soubory mimo kartu byliny, DB vrstvu kolem detailu, opakující se UI vzory, tooling (lint/test/CI), přístupnost, výkon a provoz workeru — tak, aby šly brát po jednom malém diffu s npm run verify.

Zásada: stejně jako u archivu refaktoring-100-safe.md a v2 — žádné „big bang“ commity; u vizuálu a SQL vždy explicitní akceptace a kontrola regrese.


0. Vztah k předchozím refaktorům

  • v1 (100% safe): sdílené helpery, labely, parsery — hotové v archivu refaktoring-100-safe.md; neměnit zpětně bez důvodu.
  • v2 (archiv): mechanický cleanup §1, infrastruktura §3, bezpečná část §2.3 (preview) — refaktor-v2.md. Otevřený backlog z původního §2 je v sekci „Převzatý backlog…“ níže.
  • v3: rozšířit stejný přístup na ostatní velké soubory a na procesní zlepšení (lint, testy, CI, observabilita).

Převzatý backlog z archivu refaktor v2 (§2 — /byliny a herbs.server.ts)

Zdroj archivu: refaktor-v2.md. Hotový bezpečný přesun preview helperů (herb-catalog-preview.server.ts) zůstává popsán v archivu v §2.3; zde jen otevřené kroky.

P2.1 Rozdělit app/routes/byliny.$slug.tsx po sekcích

Hotovo: sekce v app/components/herb-detail/ (hero, harvest, storage, processing, spiritual, science, images, safety, …); složení stránky v herb-detail-page.tsx (HerbDetailPage); route skládá meta, loader a předá data do HerbDetailPage.

Bezpečnostní pravidla (splněno v implementaci):

  • Postupně extrahované sekce; props podle loader dat.
  • Neměněny texty ani pořadí sekcí v rámci refaktoru.

P2.2 Rozdělit app/routes/byliny.tsx na filtr panel a výsledky

Hotovo: app/components/catalog-filter-form.tsx, catalog-intro.tsx, catalog-herb-results.tsx; výpočet „jsou aktivní filtry“ v app/lib/catalog-page-helpers.ts (catalogHasActiveFilters, typ CatalogLoaderFilterSnapshot) + Vitest catalog-page-helpers.test.ts.

P2.3 Rizikové úpravy app/db/herbs.server.ts (SQL / filtry)

  • Přepis nebo přeskupení herbIdsMatchingCatalogFilters.
  • Skládání SQL fragmentů jinak než dnes.
  • Změna logiky science, studyType, month + part.

Stav: záměrně neprovedeno v rámci v3 bez datové / URL → ID matice nebo cílených integračních testů na D1. Parsery URL (parseMonthParam, parseCatalogPmSlugs, …) mají Vitest v app/lib/*.test.ts.


1. Velké soubory a routy (kromě přeneseného backlogu P2.x)

1.1 app/routes/sezona.$month.tsx (~300+ řádků)

Hotovo: tabulka bylin v app/components/sezona/sezona-month-herbs-table.tsx (SezonaMonthHerbsTable); měsíční chipy, regiony a části v app/components/sezona/sezona-month-filters.tsx (SezonaMonthFilters); dekor (SoftBlob/LeafSprig), drobečky a úvodní blok v app/components/sezona/sezona-month-intro.tsx (SezonaMonthIntro); horní blok (obal relative + intro + filtry) v sezona-month-top.tsx (SezonaMonthTop); prázdný stav bez řádků v app/components/sezona/sezona-month-empty.tsx (SezonaMonthEmpty); meta měsíce v app/lib/sezona-month-meta.ts + sezona-month-meta.test.ts; meta přehledu /sezona v app/lib/sezona-index-meta.ts + sezona-index-meta.test.ts; hlavička přehledu /sezona v app/components/sezona/sezona-index-header.tsx (SezonaIndexHeader); mřížka měsíců přehledu v app/components/sezona/sezona-index-month-grid.tsx (SezonaIndexMonthGrid); odkazy do katalogu (?region, /byliny?month + part) v app/lib/sezona-month-catalog-links.ts + sezona-month-catalog-links.test.ts — beze změny URL, query, textů a Tailwindu v extrahovaných blocích.

1.2 app/db/herb-detail.server.ts (~470 řádků)

Hotovo (bezsqlářský krok): čisté helpery resolveHerbImageSrc a parseRecipeStepsJson v app/lib/herb-detail-helpers.ts (receptové kroky přes sdílené parseJsonStringArray v app/lib/json-string-array.ts); server modul je importuje. SQL texty a bindy beze změny.

1.3 Další DB moduly střední velikosti

Částečně: sdílená normalizace slugů v app/lib/catalog-slug-normalize.ts (normalizeCatalogSlug) — používá topics.server.ts přes normalizeTopicSlug v topic-slug.ts, processing-methods.server.ts a aliasová routa byliny-na-zpracovani.$slug. Vitest catalog-slug-normalize.test.ts. Parsování JSON polí řetězců v app/lib/json-string-array.ts (parseJsonStringArray) — spiritual-guides.server.ts a receptové kroky přes herb-detail-helpers / omitEmptyTrimmed; Vitest json-string-array.test.ts. Fragmenty SQL pro měsíc/region sezóny přesunuty do app/db/sezona-harvest-sql.server.ts (harvestCoversMonthSql, herbInRegionSql) — import v sezona.server.ts; texty SQL beze změny. Další rozdělení herbs.server.ts / sjednocení s katalogem — backlog; zásada „žádný přepis WHERE bez matice“ platí.

1.4 Komponenty s vlastní logikou

Hotovo (drobně): app/components/ritual-guide-steps.tsx — počáteční hydrated pro jednokrokové návody bez zbytečného setState v efektu; u více kroků zůstává obnova z sessionStorage v useEffect (s vědomým eslint-disable pro pravidlo set-state-in-effect v tomto souboru).

1.5 app/routes/home.tsx

Hotovo: blok „Sběr právě teď“ v app/components/home/home-sezona-teaser.tsx (HomeSezonaTeaser); celá úvodní karta (dekor, nadpis, lead, teaser, CTA katalog) v app/components/home/home-hero-card.tsx (HomeHeroCard) — beze změny textů, URL a Tailwindu.

1.6 Přehledové katalogové routy

Hotovo: úvodní bloky a mřížky karet mimo loader/meta u /ritualy (RitualyIndexIntro, RitualyIndexGuideGrid), /region (RegionIndexIntro, RegionIndexGrid), /symptomy (SymptomyIndexIntro včetně GET formuláře q, SymptomyIndexTopicGrid), /zpracovani (ZpracovaniIndexIntro, ZpracovaniIndexMethodGrid), /recepty (ReceptyIndexIntro, ReceptyIndexRecipeGrid). Routy jen skládají meta, loader a layout main.

1.7 Roadmap a dokumentace

Hotovo: obsah /roadmap v app/components/roadmap/roadmap-content.tsx (RoadmapContent); přehled /dokumentace v app/components/dokumentace/dokumentace-index-content.tsx (DokumentaceIndexContent); detail /dokumentace/:slug (drobečky + karta Markdown) v dokumentace-doc-view.tsx (DokumentaceDocView). Logika meta / loader a registry dokumentů zůstávají v routách.

1.8 Detail regionu a tématu (symptomu)

Hotovo: /region/:slugRegionDetailIntro, RegionDetailHerbGrid (app/components/region/); /symptomy/:slugSymptomyDetailIntro, SymptomyDetailHerbSection (app/components/symptomy/). Štítek regions.type sjednocen v app/lib/region-type-label.ts (regionTypeLabel) — používá RegionIndexGrid a RegionDetailIntro.

1.9 Detail rituálu a způsobu zpracování

Hotovo: /ritualy/:slugRitualyDetailIntro, RitualyDetailBody (app/components/ritualy/); /zpracovani/:slug — celý obsah stránky (včetně jednoho obalu relative) v zpracovani-detail-content.tsx (ZpracovaniDetailContent).


2. Opakující se UI a kořen aplikace

2.1 app/root.tsx — navigace a šablona

Hotovo: helper mainNavLinkClass(isActive); odkaz Přeskočit na obsah (#main-content); obal {children}id="main-content" a tabIndex={-1}.

2.2 Dekor a layout bloky

Neprovedeno (volitelné): tenký PageDecor — riziko změny hloubky DOM; až bude potřeba, samostatný diff se screenshotem.


3. Meta a obsah — konzistence (bez velkých SEO featur)

Hotovo: v app/lib/site-meta.ts konstanty SITE_BRAND_NAME, SITE_TITLE_SUFFIX, SITE_TITLE_PIPE_BRAND ( | …); websiteSocialMeta používá značku z konstanty. Titulky a popisy v meta u hlavních rout (/, /byliny, /sezona, /symptomy, /ritualy, /region, /zpracovani, /recepty, /roadmap, /dokumentace) sjednoceny přes tyto konstanty (beze změny zobrazovaného textu oproti předchozím řetězcům). Vitest: app/lib/site-meta.test.ts.


4. Tooling: lint, formát, testy, CI

4.1 ESLint (+ TypeScript plugin)

Hotovo: eslint.config.mjs@eslint/js, typescript-eslint, eslint-plugin-react-hooks; ignorované generované a build cesty.

4.2 Automatické testy

Hotovo: Vitest (vitest.config.ts), testy app/lib/month-param.test.ts, catalog-filter-params.test.ts, region-param.test.ts, site-meta.test.ts, topic-slug.test.ts, sezona-month-meta.test.ts, sezona-index-meta.test.ts, sezona-month-catalog-links.test.ts, catalog-page-helpers.test.ts, catalog-slug-normalize.test.ts, json-string-array.test.ts.

4.3 CI

Hotovo: .github/workflows/ci.yml spouští npm run verify (včetně cache npm dle setup-node).


5. Worker a provoz (workers/)

Hotovo (minimum): v workers/app.ts u scheduled runHerbMaintenance strukturovaný jednořádkový JSON log (level, component, trigger, ok, …) místo volného výpisu objektu. HTTP endpoint /__internal/herb-maintenance nadále vrací JSON tělo.


6. Výkon a assety

Částečně: Google Fonts v root.tsx už používají display=swap v URL; širší self-host / subset — samostatný úkol. Obrázky R2 / CLS — navázat na bezpecnost-a-media-stitky.md.


7. Repozitář a generované soubory

Beze změny kódu: pravidlo z v2 §3.3 platí (build/, .react-router/types, .wrangler/, worker-configuration.d.ts dle politiky — typicky necommitovat). Po merge konfliktech ověřit git ls-files.


8. Co zatím nedělat jako součást v3 refaktoru

  • Neměnit veřejné URL, slugy dokumentace ani sitemap logiku bez tasku a datové kontroly.
  • Nezasahovat do obsahu Markdownu v docs/ kvůli „úklidu“ — může změnit veřejné /dokumentace/:slug.
  • Neinstalovat lint + přepsat celý app/ v jednom PR s DB refaktorem.

Doporučené pořadí (indikativní)

  1. Stabilizovat otevřené body P2.x (P2.1–P2.2 hotovo; P2.3 čeká na matici).
  2. Jedna bezpečná extrakce z sezona.$month.tsx.
  3. První bezsqlářský split z herb-detail.server.ts.
  4. Malý helper pro NavLink třídy v root.tsx.
  5. Samostatný PR: ESLint základ.
  6. Samostatný PR: Vitest + testy parserů.

Akceptace dokumentu samotného

  • Po implementaci doplněn stavový řádek a checklisty výše.
  • Při zařazení do rozcestníku aktualizovat README.md v docs/tasks/ (řádek refaktor-v3).