Przejdź do głównej zawartości

Poziom uczestnika zajęć próbnych

Trener w trakcie zajęć próbnych wskazuje uczestnikowi poziom — czyli grupę zajęciową, na którą uczestnik powinien trafić po próbnych. Poziomem jest wprost rodzaj zajęć grupowych, więc wybór trenera od razu nadaje się do filtrowania wolnych terminów w dalszych krokach zapisu.

👤 Instrukcja dla trenera

Ścieżka: Dashboard ➔ Kalendarz ➔ [kliknij swoje zajęcia] ➔ Sprawdź obecność

Po co to jest

Uczestnik zajęć próbnych dołącza do normalnej grupy. To Ty na miejscu widzisz, czy dziecko poradzi sobie w tej grupie, czy pasuje mu inny poziom. Twój wybór trafia prosto do karty uczestnika i decyduje o tym, jakie terminy zaproponujemy rodzicowi po zajęciach.

Jak przypisać poziom

  1. Otwórz swoje zajęcia w kalendarzu i kliknij Sprawdź obecność.
  2. Uczestnicy zajęć próbnych mają pod nazwiskiem dodatkowe pole Poziom. Zwykli uczestnicy zajęć go nie mają — u nich nic się nie zmienia.
  3. Pole startuje puste. Grupa, w której odbywają się próbne, nie jest podpowiadana: uczestnik trafił do niej dlatego, że było w niej wolne miejsce i pasowała godzina, a nie dlatego, że odpowiada jego poziomowi. Wybór ma być Twoją oceną, nie zatwierdzeniem przypadku.
  4. Możesz wskazać kilka poziomów, jeśli uczestnik pasuje do więcej niż jednej grupy.
  5. Po ponownym wejściu pole pokazuje poziomy aktualnie przypisane — widzisz stan wyjściowy, także ten nadany wcześniej przez biuro.
  6. Możesz zarówno dodać poziom, jak i odznaczyć ten, który już jest — odznaczony zostanie usunięty po zapisaniu. Usuwasz wyłącznie to, co widzisz na liście: przypisania z innej lokalizacji albo do zarchiwizowanego rodzaju zajęć zostają nietknięte.
  7. Zaznacz obecność i zapisz.

Kiedy poziom jest wymagany

Poziom musisz wskazać każdemu obecnemu uczestnikowi zajęć próbnych — bez tego przycisk zapisu jest nieaktywny, a nad nim pojawia się komunikat.

Uczestnik nieobecny na próbnych poziomu nie wymaga: nie było czego oceniać, a jeden nierozstrzygnięty przypadek nie może blokować zapisu obecności całej grupy.

Uczestnik, który ma już poziom przypisany, spełnia ten warunek — pole jest wypełnione i nie musisz nic zmieniać. Nie możesz natomiast wyczyścić pola obecnemu uczestnikowi do zera: zapis zostanie zablokowany, dopóki nie wskażesz przynajmniej jednego poziomu. Nieobecnemu wolno wyczyścić wszystko.

Ile masz czasu

Zwykłą obecność oznacza się do 35 minut od startu zajęć. Zajęcia, na których jest ktoś z próbnych, mają dłuższe okno — 24 godziny od zakończenia zajęć — bo poziom ocenia się w trakcie i pod koniec zajęć, a nie na starcie.

Z tego samego powodu zajęcia z uczestnikiem próbnym pokazują przycisk Sprawdź obecność nawet wtedy, gdy dany rodzaj zajęć ma wyłączone sprawdzanie obecności — inaczej nie byłoby jak nadać poziomu.

Pomyłka

Przypisania poprawia biuro: Dashboard ➔ Zadania albo karta uczestnika.

🛠 Dokumentacja techniczna

Model danych

Nie powstała żadna nowa tabela ani migracja. Poziom to rodzaj zajęć, więc przypisanie ląduje w istniejącej tabeli player_activity_types (UNIQUE(player_id, activity_type_id, tenant_id), kolumna assigned_by).

Uczestnik zajęć próbnych to wpis w JSON-ie game.attendees z type: 'skill-assessment' — ten sam mechanizm, z którego korzysta obecność (present).

Przepływ

Synchronizacja zamiast dopisywania

syncTrialLevels zestawia wybór trenera z tym, co jest w bazie, i wykonuje różnicę: dodaje zaznaczone, usuwa odznaczone. Zakres usuwania jest ograniczony do poziomów, które trener w ogóle widział — czyli aktywnych typów group z miasta i ulicy kortu, wyliczonych po stronie serwera, a nie przysłanych przez klienta. Dzięki temu:

  • odznaczenie w UI faktycznie kasuje przypisanie (inaczej pole pokazywałoby stan, na który nie da się wpłynąć),
  • przypisanie spoza tej listy — inne miasto, typ indywidualny, typ zarchiwizowany — nigdy nie zostanie skasowane, nawet gdyby klient je przysłał.

Z tego samego powodu getTrialLevelOptions zwraca assignments przefiltrowane do widocznych typów: pole nie może pokazywać wartości, której nie ma na liście wyboru.

Pliki

PlikRola
lib/actions/trial-level.tsgetTrialLevelOptions, syncTrialLevels, walidacja wymagalności
lib/actions/game.tsmarkAttendancetrzeci, opcjonalny argument trialLevels; zapisuje poziomy przed obecnością

| app/api/games/[gameId]/trial-levels/route.ts | odczyt opcji dla dialogu (route handler, nie server action) | | app/(dashboard)/dashboard/schedule/components/AttendanceChecker.tsx | pole Poziom na karcie uczestnika próbnego | | components/schedule/activity-details-dialog.tsx | pobranie opcji, walidacja przed zapisem, okno czasowe | | lib/utils/trial-level-selection.ts | stan pola budowany wyłącznie z zapisanych przypisań | | settings.ts | HOURS_AFTER_GAME_END_TO_ASSIGN_TRIAL_LEVEL |

Lista poziomów

activity_types filtrowane po type = 'group', archived = 0 oraz mieście i ulicy kortu, na którym odbywają się zajęcia. Filtrujemy po type, nie po category = 'Szkółki' — kategoria to wolny tekst, który tenant może przemianować.

Autoryzacja

Akcje addPlayerActivityType / setPlayerActivityTypes chroniło dotąd wyłącznie to, że jedynym wejściem była strona /dashboard/tasks ograniczona do ADMIN/BACKOFFICE. Ścieżka trenera ma własne guardy, niezależne od dostępu do strony:

  • rola INSTRUCTOR, ADMIN lub BACKOFFICE
  • canInstructorAccessGame() — przypisany trener albo zastępca tych zajęć
  • gracz musi być uczestnikiem tej gry z type = 'skill-assessment'
  • rodzaj zajęć musi być aktywnym typem group tego samego tenanta

Walidacja wymagalności („każdy obecny próbny ma poziom") działa po stronie serwera, nie tylko w UI.

Kontrakt markAttendance

Trzeci argument rozstrzyga, czy wymagalność jest egzekwowana:

  • pominięty (undefined) — wywołanie sprzed tej zmiany, np. formularz edycji zajęć administratora (EditGameForm.tsx). Obecność zapisuje się jak dotąd, poziomów nie dotykamy i niczego nie wymagamy. Bez tego rozróżnienia obecny uczestnik próbny bez poziomu blokowałby administratorowi zapis w widoku, który nie ma pola poziomu.
  • tablica (również pusta) — wywołanie z widoku obecności trenera. Poziomy zapisujemy, a wymagalność jest sprawdzana.

Testy

lib/actions/trial-level.test.ts — 15 testów: filtrowanie listy poziomów, domyślne zaznaczenie, dopisywanie bez kasowania, idempotencja, wymagalność przy obecnym / brak wymagalności przy nieobecnym, odrzucenie gracza spoza zajęć, typu spoza group i typu z innego tenanta.