Refaktoring 100% safe — přehlednost projektu

Stav dokumentu: Hotovo (archiv docs/tasks/done/) — kroky 1–6 hotové: sdílené parsování měsíce v app/lib/month-param.ts, sdílené formátování rozsahu měsíců v app/lib/month-format-cs.ts, čisté helpery katalogové stránky v app/lib/catalog-page-helpers.ts, parsery katalogových filtrů v app/lib/catalog-filter-params.ts, rozdělené label slovníky v app/lib/labels/ a cílený import cleanup v aktivně měněných souborech.

Cíl: postupně udělat projekt přehlednější a profesionálnější čistě mechanickými refaktory, které jsou ověřitelné přes TypeScript a build.

Rozsah: React Router/Vite aplikace (app/), sdílené knihovní helpery (app/lib/), částečně Cloudflare worker soubory pouze pokud půjde o přesun bez změny runtime chování. Dokumentace a task přehledy se mohou aktualizovat průběžně.

Mimo scope: změny SQL logiky, migrací, rout/URL, veřejné copy, CSS tříd, vizuálního návrhu, dependency upgrade, přidání nové funkčnosti, změna seed dat, mazání existujícího obsahu.


Bezpečnostní pravidla (návrhová — pro budoucí kroky stejného typu)

Každý další krok ve stylu „100 % safe“ by měl splnit:

  • Před změnou je čistý git status --short, nebo jsou cizí změny jasně oddělené.
  • Změna je jeden mechanický typ refaktoru: přesun, přejmenování interního helperu, barrel re-export, odstranění lokální duplicity.
  • Nemění se texty viditelné návštěvníkům, názvy CSS tříd, pořadí renderovaných bloků, SQL podmínky, URL parametry ani data.
  • Po změně projde npm run typecheck a npm run build.
  • Diff je zkontrolovaný ručně: očekávané jsou přesuny a importy, ne nové chování.
  • Jeden dokončený refaktor = jeden malý commit.

Audit: bezpeční kandidáti

OblastSoučasný stavProč je refaktor bezpečný
Parsování měsíceparseMonthParam je duplicitně v app/routes/byliny.tsx, app/routes/sezona.$month.tsx, app/routes/co-sbirat.$month.tsx.Jde o čistou funkci bez I/O; lze přesunout beze změny implementace.
Formátování měsíců na kartě bylinymonthLabel a formatHarvestMonths jsou lokální v app/routes/byliny.$slug.tsx, vedle existujících měsíčních helperů v app/lib/.Jde o čisté mapování čísla měsíce na text; lze přesunout s totožnými výstupy.
Helpery katalogu /bylinyapp/routes/byliny.tsx kombinuje loader, meta, UI a čisté helpery (catalogDescription, herbListCountPhrase, buildBylinySearch, QUICK_CHIPS).Přesun helperů a konstant nemění JSX ani loader data.
Parsování katalogových filtrůapp/db/herbs.server.ts obsahuje DB dotazy i URL/parser helpery (parseTopicScopeParam, parseScienceCatalogFilter, parseScienceMinTier, parseCatalogPmSlugs).Parsery jsou čisté; herbs.server.ts může exporty zachovat přes re-export, aby se nemusely měnit call-sites naráz.
Label slovníkyapp/lib/claim-labels.ts má cca 350 řádků a míchá témata, vědu, bezpečnost, obrázky, recepty a zpracování.Lze rozdělit po doménách a ponechat claim-labels.ts jako barrel re-export, takže existující importy zůstanou funkční.

Checklist

1. Sdílené parsování měsíce

Soubory:

  • Vytvořit: app/lib/month-param.ts

  • Upravit: app/routes/byliny.tsx

  • Upravit: app/routes/sezona.$month.tsx

  • Upravit: app/routes/co-sbirat.$month.tsx

  • Přesunout současnou implementaci parseMonthParam beze změny logiky do app/lib/month-param.ts.

  • Exportovat ji jako parseMonthParam(raw: string | null | undefined): number | null.

  • Nahradit lokální kopie importem ve třech routách.

  • Ověřit ručně zachované chování: null, undefined, "", "0", "13", "abc" vrací null; "1", "01", "12" vrací platný měsíc.

  • Spustit npm run typecheck.

  • Spustit npm run build.

2. Sdílené formátování rozsahu měsíců

Soubory:

  • Upravit: app/lib/month-labels-cs.ts nebo vytvořit app/lib/month-format-cs.ts

  • Upravit: app/routes/byliny.$slug.tsx

  • Přesunout lokální monthLabel a formatHarvestMonths z detailu byliny do sdíleného helperu.

  • Zachovat přesné výstupy včetně malých písmen a pomlčky: například 1leden, 1–3leden–březen.

  • V detailu byliny ponechat jen import a volání helperu.

  • Spustit npm run typecheck.

  • Spustit npm run build.

3. Vyčistit route /byliny od čistých helperů

Soubory:

  • Vytvořit: app/lib/catalog-page-helpers.ts

  • Upravit: app/routes/byliny.tsx

  • Přesunout catalogDescription, herbListCountPhrase, buildBylinySearch, hasTighterScienceMinFilter a QUICK_CHIPS do app/lib/catalog-page-helpers.ts.

  • Neměnit žádný text v QUICK_CHIPS ani žádné parametry generovaných odkazů.

  • V app/routes/byliny.tsx nahradit lokální definice importem.

  • Zkontrolovat diff: v JSX se nemají změnit Tailwind třídy, texty ani pořadí elementů.

  • Spustit npm run typecheck.

  • Spustit npm run build.

4. Oddělit parsery katalogových filtrů od DB dotazů

Soubory:

  • Vytvořit: app/lib/catalog-filter-params.ts

  • Upravit: app/db/herbs.server.ts

  • Volitelně upravit později: app/routes/byliny.tsx

  • Přesunout typy TopicScopeFilter, ScienceCatalogFilter, ScienceMinTier a parsery parseTopicScopeParam, parseScienceCatalogFilter, parseSpiritualCatalogFlag, parseScienceMinTier, parseCatalogPmSlugs.

  • V app/db/herbs.server.ts zachovat kompatibilní re-exporty, aby stávající importy z rout zůstaly funkční.

  • Nepřesouvat SQL builder herbIdsMatchingCatalogFilters v tomto kroku.

  • Zkontrolovat diff: SQL řetězce a bind pořadí musí zůstat beze změny.

  • Spustit npm run typecheck.

  • Spustit npm run build.

5. Rozdělit claim-labels.ts přes barrel export

Soubory:

  • Vytvořit: app/lib/labels/topic-labels.ts

  • Vytvořit: app/lib/labels/science-labels.ts

  • Vytvořit: app/lib/labels/safety-labels.ts

  • Vytvořit: app/lib/labels/media-processing-labels.ts

  • Upravit: app/lib/claim-labels.ts

  • Rozdělit konstanty a label funkce podle domén, ale neměnit hodnoty slovníků.

  • Ponechat app/lib/claim-labels.ts jako barrel soubor s export * from "./labels/...".

  • Neaktualizovat plošně existující importy v celé aplikaci v tom samém kroku; kompatibilita barrel exportu je hlavní bezpečnostní pojistka.

  • Zkontrolovat diff slovníků: žádná česká hodnota ani fallback chování se nesmí změnit.

  • Spustit npm run typecheck.

  • Spustit npm run build.

6. Volitelný import cleanup po stabilizaci

Soubory:

  • Upravit jen call-sites, které už používají rozdělené helpery.

  • Až budou předchozí kroky v main větvi, přesměrovat nové nebo aktivně měněné soubory na cílenější importy (app/lib/labels/..., app/lib/catalog-filter-params).

  • Nedělat plošný import churn přes celý projekt bez funkčního důvodu.

  • Spustit npm run typecheck.

  • Spustit npm run build.


Věci záměrně nezařazené jako 100% safe

  • Přepis SQL v app/db/herbs.server.ts nebo app/db/herb-detail.server.ts — vysoká hodnota, ale snadno změní výsledky katalogu.
  • Extrakce velkých JSX sekcí z app/routes/byliny.$slug.tsx — mechanicky možná, ale bez screenshot/regresních testů může nechtěně změnit render.
  • Úpravy veřejné copy a odstranění technických textů — existuje samostatný task odstraneni-technicke-copy-pro-navstevniky.md, ale jde o produktovou změnu, ne čistý refaktor.
  • Dependency upgrade, přidání lint/test stacku nebo změny build nástrojů — užitečné později, ale není to bezrizikový refaktor.
  • Mazání console.log ve workeru — může změnit observabilitu údržbového endpointu.

Akceptace celého projektu

  • app/routes/byliny.tsx, app/routes/byliny.$slug.tsx, app/db/herbs.server.ts a app/lib/claim-labels.ts jsou menší nebo mají jasnější odpovědnosti.
  • Veřejné stránky mají stejné routy, texty, metadata, třídy a datové výsledky jako před refaktorem.
  • npm run typecheck a npm run build prochází po každém dokončeném kroku.
  • Každý krok je samostatně revertovatelný.