Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions .claude/skills/reform-ticket/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,15 +192,38 @@ 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:

```bash
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 > <ideiglenes fájl>`, majd
`gh release create v0.3.0 --title "v0.3" --notes-file <ideiglenes fájl>`.
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:
Expand Down
6 changes: 3 additions & 3 deletions .claude/skills/reformstudio-ui-skill/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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ó

Expand Down
2 changes: 1 addition & 1 deletion .cursor/rules/release-notes.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down
61 changes: 61 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# 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ü (é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 <verzió>`.

## 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)
- **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
- **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.**
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
2 changes: 1 addition & 1 deletion apps/api/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@reform/api",
"version": "0.1.0",
"version": "0.3.0",
"private": true,
"scripts": {
"build": "nest build",
Expand Down
2 changes: 1 addition & 1 deletion apps/web/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@reform/web",
"version": "0.1.0",
"version": "0.3.0",
"private": true,
"type": "module",
"scripts": {
Expand Down
5 changes: 2 additions & 3 deletions apps/web/src/app/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,14 @@ import { DemoSandboxPage } from '@/pages/demo-sandbox';
import { MonitorPage } from '@/pages/monitor';
import { MonitorsPage } from '@/pages/monitors';
import {
CURRENT_VERSION,
RECEPTION_PATHS,
ReceptionPage,
useUnseenReleaseNotesCount,
} from '@/pages/reception';
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
Expand All @@ -36,7 +35,7 @@ const UiPreviewPage = import.meta.env.DEV
const AppLayout: React.FC = () => {
const newsCount = useUnseenReleaseNotesCount();
return (
<AppShell newsCount={newsCount} version={CURRENT_VERSION}>
<AppShell newsCount={newsCount} version={APP_RELEASE_VERSION}>
<Outlet />
</AppShell>
);
Expand Down
21 changes: 21 additions & 0 deletions apps/web/src/entities/release-note/index.ts
Original file line number Diff line number Diff line change
@@ -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';
32 changes: 32 additions & 0 deletions apps/web/src/entities/release-note/model/releaseNoteGroups.ts
Original file line number Diff line number Diff line change
@@ -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<string, ReleaseNote[]>();
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',
});
60 changes: 60 additions & 0 deletions apps/web/src/entities/release-note/model/releaseNotes.test.ts
Original file line number Diff line number Diff line change
@@ -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,
);
});
});
Loading
Loading