Krzysztof Cieślik 2593e81498 Inicjalna wersja systemu zarządzania rezerwacjami (RMS)
SPA zbudowane w React 19 + Vite 8 z pełnym zestawem funkcjonalności:
autentykacja z 2FA, kreator rezerwacji, panel admina, analityka,
GraphQL (Apollo Client + SchemaLink), React Query, Storybook,
testy jednostkowe (Vitest + RTL) i e2e (Playwright).
2026-06-21 06:23:36 +02:00

Reservation Management System

Aplikacja SPA do zarządzania rezerwacjami zbudowana w React 19 + Vite 8. Umożliwia klientom przeglądanie dostępnych terminów, dokonywanie rezerwacji z płatnością depozytu, zarządzanie historią rezerwacji oraz wystawianie opinii. Administratorzy mają dostęp do panelu zarządzania, kalendarza rezerwacji, analityki i eksportu danych.


Uruchomienie

# Terminal 1  REST API (json-server na porcie 3001)
npm run api

# Terminal 2  Vite dev server (port 5173)
npm run dev

# Testy jednostkowe (Vitest + RTL)
npm test

# Testy e2e (Playwright)
node test_rms.mjs

# Storybook (port 6006)
npm run storybook

Uwaga: przed uruchomieniem test_rms.mjs oba serwery muszą być aktywne. Test automatycznie przywraca dane seed (r1, r2) do stanu pending przed każdym przebiegiem.


Dane testowe

Rola E-mail Hasło
Admin admin@reservations.dev Admin1234!
Klient anna.kowalski@example.com Client1234!

Logowanie zawsze uruchamia weryfikację 2FA kod jest wyświetlany bezpośrednio w interfejsie (symulowany e-mail).


Stos technologiczny

Warstwa Technologia
UI React 19, Vite 8, SCSS Modules
Routing React Router v7
Zapytania REST TanStack React Query v5 + Axios
Zapytania GraphQL Apollo Client v4 + SchemaLink (in-memory)
Formularze Formik + Zod (zod-formik-adapter)
Ikony Lucide React
REST mock json-server (db.json)
Testy jednostkowe Vitest + React Testing Library
Testy e2e Playwright
Dokumentacja Storybook 8

Struktura projektu

web_projekt/
├── db.json                     # Baza danych json-server (users, services, reservations)
├── test_rms.mjs                # Testy e2e Playwright (32 testy)
├── src/
│   ├── main.jsx                # Punkt wejścia: Apollo Client, QueryClient, renderowanie
│   ├── App.jsx                 # Router, lazy loading, ErrorBoundary, Suspense, ProtectedRoute
│   ├── index.css               # Reset + CSS custom properties (tryb ciemny/jasny)
│   ├── styles/
│   │   ├── _variables.scss     # Tokeny projektu: kolory, spacing, typografia, cienie, media queries
│   │   └── main.scss           # Globalne style bazowe
│   ├── api/
│   │   ├── reservations.js     # CRUD rezerwacji przez Axios (json-server :3001)
│   │   ├── services.js         # Pobieranie listy usług
│   │   └── users.js            # Pobieranie i aktualizacja użytkowników
│   ├── context/
│   │   ├── AuthContext.jsx     # Stan uwierzytelnienia, 2FA, role, sesja w localStorage
│   │   └── ThemeContext.jsx    # Przełącznik jasny/ciemny motyw (data-theme na <html>)
│   ├── hocs/
│   │   └── withRole.jsx        # HOC: renderuje komponent tylko dla dozwolonych ról
│   ├── hooks/
│   │   ├── useCreateReservation.js  # useMutation: POST /reservations
│   │   ├── useDeleteReservation.js  # useMutation: DELETE /reservations/:id
│   │   ├── useReservations.js       # useQuery: GET /reservations (wszystkie)
│   │   ├── useServices.js           # useQuery: GET /services
│   │   ├── useSlotReservations.js   # useQuery: GET /reservations?serviceId&date
│   │   ├── useUpdateReservation.js  # useMutation: PATCH /reservations/:id
│   │   └── useUserReservations.js   # useQuery: GET /reservations?userId
│   ├── pages/
│   │   ├── LoginPage.jsx       # Formularz logowania (Formik+Zod) + ekran 2FA z podglądem kodu
│   │   ├── LoginPage.module.scss
│   │   ├── RegisterPage.jsx    # Rejestracja z walidacją Zod i weryfikacją e-mail
│   │   ├── RegisterPage.module.scss
│   │   ├── DashboardPage.jsx   # Panel klienta: AvailabilitySearch, SlotFinder, BookingWizard, MyReservations, ProfileEditModal
│   │   ├── DashboardPage.module.scss
│   │   ├── ReservationsPage.jsx # Historia rezerwacji z filtrami, anulowaniem, RescheduleModal, ReviewsSection, Google Calendar, re-book
│   │   ├── ReservationsPage.module.scss
│   │   ├── AdminPage.jsx       # Panel admina: tabela rezerwacji, UserManagement, AnalyticsDashboard, AdminCalendar, blokowanie terminów (useTransition)
│   │   └── AdminPage.module.scss
│   ├── components/
│   │   ├── AvailabilitySearch.jsx        # Wyszukiwanie wolnych slotów z synchronizacją URL (useSearchParams)
│   │   ├── AvailabilitySearch.module.scss
│   │   ├── BookingWizard.jsx             # 4-krokowy kreator rezerwacji (Usługa → Data → Wymagania → Podsumowanie)
│   │   ├── BookingWizard.module.scss
│   │   ├── BookingForm.jsx               # Uproszczony formularz rezerwacji (react-hook-form)
│   │   ├── BookingForm.module.scss
│   │   ├── SlotFinder.jsx                # Inteligentny finder slotów z punktacją (scoreSlot, findSlots)
│   │   ├── SlotFinder.module.scss
│   │   ├── PaymentModal.jsx              # Modal płatności: Karta / Google Pay / Przelew bankowy (Portal)
│   │   ├── PaymentModal.module.scss
│   │   ├── RescheduleModal.jsx           # Modal zmiany terminu rezerwacji (Portal)
│   │   ├── RescheduleModal.module.scss
│   │   ├── ProfileEditModal.jsx          # Modal edycji profilu i preferencji powiadomień (Portal, Formik+Zod)
│   │   ├── ProfileEditModal.module.scss
│   │   ├── ReviewsSection.jsx            # Sekcja opinii (GraphQL: useQuery + useMutation przez Apollo)
│   │   ├── ReviewsSection.module.scss
│   │   ├── ProfileView.jsx               # Widok profilu (GraphQL: userProfile query)
│   │   ├── ProfileView.module.scss
│   │   ├── MyReservations.jsx            # Sidebar z aktywnymi rezerwacjami użytkownika
│   │   ├── MyReservations.module.scss
│   │   ├── AdminCalendar.jsx             # Widok kalendarza dla admina (miesiąc, kliknięcie dnia, panel boczny)
│   │   ├── AdminCalendar.module.scss
│   │   ├── AnalyticsDashboard.jsx        # Statystyki rezerwacji z eksportem CSV (DataRenderer, useMemo)
│   │   ├── AnalyticsDashboard.module.scss
│   │   ├── UserManagement.jsx            # Zarządzanie użytkownikami przez admina (tabela, dezaktywacja, reset hasła)
│   │   ├── UserManagement.module.scss
│   │   ├── Modal.jsx                     # Bazowy komponent modala (Portal, useCallback, Escape key, aria)
│   │   ├── Modal.module.scss
│   │   ├── StatusBadge.jsx               # Odznaka statusu rezerwacji (warianty kolorów, rozmiary, aria-label)
│   │   ├── StatusBadge.module.scss
│   │   ├── StatusBadge.test.jsx          # Testy RTL dla StatusBadge
│   │   ├── ThemeToggle.jsx               # Przycisk przełączania motywu (jasny/ciemny)
│   │   ├── ThemeToggle.module.scss
│   │   ├── DataRenderer.jsx              # Render-prop: opakowuje useQuery, przekazuje dane przez children()
│   │   ├── ErrorBoundary.jsx             # Class component: łapie błędy runtime, wyświetla fallback UI
│   │   ├── ErrorBoundary.module.scss
│   │   ├── LoadingSpinner.jsx            # Animowany spinner ładowania
│   │   ├── LoadingSpinner.module.scss
│   │   └── ProtectedRoute.jsx            # Guard routingu: sprawdza rolę i przekierowuje
│   ├── stories/
│   │   ├── StatusBadge.stories.jsx       # Storybook: wszystkie warianty odznaki statusu
│   │   ├── Modal.stories.jsx             # Storybook: modal informacyjny i destrukcyjny
│   │   └── ThemeToggle.stories.jsx       # Storybook: przełącznik motywu
│   └── tests/
│       ├── LoginPage.test.jsx            # RTL: formularz logowania, błędy walidacji
│       ├── BookingForm.test.jsx          # RTL: formularz rezerwacji, react-hook-form
│       ├── ProtectedRoute.test.jsx       # RTL: ochrona tras, przekierowania
│       └── StatusBadge.test.jsx          # RTL: warianty statusu
└── public/
    └── index.html                        # Zawiera <div id="root"> i <div id="portal-root">

Architektura danych

REST (json-server :3001)

  • GET/POST /reservations rezerwacje
  • GET /services usługi
  • GET/PATCH /users użytkownicy
  • Filtrowanie przez query params: ?userId=, ?serviceId=, ?date=

GraphQL (Apollo Client in-memory, bez zewnętrznego serwera)

Schema i resolvery zdefiniowane w main.jsx, wykonywane lokalnie przez SchemaLink:

type Query {
  userProfile(id: ID!): UserProfile
  serviceReviews(serviceId: String!): [Review!]!
  userReviews(userId: String!): [Review!]!
}
type Mutation {
  submitReview(reservationId: String!, serviceId: String!, ...): Review!
}

Lista wymagań i ich realizacja

Wymagania funkcjonalne (11)

# Kryterium Realizacja Status
F1 System uwierzytelniania i autoryzacji AuthContext.jsx logowanie e-mail + 2FA (kod wyświetlany w UI); role client/admin; sesja w localStorage; rejestracja z weryfikacją e-mail (RegisterPage.jsx); ProtectedRoute blokuje dostęp wg roli [OK]
F2 Zarządzanie profilami użytkowników ProfileEditModal.jsx edycja danych (Formik+Zod, PATCH /users), 5 preferencji powiadomień (toggle switches: potwierdzenie, anulowanie, przypomnienie 24h, zmiana terminu, promocje); ProfileView.jsx dane z GraphQL; historia w ReservationsPage.jsx [OK]
F3 Wyszukiwanie i przeglądanie dostępności AvailabilitySearch.jsx filtracja po dacie i usłudze, siatka slotów, URL sync (useSearchParams); SlotFinder.jsx ranking slotów w zakresie dat z preferencjami (rano/południe/wieczór), pasek score [OK]
F4 Proces rezerwacji BookingWizard.jsx 4 kroki: wybór usługi, data+czas (blokada zajętych slotów), wymagania specjalne, podsumowanie z ceną; PaymentModal.jsx 3 metody płatności, potwierdzenie z paragonem [OK]
F5 System płatności online PaymentModal.jsx karta kredytowa (Formik, walidacja), Google Pay (symulacja), przelew bankowy (IBAN/BIC, numer referencyjny); depozyt 50% ceny; transactionId zapisywany w rezerwacji [OK]
F6 Zarządzanie rezerwacjami przez użytkowników ReservationsPage.jsx filtry (wszystkie/nadchodzące/minione/anulowane), anulowanie z potwierdzeniem, RescheduleModal.jsx (zmiana terminu), "Book again" (re-book), Google Calendar link [OK]
F7 Panel zarządzania rezerwacjami (admin) AdminPage.jsx tabela rezerwacji (Confirm/Cancel/Delete), AdminCalendar.jsx (miesiąc, panel dnia), blokowanie i zwalnianie terminów z datepickerem i listą [OK]
F8 Zarządzanie użytkownikami (admin) UserManagement.jsx tabela użytkowników, dezaktywacja konta (toggle), symulacja resetu hasła; dostęp chroniony przez HOC withRole(['admin']) [OK]
F9 Analityka i raportowanie AnalyticsDashboard.jsx statystyki (łączna liczba, potwierdzone, anulowane, przychód z depozytów, średnia ocena); wykresy słupkowe CSS; eksport CSV z nagłówkami [OK]
F10 Integracja z zewnętrznymi systemami Google Calendar: link eventedit generowany dynamicznie z datą/godziną/tytułem dla każdej nadchodzącej rezerwacji; pełne REST API dostępne dla zewnętrznych integracji [OK]
F11 System opinii i ocen ReviewsSection.jsx ocena gwiazdkowa (15) + komentarz, zapis przez GraphQL mutation submitReview; pobieranie przez serviceReviews query; widoczne po rozwinięciu minionej rezerwacji [OK]

Wymagania wizualne BIU ZAO (6)

# Kryterium Realizacja Status
V1 Spójny i nowoczesny interfejs Jeden design system: tokeny w _variables.scss (paleta primary/accent/gray, spacing 4px scale, typografia, cienie), spójne BEM, Lucide icons, karty z border-radius, modale z overlay [OK]
V2 Pełna responsywność 12 breakpointów w SCSS ($bp-xs 480px$bp-2xl 1536px); grid w DashboardPage stackuje kolumny, tabela admina scrolluje poziomo, wizard adaptuje układ pól [OK]
V3 Animacje i efekty przejścia CSS transition na przyciskach/kartach/modalach; @keyframes pulse na wyróżnionej karcie rezerwacji; spinner ładowania CSS; hover lift (box-shadow + transform) [OK]
V4 Wizualny feedback dla interakcji StatusBadge kolorystycznie odróżnia statusy; :disabled/:hover/:focus-visible na wszystkich elementach interaktywnych; błędy inline w formularzach; spinner na przyciskach pending [OK]
V5 Estetyczne wykorzystanie SCSS SCSS Modules z BEM, @use '../styles/variables' as *, zagnieżdżone reguły &__, &--, CSS custom properties dla motywu (--clr-bg, --clr-text etc.), media queries przez zmienne [OK]
V6 Wykorzystanie wbudowanych komponentów Natywne <input type="date">, <input type="time">, <select>, <textarea>, <dialog role="dialog">; <dl>/<dt>/<dd> dla danych rezerwacji; semantyczny HTML5 (<header>, <main>, <aside>) [OK]

Wymagania techniczne BIU ZAO (10)

# Kryterium Realizacja Status
T1 Podstawowe hooki React useState stan formularzy, UI, modali; useEffect inicjalizacja auth z localStorage, scroll do karty przez useRef; useContext useAuth(), useTheme() w całej aplikacji [OK]
T2 Custom hooki 7 hooków w src/hooks/: useServices, useUserReservations, useSlotReservations, useReservations, useCreateReservation, useUpdateReservation, useDeleteReservation [OK]
T3 React Router React Router v7: BrowserRouter, Routes, Route, Navigate, Outlet, Link, useNavigate, useLocation, useSearchParams; chronione trasy przez ProtectedRoute z allowedRoles [OK]
T4 Zarządzanie stanem (Context API) AuthContext użytkownik, 2FA (pendingUser/twoFACode/verify2FA), role, sesja; ThemeContext motyw jasny/ciemny z localStorage i data-theme na <html> [OK]
T5 Obsługa zapytań API Axios w src/api/ dla REST (json-server); Apollo Client SchemaLink dla GraphQL (in-memory schema z resolverami w main.jsx) [OK]
T6 Techniki optymalizacyjne React.lazy + Suspense (DashboardPage, AdminPage); useMemo (statystyki w AnalyticsDashboard, maxScore w SlotFinder); useCallback (auth functions, Escape handler w Modal) [OK]
T7 Wzorce kompozycji komponentów HOC withRole(['admin'])(Component) z displayName; Render props DataRenderer delegacja renderowania przez children jako funkcję; oba używane w komponentach produkcyjnych [OK]
T8 Obsługa formularzy i walidacja Formik + Zod (toFormikValidationSchema): LoginPage, RegisterPage, ProfileEditModal; react-hook-form + zodResolver: BookingForm; walidacja krokowa w BookingWizard [OK]
T9 Konsekwentny styl kodu SCSS BEM, camelCase hooks/functions, PascalCase komponenty, styles['block__element--modifier'] we wszystkich SCSS Modules, ESLint, jednolite formatowanie [OK]
T10 Nowoczesny JavaScript Destrukturyzacja: const { user, logout } = useAuth(), const { password: _omit, ...safeUser } = match; spread: { ...prev, [key]: value }; optional chaining ?.; nullish ??; template literals [OK]

Wymagania dodatkowe BIU ZAO (11)

# Kryterium Realizacja Status
D1 React Suspense i Error Boundaries ErrorBoundary.jsx (class component z componentDidCatch, fallback UI + przycisk reload); <Suspense fallback={<LoadingSpinner/>}> w App.jsx opakowuje lazy-loaded strony [OK]
D2 Zaawansowana obsługa formularzy Formik + toFormikValidationSchema(zodSchema): LoginPage, RegisterPage, ProfileEditModal; react-hook-form + zodResolver: BookingForm; oba podejścia w jednym projekcie [OK]
D3 GraphQL z Apollo Client Apollo Client v4 + makeExecutableSchema + SchemaLink; in-memory resolvery dla userProfile, serviceReviews, userReviews, submitReview (store w pamięci); useQuery/useMutation z @apollo/client/react [OK]
D4 React Portals 4 komponenty mountowane do #portal-root przez createPortal(): Modal.jsx, PaymentModal.jsx, ProfileEditModal.jsx, RescheduleModal.jsx [OK]
D5 React.lazy i dynamic imports lazy(() => import('./pages/DashboardPage')) i lazy(() => import('./pages/AdminPage')) w App.jsx; ładowanie on-demand przy pierwszym wejściu na trasę [OK]
D6 Render props i HOC DataRenderer.jsx render prop (children jako funkcja), używany w AnalyticsDashboard; withRole.jsx HOC z displayName, używany w AdminPage; oba wzorce produkcyjne [OK]
D7 React Query TanStack React Query v5: 7 custom hooków, staleTime 5 min, invalidateQueries po mutacjach (lista rezerwacji odświeżana po każdej zmianie), isPending dla UX [OK]
D8 React DevTools WithRole.displayName dla czytelności drzewa; QueryClient kompatybilny z React Query Devtools; Apollo InMemoryCache widoczna w Apollo DevTools [OK]
D9 Testy z React Testing Library 5 plików testowych, 25+ testów (Vitest): LoginPage (formularz, błędy, submit), BookingForm (walidacja RHF), ProtectedRoute (przekierowania, role), StatusBadge (warianty x2) [OK]
D10 Storybook 3 pliki stories w src/stories/: StatusBadge (wszystkie statusy + rozmiary), Modal (Default + Danger z useState wrapper), ThemeToggle (z etykietą); Storybook 8 + @storybook/react-vite [OK]
D11 React Concurrent Mode useTransition w AdminPage.jsx: przełączanie zakładek (Tabela/Kalendarz/Analityka/Użytkownicy) przez startTransition(() => setMainTab(key)) nie blokuje UI przy ciężkich re-renderach [OK]

Wyniki testów

Vitest (jednostkowe):  25 passed, 0 failed
Playwright (e2e):      32 passed, 0 failed, 2 warnings
Description
No description provided
Readme 2.4 MiB
Languages
JavaScript 64.2%
SCSS 34.3%
Just 1.2%
Dockerfile 0.2%
HTML 0.1%