OPORA — UI flow
Tento dokument definuje cílový UI flow pro OPORA (future-facing). Prioritou je škálovatelná SaaS struktura, jasné oddělení veřejné části a autentizované aplikace a kanonický datový model, kde všechno je Projekt.
Projektové trasy a návaznosti byly sladěny s kódem 11. 9. 2026. Podrobný kontrakt určuje [Projects UI flow](03-application/projects-ui-flow.md). Plánované moduly níže nejsou potvrzením implementace ani vydání.
Klíčová rozhodnutí (pro tento flow nevyjednatelná)
- Marketing je veřejný na
/…(bez nutnosti přihlášení). - **Aplikace je pod
/app/*** (autentizace je výchozí požadavek). - Projekty jsou kanonický zdroj.
- Neexistuje samostatný
/calculator. “Kalkulátor” je editace Projektu. - Post-login routing probíhá přes
/post-auth.
0) Mentální model architektury (vrstvy)
flowchart TD
Marketing[Layer1_Marketing] --> Auth[Layer2_Authentication]
Auth --> Org[Layer3_OrganizationContext]
Org --> Project[Layer4_ProjectContext]
Project --> Modules[Layer5_FeatureModules]1) Kompletní katalog stránek (cílový stav)
1.1 Veřejný marketing (bez session)
/— Landing/system— Produkt / systém/tarify— Cenové plány/kontakt— Kontakt
Veřejné “essentials”:
/terms/privacy/cookies/status
1.2 Autentizace (životní cyklus session)
/sign-in/sign-up/forgot-password/reset-password/api/auth/confirm— email/OTP confirmation callback (neobsahuje produktovou logiku)/post-auth— jediná stránka, která rozhoduje “co dál” po přihlášení/signed-out(volitelné)
1.3 `/app/*` entry + kontext organizace (vyžaduje session)
/app— vstup do aplikace (redirect na default, typicky/app/projects)/app/onboarding— vytvoření první organizace (první login / bez membership)/app/org-select— volba aktivní organizace (multi-org)/app/dashboard— KPI přehled (bez editace)
1.4 Projekty (kanonická entita)
/app/projects— seznam, hledání a filtry;/app/projects/archive— archiv projektů./app/projects/new— vytvořit koncept projektu./app/projects/[projectId]— Přehled a doporučený další krok./app/projects/[projectId]/edit— Návrh: Konstrukce, Podmínky a Kontroly./app/projects/[projectId]/results— Výsledky: aktuálnost, kusovník, cena a kontroly./app/projects/[projectId]/documents— Dokumenty: exporty, přílohy a revize./app/projects/[projectId]/operations— Provoz: připravenost, předání, kontroly a závady./app/projects/[projectId]/details— Údaje projektu; aktivní záložka Přehled./app/projects/[projectId]/technical-review— odborné posouzení; aktivní záložka Výsledky.
Hlavní navigace má pět záložek: Přehled · Návrh · Výsledky · Dokumenty · Provoz. Čtenář může otevřít Návrh bez možnosti editace. Revize a sdílení používají řízený dokumentový registr /app/documents; samostatné projektové /versions a /share nejsou implementované cíle tohoto workflow.
1.5 Moduly
- Sklad (implementováno):
/app/warehouse— pracovní přehled zásob/app/warehouse/items/[itemId]— položka, stavy, limity a historie/app/warehouse/operations— neměnný deník operací/app/warehouse/reservations— životní cyklus rezervací/app/warehouse/counts— inventury a kontrola rozdílů/app/warehouse/locations— hierarchie lokací- Blueprints (plánované):
/app/blueprints/app/blueprints/[blueprintId]- Settings:
/app/settings/app/settings/organization/app/settings/members/app/settings/profile/app/settings/billing
1.6 Utility + gating stránky (pro škálování SaaS)
Uvnitř aplikace:
/app/access-denied(RBAC)/app/subscription-required(bez předplatného)/app/upgrade-required(plán je příliš nízký)/app/maintenance(volitelné)
Na úrovni frameworku:
app/not-found.tsxapp/error.tsxapp/loading.tsx
3) Guard logika (jak se vynucuje přístup)
3.1 Routing pravidlo: `/app/*` vyžaduje autentizaci
Core invariant:
- Jakýkoli request na
/app/*bez validní session redirectuje na: /sign-in?redirect=/app/...
Tím odpadá křehká “public route allowlist” logika pro marketing stránky.
Explicitní rozdělení:
- Mimo
/appžijí pouze auth/session lifecycle stránky:/sign-in,/sign-up,/forgot-password,/reset-password,/post-autha callback/api/auth/confirm. - Všechno ostatní, co je “produkt”, je pod
/app/*.
3.1.1 Bez legacy top-level app rout
Legacy routy jako /dashboard, /projects, /settings, /calculator záměrně nepatří do cílové mapy.
- Doporučené chování během migrace: 301 redirect na jejich
/app/*ekvivalenty. - Doporučené chování po migraci: 404 (nebo ponechat redirecty natrvalo, pokud chcete stabilní backlinks).
3.2 `/post-auth` je jediný post-login router
Zde se rozhoduje onboarding, volba org a default landing.
flowchart TD
PostAuth["/post-auth"] --> HasOrg{Has_any_org_membership?}
HasOrg -->|No| GoOnboarding[Redirect_/app/onboarding]
HasOrg -->|Yes| MultiOrg{Multiple_orgs?}
MultiOrg -->|No| GoProjects[Redirect_/app/projects]
MultiOrg -->|Yes| HasActive{Active_org_selected?}
HasActive -->|No| GoOrgSelect[Redirect_/app/org-select]
HasActive -->|Yes| GoProjects3.3 Org kontext je povinný uvnitř `/app/*`
Po autentizaci všechny app routy předpokládají aktivní kontext organizace.
Pokud org kontext chybí / je nevalidní:
- redirect na
/app/onboarding(žádné membership) - redirect na
/app/org-select(multi-org nebo nevalidní selection)
3.4 RBAC + subscription gating (na úrovni funkcí)
flowchart TD
AppRoute[Request_/app/... ] --> SessionOK{Session_ok?}
SessionOK -->|No| ToSignIn[Redirect_/sign-in?redirect=...]
SessionOK -->|Yes| OrgOK{Org_context_ok?}
OrgOK -->|No| ToOrgFix[Redirect_/app/onboarding_or_/app/org-select]
OrgOK -->|Yes| RBAC{Has_permission?}
RBAC -->|No| Denied[Redirect_/app/access-denied]
RBAC -->|Yes| PlanGate{Plan_allows_feature?}
PlanGate -->|No| Upgrade[Redirect_/app/upgrade-required]
PlanGate -->|Yes| Allow[Allow_request]4) Projekty jsou kanonické (kalkulátor je mód Projektu)
4.1 Princip
Projekt propojuje návrh, výpočet, výsledky, dokumentové revize a provoz. Návrh má hlavní akci Uložit a spočítat; ruční potvrzení částí je samostatnou podmínkou přechodu k přípravě montáže. Výpočet části automaticky nepotvrzuje. Konstrukce je vložená do pracovního prostoru; celá obrazovka je explicitní volba. Změna vstupů zneplatní závislá potvrzení a aktuálnost výsledků.
flowchart LR
Projects["/app/projects"] -->|"New_project"| New["/app/projects/new"]
New -->|"Create_draft"| Edit["/app/projects/:projectId/edit"]
Edit -->|"Save_and_calculate"| Results["/app/projects/:projectId/results"]
Results -->|"Iterate"| Edit
Results --> Documents["/app/projects/:projectId/documents"]
Results --> Review["/app/projects/:projectId/technical-review"]
Home["/app/projects/:projectId"] --> Operations["/app/projects/:projectId/operations"]Otevření Provozu není souhlas se zahájením práce. Vydání dokumentu není technické schválení konstrukce. Obě rozhodnutí mají samostatné serverové brány.
4.3 Dokumenty, exporty a přístupové podmínky
Výsledky vedou k Dokumentům. Vytvoření výstupu podle jeho druhu kontroluje tenant, oprávnění, tarif, aktuálnost výpočtu a technickou připravenost. Vyšší tarif neodstraní technickou blokaci. Řízené revize mají samostatné submit/approve/issue workflow.
Stažení historického souboru nevyžaduje nový výpočet ani opětovné technické schválení. Endpoint ověřuje oprávnění, tenant, aktivní projekt a přesnou vazbu revize/artefaktu; u exportní úlohy také stav READY. Kontroluje uložený obsah, scan a expiraci podle typu souboru; vydaná řízená revize má vlastní výjimku pro expiraci. Stažení starého dokumentu neznamená schválení aktuálního návrhu.
flowchart LR
Results["/app/projects/:projectId/results"] --> Documents["/app/projects/:projectId/documents"]
Documents --> ExportGate{Server_output_gates_pass?}
ExportGate -->|No| Reason[Specific_block_reason_and_remediation]
ExportGate -->|Yes| Artifact[Create_or_download_exact_artifact]4.4 Role dashboardu (jen přehled)
Dashboard je read-only přehled. Má pouze deep-linkovat do Projektů.
flowchart LR
Dash["/app/dashboard"] --> Projects["/app/projects"]
Dash -->|"Open_recent_project"| ProjectHome["/app/projects/:projectId"]
Dash -->|"Create_project"| New["/app/projects/new"]5) Pricing a konverzní funnel (SaaS-konzistentní)
CTA na pricingu mají zachovat záměr pomocí query parametrů:
- Nový uživatel:
/sign-up?plan=pro - Vrací se:
/sign-in?redirect=/app/projects&plan=pro
flowchart TD
Tarify["/tarify"] -->|"Choose_plan"| SignUp["/sign-up?plan=..."]
Tarify -->|"Existing_account"| SignIn["/sign-in?redirect=/app/projects&plan=..."]
SignUp --> Confirm["/api/auth/confirm"]
Confirm --> PostAuth["/post-auth"]
PostAuth --> Projects["/app/projects"]