Migrovane z
docs-old-cvrn/guides/AKO_TO_FUNGUJE.md.
Tento dokument je centralny technicky prehlad aplikacie CVRN. Ciel: na jednom mieste popisat, co appka robi, ake ma flow, ake ma pravidla pristupu, a kde je logika v kode a databaze.
Stav dokumentu: aktualizovany podla kodu k 2026-02-12.
1) Co je CVRN
CVRN je minimalisticka komunitna web appka na poziciavanie bicyklov.
Aplikacia riesi:
- prihlasenie cez Google (Supabase Auth),
- allowlist pristup pre clenov komunity,
- pravidlo "1 user = max 1 aktivne pozicany bicykel",
- user dashboard (vyber bicykla alebo aktualna jazda),
- admin cast (allowlist, stavy bicyklov, kody, poznamky, historia),
- statistiky komunity na route
/stats, - verejny changelog na route
/changelog.
2) Role a pristup
| Rola | Pristup | Typicke moznosti |
|---|---|---|
| Neprihlaseny navstevnik | Verejny landing (/landing, /log, /ciele, /amnestia, /krstiny, /onboarding, /adopcia, /pravidla, /desatoro, /contact) + public route (/login, /auth/callback, /changelog) | Informacie o projekte + prihlasenie |
| Prihlaseny mimo allowlistu | Redirect na /not-authorized (fallback view existuje aj na /) | Poziadat o aktivaciu |
| Prihlaseny allowlisted user | Dashboard /, statistiky /stats | Pozicat/vratit bicykel, vidiet community stats |
| Admin | Vsetko ako allowlisted user + /admin | Spravovat allowlist, bicykle, historiu |
3) Route mapa (co je kde)
/login- Google OAuth login.
- Informacia o pravidlach komunity a spracuvani osobnych udajov.
/auth/callback- OAuth callback, vymena code za session.
/- Hlavny dashboard.
- Stav A: user nema bicykel -> zoznam bicyklov + rent dialog.
- Stav B: user ma bicykel -> karta "Aktualna jazda" + kod zamku + return formular.
/stats- 3 komunitne grafy za vybrany mesiac + month switcher.
- Pristup iba pre allowlisted usera.
/admin- Admin panel (allowlist, bicykle, historia jazd).
- Pristup iba pre admina.
/not-authorized- Stranka pre usera mimo allowlistu.
/changelog- Verejna stranka citajuca
docs/CHANGELOG.md.
- Verejna stranka citajuca
/landing,/log,/ciele,/amnestia,/krstiny,/onboarding,/adopcia,/pravidla,/desatoro,/contact- Verejny obsah pre landing web.
- Primarne obsluhovany na hoste
cvrn.sk/www.cvrn.sk.
4) Hlavicka, paticka, globalne UI spravanie
- Hlavicka (
SiteHeader):- brand logo (SVG
32px, light/dark varianta) + textcvrn.sk(link na/, hover/focus reveal na desktope), Toggle Mode(light/dark) + klavesaD,- ikona statistik (link
/stats), - cervene tlacidlo
Pomoc(mailto), Admintlacidlo iba pre admina,Odhlasit.
- brand logo (SVG
- Tlacidlo
Pomocma dynamicky predmet:- ak ma user aktivny bicykel:
Problem s bicyklom: <nazov>, - inak vseobecny predmet.
- ak ma user aktivny bicykel:
- Paticka (
SiteFooter):- zobrazi verziu appky
vX.Y.Z, - verzia je link na
/changelog.
- zobrazi verziu appky
- Theme:
- default podla localStorage / system preference,
- prepina sa tlacidlom alebo klavesou
D(mimo input/textarea/select).
5) User flow podrobne
5.1 Login flow
- User otvori
/login. - Klikne
Prihlasit sa cez Google. - OAuth redirect ide cez Supabase.
/auth/callbackdokonci session.- Middleware pusti usera dalej podla stavu pristupu.
5.2 User mimo allowlistu
- Primarny flow: middleware redirectne usera na
/not-authorized. - Fallback v dashboard kode: existuje aj cakaren karta "Ucet caka na aktivaciu" s CTA mailto.
5.3 Dashboard: user nema pozicany bicykel
Zobrazi sa zoznam bicyklov z RPC list_bikes_public().
- Stavy bicykla:
available(dostupny),rented(pozicany),service(v servise),issue_notezapina warning variant.
- Klikatelny je iba
availablebike. - Klik otvori dialog "Pozicat bicykel".
Rent dialog obsahuje:
- text:
Chcete si pozicat bicykel <nazov>?, - obrazok bicykla,
- warning panel s
issue_note(ak existuje), - spodne iba tlacidlo
Pozicat(zavretie je cez krizik vpravo hore).
Obrazok bicykla v dialogu:
- nacitava sa zo statickeho suboru
public/<nazov-bicykla>.png, - URL sa sklada z mena bicykla +
.png(encodeURIComponentpre bezpecne znaky), - kontajner je stvorcovy (
aspect-square) a obrazok sa oreze cezobject-cover, - ak subor neexistuje, zobrazi sa fallback hlaska (nie rozbity image).
5.4 Pozicanie bicykla (mutacia)
- Formular vola
rentBikeAction. - Action vola RPC
rent_bike(bike_id). - DB pravidla idu cez centralny transition guard model (
bike_transition_guard+bike_transition_apply):- user musi byt prihlaseny,
- user musi byt allowlisted,
- user nesmie mat iny aktivny rental,
- bike musi existovat a byt
available.
- Pri uspechu:
- bicykel ide do
rented, - naplni sa
current_user_id, - vytvori sa zaznam v
rentals, - action spravi
revalidatePath("/")arevalidatePath("/stats").
- bicykel ide do
5.5 Dashboard: user ma pozicany bicykel
Zobrazi sa karta "Aktualna jazda":
- nazov bicykla,
- kod zamku (
secret_code), - pripomienka na ocistenie bicykla a reset kodu na
0000, - volitelna poznamka pre servis,
- tlacidlo
Vratit bicykel.
Dolezite:
- v aktualnej jazde sa obrazok bicykla uz nezobrazuje,
- v admin casti sa obrazok bicykla tiez nezobrazuje.
5.6 Vratenie bicykla (mutacia)
- Formular vola
returnBikeAction. - Action vola RPC
return_bike(note_text). - DB update ide cez rovnake centralne transition guard jadro:
- bike ->
available, current_user_id = null,- aktivny rental dostane
returned_at = now(), - ak je poznamka, ulozi sa do
rentals.return_notea tiez dobikes.issue_note.
- bike ->
- Action revaliduje
/aj/stats.
6) Statisticka stranka /stats
Route zobrazuje 3 grafy za vybrany mesiac (timezone Europe/Bratislava).
Vpravo hore je month switcher (Select) a stav mesiaca je v URL:
/stats?month=YYYY-MM- ak
monthchyba alebo je neplatny, fallback je aktualny mesiac.
Select obsahuje:
- aktualny mesiac (vzdy),
- historicke mesiace od prveho mesiaca s datami.
Vypozicky po dnoch
- denny graf pre vybrany mesiac,
- metrika
Celkovoza vybrany mesiac, - tooltip
Vypozicky: X.
Vypozicky podla bicykla
- horizontalne bary pre bicykle,
- sumar vybraneho mesiaca + najviac vyuzivany bicykel.
Najaktivnejsi cyklista
- radial graf podielu top cyklistu,
- pocet vypoziciek top cyklistu za vybrany mesiac,
- zoznam dalsich cyklistov.
Data berie stranka cez RPC:
stats_get_monthly_daily_rentals(...),stats_get_monthly_rentals_by_bike(...),stats_get_monthly_rentals_by_cyclist(...).stats_get_available_months(...).
Ak stats RPC chybi alebo zlyha, UI zobrazi error banner s hintom na patchy:
003a004(hlavne mesacne agregacie),008(zoznam mesiacov pre switcher).
7) Admin flow /admin
Admin panel ma 3 casti:
- Allowlist
- pridanie e-mailu,
- odobratie e-mailu.
- Bicykle
- prehlad stavu a poznamok,
- edit
secret_code, - prepnutie
service <-> available(nie prirented), - vymazanie
issue_note.
- Historia jazd
- poslednych 200 zaznamov,
- user, bike, rented_at, returned_at, return_note.
- Admin zasahy (audit trail)
- poslednych 200 admin operacii,
- akcie: zmena kodu, zmena stavu, vymazanie poznamky,
- doplnene akcie pre PUK flow:
- uspesne zobrazenie historie kodov,
- neuspesne overenie PUK.
- Historia kodov bicykla (PUK)
- pri zmene kodu sa predchadzajuci kod ulozi do historie pre dany bicykel,
- v audite pri "Zmena kodu" je tlacidlo
Historia kodov, - po kliknuti sa otvori centrovany modal so 6-policovym PUK inputom,
- po uspesnom overeni PUK sa zobrazi cely historicky zoznam starych kodov pre dany bicykel (cas, admin, kod).
Admin akcie idu cez server actions a bike mutacie pouzivaju jednotny DB transition guard:
adminAddAllowedEmailAction,adminRemoveAllowedEmailAction,adminUpdateBikeCodeAction,adminSetBikeStatusAction,adminClearBikeNoteAction.
8) Datovy model (Supabase)
Tabulky:
profiles- profil usera (is_admin,email),bikes- aktualny stav bicykla (status,secret_code,current_user_id,issue_note),rentals- historia vypoziciek,allowed_emails- allowlist.admin_operations- audit admin operacii.bike_code_history- historia starych kodov po zmene kodu bicykla.admin_puk_config- hash PUK kodu pre overenie zobrazenia historie.
Hard pravidla v DB (indexy/constraints):
bikes_status_check: ibaavailable|rented|service,- max 1 aktivny rental na usera (
rentals_one_active_per_user), - max 1 aktivny rental na bicykel (
rentals_one_active_per_bike), bikes.current_user_idje unikatny pre aktivne priradenie (bikes_one_user_one_bike).
Automaticke zalozenie profilu:
- trigger
handle_new_user()vytvori profil po prvom prihlase, - prvy user v systeme sa stane adminom,
- prvy user sa automaticky prida do
allowed_emails.
9) RPC katalog (biznis logika)
Auth/role helpery:
is_admin()is_allowed()
User-safe read RPC:
list_bikes_public()get_my_bike()
Mutacne RPC:
rent_bike(bike_id)return_bike(note_text)
Admin RPC:
admin_list_rentals(limit_count)admin_list_operations(limit_count)admin_update_bike_code(bike_id, new_secret_code, reason_text)admin_set_bike_status(bike_id, next_status, reason_text)admin_clear_bike_note(bike_id, reason_text)admin_reveal_bike_code_history(p_bike_id, p_puk_code)
Stats RPC:
stats_get_monthly_daily_rentals(month_start, tz)stats_get_monthly_rentals_by_bike(month_start, tz)stats_get_monthly_rentals_by_cyclist(month_start, tz)stats_get_available_months(tz)
10) Bezpecnostny model
Klucove pravidlo: bezny user nesmie vidiet kody zamkov vsetkych bicyklov.
Ako je to spravene:
- RLS povoluje direct SELECT/UPDATE na citlive tabulky iba adminovi,
- bezny user cita iba cez security-definer RPC,
list_bikes_public()vracia verejne data bezsecret_code,get_my_bike()vraciasecret_codeiba pre bike, ktory ma aktualny user pozicany,- mutacie idu cez server action -> RPC, nie priamo z klienta.
11) Middleware pravidla
middleware.ts kontroluje:
- host-based flow:
cvrn.skawww.cvrn.sk-> landing (root/sa rewrite na/landing),- app route na apex hoste sa redirectuju na
app.cvrn.sk.
- na app hoste (
app.cvrn.sk) standardne auth pravidla:- session (neprihlaseny ->
/login), - allowlist (
is_allowed), - admin route (
/adminlen pre admina), - public route ostavaju dostupne bez auth.
- session (neprihlaseny ->
12) Kde je co v kode
Hlavne stranky:
src/app/page.tsxsrc/app/login/page.tsxsrc/app/stats/page.tsxsrc/app/admin/page.tsxsrc/app/not-authorized/page.tsxsrc/app/changelog/page.tsxsrc/app/landing/page.tsxsrc/app/log/page.tsxsrc/app/ciele/page.tsxsrc/app/amnestia/page.tsxsrc/app/krstiny/page.tsxsrc/app/onboarding/page.tsxsrc/app/adopcia/page.tsxsrc/app/pravidla/page.tsxsrc/app/desatoro/page.tsxsrc/app/contact/page.tsx
Klucove komponenty:
src/app/_components/bike-list.tsx(zoznam + rent dialog + obrazok)src/components/site-header.tsxsrc/components/site-footer.tsxsrc/components/theme-toggle.tsx
Server a auth vrstva:
src/app/actions.ts(server actions)src/lib/supabase/server.tssrc/lib/supabase/browser.tssrc/lib/supabase/middleware.tsmiddleware.ts
DB a patchy:
supabase/schema.sqlsupabase/seed.sqlsupabase/patches/001_fix_rent_bike.sqlsupabase/patches/002_fix_rent_bike_ambiguous_id.sqlsupabase/patches/003_add_stats_rpc.sqlsupabase/patches/004_add_monthly_cyclist_stats.sqlsupabase/patches/005_add_admin_operations_rpc.sqlsupabase/patches/006_add_puk_code_history.sqlsupabase/patches/007_add_bike_transition_guard_model.sql
13) Staticke assety pre bicykle (obrazky)
Miesto:
public/
Pravidlo nazvu:
- presne
public/<nazov-bicykla-z-db>.png
Priklad:
- ak je v DB nazov bicykla
Vendelin, subor jepublic/Vendelin.png; - ak je v DB nazov bicykla
Vendelín, subor jepublic/Vendelín.png.
Odporucanie:
- drzat presnu zhodu nazvu s hodnotou
bikes.name(vratane diakritiky), - ak sa bike premenuje v DB, premenuj aj subor v
public/.
14) Prevadzkove poznamky
- Potrebne env premenne:
NEXT_PUBLIC_SUPABASE_URLNEXT_PUBLIC_SUPABASE_ANON_KEY
- Pre plne stats je nutne mat patchy
003a004. - Pre centralny bike transition guard model je nutne mat patch
007(ak nebezis fresh install zoschema.sql). - Changelog release informacie su v
docs/CHANGELOG.md. - Release pravidla (SemVer) su v
docs/VERSIONING.md.
15) Mental model na zapamatanie
Jedna veta:
"Next.js riesi UI a flow; Supabase riesi identitu, data a tvrde pravidla."
Ak menis funkcionalitu, vzdy si rozdel zmenu na 3 vrstvy:
- UI/UX (React komponenty),
- orchestrace (server actions + redirect/revalidate),
- data pravidla (RPC + RLS + indexy/constraints).
On This Page
1) Co je CVRN2) Role a pristup3) Route mapa (co je kde)4) Hlavicka, paticka, globalne UI spravanie5) User flow podrobne5.1 Login flow5.2 User mimo allowlistu5.3 Dashboard: user nema pozicany bicykel5.4 Pozicanie bicykla (mutacia)5.5 Dashboard: user ma pozicany bicykel5.6 Vratenie bicykla (mutacia)6) Statisticka stranka /stats7) Admin flow /admin8) Datovy model (Supabase)9) RPC katalog (biznis logika)10) Bezpecnostny model11) Middleware pravidla12) Kde je co v kode13) Staticke assety pre bicykle (obrazky)14) Prevadzkove poznamky15) Mental model na zapamatanie