From f832d9cecd1711f4e60f72405d7bc0eb0ab5b282 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Sikl=C3=B3di?= Date: Wed, 11 Nov 2026 21:56:54 +0100 Subject: [PATCH 1/4] =?UTF-8?q?docs:=20=C3=B6sszes=C3=ADtett=20kiad=C3=A1s?= =?UTF-8?q?i=20jegyz=C3=A9k=20(CHANGELOG.md)=20v0.1=E2=80=93v0.3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..631aff7 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,60 @@ +# ReformStudioSync — Kiadási jegyzék + +A verziók a legújabbtól a legrégebbiig. A `demo` ágon gyűlő változások a következő verzió alá kerülnek, és a `main`-re kerüléskor válnak kiadássá (Git tag + GitHub Release). Az alkalmazáson belüli Újdonságok menü forrása: `apps/web/src/pages/reception/model/releaseNotes.ts`. + +## v0.3 — a `demo`-n, a következő `main` kiadással élesedik + +### Új funkciók és oldalak +- **Belépés e-mailben kapott kóddal:** jelszó helyett a megadott e-mail címre érkező 6 jegyű kóddal lehet belépni; a kód 10 percig érvényes, és csak egyszer használható. (TICKET-35) +- **Új oldalsáv és Beállítások:** sötét, lebegő bal oldali menü; a nevedre kattintva felcsúszó panelből éred el a Beállításokat, a téma kapcsolót és a kijelentkezést. A téma mellett a felület színe is választható. (TICKET-28) +- **Monitorok oldal:** a vendégmonitorok és tabletek kezelése saját oldalt kapott, a profilpanelből érhető el. (TICKET-38) +- **Születésnapi köszöntés:** a születésnapos vendéget konfetti köszönti a Vendégmonitoron. (TICKET-36) +- **Vendég neme, női köredzés:** új vendég felvételekor a nem kötelező, a keresztnévből előtöltve (a meglévő vendégeknél a keresztnév alapján kitöltve). A csak nőknek szóló szolgáltatás (női köredzés) bérlete és tagsága férfi vendégnek nem adható el, és vele nem léptethető be; „nincs megadva” nemnél figyelmeztetés. Új szolgáltatásnál „Csak nőknek” jelölő. (TICKET-42) + +### Fejlesztések +- **Új navigáció:** a felső fülsor helyett bal oldali menü (Recepció, Vendégek, Bérletek és termékek, Pénzügy); minden résznek saját címe van, könyvjelzőzhető, és frissítés után ugyanott maradsz. (TICKET-21) +- **Megújult felület:** egységes kártyák, táblázatok, gombok és ablakok világos és sötét témában. + - Recepció: felül gyorsműveletek és napi összesítő, alatta beolvasás, utoljára azonosított vendég, vendégkereső, mai kassza és mai érkezések. (TICKET-22) + - Vendégek: áttekinthető táblázat (kártyaszám, név, telefon, bérlet, fennmaradó alkalmak, lejárat, állapot), soronként nyíló adatlap. (TICKET-23) + - Pénzügy, Bérletek és termékek, Újdonságok, bejelentkezés és demó. (TICKET-24) +- **Belépések a vendégadatlapon:** új „Belépések” fül (időpont, köredzés vagy kezelés, bérlet, rögzítő, állapot: sikeres / sztornózott / elutasított az okkal); a Bérletek fülön bérletenként is. (TICKET-40) +- **Szűrhető Újdonságok:** típus szerinti szűrés, kártyánként nyitható részletek. (TICKET-37) +- **Egységes hibaüzenetek:** minden hiba egyformán jelenik meg; lejárt bejelentkezésnél automatikusan a belépőoldalra visz. (TICKET-9) + +### Javítások +- **Beolvasás alkalmas bérlettel:** ha a vendégnek csak alkalmas bérlete van, a csippantás után a kezelésválasztó ablak nyílik meg (előre kitöltve), és a levonás a megerősítéskor történik; nincs több ingyenes köredzés-belépés kezelésbérlettel. (TICKET-39) +- **Bérletfagyasztás:** feloldáskor naptári napok szerint hosszabbodik a lejárat; csak érvényes bérlet fagyasztható; az előzményekben látszik, ki fagyasztott vagy oldott fel. (TICKET-41) +- **Szolgáltatáshoz illő üdvözlés:** a Vendégmonitor és a recepció a szolgáltatás szerint köszönt (köredzés: „Jó edzést”, kezelés: „Kellemes kezelést”, kozmetika: „Kellemes kikapcsolódást”); „Női Köredzés” csak a csak nőknek szóló köredzésnél. (TICKET-43) +- **Vendégmonitor kapcsolat:** + - valós kapcsolatállapot a fejlécben; a recepción bontott párosítás után a monitor azonnal a párosító kódot kéri (TICKET-32); + - a törölt vagy új kódot kapott kijelző azonnal lekapcsolódik (TICKET-31); + - az „Online (N kijelző)” csak a ténylegesen kapcsolódó monitorokat számolja (TICKET-30); + - a monitor és a recepció tartósan kapcsolódva marad, az üdvözlés nem vész el (TICKET-29). +- **Adatvédett Vendégmonitor:** soha nem mutat tartozást vagy elutasítási okot. (TICKET-17) +- **Kezeléslevonás:** az „1 Alkalom Levonása & Üdvözlés” jelzi, mi hiányzik (vendég, kezelés, bérlet), és ha még nincs felvett kezelés. (TICKET-27) +- **Befizetés:** bármilyen pozitív, egész forintösszeg rögzíthető (pl. 3 000 Ft), érvénytelen összegnél hibaüzenet. (TICKET-25) +- **Pontos alkalomszám:** a hátralévő alkalmak mindig a ténylegesen levont, vissza nem vont kezelésekből számolódnak, sztornó után is. (TICKET-16) +- **Havi tagdíjak:** minden hónapban automatikusan esedékessé válnak, így a tartozások és a késési kategóriák pontosak. (TICKET-13) + +## v0.2 — 2026-10-22 + +### Új funkciók és oldalak +- **Globális QR-kód és vonalkód olvasó:** a fizikai olvasó (USB / Bluetooth) minden megnyitott oldalon működik (`/reception`, `/monitor`, `/tablet`, `/demo`), fókusztól függetlenül; kereső- vagy űrlapmezőbe nem ír bele véletlenül; a magyar billentyűzetkiosztás miatt eltolt karaktereket javítja, és felismeri az URL-, JSON- és előtagos (`REFORM:100001`, `#100001`) kódokat; a fejlécben egy kattintással szüneteltethető. +- **Kétmódú Vendégmonitor:** a recepciós gép második kijelzőjén párosítás nélkül, önálló tableten / TV-n a recepción generált, 10 percig érvényes 6 jegyű kóddal. Kijelzők elnevezése, átnevezése, új kód, párosítás bontása és Teszt Jel küldése. +- **Köredzés és alkalmas kezelés:** havi tagsággal vagy időalapú bérlettel köredzésnél nincs levonás; alkalmas kezelésnél (pl. Hypoxi, Reformer) külön ablakban választható a kezelés és a bérlet (-1 alkalom), indoklással visszavonható. Az üdvözlés ideje 3–30 mp között állítható. +- **Havi tagságok és pénzügy:** tagságok (aktív, szüneteltetett, megszüntetett) és esedékességek; hátralék-kategóriák (1–5, 6–15, 15+ nap) recepciós figyelmeztetéssel; részbefizetés és célzott befizetés tagdíjhoz vagy bérlethez. +- **Bővített vendégkartoték:** testmérések (súly, testzsír%, izomtömeg, körméretek), automatikus WebP képoptimalizálás a vendégfotókhoz, belső megjegyzések és e-mail napló. +- **Tablet aláíró felület (`/tablet`):** GDPR és állapotfelmérő ívek aláírása. +- **Napi műszerfal:** születés- és névnapos vendégek, lejáró bérletek, szolgáltatás-megoszlás. + +### Fejlesztések +- **Dupla csippantás elleni védelem:** a védelmi ablak 60 mp-ről 10 mp-re csökkent, egy kattintással felülbírálható. +- **Sötét téma:** jobb olvashatóság a kártyákon, jelvényeken és gombokon. + +## v0.1 — 2026-10-20 (első verzió) + +- **Recepció (`/reception`):** beléptetés vonalkóddal, automatikus bérletválasztással (időalapú bérlet, utána a leghamarabb lejáró alkalmas bérlet) és dupla lehúzás elleni védelemmel; visszaigazoló értesítések minden művelethez; egy kattintásos sztornó (beléptetés és fizetés) és bérletmegújítás; offline beolvasási puffer, amely a kapcsolat visszatérésekor automatikusan szinkronizál. +- **Vendégkartoték (`/guests`):** vendégfelvétel, bérlettörténet, felhasználási napló; digitális belépőkártya (Code-128 vonalkód + QR-kód, PNG letöltés és nyomtatás); bérlethosszabbítás (+N nap), fagyasztás és feloldás. +- **Valós idejű Vendégmonitor (`/monitor`):** a recepciós gép második kijelzőjén vagy párosított tableten; a képernyő nem alszik el. +- **Demó (`/demo`):** élő adatbázistól független próbakörnyezet virtuális vonalkódolvasóval és beágyazott monitor-előnézettel. +- **Bejelentkezés és sötét téma.** From 474607f6aa5b2fb3e0d2ea94a2584199a84509bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Sikl=C3=B3di?= Date: Wed, 11 Nov 2026 22:01:15 +0100 Subject: [PATCH 2/4] =?UTF-8?q?docs:=20terv=20=E2=80=94=20verzi=C3=B3kezel?= =?UTF-8?q?=C3=A9s=20=C3=A9s=20kiad=C3=A1s=20(TICKET-44)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- docs/plans/2026-11-11-verziokezeles.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 docs/plans/2026-11-11-verziokezeles.md diff --git a/docs/plans/2026-11-11-verziokezeles.md b/docs/plans/2026-11-11-verziokezeles.md new file mode 100644 index 0000000..ef2d14c --- /dev/null +++ b/docs/plans/2026-11-11-verziokezeles.md @@ -0,0 +1,22 @@ +# Terv — 2026-11-11 — Verziókezelés és kiadás + +Állapot: Folyamatban (TICKET-44) + +Kérés (Márk): a demón is vezessük a kiadásokat, hogy a `main`-re küldéskor a verzió egyből ott legyen. A demón a v0.3 gyűlik; kell egy átfogó, a korábbi verziókat is tartalmazó kiadási jegyzék. + +## Jegy +| Jira | Cím | Típus | Méret | +| --- | --- | --- | --- | +| TICKET-44 | Verziókezelés: egy helyen a verziószám, Újdonságokból épülő verzió-ablak, kiadás a main-re küldéskor | IMPROVEMENT | S–M | + +## Tartalom +1. **Verziószám egy helyen:** `package.json` (gyökér és workspace-ek) `0.3.0`. A web a buildben kapja meg (Vite `define`); a bejelentkezőoldal verziójelvénye (`VersionBadge`) és a Vendégmonitor fejléc-chipje ebből olvas (most be van égetve: „v0.2”). +2. **Verzió-ablak az Újdonságokból:** a `VersionChangelogModal` a `RELEASE_NOTES`-ból épül, verziónként csoportosítva, a jelenlegi verzió elöl; a kézzel írt v0.2-es tartalom megszűnik. A v0.1 tételei bekerülnek a `releaseNotes.ts`-be (`jiraKey: null`). +3. **`CHANGELOG.md`** a repó gyökerében: összesített, verziónkénti kiadási jegyzék (v0.1–v0.3). +4. **Kiadás:** a demo → main PR összevonása után a Koordinátor: `git tag v` + `gh release create` a `CHANGELOG.md` adott verziójú részével. Leírás: `docs/WORKFLOW.md`, `reform-ticket` skill. +5. **Új verzió nyitása:** kiadás után a demón a verzió 0.4.0-ra emelkedik; unit teszt ellenőrzi, hogy egy Újdonságok-bejegyzés verziója sem nagyobb a `package.json` verziójánál. + +## Elfogadási feltételek +- A demón a bejelentkezőoldalon és a Vendégmonitoron „v0.3” látszik; a jelvényre kattintva a verzió-ablak v0.3, v0.2, v0.1 szerint mutatja a változásokat. +- A `main`-re kerüléskor létrejön a `v0.3.0` tag és a GitHub Release. +- CI zöld; kézi teszt világos és sötét témában. From 0d1a75a269330d8f816a7dce9f8b154d2c0f112b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Sikl=C3=B3di?= Date: Wed, 11 Nov 2026 22:09:19 +0100 Subject: [PATCH 3/4] =?UTF-8?q?feat(web):=20TICKET-44=20verzi=C3=B3sz?= =?UTF-8?q?=C3=A1m=20egy=20helyen,=20=C3=9Ajdons=C3=A1gokb=C3=B3l=20=C3=A9?= =?UTF-8?q?p=C3=BCl=C5=91=20verzi=C3=B3-ablak?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - A verziószám egyetlen forrása a gyökér package.json (0.3.0; a workspace-ek és a package-lock.json is). A web a Vite/Vitest `define`-ból kapja (`__APP_VERSION__`), a `shared/config` adja: APP_VERSION, APP_RELEASE_VERSION („0.3”), APP_VERSION_LABEL („v0.3”). - A bejelentkezőoldal/tablet verziójelvénye, a Vendégmonitor fejléc-chipje és az oldalsáv ebből olvas (eddig égetett „v0.2”, ill. a legújabb Újdonságok-bejegyzés verziója). - A verzió-ablak a RELEASE_NOTES-ból épül, verziónként: elöl a jelenlegi verzió nyitva, a korábbiak lenyithatók; tételenként típus-jelvény, cím, összefoglaló. A kézzel írt v0.2-es tartalom megszűnt. - FSD: az Újdonságok adata a pages/reception-ből az entities/release-note slice-ba került (verziócsoportosító és dátumformázó helperrel); az importok és a hivatkozó dokumentumok igazítva. - A v0.1 tételei bekerültek az Újdonságok végére (jiraKey: null). - Unit teszt: egy bejegyzés verziója sem nagyobb a package.json verziójánál, és a 0.3-tól kezdődő bejegyzéseknek van jiraKey-je. - Kiadás lépés: docs/WORKFLOW.md 2.5 és a reform-ticket skill (CHANGELOG dátum, tag, gh release, új verzió nyitása a demón); scripts/release-notes.sh kivágja a CHANGELOG adott verziójú szakaszát (nem taggel, nem pushol). - Újdonságok bejegyzés (IMPROVEMENT) és CHANGELOG tétel. Co-Authored-By: Claude Opus 5.5 --- .claude/skills/reform-ticket/SKILL.md | 27 +- .claude/skills/reformstudio-ui-skill/SKILL.md | 6 +- .cursor/rules/release-notes.mdc | 2 +- AGENTS.md | 2 +- CHANGELOG.md | 3 +- CLAUDE.md | 2 +- apps/api/package.json | 2 +- apps/web/package.json | 2 +- apps/web/src/app/App.tsx | 5 +- apps/web/src/entities/release-note/index.ts | 21 ++ .../release-note/model/releaseNoteGroups.ts | 32 ++ .../release-note/model/releaseNotes.test.ts | 60 ++++ .../release-note}/model/releaseNotes.ts | 75 ++++- apps/web/src/pages/monitor/ui/MonitorPage.tsx | 3 +- apps/web/src/pages/reception/index.ts | 1 - .../pages/reception/model/receptionTabs.ts | 2 +- .../reception/model/releaseNotesStore.ts | 2 +- .../src/pages/reception/ui/WhatsNewPanel.tsx | 30 +- apps/web/src/shared/config/index.ts | 7 + apps/web/src/shared/config/version.ts | 22 ++ apps/web/src/vite-env.d.ts | 3 + .../ui/VersionChangelogModal.tsx | 291 +++++++----------- apps/web/vite.config.ts | 9 + apps/web/vitest.config.ts | 9 + docs/ARCHITECTURE.md | 4 +- docs/WORKFLOW.md | 34 +- package-lock.json | 10 +- package.json | 2 +- packages/shared/package.json | 2 +- scripts/release-notes.sh | 41 +++ 30 files changed, 477 insertions(+), 234 deletions(-) create mode 100644 apps/web/src/entities/release-note/index.ts create mode 100644 apps/web/src/entities/release-note/model/releaseNoteGroups.ts create mode 100644 apps/web/src/entities/release-note/model/releaseNotes.test.ts rename apps/web/src/{pages/reception => entities/release-note}/model/releaseNotes.ts (89%) create mode 100644 apps/web/src/shared/config/version.ts create mode 100755 scripts/release-notes.sh diff --git a/.claude/skills/reform-ticket/SKILL.md b/.claude/skills/reform-ticket/SKILL.md index b2a3f42..459c117 100644 --- a/.claude/skills/reform-ticket/SKILL.md +++ b/.claude/skills/reform-ticket/SKILL.md @@ -192,8 +192,9 @@ Utána várj. A `main` felé csak kifejezett „oké” vagy „mehet a main” ## 8. PR `demo` → `main`, és lezárás „Oké” után a `references/demo-es-main-pr.md` szerint nyiss PR-t a `demo`-ról a -`main`-re. Ha a ticket felhasználó számára látható újdonság, kérdezd meg, kell-e -verzióléptetés (`docs/versions/` és a `widgets/version-changelog`). +`main`-re. A `demo` a következő verzión áll (gyökér `package.json`, pl. `0.3.0`), +a `main`-re kerüléskor ez lesz a kiadás; a PR címébe írd bele a verziót +(„demo → main: v0.3 (TICKET-NN, …)”). A `main` merge után: @@ -201,6 +202,28 @@ A `main` merge után: python .claude/skills/reform-ticket/scripts/reform_ticket.py transition TICKET-NN "Kész" ``` +### Kiadás + +Közvetlenül a `main` merge után, a `docs/WORKFLOW.md` 2.5 pontja szerint (a példa +a v0.3): + +1. `CHANGELOG.md`: a `## v0.3 — a demo-n …` címsorba a merge dátuma + (`## v0.3 — ÉÉÉÉ-HH-NN`), a tételek egyeztetése az Újdonságok 0.3-as bejegyzéseivel. +2. Tag a `main` merge commitjára: + `git fetch origin && git tag -a v0.3.0 origin/main -m "v0.3" && git push origin v0.3.0` +3. GitHub Release a CHANGELOG szakaszával: + `bash scripts/release-notes.sh 0.3 > `, majd + `gh release create v0.3.0 --title "v0.3" --notes-file `. + A szkript csak kivágja a szakaszt, nem taggel és nem pushol. +4. Új verzió nyitása a demón (külön ág, PR a `demo`-ra): `npm version 0.4.0 + --workspaces --include-workspace-root --no-git-tag-version` (négy `package.json` + és a `package-lock.json`), a CHANGELOG-ban a dátum és fölé új + `## v0.4 — a demo-n, a következő main kiadással élesedik` szakasz. Innentől az + Újdonságok bejegyzései `version: '0.4'`-et kapnak. + +A tag, a push és a Release kifelé látszó lépés: a Megrendelő „mehet a main”-je +erre is vonatkozik, de ha bármi eltér (pl. a `main`-en más is van), előbb szólj. + ## 9. Beszámoló Röviden, magyarul: diff --git a/.claude/skills/reformstudio-ui-skill/SKILL.md b/.claude/skills/reformstudio-ui-skill/SKILL.md index d2bf8ad..cf64d21 100644 --- a/.claude/skills/reformstudio-ui-skill/SKILL.md +++ b/.claude/skills/reformstudio-ui-skill/SKILL.md @@ -340,8 +340,8 @@ verzió rövid alakja („v0.3”) látszik. oldalsáv csukódása zárja. Billentyűzettel nyitva a fókusz a panel első elemére kerül. Mobilon nyitott panelnél az Esc csak a panelt zárja. - **Verzió**: a sor alatt a futó verzió („Verzió 0.3”, ikonsávban „v0.3”), 12 px - `sidebar-muted` `tabular-nums`, link az Újdonságokra. Az értéke a legújabb - `releaseNotes.ts` bejegyzés verziója. + `sidebar-muted` `tabular-nums`, link az Újdonságokra. Az értéke a gyökér + `package.json` verziója major.minor alakban (`shared/config`: `APP_RELEASE_VERSION`). ### 4.3 Fejléc @@ -823,7 +823,7 @@ kérdezd meg a felhasználót, ne találj ki negyediket. vonalkódolvasót a `/reception` és a `/demo` oldalon. - Az `references/accessibility.md` ellenőrzőlistája végigment. - Felhasználó számára látható változásnál bejegyzés a - `apps/web/src/pages/reception/model/releaseNotes.ts`-ben (`jiraKey` kötelező). + `apps/web/src/entities/release-note/model/releaseNotes.ts`-ben (`jiraKey` kötelező). ## 11. Beszámoló diff --git a/.cursor/rules/release-notes.mdc b/.cursor/rules/release-notes.mdc index a2bc644..563a2c5 100644 --- a/.cursor/rules/release-notes.mdc +++ b/.cursor/rules/release-notes.mdc @@ -6,7 +6,7 @@ alwaysApply: true # Kötelező Újdonságok Bejegyzés (Release Notes) -- Minden felhasználó számára érzékelhető változáshoz új bejegyzés kerül az `apps/web/src/pages/reception/model/releaseNotes.ts` `RELEASE_NOTES` tömbjének **elejére**. +- Minden felhasználó számára érzékelhető változáshoz új bejegyzés kerül az `apps/web/src/entities/release-note/model/releaseNotes.ts` `RELEASE_NOTES` tömbjének **elejére**. - **Kötelező a `jiraKey`** (pl. `KAN-12`) a visszakövethetőséghez; ugyanez a kulcs szerepel a commit üzenetben is. - **`link` csak `NEW_PAGE` / `NEW_FEATURE` típusnál**, és csak akkor, ha az újdonság a felületen ténylegesen megtekinthető (`receptionTab` vagy `route`). `IMPROVEMENT` / `FIX` esetén csak szöveges leírás. - Az `id` stabil és egyedi; meglévő bejegyzés `id`-ját ne módosítsd. diff --git a/AGENTS.md b/AGENTS.md index 369fd12..5255b5b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -32,7 +32,7 @@ A [`scripts/ci-wait.sh`](scripts/ci-wait.sh) az aktuális ág PR-ját figyeli (v ## Kötelező szabályok -- **Újdonságok:** minden felhasználó számára érzékelhető változáshoz bejegyzés az `apps/web/src/pages/reception/model/releaseNotes.ts`-be, kötelező `jiraKey`-jel ([`docs/WORKFLOW.md`](docs/WORKFLOW.md), [`.cursor/rules/release-notes.mdc`](.cursor/rules/release-notes.mdc)). +- **Újdonságok:** minden felhasználó számára érzékelhető változáshoz bejegyzés az `apps/web/src/entities/release-note/model/releaseNotes.ts`-be, kötelező `jiraKey`-jel ([`docs/WORKFLOW.md`](docs/WORKFLOW.md), [`.cursor/rules/release-notes.mdc`](.cursor/rules/release-notes.mdc)). - **UI:** `apps/web` felületi munkánál a [`reformstudio-ui-skill`](.claude/skills/reformstudio-ui-skill/SKILL.md) szerint ([`.cursor/rules/ui-design.mdc`](.cursor/rules/ui-design.mdc)). - **Téma:** világos és sötét téma mindenhol ([`.cursor/rules/theme-support.mdc`](.cursor/rules/theme-support.mdc)); a Vendégmonitor kivétel. - **FSD rétegek:** `npm run lint:fsd` ([`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) 1.2). diff --git a/CHANGELOG.md b/CHANGELOG.md index 631aff7..7adecab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # ReformStudioSync — Kiadási jegyzék -A verziók a legújabbtól a legrégebbiig. A `demo` ágon gyűlő változások a következő verzió alá kerülnek, és a `main`-re kerüléskor válnak kiadássá (Git tag + GitHub Release). Az alkalmazáson belüli Újdonságok menü forrása: `apps/web/src/pages/reception/model/releaseNotes.ts`. +A verziók a legújabbtól a legrégebbiig. A `demo` ágon gyűlő változások a következő verzió alá kerülnek, és a `main`-re kerüléskor válnak kiadássá (Git tag + GitHub Release). Az alkalmazáson belüli Újdonságok menü (és a bejelentkezőoldal verzió-ablaka) forrása: `apps/web/src/entities/release-note/model/releaseNotes.ts`. A verziószám egyetlen forrása a gyökér `package.json`; a kiadás menete: `docs/WORKFLOW.md` → „Kiadás”. Egy verzió szakasza: `bash scripts/release-notes.sh `. ## v0.3 — a `demo`-n, a következő `main` kiadással élesedik @@ -19,6 +19,7 @@ A verziók a legújabbtól a legrégebbiig. A `demo` ágon gyűlő változások - Pénzügy, Bérletek és termékek, Újdonságok, bejelentkezés és demó. (TICKET-24) - **Belépések a vendégadatlapon:** új „Belépések” fül (időpont, köredzés vagy kezelés, bérlet, rögzítő, állapot: sikeres / sztornózott / elutasított az okkal); a Bérletek fülön bérletenként is. (TICKET-40) - **Szűrhető Újdonságok:** típus szerinti szűrés, kártyánként nyitható részletek. (TICKET-37) +- **Verziónkénti változáslista:** a bejelentkezésnél és a Vendégmonitoron mindig a futó verzió látszik; a verziószámra kattintva az Újdonságokból épülő, verziónként lenyitható lista nyílik (elöl a jelenlegi verzió). (TICKET-44) - **Egységes hibaüzenetek:** minden hiba egyformán jelenik meg; lejárt bejelentkezésnél automatikusan a belépőoldalra visz. (TICKET-9) ### Javítások diff --git a/CLAUDE.md b/CLAUDE.md index 868f019..25e652b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -10,7 +10,7 @@ Monorepo: `apps/api` (NestJS + Prisma), `apps/web` (React + Vite + Tailwind, Fea ## Kötelező szabályok -- Minden felhasználó számára érzékelhető változáshoz bejegyzés kell az `apps/web/src/pages/reception/model/releaseNotes.ts`-be (Újdonságok menü): kötelező `jiraKey` (KAN-NN); `link` csak `NEW_PAGE`/`NEW_FEATURE` esetén, és csak ha az újdonság ténylegesen megtekinthető. +- Minden felhasználó számára érzékelhető változáshoz bejegyzés kell az `apps/web/src/entities/release-note/model/releaseNotes.ts`-be (Újdonságok menü): kötelező `jiraKey` (KAN-NN); `link` csak `NEW_PAGE`/`NEW_FEATURE` esetén, és csak ha az újdonság ténylegesen megtekinthető. - Minden `apps/web` felületi munkánál a **`reformstudio-ui-skill`** (`.claude/skills/reformstudio-ui-skill/SKILL.md`) az irányadó. - FSD rétegszabályok (`npm run lint:fsd`), sötét/világos téma (`.cursor/rules/theme-support.mdc`), magyar UI szöveg. - Jelentés előtt: `bash .claude/skills/reform-ticket/scripts/gate.sh`. diff --git a/apps/api/package.json b/apps/api/package.json index 8e152ae..f108f9c 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -1,6 +1,6 @@ { "name": "@reform/api", - "version": "0.1.0", + "version": "0.3.0", "private": true, "scripts": { "build": "nest build", diff --git a/apps/web/package.json b/apps/web/package.json index 6e317e4..d98aff8 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -1,6 +1,6 @@ { "name": "@reform/web", - "version": "0.1.0", + "version": "0.3.0", "private": true, "type": "module", "scripts": { diff --git a/apps/web/src/app/App.tsx b/apps/web/src/app/App.tsx index a4be7c0..b278ebf 100644 --- a/apps/web/src/app/App.tsx +++ b/apps/web/src/app/App.tsx @@ -12,7 +12,6 @@ import { DemoSandboxPage } from '@/pages/demo-sandbox'; import { MonitorPage } from '@/pages/monitor'; import { MonitorsPage } from '@/pages/monitors'; import { - CURRENT_VERSION, RECEPTION_PATHS, ReceptionPage, useUnseenReleaseNotesCount, @@ -20,7 +19,7 @@ import { import { SettingsPage } from '@/pages/settings'; import { TabletDocumentPage } from '@/pages/tablet-document'; import { AppShell } from '@/widgets/app-shell'; -import { APP_ROUTES } from '@/shared/config'; +import { APP_RELEASE_VERSION, APP_ROUTES } from '@/shared/config'; // Fejlesztői UI-előnézet (`/dev/ui`): csak `npm run dev:web` alatt, a buildbe nem kerül be. const UiPreviewPage = import.meta.env.DEV @@ -36,7 +35,7 @@ const UiPreviewPage = import.meta.env.DEV const AppLayout: React.FC = () => { const newsCount = useUnseenReleaseNotesCount(); return ( - + ); diff --git a/apps/web/src/entities/release-note/index.ts b/apps/web/src/entities/release-note/index.ts new file mode 100644 index 0000000..282ff6e --- /dev/null +++ b/apps/web/src/entities/release-note/index.ts @@ -0,0 +1,21 @@ +export { + countUnseenReleaseNotes, + getJiraIssueUrl, + isReleaseNoteFilter, + matchesReleaseNoteFilter, + RELEASE_NOTE_FILTERS, + RELEASE_NOTE_KIND_LABELS, + RELEASE_NOTES, +} from './model/releaseNotes'; +export type { + ReceptionMainTab, + ReleaseNote, + ReleaseNoteFilter, + ReleaseNoteKind, + ReleaseNoteLink, +} from './model/releaseNotes'; +export { + formatReleaseNoteDate, + groupReleaseNotesByVersion, +} from './model/releaseNoteGroups'; +export type { ReleaseNoteVersionGroup } from './model/releaseNoteGroups'; diff --git a/apps/web/src/entities/release-note/model/releaseNoteGroups.ts b/apps/web/src/entities/release-note/model/releaseNoteGroups.ts new file mode 100644 index 0000000..2c51093 --- /dev/null +++ b/apps/web/src/entities/release-note/model/releaseNoteGroups.ts @@ -0,0 +1,32 @@ +import { compareReleaseVersions } from '@/shared/config'; +import type { ReleaseNote } from './releaseNotes'; + +export interface ReleaseNoteVersionGroup { + version: string; + /** A verzió legfrissebb bejegyzésének dátuma (ISO). */ + date: string; + notes: ReleaseNote[]; +} + +/** Verziónként csoportosít, a legújabb verzió elöl; a csoporton belül a tömb sorrendje marad. */ +export const groupReleaseNotesByVersion = ( + notes: readonly ReleaseNote[], +): ReleaseNoteVersionGroup[] => { + const groups = new Map(); + for (const note of notes) { + groups.set(note.version, [...(groups.get(note.version) ?? []), note]); + } + return Array.from(groups, ([version, items]) => ({ + version, + date: items[0].date, + notes: items, + })).sort((a, b) => compareReleaseVersions(b.version, a.version)); +}; + +/** `2026-11-11` → `2026. nov. 11.` */ +export const formatReleaseNoteDate = (isoDate: string): string => + new Date(`${isoDate}T12:00:00`).toLocaleDateString('hu-HU', { + year: 'numeric', + month: 'short', + day: 'numeric', + }); diff --git a/apps/web/src/entities/release-note/model/releaseNotes.test.ts b/apps/web/src/entities/release-note/model/releaseNotes.test.ts new file mode 100644 index 0000000..404484f --- /dev/null +++ b/apps/web/src/entities/release-note/model/releaseNotes.test.ts @@ -0,0 +1,60 @@ +import { describe, expect, it } from 'vitest'; +import { + APP_RELEASE_VERSION, + APP_VERSION, + compareReleaseVersions, +} from '@/shared/config'; +import { groupReleaseNotesByVersion } from './releaseNoteGroups'; +import { RELEASE_NOTES } from './releaseNotes'; + +// TICKET-44: a verzió egyetlen forrása a gyökér `package.json` (Vite/Vitest `define`). +describe('Újdonságok és verziószám', () => { + it('a package.json verziója major.minor.patch alakú', () => { + expect(APP_VERSION).toMatch(/^\d+\.\d+\.\d+$/); + expect(APP_RELEASE_VERSION).toMatch(/^\d+\.\d+$/); + }); + + it('egy bejegyzés verziója sem nagyobb a package.json verziójánál', () => { + const ahead = RELEASE_NOTES.filter( + (note) => compareReleaseVersions(note.version, APP_RELEASE_VERSION) > 0, + ).map((note) => `${note.id} (v${note.version})`); + expect(ahead).toEqual([]); + }); + + it('a 0.3-tól kezdődő bejegyzéseknek van Jira kulcsa', () => { + const missing = RELEASE_NOTES.filter( + (note) => + compareReleaseVersions(note.version, '0.3') >= 0 && !note.jiraKey, + ).map((note) => note.id); + expect(missing).toEqual([]); + }); + + it('az azonosítók egyediek', () => { + const ids = RELEASE_NOTES.map((note) => note.id); + expect(new Set(ids).size).toBe(ids.length); + }); +}); + +describe('compareReleaseVersions', () => { + it('számként hasonlít, nem szövegként', () => { + expect(compareReleaseVersions('0.10', '0.9')).toBeGreaterThan(0); + expect(compareReleaseVersions('0.3', '0.3')).toBe(0); + expect(compareReleaseVersions('0.2', '1.0')).toBeLessThan(0); + }); +}); + +describe('groupReleaseNotesByVersion', () => { + it('verziónként csoportosít, a legújabb verzió elöl', () => { + const groups = groupReleaseNotesByVersion(RELEASE_NOTES); + const versions = groups.map((g) => g.version); + expect(versions).toEqual( + [...versions].sort((a, b) => compareReleaseVersions(b, a)), + ); + for (const version of ['0.3', '0.2', '0.1']) { + expect(versions).toContain(version); + } + expect(groups.reduce((sum, g) => sum + g.notes.length, 0)).toBe( + RELEASE_NOTES.length, + ); + }); +}); diff --git a/apps/web/src/pages/reception/model/releaseNotes.ts b/apps/web/src/entities/release-note/model/releaseNotes.ts similarity index 89% rename from apps/web/src/pages/reception/model/releaseNotes.ts rename to apps/web/src/entities/release-note/model/releaseNotes.ts index 293255f..48a5b40 100644 --- a/apps/web/src/pages/reception/model/releaseNotes.ts +++ b/apps/web/src/entities/release-note/model/releaseNotes.ts @@ -96,6 +96,20 @@ export const getJiraIssueUrl = (jiraKey: string): string => `${JIRA_BASE_URL}/browse/${encodeURIComponent(jiraKey)}`; export const RELEASE_NOTES: ReleaseNote[] = [ + { + id: 'v0.3-version-changelog-from-news', + version: '0.3', + date: '2026-11-11', + kind: 'IMPROVEMENT', + title: 'Verziónkénti változáslista', + summary: + 'A verziószám és a verziónkénti változáslista egy helyről frissül. A bejelentkezésnél és a Vendégmonitoron mindig a futó verzió látszik, és a verziószámra kattintva verziónként láthatod, mi változott.', + details: [ + 'A változáslista az Újdonságok bejegyzéseiből épül: elöl a jelenlegi verzió nyitva, alatta a korábbi verziók egy kattintással lenyithatók.', + 'Az Újdonságok közé a legelső (v0.1) verzió tételei is bekerültek.', + ], + jiraKey: 'TICKET-44', + }, { id: 'v0.3-fix-pass-freeze-calendar-days', version: '0.3', @@ -486,7 +500,62 @@ export const RELEASE_NOTES: ReleaseNote[] = [ summary: 'Kártyák, státusz-jelvények és gombok jobb olvashatósága sötét témában.', jiraKey: null, }, + { + id: 'v0.1-reception-check-in', + version: '0.1', + date: '2026-10-20', + kind: 'NEW_PAGE', + title: 'Recepció (/reception)', + summary: + 'Beléptetés vonalkóddal, automatikus bérletválasztással és dupla lehúzás elleni védelemmel.', + details: [ + 'A rendszer előbb az időalapú bérletet, utána a leghamarabb lejáró alkalmas bérletet választja.', + 'Minden művelet visszaigazoló értesítést ad; a beléptetés és a fizetés egy kattintással sztornózható, a bérlet megújítható.', + 'Kapcsolat nélkül a beolvasások helyi pufferbe kerülnek, és a kapcsolat visszatérésekor automatikusan szinkronizálódnak.', + ], + jiraKey: null, + }, + { + id: 'v0.1-guest-file', + version: '0.1', + date: '2026-10-20', + kind: 'NEW_PAGE', + title: 'Vendégkartoték (/guests)', + summary: + 'Vendégfelvétel, bérlettörténet és felhasználási napló egy helyen.', + details: [ + 'Digitális belépőkártya vonalkóddal és QR-kóddal, PNG letöltéssel és nyomtatással.', + 'A bérlet hosszabbítható (+N nap), fagyasztható és feloldható.', + ], + jiraKey: null, + }, + { + id: 'v0.1-guest-monitor', + version: '0.1', + date: '2026-10-20', + kind: 'NEW_PAGE', + title: 'Valós idejű Vendégmonitor (/monitor)', + summary: + 'A recepciós gép második kijelzőjén vagy párosított tableten köszönti a belépő vendéget; a képernyő nem alszik el.', + jiraKey: null, + }, + { + id: 'v0.1-demo-sandbox', + version: '0.1', + date: '2026-10-20', + kind: 'NEW_PAGE', + title: 'Demó mód (/demo)', + summary: + 'Az élő adatbázistól független próbakörnyezet virtuális vonalkódolvasóval és beágyazott monitor-előnézettel.', + jiraKey: null, + }, + { + id: 'v0.1-login-dark-theme', + version: '0.1', + date: '2026-10-20', + kind: 'NEW_FEATURE', + title: 'Bejelentkezés és sötét téma', + summary: 'Munkatársi bejelentkezés, és a felület sötét témában is használható.', + jiraKey: null, + }, ]; - -/** A futó verzió: a legújabb bejegyzésé (az oldalsáv alján látszik). */ -export const CURRENT_VERSION = RELEASE_NOTES[0].version; diff --git a/apps/web/src/pages/monitor/ui/MonitorPage.tsx b/apps/web/src/pages/monitor/ui/MonitorPage.tsx index 185a958..cdbe6b6 100644 --- a/apps/web/src/pages/monitor/ui/MonitorPage.tsx +++ b/apps/web/src/pages/monitor/ui/MonitorPage.tsx @@ -26,6 +26,7 @@ import { useMonitorChannel, } from '@/shared/lib/monitor-channel'; import { api } from '@/shared/api'; +import { APP_VERSION_LABEL } from '@/shared/config'; import { mockStudioEngine } from '@/shared/api'; import { notify } from '@/shared/lib/notify'; import { soundFeedback } from '@/shared/lib/sound'; @@ -477,7 +478,7 @@ export const MonitorPage: React.FC = () => { : `Párosított Önálló Kijelző (${deviceName ?? 'Tablet'})`} - v0.2 + {APP_VERSION_LABEL} diff --git a/apps/web/src/pages/reception/index.ts b/apps/web/src/pages/reception/index.ts index f094d90..5d52929 100644 --- a/apps/web/src/pages/reception/index.ts +++ b/apps/web/src/pages/reception/index.ts @@ -1,4 +1,3 @@ export { ReceptionPage } from './ui/ReceptionPage'; export { RECEPTION_PATHS } from './model/receptionTabs'; export { useUnseenReleaseNotesCount } from './model/releaseNotesStore'; -export { CURRENT_VERSION } from './model/releaseNotes'; diff --git a/apps/web/src/pages/reception/model/receptionTabs.ts b/apps/web/src/pages/reception/model/receptionTabs.ts index 225429e..39d260e 100644 --- a/apps/web/src/pages/reception/model/receptionTabs.ts +++ b/apps/web/src/pages/reception/model/receptionTabs.ts @@ -1,5 +1,5 @@ import { APP_ROUTES, normalizePathname } from '@/shared/config'; -import type { ReceptionMainTab } from './releaseNotes'; +import type { ReceptionMainTab } from '@/entities/release-note'; export type ReceptionTab = ReceptionMainTab | 'news'; diff --git a/apps/web/src/pages/reception/model/releaseNotesStore.ts b/apps/web/src/pages/reception/model/releaseNotesStore.ts index 4f45b97..c31b0b1 100644 --- a/apps/web/src/pages/reception/model/releaseNotesStore.ts +++ b/apps/web/src/pages/reception/model/releaseNotesStore.ts @@ -1,6 +1,6 @@ import { create } from 'zustand'; import { persist } from 'zustand/middleware'; -import { countUnseenReleaseNotes } from './releaseNotes'; +import { countUnseenReleaseNotes } from '@/entities/release-note'; interface ReleaseNotesState { seenIds: string[]; diff --git a/apps/web/src/pages/reception/ui/WhatsNewPanel.tsx b/apps/web/src/pages/reception/ui/WhatsNewPanel.tsx index 2df41c2..d9db487 100644 --- a/apps/web/src/pages/reception/ui/WhatsNewPanel.tsx +++ b/apps/web/src/pages/reception/ui/WhatsNewPanel.tsx @@ -10,7 +10,9 @@ import { ToggleGroupItem, } from '@/shared/ui'; import { + formatReleaseNoteDate, getJiraIssueUrl, + groupReleaseNotesByVersion, isReleaseNoteFilter, matchesReleaseNoteFilter, RELEASE_NOTE_FILTERS, @@ -19,16 +21,9 @@ import { type ReceptionMainTab, type ReleaseNote, type ReleaseNoteFilter, -} from '../model/releaseNotes'; +} from '@/entities/release-note'; import { useReleaseNotesStore } from '../model/releaseNotesStore'; -const formatNoteDate = (isoDate: string) => - new Date(`${isoDate}T12:00:00`).toLocaleDateString('hu-HU', { - year: 'numeric', - month: 'short', - day: 'numeric', - }); - const FILTER_COUNTS = Object.fromEntries( RELEASE_NOTE_FILTERS.map(({ value }) => [ value, @@ -63,14 +58,13 @@ export const WhatsNewPanel: React.FC = ({ ); // Csak a szűrőnek megfelelő bejegyzések; üres verziócsoport nem keletkezik. - const byVersion = useMemo(() => { - const groups = new Map(); - for (const note of RELEASE_NOTES) { - if (!matchesReleaseNoteFilter(note, filter)) continue; - groups.set(note.version, [...(groups.get(note.version) ?? []), note]); - } - return Array.from(groups.entries()); - }, [filter]); + const byVersion = useMemo( + () => + groupReleaseNotesByVersion( + RELEASE_NOTES.filter((note) => matchesReleaseNoteFilter(note, filter)), + ), + [filter], + ); const toggleDetails = (id: string) => setExpandedIds((prev) => { @@ -118,7 +112,7 @@ export const WhatsNewPanel: React.FC = ({
- {byVersion.map(([version, notes]) => ( + {byVersion.map(({ version, date, notes }) => (
= ({ v{version} - {formatNoteDate(notes[0].date)} + {formatReleaseNoteDate(date)}
diff --git a/apps/web/src/shared/config/index.ts b/apps/web/src/shared/config/index.ts index 26890e2..c0c0764 100644 --- a/apps/web/src/shared/config/index.ts +++ b/apps/web/src/shared/config/index.ts @@ -1,2 +1,9 @@ export { APP_ROUTES, normalizePathname } from './routes'; export type { AppRouteKey } from './routes'; +export { + APP_RELEASE_VERSION, + APP_VERSION, + APP_VERSION_LABEL, + compareReleaseVersions, + toReleaseVersion, +} from './version'; diff --git a/apps/web/src/shared/config/version.ts b/apps/web/src/shared/config/version.ts new file mode 100644 index 0000000..be481c9 --- /dev/null +++ b/apps/web/src/shared/config/version.ts @@ -0,0 +1,22 @@ +// A futó verzió (TICKET-44). Egyetlen forrása a gyökér `package.json`; a build `__APP_VERSION__`-ként +// adja át. A felületen és az Újdonságokban a kiadás verziója látszik: major.minor (`0.3`). + +/** Teljes verzió a `package.json`-ból, pl. `0.3.0`. */ +export const APP_VERSION: string = __APP_VERSION__; + +/** `0.3.0` → `0.3`. */ +export const toReleaseVersion = (version: string): string => + version.split('.').slice(0, 2).join('.'); + +/** Két kiadási verzió (`0.3`, `0.10`) számszerű összevetése; negatív, ha `a` a régebbi. */ +export const compareReleaseVersions = (a: string, b: string): number => { + const [aMajor = 0, aMinor = 0] = a.split('.').map(Number); + const [bMajor = 0, bMinor = 0] = b.split('.').map(Number); + return aMajor - bMajor || aMinor - bMinor; +}; + +/** A futó kiadás verziója, pl. `0.3` (az Újdonságok `version` mezőjével egyező alak). */ +export const APP_RELEASE_VERSION = toReleaseVersion(APP_VERSION); + +/** A felületen megjelenő verzió, pl. `v0.3`. */ +export const APP_VERSION_LABEL = `v${APP_RELEASE_VERSION}`; diff --git a/apps/web/src/vite-env.d.ts b/apps/web/src/vite-env.d.ts index 11f02fe..ad00880 100644 --- a/apps/web/src/vite-env.d.ts +++ b/apps/web/src/vite-env.d.ts @@ -1 +1,4 @@ /// + +/** A gyökér `package.json` verziója (pl. `0.3.0`), a Vite `define` adja (`vite.config.ts`). */ +declare const __APP_VERSION__: string; diff --git a/apps/web/src/widgets/version-changelog/ui/VersionChangelogModal.tsx b/apps/web/src/widgets/version-changelog/ui/VersionChangelogModal.tsx index 055ad89..666569e 100644 --- a/apps/web/src/widgets/version-changelog/ui/VersionChangelogModal.tsx +++ b/apps/web/src/widgets/version-changelog/ui/VersionChangelogModal.tsx @@ -1,5 +1,14 @@ -import React from 'react'; +import React, { useState } from 'react'; import { + formatReleaseNoteDate, + groupReleaseNotesByVersion, + RELEASE_NOTE_KIND_LABELS, + RELEASE_NOTES, + type ReleaseNoteVersionGroup, +} from '@/entities/release-note'; +import { APP_RELEASE_VERSION, APP_VERSION_LABEL } from '@/shared/config'; +import { + Badge, Button, Dialog, DialogBody, @@ -12,15 +21,96 @@ import { DialogTrigger, } from '@/shared/ui'; -const sectionTitleClassName = 'text-[13px] font-semibold text-foreground'; -const listClassName = - 'list-disc space-y-1.5 pl-5 text-[13px] text-muted-foreground [&_strong]:text-foreground'; +// A jelenlegi verzió mindig elöl van, akkor is, ha még nincs bejegyzése (kiadás utáni új verzió). +const buildVersionGroups = (): ReleaseNoteVersionGroup[] => { + const groups = groupReleaseNotesByVersion(RELEASE_NOTES); + const current = groups.find((g) => g.version === APP_RELEASE_VERSION) ?? { + version: APP_RELEASE_VERSION, + date: '', + notes: [], + }; + return [current, ...groups.filter((g) => g !== current)]; +}; + +const VERSION_GROUPS = buildVersionGroups(); + +const VersionSection: React.FC<{ + group: ReleaseNoteVersionGroup; + isCurrent: boolean; +}> = ({ group, isCurrent }) => { + const [open, setOpen] = useState(isCurrent); + const headingId = `version-${group.version}`; + const listId = `version-${group.version}-notes`; + + return ( +
+
+

+ v{group.version} +

+ {isCurrent && ( + + Jelenlegi verzió + + )} + + {group.date && `${formatReleaseNoteDate(group.date)} · `} + {group.notes.length} változás + + {group.notes.length > 0 && ( + + )} +
+ + {group.notes.length === 0 ? ( +

+ Ebben a verzióban még nincs bejegyzett változás. +

+ ) : ( + + )} +
+ ); +}; interface VersionBadgeProps { className?: string; } -// A verziószám a bejelentkezésnél; kattintásra a v0.2 kiadási jegyzéke nyílik. +// A futó verzió a bejelentkezésnél; kattintásra a verziónkénti változáslista nyílik, amely az +// Újdonságok bejegyzéseiből épül (TICKET-44). export const VersionBadge: React.FC = ({ className }) => ( @@ -28,196 +118,33 @@ export const VersionBadge: React.FC = ({ className }) => ( variant="link" size="sm" className={className} - aria-label="v0.2 kiadási jegyzék megnyitása" + aria-label={`${APP_VERSION_LABEL} változáslista megnyitása`} > - v0.2 + {APP_VERSION_LABEL} - ReformStudioSync v0.2 kiadási jegyzék + + ReformStudioSync {APP_VERSION_LABEL} változáslista + - Az előző (v0.1) verzióhoz képest bekerült új funkciók, opciók és - fejlesztések. + Verziónként, mi került be az alkalmazásba. A jelenlegi verzió van + elöl, a korábbiak lenyithatók. - {/* 1. Globális QR / Vonalkód Szkenner Csatorna */} -
-

- 1. Globális 2D QR-kód és Vonalkód Szkenner Csatorna -

-
    -
  • - Oldalaktól és fókusztól független olvasás: A - csatlakoztatott fizikai 2D QR- és vonalkódolvasó (USB/Bluetooth - HID) mostantól bármely megnyitott ablakban ( - /reception,{' '} - /monitor,{' '} - /tablet,{' '} - /demo) azonnal érzékeli a - leolvasást. -
  • -
  • - Input Stealth Guard védelem: Ha a kurzor éppen - egy keresőmezőben vagy űrlapon áll, a gépi QR-olvasás nem íródik - bele véletlenül a szövegmezőbe, és nem küldi el az űrlapot. -
  • -
  • - - Magyar (HU QWERTZ) billentyűzet és okos QR feloldás: - {' '} - Automatikusan javítja a magyar billentyűzetkiosztás miatt eltolt - karaktereket ( - §'"+!%/=() →{' '} - 0-9), valamint felismeri az - URL-eket, JSON kódokat és előtagokat ( - REFORM:100001,{' '} - #100001). -
  • -
  • - Élő Szkenner Csatorna kapcsoló: A fejlécben 1 - kattintással szüneteltethető vagy visszakapcsolható a fizikai - olvasó figyelése, és látható az utoljára beolvasott kód. -
  • -
-
- - {/* 2. Fejlett Dual-Mode Vendégmonitor és 6 Jegyű Párosítás */} -
-

- 2. Megújult Dual-Mode Vendégmonitor & 6 Jegyű Tablet Párosítás -

-
    -
  • - 1. Üzemmód — Azonos PC Másodlagos Kijelző: Ha a - recepciós gépen be vagy jelentkezve, a{' '} - /monitor oldal{' '} - párosító kód megadása nélkül azonnal működik. -
  • -
  • - 2. Üzemmód — Különálló Tablet / iPad / TV: Nem - bejelentkezett eszközön a{' '} - /monitor oldal biztonsági - zárolási képernyőt mutat, amíg be nem ütik a recepción generált{' '} - 10 percig érvényes 6 jegyű párosító kódot. -
  • -
  • - Teljes eszközmenedzsment és Teszt Jel: Egyedi - kijelzőnév-ellenőrzés, átnevezés, lejárati visszaszámláló, új kód - generálása, távoli vagy helyi párosítás-bontás, valamint{' '} - Teszt Jel küldése közvetlenül a kijelzőkre. -
  • -
-
- - {/* 3. Köredzés vs. Alkalmas Kezelés & Adatvédett Monitor */} -
-

- 3. Köredzés vs. Alkalmas Kezelés és Adatvédett Vendégmonitor -

-
    -
  • - Kettős érkezési logika: Havi tagságos vagy - időkorlátos Köredzésnél a rendszer{' '} - 0 alkalmat von le; Alkalmas kezelésnél (pl. - Hypoxi, Reformer) dedikált ablakban választható ki a kezelés és a - bérlet (-1 alkalom), amely - indoklással vissza is vonható. -
  • -
  • - Szigorú adatvédelem a Vendégmonitoron: A vendégek - felé fordított kijelzőn soha nem jelenik meg tartozás vagy - pénzügyi figyelmeztetés — köredzésnél csak az üdvözlés, kezelésnél - pedig a kezelés neve és a hátralévő alkalmak száma látható. -
  • -
  • - Állítható üdvözlési idő: Az Admin fülön 3 és 30 - másodperc között állítható az üdvözlő üzenet megjelenítési ideje. -
  • -
-
- - {/* 4. Pénzügy, Havi Tagságok, Kartoték és Tablet Aláírás */} -
-
-

- 4. Havi Tagságok & Pénzügyi Allokáció -

-
    -
  • - Havi köredzés tagságok ( - ACTIVE,{' '} - PAUSED,{' '} - TERMINATED) és esedékességek - kezelése. -
  • -
  • - Hátralék-kategóriák (1–5,{' '} - 6–15,{' '} - 15+ nap) külön recepciós - figyelmeztetéssel. -
  • -
  • - Részbefizetés (PARTIAL) és - célzott befizetés rögzítése konkrét tagdíjhoz vagy bérlethez. -
  • -
-
- -
-

- 5. Bővített Kartoték & Tablet Aláírás -

-
    -
  • - Testmérések naplózása (súly, testzsír%, izomtömeg, körméretek). -
  • -
  • - Kliensoldali automatikus WebP képoptimalizáló a - vendégfotókhoz. -
  • -
  • Belső recepciós megjegyzések és kiküldött e-mail napló.
  • -
  • - Dedikált /tablet aláíró felület GDPR és - állapotfelmérő ívekhez. -
  • -
-
-
- - {/* 6. Egyéb változások a v0.1-hez képest */} -
-

- Mi változott még a v0.1-hez képest? -

-
    -
  • - Gyorsabb dupla-leolvasás védelem: A véletlen - dupla csippantás védelmi ablaka 60 mp-ről{' '} - 10 másodpercre finomhangolva, 1 kattintásos - felülbírálási lehetőséggel. -
  • -
  • - Napi műszerfal (Dashboard):{' '} - Születésnapos/névnapos ünnepeltek, lejáró bérletek és - szolgáltatás-megoszlás összesítő. -
  • -
  • - Sötét mód (Dark Mode) kontrasztjavítások:{' '} - Kártyák, státusz-jelvények és gombok olvashatóságának - finomhangolása sötét recepciós témában. -
  • -
-
+ {VERSION_GROUPS.map((group) => ( + + ))}
-

- Részletes műszaki dokumentáció:{' '} - docs/versions/0.2v.md -

diff --git a/apps/web/vite.config.ts b/apps/web/vite.config.ts index aea5390..9390860 100644 --- a/apps/web/vite.config.ts +++ b/apps/web/vite.config.ts @@ -1,9 +1,18 @@ +import { readFileSync } from 'fs'; import path from 'path'; import react from '@vitejs/plugin-react'; import { defineConfig } from 'vite'; +// A verziószám egyetlen forrása a gyökér `package.json` (TICKET-44); a web `__APP_VERSION__`-ként kapja. +const { version: appVersion } = JSON.parse( + readFileSync(path.resolve(__dirname, '../../package.json'), 'utf8'), +) as { version: string }; + export default defineConfig({ plugins: [react()], + define: { + __APP_VERSION__: JSON.stringify(appVersion), + }, resolve: { alias: { '@': path.resolve(__dirname, './src'), diff --git a/apps/web/vitest.config.ts b/apps/web/vitest.config.ts index cc4733f..1bbb402 100644 --- a/apps/web/vitest.config.ts +++ b/apps/web/vitest.config.ts @@ -1,7 +1,16 @@ +import { readFileSync } from 'fs'; import path from 'path'; import { defineConfig } from 'vitest/config'; +// Ugyanaz a verziószám, mint a buildben (`vite.config.ts`): a gyökér `package.json`-ból. +const { version: appVersion } = JSON.parse( + readFileSync(path.resolve(__dirname, '../../package.json'), 'utf8'), +) as { version: string }; + export default defineConfig({ + define: { + __APP_VERSION__: JSON.stringify(appVersion), + }, test: { environment: 'jsdom', include: ['src/**/*.test.{ts,tsx}'], diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 4dbd2cd..038f021 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -21,8 +21,8 @@ Az `apps/web/src` könyvtár rétegei felülről lefelé. Egy réteg csak az ala | `pages/` | `login`, `reception`, `monitor`, `monitors`, `settings`, `tablet-document`, `demo-sandbox` | Útvonalanként egy oldal | | `widgets/` | `guest-profile`, `version-changelog` | Önálló, összetett UI blokkok | | `features/` | `scanner-channel`, `sell-pass`, `deduct-treatment`, `record-payment`, `toggle-theme` | Felhasználói műveletek | -| `entities/` | `guest`, `check-in`, `display-device` | Üzleti entitások UI-ja és állapota (offline puffer, szkenner csatorna store, kijelzőlista lekérdezése) | -| `shared/` | `api`, `auth`, `theme`, `lib/*` | REST kliens + mock motor, session store, téma store, notify/sound/szkenner/monitor csatorna segédek | +| `entities/` | `guest`, `check-in`, `display-device`, `release-note` | Üzleti entitások UI-ja és állapota (offline puffer, szkenner csatorna store, kijelzőlista lekérdezése, Újdonságok adatai) | +| `shared/` | `api`, `auth`, `config`, `theme`, `lib/*` | REST kliens + mock motor, session store, útvonalak és a futó verzió (`config`), téma store, notify/sound/szkenner/monitor csatorna segédek | A szabályokat a [Steiger](https://github.com/feature-sliced/steiger) linter ellenőrzi: `npm run lint:fsd`. A TypeScript- és React-szabályokat az ESLint (`eslint.config.mjs`) a teljes monorepón: `npm run lint` / `npm run lint:fix`. diff --git a/docs/WORKFLOW.md b/docs/WORKFLOW.md index 4b7973c..83a98ff 100644 --- a/docs/WORKFLOW.md +++ b/docs/WORKFLOW.md @@ -80,18 +80,44 @@ A Koordinátor minden workernek önálló, teljes briefet ad: 1. Koordinátor ellenőrzi a worker eredményeket (review, gate újrafuttatása). 2. „Mehet” után PR-ok a `demo`-ra, Jira → *Ellenőrzés alatt*, tesztlista a Megrendelőnek. 3. „Oké” után PR `demo` → `main`, merge után Jira → *Kész*. -4. Ha kiadás készül: `docs/versions/v.md`, `docs/DEVELOPMENT_LOG.md`, és a verziószám a `widgets/version-changelog`-ban. +4. A `main` merge után **Kiadás** (2.5): tag, GitHub Release, utána új verzió nyitása a demón. 5. Összegző jelentés a Megrendelőnek: mi készült el, mi maradt nyitva, melyik ticket milyen állapotban van. +### 2.5. Kiadás (a `demo` → `main` PR összevonása után) + +A verziószám egyetlen forrása a gyökér `package.json` `version` mezője (a workspace-ek `package.json`-ja és a `package-lock.json` ugyanezt tükrözi). A web a buildben kapja meg (`__APP_VERSION__`, `apps/web/vite.config.ts`), és `shared/config` (`APP_VERSION_LABEL`, pl. „v0.3”) mutatja a bejelentkezőoldalon, a Vendégmonitor fejlécében és az oldalsáv alján. A `demo` mindig a **következő**, még ki nem adott verzión áll; a `main`-re kerüléskor ez lesz a kiadás. + +A Koordinátor a `main` merge után (a példa a v0.3): + +1. **CHANGELOG véglegesítése:** a `CHANGELOG.md` `## v0.3 — a demo-n …` címsora helyett `## v0.3 — `; a szakasz tételeit vesd össze az Újdonságok 0.3-as bejegyzéseivel. +2. **Tag a `main` merge commitjára:** + ```bash + git fetch origin + git tag -a v0.3.0 origin/main -m "v0.3" # origin/main = a demo → main merge commit + git push origin v0.3.0 + ``` +3. **GitHub Release** a CHANGELOG adott szakaszával (`scripts/release-notes.sh` csak kivágja, nem taggel és nem pushol): + ```bash + bash scripts/release-notes.sh 0.3 > + gh release create v0.3.0 --title "v0.3" --notes-file + ``` +4. **Új verzió nyitása a demón** (külön ág, PR a `demo`-ra, pl. `release/v0.4`): + - verzió minor emelése mindenhol: `npm version 0.4.0 --workspaces --include-workspace-root --no-git-tag-version` (a négy `package.json` és a `package-lock.json` saját `version` mezői; nézd át a diffet); + - a CHANGELOG 1. pont szerinti dátuma, és fölé új szakasz: `## v0.4 — a demo-n, a következő main kiadással élesedik`; + - innentől az Újdonságok új bejegyzései `version: '0.4'`-et kapnak. + Az Újdonságok-teszt (`entities/release-note/model/releaseNotes.test.ts`) elbukik, ha egy bejegyzés verziója nagyobb a `package.json`-énál, vagy ha egy 0.3-tól kezdődő bejegyzésnek nincs `jiraKey`-je. +5. Jelentés a Megrendelőnek: a Release linkje és az új demós verzió. + --- -## 3. Újdonságok bejegyzés (`apps/web/src/pages/reception/model/releaseNotes.ts`) +## 3. Újdonságok bejegyzés (`apps/web/src/entities/release-note/model/releaseNotes.ts`) -A Recepció **„Újdonságok”** menüpontja (`pages/reception/ui/WhatsNewPanel.tsx`) a `RELEASE_NOTES` tömbből épül. Minden felhasználó számára érzékelhető változáshoz kell bejegyzés. +A Recepció **„Újdonságok”** menüpontja (`pages/reception/ui/WhatsNewPanel.tsx`) és a bejelentkezőoldal verzió-ablaka (`widgets/version-changelog`) a `RELEASE_NOTES` tömbből épül. Minden felhasználó számára érzékelhető változáshoz kell bejegyzés. | Mező | Szabály | | --- | --- | | `id` | Stabil, egyedi (pl. `v0.3-guest-export`). Utólag nem módosítható — erre épül az olvasottság jelölése. | +| `version` | A `demo` jelenlegi verziója major.minor alakban (a gyökér `package.json`-ból, pl. `0.3.0` → `'0.3'`); nagyobb nem lehet (unit teszt ellenőrzi). | | `kind` | `NEW_PAGE` (új oldal), `NEW_FEATURE` (új funkció), `IMPROVEMENT` (fejlesztés), `FIX` (javítás). | | `jiraKey` | **Kötelező** KAN kulcs (pl. `KAN-12`) a visszakövethetőséghez. `null` csak a Jira előtti (≤ v0.2) tételeknél megengedett. | | `link` | **Csak** `NEW_PAGE` / `NEW_FEATURE` esetén, és **csak ha az újdonság a felületen ténylegesen megtekinthető**. Recepciós fülre: `{ type: 'receptionTab', tab }`, külön oldalra: `{ type: 'route', path }`. `IMPROVEMENT` / `FIX` esetén csak leírás van — a típus ezt kikényszeríti. | @@ -112,4 +138,4 @@ A Recepció **„Újdonságok”** menüpontja (`pages/reception/ui/WhatsNewPane - **Mock pár:** minden új vagy módosított API-végponthoz `shared/api/mock-engine.ts` pár. - **Tranzakciók:** bérlet-/pénzügyi módosítás csak atomi Prisma `$transaction`-ben. - **Gate jelentés előtt:** `bash .claude/skills/reform-ticket/scripts/gate.sh`. Sikertelen ellenőrzést kimenettel együtt kell jelenteni. -- **Dokumentáció:** architektúra-változás → `docs/ARCHITECTURE.md`; kiadás → `docs/versions/`; minden felhasználói változás → Újdonságok bejegyzés. +- **Dokumentáció:** architektúra-változás → `docs/ARCHITECTURE.md`; kiadás → `CHANGELOG.md` (2.5); minden felhasználói változás → Újdonságok bejegyzés. diff --git a/package-lock.json b/package-lock.json index 75bfe78..ea20b91 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "reform-studio-sync", - "version": "0.1.0", + "version": "0.3.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "reform-studio-sync", - "version": "0.1.0", + "version": "0.3.0", "workspaces": [ "apps/*", "packages/*" @@ -27,7 +27,7 @@ }, "apps/api": { "name": "@reform/api", - "version": "0.1.0", + "version": "0.3.0", "dependencies": { "@nestjs/common": "^10.4.7", "@nestjs/config": "^3.3.0", @@ -61,7 +61,7 @@ }, "apps/web": { "name": "@reform/web", - "version": "0.1.0", + "version": "0.3.0", "dependencies": { "@radix-ui/react-alert-dialog": "^1.2.1", "@radix-ui/react-checkbox": "^1.4.1", @@ -13681,7 +13681,7 @@ }, "packages/shared": { "name": "@reform/shared", - "version": "0.1.0", + "version": "0.3.0", "devDependencies": { "typescript": "^5.6.3" } diff --git a/package.json b/package.json index 64c70a7..6a20b92 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "reform-studio-sync", - "version": "0.1.0", + "version": "0.3.0", "private": true, "description": "ReformStudioSync — Egystúdiós (SaaS-ready) Recepciós és Valós Idejű Vendégmonitor Rendszer", "workspaces": [ diff --git a/packages/shared/package.json b/packages/shared/package.json index 62649cc..e7b8ac7 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -1,6 +1,6 @@ { "name": "@reform/shared", - "version": "0.1.0", + "version": "0.3.0", "main": "./dist/index.js", "types": "./dist/index.d.ts", "exports": { diff --git a/scripts/release-notes.sh b/scripts/release-notes.sh new file mode 100755 index 0000000..847f879 --- /dev/null +++ b/scripts/release-notes.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +# Egy verzió kiadási jegyzéke a CHANGELOG.md-ből (docs/WORKFLOW.md „Kiadás”, TICKET-44). +# bash scripts/release-notes.sh [CHANGELOG fájl] pl. 0.3, v0.3 vagy 0.3.0 +# +# A `## v …` szakasz törzsét írja a standard kimenetre (a címsor nélkül), a +# következő `## v` címsorig. Csak olvas: nem taggel, nem pushol, nem hoz létre release-t. +# bash scripts/release-notes.sh 0.3 > /tmp/v0.3.md +# gh release create v0.3.0 --title "v0.3" --notes-file /tmp/v0.3.md +set -euo pipefail + +if [ $# -lt 1 ]; then + echo "Használat: bash scripts/release-notes.sh [CHANGELOG fájl]" >&2 + exit 2 +fi + +VERSION="${1#v}" +VERSION=$(echo "$VERSION" | cut -d. -f1-2) +FILE="${2:-$(dirname "$0")/../CHANGELOG.md}" + +if [ ! -f "$FILE" ]; then + echo "Nem található: $FILE" >&2 + exit 2 +fi + +NOTES=$(awk -v heading="## v$VERSION" ' + { sub(/\r$/, "") } + index($0, "## v") == 1 { + if (found) exit + rest = substr($0, length(heading) + 1) + if (index($0, heading) == 1 && (rest == "" || rest ~ /^[ \t]/)) { found = 1; next } + } + found { print } +' "$FILE") + +if [ -z "${NOTES//[[:space:]]/}" ]; then + echo "A(z) v$VERSION szakasz nem található vagy üres: $FILE" >&2 + exit 1 +fi + +# Az elején és a végén lévő üres sorok nélkül. +printf '%s\n' "$NOTES" | sed -e '/./,$!d' | sed -e :a -e '/^\n*$/{$d;N;ba' -e '}' From db68cf9a8ab650e435e4731af1679878d482241b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Sikl=C3=B3di?= Date: Wed, 11 Nov 2026 22:54:21 +0100 Subject: [PATCH 4/4] =?UTF-8?q?fix(scripts):=20a=20ci-wait=20workflow-nk?= =?UTF-8?q?=C3=A9nt=20a=20legfrissebb=20fut=C3=A1st=20n=C3=A9zi?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A beragadt (job nélkül sorban álló) régi futást így az újraindított futás felülírja. Co-Authored-By: Claude Opus 5.5 --- scripts/ci-wait.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/ci-wait.sh b/scripts/ci-wait.sh index 709fd14..b563b2d 100644 --- a/scripts/ci-wait.sh +++ b/scripts/ci-wait.sh @@ -35,8 +35,10 @@ LAST="" while :; do CHECKS=$(gh pr checks "$PR" --json name,bucket,state --jq '.[] | "\(.bucket)\t\(.name)\t\(.state)"' 2>&1) CHECKS_RC=$? - RUNS=$(gh run list --commit "$SHA" --json databaseId,name,status,conclusion \ - --jq '.[] | "\(.status)\t\(.conclusion)\t\(.name)\t\(.databaseId)"' 2>&1) + # Workflow-nként csak a legfrissebb futás számít: a beragadt régi futást az újraindított + # (PR újranyitás, workflow_dispatch) futás felülírja. + RUNS=$(gh run list --commit "$SHA" --json databaseId,name,status,conclusion,createdAt \ + --jq 'group_by(.name) | map(max_by(.createdAt)) | .[] |"\(.status)\t\(.conclusion)\t\(.name)\t\(.databaseId)"' 2>&1) RUNS_RC=$? # A `gh pr checks` 8-as kóddal jelzi a függő checket; ez nem hiba.