Trudny / egzaminacyjny · lekcja 27
Projekt 8 (końcowy): System rezerwacji wizyt — Angular + logowanie + zadanie kontrolne
Ostatni, czwarty projekt i jednocześnie podsumowanie całego działu. Łączymy WSZYSTKO: Angular (komponenty, formularze, routing, serwisy), ASP.NET Core Web API z bazą danych, oraz logowanie użytkowników (ASP.NET Core Identity, lekcja 14) — dokładnie ten typ peł...
Zacznij tutaj
Po co się tego uczymy?
Wprowadzenie
Teoria
Wymagania funkcjonalne systemu rezerwacji:
- Lista dostępnych terminów — widoczna dla WSZYSTKICH odwiedzających (komponent publiczny, bez logowania);
- Rezerwacja terminu — WYMAGA zalogowania; zalogowany użytkownik wybiera wolny termin i go rezerwuje;
- "Moje rezerwacje" — strona (chroniona) pokazująca WYŁĄCZNIE rezerwacje zalogowanego użytkownika;
- Anulowanie rezerwacji — użytkownik może odwołać WŁASNĄ rezerwację;
- Logowanie i rejestracja — ASP.NET Core (lekcja 14), z tokenem/ciasteczkiem uwierzytelniającym rozpoznawanym przez Angular.
Logowanie w architekturze Angular + Web API. W parze Razor Pages (jedna aplikacja), Identity działa "w tle" automatycznie przez ciasteczka. W architekturze Angular+API mamy DWIE osobne aplikacje (inny port!) — logowanie zwykle realizuje się przez token (najczęściej JWT — JSON Web Token): backend po poprawnym zalogowaniu zwraca token, Angular zapisuje go (np. w pamięci przeglądarki) i DOŁĄCZA do KAŻDEGO kolejnego żądania w nagłówku Authorization: Bearer <token>. Backend na podstawie tego nagłówka rozpoznaje, KTO wysyła żądanie, bez potrzeby przechowywania sesji po stronie serwera. To rozwiązanie technicznie różni się od ciasteczek sesyjnych z lekcji 13, ale odpowiada na TEN SAM problem — informator CKE wprost dopuszcza obie metody: "obsłużyć sesje LUB JWT".
Model danych. Termin (Data, CzyZarezerwowany), Rezerwacja (TerminId, UzytkownikId, DataUtworzenia) — relacja jeden-do-jednego między terminem a rezerwacją, jeden-do-wielu między użytkownikiem a jego rezerwacjami (EF Core, lekcje 14-16).
Kluczowy problem: unikanie podwójnej rezerwacji. Backend MUSI ponownie sprawdzić dostępność terminu TUŻ PRZED zapisem (nie tylko przy wyświetleniu listy) — jeśli dwóch użytkowników niemal jednocześnie próbuje zarezerwować ten sam termin, backend jako "źródło prawdy" musi to wykryć i jednego z nich odrzucić z czytelnym komunikatem błędu (kod 409 Conflict).
Struktura komponentów Angular: TerminyComponent (publiczny, lista + przycisk "Zarezerwuj", przekierowujący na logowanie jeśli niezalogowany), LogowanieComponent/RejestracjaComponent, MojeRezerwacjeComponent (chroniony przez Angular Route Guard — mechanizm blokujący dostęp do trasy bez ważnego tokenu, analogiczny do [Authorize] z ASP.NET Core).
Zobacz zależności
Schemat
Gość (niezalogowany)
│
▼
Pages/Terminy/Lista.cshtml (publiczna) - widzi dostępne terminy
│
│ klika "Zarezerwuj" → przekierowanie na logowanie (jeśli niezalogowany)
▼
Pages/Konto/Logowanie.cshtml → po zalogowaniu wraca (ReturnUrl)
│
▼
Pages/Rezerwacje/Zarezerwuj.cshtml [Authorize]
│
│ OnPostAsync: PONOWNE sprawdzenie czy termin nadal wolny
│ (ochrona przed podwójną rezerwacją)
▼
Nowa Rezerwacja (TerminId, UzytkownikId) → SaveChangesAsync()
Termin.CzyZarezerwowany = true → SaveChangesAsync()
│
▼
Pages/Rezerwacje/Moje.cshtml [Authorize]
context.Rezerwacje.Include(r => r.Termin)
.Where(r => r.UzytkownikId == User Id zalogowanego)
Administrator: Pages/Admin/ZarzadzajTerminami.cshtml [Authorize(Roles="Admin")]
dodawanie/usuwanie dostępnych terminów
Połącz z praktyką
Przykład z życia
System rezerwacji wizyt u fryzjera, lekarza czy w gabinecie kosmetycznym — klient przegląda dostępne terminy, loguje się, rezerwuje wybrany termin i może go później odwołać. To ostatni, syntetyzujący projekt tego działu, łączący front-end (Angular), backend (ASP.NET Core Web API) i bazę danych (EF Core) w jedną, kompletną, praktyczną aplikację.