Claude/kind ptolemy 9 mvh0 - #42
Open
fpudelko wants to merge 649 commits into
Open
Conversation
fpudelko
force-pushed
the
claude/kind-ptolemy-9Mvh0
branch
2 times, most recently
from
June 8, 2026 11:51
4da9553 to
8ddcd4f
Compare
fix: H1 w hero na mobile — 2 linie zamiast 3, mniejszy niż w PR #72
… claude/match-page-pr-review-udtrxx # Conflicts: # docs/llm-context.md # frontend/public/llm-context.md
Bloki z przyciskami "Zawodnik z pola" / "Bramkarz" przy dopisywaniu gościa miały wcięcie przesunięte o 2 spacje względem otaczającego JSX. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017Gu3t6mXHrLq5jz7pJJfxs
Strona meczu: drobnica UI (11 poprawek)
- /prywatnosc i /regulamin: usuń banner "to tylko szablon prototypu", wypełnij placeholdery [nazwa podmiotu]/[adres], popraw sprzeczności (bojo.app -> bojo.pl, zasięg, limit odpowiedzialności vs bezpłatność), dopisz brakujące elementy RODO i regulaminu (ograniczenie przetwarzania, transfer poza EOG, cookies, reklamacje, odstąpienie). Dane usługodawcy w lib/legal.ts. - Kreator meczu (/wydarzenia/nowe): numerki kroków są klikalne i walidują jak "Dalej" (lib/eventWizard.ts, pod testy); jeden przyklejony pasek "Wróć"/"Dalej" w jednej linii zamiast dwóch osobnych przycisków na krok; dolny panel nawigacji chowa się w kreatorze. - Dolny panel chowa się też na stronie meczu, dopóki użytkownik nie dołączył (lib/bottomNavVisibility.tsx) - nie zasłania już przycisków "Dołącz"/"Obserwuj" ani modali. Usunięty zdublowany przycisk "+" na /wydarzenia, "Gry" -> "Znajdź grę". - Zaproszenia na mecz: nowa zakładka "Zaproszenia" na /moje-gry (?tab=zaproszenia) i plakietka z licznikiem na /wydarzenia, widoczna tylko gdy jest co najmniej jedno zaproszenie. Wspólny hook lib/useMyInvites.ts i komponent InviteList współdzielony z dashboardem. Co zostało celowo bez zmian: auto-awans z rezerwy, migracje SQL, lib/invites.ts (martwy kod, nie ruszany). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0116k4YFHqdjsCVYUtChQThB
…-flow-y282kw Event wizard UX: clickable steps, sticky nav, invites tab
Naprawa buildu produkcyjnego (master jest zepsuty)
… karty przy dlugim tytule
…overflow Dwie naprawy z testów: zaproszenia od uczestnika + rozjeżdżające się karty
Import boisk z OSM: lubelskie na próbę, nazwy z kontekstu, zero AI
Karuzela na mapie nad nawigacją + domyślny skład zależny od sportu
Import OSM: wybór bramki publikacji + odmiana w nazwach miejscowości
Agent sam merguje swój PR po zielonym CI
Mapa bez zaszytego Poznania + skrypt publikujący lubelskie
Zamiast przeklejac wyniki SQL z Supabase: read-only skrypt, ktory odtwarza zapytanie getExplorerFields() warunek po warunku i wypisuje lejek do logu GitHub Actions. Sekrety juz tam sa, agent nie potrzebuje wlasnego dostepu do bazy. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017dvpk3tbb8nsot5XNTaS8C
chore: diagnostyka — czemu obiektów z lubelskiego nie widać na mapie
Diagnostyka (workflow 'Diagnoza mapy') potwierdzila, ze dane sa w porzadku: 1638 obiektow lubelskiego przechodzi filtr mapy. Nie bylo ich widac, bo MapContainer startowal na sztywno z center=POZNAN i zoom=11. - widok startowy: cala Polska (POLSKA / POLSKA_ZOOM w mapIcons.ts) - przycisk pinezki w rogu mapy pyta o geolokalizacje i skacze na okolice uzytkownika; zgoda pytana dopiero po kliknieciu - 'wielofunkcyjne' (OSM sport=multi) dopisane do EXPLORER_SPORTS i SPORT_CONFIG - 162 obiekty w samym lubelskiem odpadaly po cichu Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017dvpk3tbb8nsot5XNTaS8C
fix: mapa otwiera się na Polsce, nie na Poznaniu
Build produkcyjny na Vercelu ciagnal sie ponad 40 minut i nie konczyl,
wiec poprzednia zmiana mapy w ogole nie doszla na produkcje.
Przyczyna: generateStaticParams() zwracalo slug KAZDEGO boiska, a
resolveField() po slugu robilo select('*') na calej tabeli fields - raz
w generateMetadata i raz w komponencie. Koszt rosl kwadratowo: ~1500
obiektow (Poznan) jeszcze przechodzilo, ~4600 po imporcie z OSM juz nie.
- generateStaticParams() zwraca [], revalidate = 86400 -> strona boiska
powstaje przy pierwszym wejsciu i siedzi w cache przez dobe
- slug -> id przez wspolny indeks z TTL zamiast pelnego selecta na render
Czas builda przestaje zalezec od wielkosci katalogu - warunek dojscia do
dziesiatek tysiecy obiektow z calej Polski.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017dvpk3tbb8nsot5XNTaS8C
…talogu perf: strony boisk na żądanie zamiast prerenderu całego katalogu
…uszach Trzeci przebieg wskazal wlasciwa przyczyne. `webServer.env` w konfiguracji Playwrighta ustawialo atrapy Supabase NA SZTYWNO, wiec proces `npm run start` renderowal strony bez dostepu do bazy. Klient mial poprawny adres — wartosci `NEXT_PUBLIC_*` sa wstawiane do paczki przy buildzie, a build w tym zadaniu dostawal je z GITHUB_ENV. Ale `/wydarzenia/[id]/page.tsx` to komponent SERWEROWY (buduje metadane Open Graph i JSON-LD) i czyta baze po stronie Node. Serwer nie widzial nic. Teraz atrapy sa wartoscia ZAPASOWA: testy klikalnosci i zrzuty widokow publicznych maja dzialac bez zadnej bazy, a scenariusze dostaja prawdziwy adres lokalnego stosu. Zweryfikowane lokalnie: zrzuty widokow publicznych nadal 7/7 na atrapach. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017dvpk3tbb8nsot5XNTaS8C
Piec przebiegow w CI, za kazdym razem ten sam objaw: "nie ma przycisku Dolacz". Objaw, nie przyczyna — a diagnostyka, ktora dopisalem do skryptu stosu, wypisuje sie na POCZATKU zadania, czyli w czesci logu, ktorej z tego srodowiska nie widze (dostep mam tylko do konca). `otworzMecz()` i `zaloguj()` wklejaja teraz to, co realnie widzi przegladarka (pierwsze 600 znakow tekstu strony plus adres), wprost w tresc bledu. Bledy Playwright drukuje na koncu logu, wiec nastepny przebieg powie, czy strona mowi "Nie znaleziono", czy stoi pusta, czy wisi na ladowaniu. To nie jest naprawa — to zamiana zgadywania na odczyt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017dvpk3tbb8nsot5XNTaS8C
…jego tresci Szosty przebieg i nadal nie znam przyczyny, ale wiem juz, DLACZEGO jej nie znam: przy 17 bledach Playwright konczy log lista nazw testow, a tresc pierwszego bledu — z tekstem strony, ktory sam dopisalem — zostaje wypchnieta poza koncowke logu, jedyna czesc dostepna z tego srodowiska. `--max-failures=1` sprawia, ze log konczy sie pelna trescia jednego bledu. Skrot dla wlasciciela: artefakt `scenariusze-raport` zawiera raport HTML z ta sama trescia. Otwarcie go i przeslanie komunikatu zalatwia sprawe szybciej niz kolejny przebieg. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017dvpk3tbb8nsot5XNTaS8C
… w stringu validateEmail() sprawdzała obecność '@' i '.' NIEZALEŻNIE od siebie, więc kolejność nie miała znaczenia — adres w rodzaju "jan.kowalski@d" przechodził, bo kropka jest (przed @), mimo że domena "d" nie ma TLD-u. RPC dolacz_do_meczu_jako_goscie() już tego pilnuje poprawnie (LIKE '%@%.%' w Postgresie jest sekwencyjny, wymaga kropki PO @), więc luka była tylko po stronie frontendu. Regex /^[^\s@]+@[^\s@]+\.[^\s@]+$/ wymaga kropki w domenie z czymś po niej i zabrania spacji. Dziewięć nowych testów w validation.test.ts. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GsKGLN5RtLEwW1WwGbtEmK
…domenie) Popraw walidację e-maila: kropka musi być w domenie
…ień (#163) * Napraw brak powiadomienia o niepełnym imieniu (dzwonek) Trigger z migracji 070/071 jest poprawnie zdefiniowany i włączony, ale w produkcyjnej bazie nigdy nie wstawił ani jednego powiadomienia uzupelnij_profil — potwierdzone zapytaniem po danych: zero wierszy tego typu mimo dziesiątek kont z niepełną nazwą, przyczyna nieznana (trigger on_auth_user_created na tej samej tabeli działa niezawodnie). Migracja 085 dodaje RPC zglos_brak_pelnej_nazwy(), wołane z auth.tsx przy SIGNED_IN dla świeżych kont (<10 min) tym samym warunkiem isPelneImie(), którego już używa baner na pulpicie — jedno źródło prawdy zamiast dwóch niezależnych implementacji. Trigger zostaje jako potencjalny drugi nadawca; NOT EXISTS w RPC chroni przed duplikatem. WYMAGA RĘCZNEGO URUCHOMIENIA migracji 085 w Supabase SQL Editor. * Zachęta do zaproszenia gościa do Bojo zaraz po dodaniu Dziś organizator musiał sam zauważyć mały link "Zaproś do Bojo" przy imieniu gościa w składzie. Nowy modal (GuestInviteNudge) pokazuje się proaktywnie zaraz po dodaniu gościa, z argumentacją opartą na realnym zachowaniu aplikacji: gość bez konta nie dostaje powiadomienia o zmianie terminu/odwołaniu meczu, nie zostaje w bazie graczy organizatora, i organizator musi ręcznie śledzić jego udział. Pokazuje się raz na wydarzenie, żeby dopisanie kilkunastu osób pod rząd nie zasypało modalami. addGuest() zwraca teraz też id/claimToken (claim_token jest już generowany automatycznie triggerem z migracji 066, nie trzeba nic zmieniać w bazie). Logika udostępniania (Web Share / schowek) wydzielona do udostepnijZaproszenieGoscia() w guestClaim.ts, współdzielona przez nowy modal i istniejący przycisk "Zaproś do Bojo" w składzie. * Modal wyboru roli po rejestracji (organizator/gracz) Świeżo zarejestrowany użytkownik nie miał żadnej podpowiedzi, co robić dalej. Nowy globalny modal (PostSignupRoleModal) pokazuje się raz, tylko po organicznej rejestracji — gdy zapamiętany cel logowania jest jednym z neutralnych miejsc (/, /wydarzenia, /moje-gry, /mapa) albo nieznany. Bezpieczniejszy domyślny wynik niż lista "kontekstów dołączania": nieznany cel NIE pokazuje modala, więc rejestracja w trakcie dołączania do meczu, przejęcia wpisu gościa czy dołączania do grupy nie zostaje przerwana. Proponuje "Jestem organizatorem" (prosto do /grupy/nowe, wizualnie pierwsze) albo "Jestem graczem" (/grupy albo /wydarzenia). Ograniczone do świeżych kont (<10 min), żeby nie zaskoczyć istniejących użytkowników przy pierwszym logowaniu po wdrożeniu. * Popraw treść mockupu kreatora na landingu (krok 2/3, nie 3/3) Mockup "Kiedy i ile" na landingu pokazywał wskaźnik kroku jako 3/3, choć w realnym kreatorze (STEP_TITLES w wydarzenia/nowe/page.tsx) ten krok jest 2 z 3. Brakowało też kafelka "Wydarzenie cykliczne", a "Czas gry" był rysowany jako rząd pigułek zamiast dropdowna z godziną końca — żadne z tych trzech nie miało odpowiednika w działającym kodzie. Mockupy zostają rysowane w JSX (świadoma decyzja udokumentowana w pliku: zrzut ekranu miękczeje przy DPI, waży więcej i rozjeżdża się z UI) — poprawiona jest wyłącznie treść, żeby odpowiadała dzisiejszemu krokowi 2. * Zaktualizuj dokumentację: migracja 085, zaproszenie gościa, wybór roli docs/baza-danych.md — wpis o migracji 085 w tabeli migracji i w spisie RPC, poprawka zdania "powiadomienia wyłącznie z wyzwalaczy" (teraz też wąsko uprawnione RPC). docs/funkcje.md — zaproszenie gościa ma teraz proaktywny modal, sekcja "Powiadomienia" opisuje naprawę, "Gdzie ląduje zalogowany" opisuje nowy modal wyboru roli. docs/llm-context.md — nowy wpis w "Ostatnie zmiany" (limit 10, usunięty najstarszy), zaktualizowany znacznik "Stan na". Kopia publiczna zsynchronizowana przez npm run sync:llm-context. * fix: renumber migration 085 → 086 due to PR #156 merge conflict Migracja 085 była zarezerwowana przez PR #156 (zapobieganie duplikatom wpisu gościa). Ta zmiana renumeruje RPC powiadomienia o braku nazwy na 086, ponieważ oba PR-y trafiły do repozytorium w tej samej numeracji. Zmienione pliki: - supabase/migrations/086_rpc_powiadomienie_braku_nazwy.sql (było 085) - docs/baza-danych.md — aktualizacja numeracji w tekście i tabelach - docs/funkcje.md — aktualizacja numeracji - docs/llm-context.md — aktualizacja w sekcji "Ostatnie zmiany" i metadanych - frontend/public/llm-context.md — aktualizacja publicznej kopii (npm run sync) Co nie zmienia się: - Treść i logika RPC — identyczna - Funkcjonalność auth.tsx — identyczna - Baza danych — identyczna (migracja będzie wklejana ręcznie w Supabase) CI: - npm run check:docs — ✓ spójność dokumentacji - npm run build — ✓ build Co dalej: PR #157 może teraz zostać zmergowany gdy CI przejdzie. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012V6cTYrmkbEzKMuR1rSSmK * fix: update migration comment to match filename (086 not 085) * Napraw cztery problemy z integracją modali onboardingowych i powiadomień 1. GuestInviteNudge — skróć nagłówek i punkty (zbyt gadatliwe) 2. PostSignupRoleModal — dodaj logging dla każdej ścieżki warunkowej aby móc debugować, dlaczego modal się nie pokazuje. Logowanie pomaga zidentyfikować: czy konto zbyt stare, czy już widziane, czy cel nie neutralny, czy sessionStorage niedostępny. 3. Napraw timing bug w auth.tsx — przenies tracking logowania i RPC powiadomienia PRZED early-return dla powrotu post-logowania. Wcześniej `odbierzPowrot()` mogła powodować `return` zanim kod osiągnąłby RPC czy PostSignupRoleModal effect. Teraz tracking i RPC zawsze się wykonują, a redirect `odbierzPowrot()` idzie na koniec. 4. Dodaj error logging do RPC zglos_brak_pelnej_nazwy() — błędy typu "function not found" (migracja niewgrana) były całkowicie niewidoczne. Teraz logują się do console.error dla diagnostyki. Dodaj logging do powrotPoLogowaniu.ts dla ostatniZamierzonyCel() — pomaga śledzić, czy sesja ma zapamiętany cel i czy jest ważny. Co to rozwiązuje: - Problem 1 (GuestInviteNudge): Modal działa, tekst jest teraz bardziej zwięzły i czytelny. - Problem 2 (PostSignupRoleModal): Koniec domysłów — console.debug pokazuje dokładnie, dlaczego modal się nie pojawia. Również naprawiony timing bug zapewnia, że RPC i tracking zawsze się wykonują. - Problem 3 (Notification): Teraz widać w console, gdy RPC 'zglos_brak_pelnej_nazwy' nie istnieje (404 — migracja 086 niewgrana) lub inne błędy. Uwaga: PostSignupRoleModal ma 8 potencjalnych przyczyn, ale większość to test metodologia (stare konto, email confirmation >10min). Logging pomaga ten problem zdiagnozować. Co wciąż trzeba sprawdzić: 1. Czy migracja 086 (RPC dla powiadomienia) zostały uruchomiona ręcznie w Supabase SQL Editor? (migracje nigdy nie autodeployują) 2. Czy test PostSignupRoleModal był na faktycznie nowym koncie (<10 min stare)? 3. Czy domena testowa jest na liście dozwolonych redirect URL w Supabase? Co NIE zmienia: - Migracja 086 SQL (poprawna syntaktycznie) - Struktura PostSignupRoleModal (poprawna logika) - RLS polityki czy dane w bazie Co robić dalej: - Sprawdzić console.debug w przeglądarce przy testowaniu rejestracji - Jeśli RPC daje 404, uruchomić migrację 086 w Supabase SQL Editor - Jeśli konto "stare", testować z faktycznie nowym kontem Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011b6a001-2472-575a-8e7e-e3a18458cb50 --------- Co-authored-by: Claude <noreply@anthropic.com>
FAQ na stronie głównej twierdziło, że dołączenie do meczu wymaga logowania — nieprawda od migracji 082 (self-service zapis gościa: imię i e-mail, bez konta). To dokładnie ten argument, którym organizator przebija opór graczy przed zakładaniem konta w obcej aplikacji, i sami go sobie zabieraliśmy. Nowe src/content/faq.ts: 36 pytań w sześciu kategoriach, jedno źródło dla całej aplikacji. components/home/landing/content.ts re-eksportuje ośmiopozycyjny podzbiór (FAQ_LANDING) jako LANDING_FAQ zamiast trzymać kopię — LandingFaq.tsx i landingContent.test.ts nie wymagały zmian poza samą treścią. Nowa strona /faq pokazuje wszystko, z własnym FAQPage JSON-LD nad dokładnie tą treścią, którą renderuje. Lista zakazanych fraz z landingContent.test.ts przeniesiona do content/zakazaneFrazy.ts (ZAKAZANE_NA_LANDINGU) — współdzielona z testem nowych stron treści w kolejnym commicie.
Dwie strony pisane pod jedno zadanie: organizator nie ma po nich ani jednej wątpliwości, co się kiedy dzieje. /jak-dziala-bojo przechodzi całą ścieżkę od kreatora po rozliczenie, z osobną sekcją o tym, co dokładnie widzi zaproszony gracz, i osobną o tym, co Bojo powiadamia i gdzie — wprost mówiąc, że SMS-ów i maili o meczu nie wysyła. /dlaczego-bojo odpowiada na "mam przecież grupę na Messengerze" tabelą porównawczą i na "moi gracze nie założą konta w kolejnej apce" wprost. Treść w content/jakDziala.ts i content/dlaczego.ts (wszystkie sekcje, także te bez niestandardowego markupu, żeby dało się testować bez renderowania — weryfikacja fraz w kolejnym commicie). Link "Zobacz krok po kroku..." pod "Trzy kroki do składu" na landingu do /jak-dziala-bojo.
/o-nas: kto robi Bojo, dlaczego, model biznesowy (dziś darmowe, w planie
prowizja od rezerwacji i płatne dodatki — żadne z tego nie działa dziś,
napisane wprost), atrybucja OpenStreetMap/ODbL. Nowy aboutPageJsonLd()
w lib/structuredData.ts, wskazujący istniejący węzeł Organization zamiast
powtarzać jego pola.
Stopka (SiteFooter.tsx) przebudowana mobile-first na dwie grupy linków
("Produkt", "Bojo") zamiast jednej płaskiej listy — kolumna na telefonie,
wiersz od md:. sitemap.ts dostaje cztery nowe trasy. llms.txt: naprawiona
ta sama nieprawda o koncie co w FAQ (dołączenie do meczu nie wymaga
logowania), liczba obiektów (~1400 → ponad 30 000, zgodnie ze stanem bazy),
usunięta nieaktualna wzmianka o "obecności" (kolumna track_attendance
usunięta migracją 064), nowa sekcja "Dla organizatora" z czterema trasami.
Dwa niezależne usprawnienia dla wydarzeń, które się już odbyły — zero migracji, zero nowych zapytań do bazy. domyslnyTerminPowtorki() (lib/recurring.ts): okno "Powtórz mecz" otwierało się z pustym polem daty i zablokowanym przyciskiem — dla cotygodniowej gierki trzy zbędne kliknięcia w miejscu, gdzie powinno być zero decyzji. Nowa funkcja liczy najbliższy przyszły termin tego samego dnia tygodnia co pierwowzór — ta sama matematyka, którą nastepnyTermin() już robi dla serii cyklicznych. Podpięcie w EventDetailClient.tsx w kolejnym commicie. doRozliczenia() (lib/myEvents.ts) + DoRozliczeniaSection: zakładka Historia na /moje-gry była płaską listą, w której mecz z zaległością wyglądał identycznie jak mecz rozliczony. Nowa sekcja na górze zakładki filtruje dane, które getMyParticipatedEvents() już zwraca (unpaidCount liczony przez toEvent()).
…jscu Po starcie meczu + 30 minut strona pokazywała organizatorowi wyłącznie jedną bursztynową linijkę "wpisz wynik" — nic o rozliczeniu ani o gościach bez konta. Dane produkcyjne: 122 rozegrane mecze, 6 zapisanych wyników, 45 nierozliczonych, zero przejętych wpisów gości. Bojo umie te rzeczy, tylko nic o nie nie prosiło we właściwym momencie. PoMeczuCard (components/events/PoMeczuCard.tsx) — czysto prezentacyjna, renderowana pod isOwner && resultsAvailable && !isCancelled, między banerem odwołania a banerem "Mecz gotowy". Trzy zadania, każde tylko gdy dotyczy danego meczu (rozlicz ekipę / wpisz wynik / zaproś gości), plus stała oferta "Powtórz mecz" — ta sama akcja i etykieta co istniejący przycisk w "Zarządzaj wydarzeniem" (świadome powielenie, nie duplikat z O-20). Gdy nic nie zostało, karta zwija się do jednej linii. Kotwice #podzial-kosztow / #wynik-meczu / #sklad dodane na istniejących kontenerach; handleOpenRepeat (z poprzedniego commitu) podpięty też pod istniejący przycisk "Powtórz mecz (skopiuj)". Zero nowego zapytania do bazy — komponent składa stan (regulars, matchResult, niePrzejeciGoscie), który EventDetailClient.tsx już liczy.
- docs/funkcje.md: nowe sekcje "Karta «Po meczu»" i "Strony treści", sekcja /moje-gry uzupełniona o "Do rozliczenia". - docs/przeplyw-organizatora.md: nowa Faza 7 — po gwizdku (O-32…O-35). - docs/llm-context.md: sekcja "Zasięg i skala" nie kłamie już o koncie przy dołączaniu; nowy wpis w "Ostatnie zmiany" (limit 10 — najstarszy usunięty); licznik testów zaktualizowany. Kopia publiczna zsynchronizowana (npm run sync:llm-context). - BACKLOG.md: /o-nas odhaczone; sprostowany fałszywy wpis o lib/landingStats.ts/getPublicVenueCount() — te pliki nie istnieją, LANDING_STATS jest zaszyty na sztywno. - AGENTS.md: reguła mobile-first w "Konwencje", wzmianka o frontend/src/content/, zaktualizowana liczba testów. - scripts/check-docs.mjs: nowa sekcja 10 — skanuje frontend/src pod kątem breakpointów max-width (Tailwind max-sm:/max-md:/… i @media max-width), dziś zero trafień; CI odrzuci pierwszy, który się pojawi. - e2e/klikalnosc.spec.ts: cztery nowe trasy w pętli "strony publiczne wstają i nie mają martwych warstw". - e2e/wzorce/*/strona-glowna.png: zregenerowane — landing urósł o nowe pytanie FAQ i dwa linki do stron treści. - src/__tests__/tresciStron.test.ts: per-jednostkowa weryfikacja treści /faq, /jak-dziala-bojo, /dlaczego-bojo, /o-nas wobec content/zakazaneFrazy.ts (ZAKAZANE_WSZEDZIE) — każda wzmianka o powiadomieniach mówi "w aplikacji", każda o SMS-ie mówi, że Bojo go nie wysyła; plus spójność FAQ ↔ FAQPage JSON-LD.
…rategy-9n3c5n Faza 1 organizatorów: strony treści, poprawione FAQ i domknięcie meczu po gwizdku
Zatrzymanie na pierwszym bledzie wreszcie pokazalo, co widzi przegladarka. Dwa znaleziska: 1. OKNO ONBOARDINGU. Po zalogowaniu wyskakuje "Zanim zaczniesz — kim jestes?" (`PostSignupRoleModal`) i przykrywa strone. Konta testowe powstaja przy seedzie, wiec dla przegladarki wygladaja na swiezo zalozone. Odklikujemy je znacznikiem w localStorage, ktorego uzywa sam komponent — zamiast klikac w okno, bo klikniecie wybraloby role i zmienilo stan, o ktorym test nic nie wie. 2. "NIE ZNALEZIONO WYDARZENIA". Meczu z seeda nie ma albo aplikacja go nie widzi. To dwie zupelnie inne przyczyny i nadal ich nie rozroznilem, wiec `otworzMecz()` pyta teraz API wprost, z tej samej przegladarki, i wkleja odpowiedz w tresc bledu: status HTTP plus poczatek tresci. Uwaga na pulapke: `process.env` nie istnieje w przegladarce, wiec adres i klucz ida do `page.evaluate` jako argumenty z procesu testu. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017dvpk3tbb8nsot5XNTaS8C
…egowanie uprawnień Cztery niezależne części tej samej strategii — maksymalne ułatwienie organizacji gry organizatorowi: 1. Naprawa buga: powiadomienie "uzupełnij profil" fizycznie zapisywało się w bazie po rejestracji, ale nigdy nie pojawiało się w dzwoneczku — wyścig między RPC a subskrypcją Realtime. Dzwoneczek teraz odświeża się jawnie po udanym zapisie. 2. Sekcja "Po meczu": przycisk "Zaproś do Bojo" rozwija skład przed scrollowaniem (wcześniej scrollował w puste miejsce); modal "Powtórz mecz" dostał pole "Koniec" i zachowuje długość meczu przy zmianie startu (wcześniej kopiował zegarową godzinę końca, dając kopie "trwające" 690 minut); tekst o BLIK-u w rozliczeniu pokazuje się tylko, gdy BLIK jest faktycznie zaakceptowaną metodą; nowy modal "Kto nie przyszedł" (wpływa na plakietkę "Niezawodny" na /gracz/[id], bez zmiany widoku składu) + adnotacja w wiadomości rozliczeniowej. 3. Delegowanie uprawnień organizatora (event_delegates, migracje 089-091): trzy niezależne uprawnienia — pełna edycja, zarządzanie składem/wynikiem, zarządzanie płatnościami — egzekwowane w RLS, nie tylko w UI. Przy okazji zaostrzone RLS player_reports (wcześniej dowolny zalogowany mógł zgłosić nieobecność kogokolwiek). 4. Usunięcie strony /o-nas wraz ze wszystkimi referencjami. Migracje 089, 090, 091 wymagają ręcznego uruchomienia w Supabase SQL Editor w tej kolejności — merge PR-a ich nie uruchamia. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V3aaHJuJQk8rYKUGsXjqnK
Szlifowanie przepływu organizatora: dzwoneczek, karta "Po meczu", delegowanie uprawnień
Umieszczam plik google3bff9cc843bcdfa8.html w frontend/public/ aby pozwolić Google Search Console na weryfikację właściwości https://www.bojo.pl/ Claude-Session: https://claude.ai/code/session_01F7ms34cwVNdfqxaMCbcjvr Co-authored-by: Claude <noreply@anthropic.com>
Przy większej ekipie/grupie lista kandydatów z trzema przełącznikami każdy zajmowała cały ekran. Pierwsza osoba zostaje rozwinięta domyślnie, reszta zwinięta do samej nazwy — klik w nazwę/chevron rozwija i zwija niezależnie, zapis przełącznika nadal dzieje się od razu (bez zamykania sekcji). Powiadomienie "uzupełnij profil" (druga zgłoszona sprawa) nie wymagało zmian w kodzie — RPC zglos_brak_pelnej_nazwy (migracja 086, z wcześniejszej sesji) nigdy nie została ręcznie uruchomiona w Supabase, więc wywołanie z klienta cicho failowało. Już naprawione ręcznym uruchomieniem migracji. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V3aaHJuJQk8rYKUGsXjqnK
Modal "Uprawnienia": zwijanie listy kandydatów
…uste ekrany Zrzuty rosna z 7 do 28 widokow na kazdy rozmiar okna (56 testow razem). Wszystkie chodza BEZ bazy, w tym samym przebiegu co build produkcyjny. Komunikaty, ktore normalnie przychodza z serwera, podstawia page.route(): zle haslo, e-mail niepotwierdzony, limit prob, e-mail zajety w obu wersjach (wprost i przy ochronie przed enumeracja), rejestracja wylaczona, wyslany link logowania i resetu. Sciezka kodu w aplikacji jest prawdziwa, atrapa siedzi wylacznie w sieci — wiec zrzut pilnuje realnego przekladu mapAuthError(). Do tego ekrany, ktorych dotad nie pilnowalo nic: 404, mecz ktorego nie ma, pusta lista meczow, regulamin, prywatnosc, baner cookies, trzy widoki zachecajace do zalogowania oraz "Google zablokowane w tej przegladarce", niedostepny inaczej niz przez podstawiony User-Agent Facebooka. Baner cookies wyskakuje po 6 sekundach albo po przewinieciu 300 px — zrzut robiony na granicy tego czasu lapal go raz tak, raz nie. Domyslnie zamykany, pokazywany tylko w tescie, ktory jest o nim. Stad zmiana wzorca strony glownej na telefonie. Przy okazji, w scripts/stos-lokalny.sh: scenariusze za logowaniem padaly na 401 42501 "permission denied for table events". To nie RLS, tylko brak GRANT-ow dla rol anon/authenticated — ALTER DEFAULT PRIVILEGES Supabase dziala na obiekty tworzone przez konkretna role, a migracje CLI puszcza inna. Skrypt nadaje granty po migracjach i twardo sprawdza, czy API oddaje mecz, zamiast wypisywac odpowiedz i isc dalej. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017dvpk3tbb8nsot5XNTaS8C
GRANT-y z poprzedniego PR-a odblokowaly stos — aplikacja widzi juz dane, wiec zostaly zwykle bledy w samych testach i brak wzorcow. Oba naprawione. STRICT MODE. Ten sam komunikat pada w dwoch miejscach: na karcie w tresci i w chmurce na dole ekranu. `getByText()` trafialo w oba naraz i Playwright przerywal na "strict mode violation" — co wyglada jak blad aplikacji, a jest nieprecyzyjnym pytaniem. Dwa pomocniki: `tresc()` (zawezenie do <main>) i `chmurka()` (role=status z lib/toast.tsx). Przy okazji sprawdzamy teraz OBA miejsca osobno, bo kazde moze sie zepsuc niezaleznie. WZORCE DLA NOWYCH WIDOKOW DOPISUJA SIE SAME. Nowy zrzut nie ma z czym sie roznic, wiec nie ma czego przegladac — a wymaganie etykiety oznaczalo dodatkowa runde CI przy kazdym nowym scenariuszu. Etykieta zrzuty:zaakceptuj zostaje tam, gdzie jest naprawde potrzebna: przy widoku, ktory WYGLADA INACZEJ niz wczesniej. Logika w .github/dopisz-wzorce.sh, wspolna dla obu zadan, z ponowieniem przy wyscigu o push. Zdjete `--max-failures=1`. Bylo warunkiem czytelnosci, dopoki nie wiedzielismy, co sie dzieje. Teraz kosztuje: jeden przebieg pokazywal jeden blad zamiast wszystkich. NOWE SCENARIUSZE (9 → 22): - mecz odwolany: baner zamiast zapisu, brak przycisku Dolacz - mecz prywatny: plakietka Prywatne - mecz zagrany: brak zapisu, sklad nadal widoczny - Kopiuj link potwierdza skopiowanie - moje gry: cztery zakladki, w tym stany puste historii i zaproszen - grupy: stan pusty oraz zly kod grupy — komunikat, nie cisza - panel powiadomien - kreator meczu, krok pierwszy - okno platnosci jako calosc, nie tylko przycisk Trzy nowe mecze w seed_wizualne.sql: odwolany, prywatny, zagrany. Odwolanie z poziomu testu wymagaloby natywnego confirm() i psuloby dane innym scenariuszom — prosciej miec taki mecz od razu. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017dvpk3tbb8nsot5XNTaS8C
…uszy NOWE WZORCE TEZ PRZEZ ETYKIETE. Poprzedni commit dopisywal je sam, z rozumowaniem "nowy zrzut nie ma z czym sie roznic, wiec nie ma czego przegladac". To rozumowanie jest bledne: pierwszy zrzut widoku jest wlasnie tym, ktory warto obejrzec, bo to on staje sie wzorcem na zawsze. Jesli nowy ekran wyszedl krzywo, ciche dopisanie utrwala krzywy stan i nikt sie nie dowie. Teraz nic nie trafia do repo bez zrzuty:zaakceptuj, a bez etykiety skrypt wypisuje w logu, ile wzorcow czeka. JEDEN WATEK ZAMIAST DWOCH. Baza jest jedna na caly przebieg, a te same scenariusze leca w dwoch rozmiarach okna. Po zdjeciu --max-failures=1 oba projekty ruszylyby naraz i zapisywaly sie rownolegle na ten sam mecz — licznik "4 / 10" tam, gdzie test spodziewa sie "3 / 10", czyli falszywa regresja. Stad --workers=1 w npm run scenariusze. SPRZATANIE PO SOBIE. Ta sama przyczyna, drugi objaw: test, ktory sie zapisal, zostawial slad dla nastepnego przebiegu i dla ponowienia po bledzie. Kazdy mutujacy scenariusz konczy sie teraz wypisaniem, anulowaniem prosby albo zamknieciem okna bez zapisu. wypiszSie() celowo nie jest afterEach — wypisanie to tez przejscie uzytkownika i ma padac glosno, gdy przestanie dzialac. SIEDEM NOWYCH SCENARIUSZY (22 → 29): - prosba o dolaczenie od strony gracza: "Oczekujesz na akceptacje" wraz ze zdaniem tlumaczacym, skad sie o tym dowie - sklad: zawodnik z pola ma wlasne oznaczenie, tak jak bramkarz ma BR - okno filtrow na liscie gier - menu sortowania - formularz zakladania grupy - profil konta - kreator meczu, krok drugi Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017dvpk3tbb8nsot5XNTaS8C
Bot dopisal je jeszcze STARA wersja skryptu (ta, ktora nie pytala o etykiete), z przebiegu przerwanego w polowie. Dwa powody, zeby ich nie zostawiac: nikt ich nie ogladal, a powstaly z niepelnego przebiegu. Wzorce powstana na nowo — przez etykiete zrzuty:zaakceptuj, tak jak wszystkie pozostale. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017dvpk3tbb8nsot5XNTaS8C
…a komenda Raport Playwrighta jest artefaktem, czyli zipem. Na telefonie znaczy to: pobierz, rozpakuj, otworz plik HTML z dysku — w praktyce nie do zrobienia. A ogladanie obrazkow jest calym sensem tego workflow. Do tego etykieta, jedyna droga akceptacji, siedzi w aplikacji GitHuba gleboko pod ikona ⓘ. OBRAZKI WPROST W KOMENTARZU. .github/podglad-zrzutow.sh zbiera nowe wzorce oraz trojki expected/actual/diff, wypycha je na techniczna galaz `podglad-zrzutow` (nigdy nie mergowana) i wypisuje markdown z odnosnikami do raw.githubusercontent. GitHub renderuje je w watku PR-a — takze w aplikacji mobilnej. Artefakt z raportem HTML zostaje jako droga zapasowa. AKCEPTACJA KOMENDA. `/zrzuty ok` w osobnej linii komentarza robi to samo, co etykieta zrzuty:zaakceptuj. Wymog osobnej linii sprawia, ze zacytowanie komentarza niczego nie odpala. Etykieta dziala dalej, rownowaznie. Zadanie `kontekst` rozstrzyga w jednym miejscu, na czym pracujemy i czy akceptujemy — bez tego kazde zadanie musialoby osobno radzic sobie z tym, ze przy issue_comment nie ma ani head_ref, ani etykiet w evencie. Tresc komentarza wyjechala do .github/komentarz-zrzutow.js. Ta sama obsluguje oba zestawy, a skopiowana w dwoch miejscach rozjechalaby sie przy pierwszej poprawce. UWAGA: przy issue_comment GitHub uruchamia workflow z galezi DOMYSLNEJ. Komenda zacznie wiec dzialac dopiero po zmergowaniu tego PR-a — na nim samym akceptacja idzie jeszcze etykieta. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017dvpk3tbb8nsot5XNTaS8C
Poprzednia wersja wymagala napisania /zrzuty ok w komentarzu. Zle zrozumialem potrzebe: chodzi o mozliwosc OBEJRZENIA, nie o rytual zatwierdzania. Komenda wypada, wraca sama etykieta. RAPORT ZAMIAST ZIPA. .github/podglad-zrzutow.sh sklada jedna strone na PR: nowe widoki i trojki wzorzec / teraz / roznica. Laduje na technicznej galezi `podglad-zrzutow` jako README.md katalogu — GitHub renderuje to jako zwykla strone, wiec wchodzi sie w odnosnik z komentarza i przewija obrazki. Bez pobierania, bez rozpakowywania, bez komputera. Artefakt z raportem HTML zostaje jako droga zapasowa. SPRZATANIE PO TYGODNIU. Kazdy raport ma stempel czasu; przy kazdym przebiegu znikaja te starsze niz 7 dni, razem z pustymi katalogami PR-ow. Po tygodniu PR jest dawno zmergowany, a galaz nie ma rosnac w nieskonczonosc. Zadanie `kontekst` zostaje — rozstrzyga w jednym miejscu numer PR-a, galaz i to, czy jest etykieta. workflow_dispatch nie ma ani PR-a, ani etykiet, wiec bez tego kazde zadanie radziloby sobie z tym osobno. Tresc komentarza siedzi w .github/komentarz-zrzutow.js — ta sama obsluguje oba zestawy, a skopiowana w dwoch miejscach rozjechalaby sie przy pierwszej poprawce. Komentarz ma teraz jedno zadanie: dac odnosnik do raportu. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017dvpk3tbb8nsot5XNTaS8C
Samo continue-on-error nie wystarczalo. Workflow konczyl sie zielono, ale przy PR-ze i tak byl czerwony znaczek przy zadaniu — a to czyta sie jak zepsuty build i kaze "naprawiac" cos, co bywa dokladnie zamierzone. Teraz testy leca z `set +e`, a ich kod wyjscia jedzie dalej jako outputs.wynik i konczy w komentarzu. Kroki od raportu i od dopisywania wzorcow maja `|| true`, komentarz ma continue-on-error. Zaden z nich nie ma prawa niczego zatrzymac. Bez zmian zostaja kroki instalacyjne i build — ich awaria to prawdziwa usterka, nie roznica w wygladzie, i ma byc widoczna. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017dvpk3tbb8nsot5XNTaS8C
Przebieg na tym PR-ze mial 40 nowych widokow i zero zmienionych. Skrypt padl po cichu, a komentarz powiedzial "raportu nie udalo sie wystawic". Przyczyna: `set -e` z `pipefail` i `grep '^roznica__'`, ktory bez trafienia zwraca 1 i ubija caly skrypt. Krok mial `|| true`, wiec zadanie bylo zielone i nic tego nie zglosilo. Kazdy grep ma teraz wlasne `|| true`. Drugi blad z tej samej zmiany: zadanie ze scenariuszami czytalo jeszcze steps.test.outcome zamiast outputs.wynik. Po przejsciu na `set +e` outcome jest ZAWSZE "success", wiec komentarz nie mial jak rozpoznac udanego przebiegu. Trzecia rzecz, juz nie blad: brak obrazkow przy nieudanym przebiegu znaczy co innego niz zmiana wygladu — test padl, zanim doszlo do porownania. Komentarz mowi to teraz wprost, zamiast wysylac w strone "widoki sie zmienily". Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017dvpk3tbb8nsot5XNTaS8C
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.