Claude/kind ptolemy 9 mvh0 - #42
Open
fpudelko wants to merge 717 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
feat: gość dopisany ręcznie przejmuje swój wpis po założeniu konta
…kart Dzwonek pokazywal zero mimo trzech czekajacych zaproszen. Powiadomienia (025) powstaly wczesniej niz imienne zaproszenia (060) i nikt tych dwoch rzeczy wtedy nie polaczyl. - migracja 067: wyzwalacz na event_player_invites tworzy powiadomienie - uzupelnienie zaleglych zaproszen wstecz, ale tylko nieodrzuconych i dotyczacych meczow, ktore sie jeszcze nie odbyly - cofniete obramowanie i naglowek ZAPROSZENIE na karcie - wygladalo ciezko przy kilku zaproszeniach pod rzad. Przycisk odrzucania zostaje. UWAGA: migracja 067 wymaga recznego uruchomienia w Supabase SQL Editor. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017dvpk3tbb8nsot5XNTaS8C
fix: zaproszenie na mecz trafia do powiadomień; cofnięte obramowanie kart
Przycisk na cala szerokosc w odstepie od karty czytal sie jak osobny wiersz listy - przy trzech zaproszeniach pod rzad nie bylo wiadomo, ktorego dotyczy. Teraz waski, dosuniety do prawej krawedzi karty, bez przerwy nad soba i z zaokragleniem tylko od dolu, wiec widac przynaleznosc. Dzwonek powiadomien byl tylko w naglowku desktopowym (hidden md:flex). Na telefonie nie bylo go nigdzie - powiadomienia istnialy, ale nie dalo sie ich zobaczyc. Wstawiony obok hamburgera: dolna nawigacja ma wszystkie piec miejsc zajetych, a naglowek to jedyny element obecny na kazdym ekranie. Lista rozwijana dostala szerokosc ograniczona do okna. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017dvpk3tbb8nsot5XNTaS8C
…i licencja ODbL wymaga uznania autorstwa wszedzie, gdzie pokazujemy dane z OSM, a nie tylko pod mapa. Strona obiektu pokazuje nazwe, nawierzchnie, wymiary i udogodnienia wprost z OSM - brakowalo tam atrybucji. Przy okazji link 'Zglos poprawke' prowadzacy do notatki OSM w tym punkcie. Backlog: zglaszanie bledow (osobno aplikacja, osobno dane obiektu - inny odbiorca i inny cykl zycia) oraz otwarte punkty zgodnosci z ODbL. Przejecie profilu goscia oznaczone jako zrobione. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017dvpk3tbb8nsot5XNTaS8C
Dolny pasek nawigacji jest fixed i sam z siebie nie rezerwuje miejsca w
dokumencie. Robił to element-dystans w BottomNav.tsx, ale BottomNavGate
montuje się w layoucie PO {children}, więc dystans lądował poza kontenerem
strony — dokument dla zalogowanego na mobile miał zawsze 100vh + 64px
i każda strona przewijała się w pusty pas tła, nawet gdy treść mieściła
się na ekranie.
Nowe miejsce dla paska: zmienna --bottom-nav-h w globals.css, ustawiana
atrybutem na <html> przez BottomNavGate tylko wtedy, gdy pasek faktycznie
jest widoczny. Cztery miejsca z zaszytą na sztywno (i niezgodną ze sobą)
wysokością paska — CookieBanner, dwa miejsca w VenueExplorer — sprowadzone
do tej jednej zmiennej.
…zed meczem Cztery zmiany w przepływie tworzenia i edycji meczu: - Kreator zapamiętuje wypełniany formularz w localStorage na 12 godzin (lib/eventDraft.ts) i przywraca go po powrocie, z paskiem "Wróciliśmy do Twojego szkicu" + "Zacznij od nowa". Pomijane przy wejściu z ?group=/?fieldId= (kolizja z ich własnym prefillem). - Numer do BLIKA: dokładnie 9 cyfr, formatowane 3-3-3 w trakcie pisania (formatBlikPhone). Na stronie meczu widzi go organizator zawsze, uczestnik ze składu dopiero godzinę przed startem (canSeeBlikPhone, minutesUntilStart) — z wyjątkiem okna "Dołączam", gdzie numer jest potrzebny od razu, żeby zapłacić przy zapisie. Publikacja/edycja meczu z niepełnym numerem albo zniżką karty wyższą niż koszt jest blokowana (validatePayments, wpięta w krok 2 kreatora i w edytuj/page.tsx). - Kreator domyślnie wpisuje koszt za cały obiekt, nie od osoby — licząc cenę per uczestnik na bieżąco (efekt, nie tylko onChange), więc zmiana liczby miejsc po wpisaniu kwoty nie zostawia jej nieaktualnej. - Tytuł meczu na stronie meczu i w oknie "Dołączam" pokazuje tę samą wartość co karty na liście (eventDisplayTitle) zamiast zbitki sport+rozmiar bez formatowania. Bramka widoczności BLIKA działa wyłącznie w interfejsie — kolumna blik_phone nadal przyjeżdża w całym wierszu events (zadanie w BACKLOG.md).
Placeholder tytułu w kreatorze ("np. Czwartkowa ligówka") nie mówił, jak
mecz się nazwie po zostawieniu pustego pola — a fallback był policzony
inaczej w pięciu miejscach (surowy event.sport, sportLabel(), własne
skróty EventListCard). lib/eventTitle.ts to jedno źródło prawdy
(defaultEventTitle/eventDisplayTitle); kreator pokazuje teraz realną
nazwę meczu w placeholderze i pod polem.
…zta na /profilu Poniżej 768px zalogowany dostawał jednocześnie logo + hamburger w headerze i te same skróty w dolnej nawigacji — a wszystko, co było w hamburgerze (Moje mecze, Grupy, Moje obiekty, panel admina, motyw, Wyloguj), już istniało gdzie indziej. Header dla zalogowanego na mobile to teraz h-12 bez logo, z dzwonkiem powiadomień i awatarem prowadzącym do /profil (skutek uboczny: dzwonek, wcześniej tylko na desktopie, jest teraz dostępny na telefonie). Hamburger zostaje wyłącznie dla wylogowanych. /profil dostał nowe sekcje: Moje obiekty (hasManagedVenue), Wygląd (przełącznik motywu), Panel administratora (lib/adminLinks.ts — ta sama lista, co w AdminMenu na desktopie). hasManagedVenue przeniesione z zapytania Supabase wprost w Header.tsx do lib/api.ts. Desktop bez zmian.
Usunięty nagłówek "Twoje mecze" i przycisk "+ Nowy mecz" (mecz tworzy się z FAB-a w dolnej nawigacji, dostępnego z każdego ekranu). Zakładka "Nadchodzące" renderuje te same komponenty co pulpit zalogowanego (InvitesSection, NextMatchCard, MyMatchesSection, ObservingSection) zamiast osobno utrzymywanej listy — bez sekcji "Twoje grupy"/"Otwarte mecze", które mają własne strony. DashboardSections.tsx dostał opcjonalne limit/href (null = pełna lista bez obcięcia i bez linku "Wszystkie" wracającego na tę samą stronę) oraz title/subtitle na ObservingSection i kontrolowane dismissedIds/onDismiss na InvitesSection — wszystko z domyślnymi wartościami równymi dotychczasowemu zachowaniu pulpitu, więc strona główna nie zmienia się wizualnie ani o piksel.
…mobile docs/domena.md: nowe moduły lib/ (eventDraft, eventTitle, adminLinks, hasManagedVenue), reguła widoczności numeru BLIK w sekcji Płatności. docs/funkcje.md: mechanizm --bottom-nav-h, górny pasek dla zalogowanych na mobile + /profil, szkic kreatora, układ /moje-gry. BACKLOG.md: zadanie o numerze BLIK nadal przyjeżdżającym w całym wierszu events (bramka tylko w UI). docs/llm-context.md: dwa nowe wpisy w "Ostatnie zmiany" (limit 10 — usunięte dwa najstarsze), zaktualizowana liczba testów w nagłówku; frontend/public/llm-context.md zsynchronizowany (npm run sync:llm-context).
Pod karta byla tylko odmowa, wiec zapisanie sie wymagalo wejscia na strone meczu: odpowiedz 'tak' kosztowala trzy klikniecia, 'nie' jedno. Teraz obie sa na miejscu - zielona 'Dolaczam' zapisuje od razu, czerwona 'Odrzuc' chowa zaproszenie. Zielona jest szeroka i po prawej, czerwona waska po lewej: odmowa nie ma wygladac na rownorzedna zachete. Zapis idzie bez wyboru bramkarza i metody platnosci - te ustawienia zmienia sie potem na stronie meczu. Blokowanie odpowiedzi 'tak' do czasu ich podania odwracaloby proporcje. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017dvpk3tbb8nsot5XNTaS8C
Zdarzenia pull_request przestaly odpalac workflow - kilka PR-ow z rzedu nie dostalo zadnego przebiegu, choc ten sam kod po merge'u przechodzil na masterze. Push zadzialal za kazdym razem. Bramka, ktora czasem milczy, jest gorsza od jej braku: brak przebiegu wyglada w interfejsie podobnie do zieleni i kusi, zeby zmergowac. Galezie claude/sql/** pominiete - niosa wylacznie zapytanie do bazy. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017dvpk3tbb8nsot5XNTaS8C
…, ODbL feat: dzwonek na mobile, zaproszenia z odpowiedzią „Dołączam", atrybucja ODbL
Po dodaniu dzwonka do naglowka mobilnego komponent renderuje sie dwa razy -
raz w wersji mobilnej, raz w desktopowej, jeden ukryty CSS-em, ale oba
zamontowane. Oba wolaly channel('notifs-<userId>'), a Supabase przy
powtorzonej nazwie oddaje istniejacy kanal zamiast tworzyc nowy. Drugi
komponent trafial na kanal juz zasubskrybowany i jego .on() konczylo sie
wyjatkiem 'cannot add postgres_changes callbacks after subscribe()'.
Nazwa kanalu unikalna per instancja przez useId(), z odsianiem dwukropkow,
ktore useId wstawia, a ktore trafilyby do topiku Phoenixa.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017dvpk3tbb8nsot5XNTaS8C
fix: dwa dzwonki tworzyły ten sam kanał realtime
…odztwie Geofabrik wystawia poland-latest.osm.pbf, ale to ~1,7 GB, a osmium musi przy czytaniu trzymac w pamieci indeks pozycji wezlow - na runnerze GitHuba to gra o to, czy sie zmiesci. Do tego jeden blad w polowie przewala caly przebieg. Macierz 16 wojewodztw: miesci sie w pamieci, konczy szybciej (kilka regionow naraz) i izoluje awarie - fail-fast wylaczony, wiec padniecie jednego nie zatrzymuje pozostalych. max-parallel domyslnie 4, bo ograniczenie jest po stronie Geofabrika: szesnascie jednoczesnych pobran z jednego serwera to prosta droga do odciecia. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017dvpk3tbb8nsot5XNTaS8C
feat: workflow importujący OSM dla całej Polski, województwo po województwie
Oba probowane uklady - obwodka z naglowkiem i para przyciskow Dolaczam /Odrzuc - przeciazaly liste wizualnie. Karta zaproszenia wraca do samej karty, odpowiada sie z poziomu meczu. Przy okazji posprzatane martwe okablowanie: stan dismissedIds i handlery w DashboardSections oraz moje-gry, ktore nie mialy juz kto wywolac. Potrzeba zostaje w backlogu razem z powodami odrzucenia obu podejsc i kierunkami na nastepne - problem jest prawdziwy, bo 'tak' kosztuje wiecej klikniec niz 'nie'. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017dvpk3tbb8nsot5XNTaS8C
revert: zaproszenia bez przycisków odpowiedzi
Przy zlej nazwie regionu Geofabrik oddaje listing katalogu w HTML ze statusem 200. Skrypt zapisywal go jako .pbf i wybuchal dopiero w osmium komunikatem 'invalid BlobHeader size', z ktorego nie da sie odczytac, ze chodzilo o literowke w nazwie. - odrzucenie po content-type (html/text) - sprawdzenie podpisu OSMHeader w pierwszych 64 bajtach pliku, bo rozszerzenie w adresie niczego nie gwarantuje - to nie jest blad do ponawiania: zla nazwa nie stanie sie dobra za piatym pobraniem, wiec przerywa dane zrodlo od razu, jak przy 404 - plik czesciowy sprzatany, zeby nie zostal wziety za gotowy Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017dvpk3tbb8nsot5XNTaS8C
fix: import odrzuca pobrany HTML zamiast dławić się nim w osmium
…tenera Po zwinieciu paska adresu w Safari widoczna wysokosc okna rosnie. Kontener mapy mial h-screen (100vh), ktory tego nie zauwaza, a dolna nawigacja jest fixed, wiec trzyma sie widocznego okna. Te dwie rzeczy rozjezdzaly sie o kilkadziesiat pikseli: podpowiedz wisiala w powietrzu daleko nad panelem, a karta obiektu chowala sie pod nim. - strona mapy uzywa 100dvh zamiast 100vh (dvh sledzi zwijanie paska) - karta i podpowiedz sa fixed, tak jak nawigacja, wiec obie mierza od tej samej krawedzi - z-index nad nawigacja, zeby przycisk zamkniecia nie wpadl pod pasek Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017dvpk3tbb8nsot5XNTaS8C
…acji fix: karta boiska i podpowiedź trzymają się dolnej nawigacji, nie kontenera
Cztery drobne moduly wyciagniete pod nadchodzace przeprojektowanie /wydarzenia i /grupy/[id]. Zadnej zmiany widocznej dla uzytkownika. - components/ui/FilterPill.tsx — PillDropdown i TogglePill przeniesione z VenueExplorer.tsx, gdzie byly prywatne. Portal do body zostaje: pasek filtrow bywa overflow-x-auto i przycinalby rozwiniete menu. Doszlo tylko aria-expanded i aria-pressed. - lib/plural.ts — polska odmiana przez liczbe. W trzech miejscach stala regula `n < 5`, poprawna wylacznie dla 1-9: dla 12-14 dawala "mecze" zamiast "meczy". Regula mod-10/mod-100 z pelnym pokryciem testami. - lib/searchText.ts — foldText/foldedIncludes. Szukanie na /wydarzenia robilo includes na surowym stringu, wiec "pilka" nie znajdowalo "pilka nozna". Ta sama technika co slugify(), ale ze spacjami. - lib/geo.ts — distanceKm() przeniesione z prywatnego haversineM w app/admin/przeglad. Sortowanie "najblizej mnie" potrzebuje tego samego rachunku, a dwie kopie wzoru to dwie okazje do rozjazdu. Prog duplikatu w panelu admina przeliczony z 150 m na 0,15 km — bez zmiany zachowania. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KdUx35rru2vLECFk3wR8TA
Podglad w hero pokazywal jeden ekran, i to niepelny. Przyczyna nie byla przycieciem: PhoneMock nie mial zadanej ani wysokosci, ani proporcji, wiec ramka brala wysokosc ze swojej tresci — a tresci byla jedna karta. Teraz proporcje trzyma PhoneShell (aspect-[9/19]) i to ona wymusza pelny ekran telefonu. Trzy makiety do przewiniecia palcem: - Twoje mecze (/moje-gry) — waski pasek z dzwonkiem i awatarem, zakladki, Najblizszy mecz, Twoje najblizsze mecze, Obserwujesz, dolna nawigacja - Tworzenie meczu (/wydarzenia/nowe, krok 2) — z kosztem obiektu jako trybem domyslnym i przeliczeniem na kwote od osoby - Strona meczu (/wydarzenia/[id]) — sklad z lista graczy, koszt, komentarze Makiety rysowane w JSX, nie zrzutami ekranu: zrzut mieknie powyzej 2x DPI i rozjezdza sie z aplikacja przy pierwszej zmianie wygladu — pliki w public/mockups/ maja dzis stare logo i widoczne szkielety ladowania zamiast tresci. JSX idzie za tokenami kolorow sam. Karuzela na natywnym scroll-snapie, bez biblioteki. Aktywny slajd czytany z pozycji przewiniecia, wiec gest palcem i klik w kropke nie moga sie rozjechac. Auto-przewijanie konczy sie na zawsze przy pierwszym dotknieciu i nie startuje przy prefers-reduced-motion. Zniknelo md:rotate-[3deg] — obrocony kontener przewijany w bok to mylace trafienia palcem i przekrzywione kropki. Zweryfikowane w przegladarce: gest aktualizuje kropki, wszystkie trzy slajdy maja 564 px wysokosci (brak skakania w pionie), strona nie jest rozpychana w poziomie. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KdUx35rru2vLECFk3wR8TA
Na telefonie wylogowany widzial "Zaloguj sie" + hamburger. Teraz, od lewej: ikona mapy (/mapa), zielony przycisk "Dolacz" i ikona awatara (logowanie). "Dolacz" prowadzi na /logowanie?mode=rejestracja i otwiera formularz od razu na zakladaniu konta — bez tego przycisk obiecywalby rejestracje, a pokazywal logowanie. AuthForm dostal opcjonalny prop initialMode; domyslnie nadal 'signin', wiec pozostale 20 wejsc na /logowanie zachowuje sie bez zmian. Hamburger znika calkowicie, razem z arkuszem menu (91 linii), pulapka focusa, blokada scrolla i stanem mobileOpen. Konsekwencja swiadoma: pasek przestaje byc nawigacja dla wylogowanego. Do /wydarzenia i /wydarzenia/nowe prowadza CTA w hero, kafelek w "Co dostajesz", plywajacy przycisk + oraz stopka. Desktop dostaje oba wejscia z nazwami — tekstowe "Zaloguj sie" i zielone "Dolacz" — bo tam jest na to miejsce i chowanie logowania pod ikone nic by nie dalo. Przy okazji: usuniete martwe importy (Menu, X, ChevronRight, Search) oraz TeamIcon — komponent zdefiniowany, nigdy nierenderowany, martwy juz przed ta zmiana. Zweryfikowane w przegladarce: linki prowadza pod /mapa, /logowanie?mode=rejestracja i /logowanie, hamburgera nie ma, a ?mode=rejestracja otwiera naglowek "Zaloz konto" zamiast "Zaloguj sie". Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KdUx35rru2vLECFk3wR8TA
Landing mial cztery identyczne przyciski "Zorganizuj mecz" — hero, "Jak to dziala", "Co dostajesz" i pas pod FAQ. Cztery slabe wezwania zamiast jednego mocnego. Zostaja dwa: hero i kafelek w "Co dostajesz". "Jak to dziala" traci przycisk spod listy, a zyskuje klikalny pierwszy krok "Stworz mecz" — sekcja prowadzi do akcji wlasna trescia, zamiast powtarzac pod spodem to, co stoi juz w hero. Krok z `href` (dzis tylko pierwszy) renderuje sie jako Link ze strzalka; pozostale zostaja opisem. Pas pod FAQ znika w calosci, nie sam przycisk: "Twoja ekipa czeka na termin" istnialo wylacznie po to, zeby ten przycisk hostowac — bez niego zostalaby deklaracja bez akcji tuz nad stopka. Razem z sekcja znika stala LANDING_FINAL_CTA i jej odwolania w tescie. Uwaga: SiteFooter ma wlasny, tekstowy link "Zorganizuj mecz". To zwykla pozycja nawigacji w stopce, nie przycisk — nie byl w liczonej czworce i zostaje. Nowy test pilnuje, ze pierwszy krok ma href do /wydarzenia/nowe, a pozostale go nie maja — bez tego usuniecie href zostawiloby sekcje bez drogi dalej. Zweryfikowane w przegladarce: na landingu widoczne sa dokladnie dwa przyciski CTA (hero + "Co dostajesz") plus link w stopce, po FAQ nastepuje od razu stopka, a klikniecie kroku 1 prowadzi na /wydarzenia/nowe. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KdUx35rru2vLECFk3wR8TA
…alna # Conflicts: # docs/llm-context.md # frontend/public/llm-context.md
…aude/zacheta-instalacji # Conflicts: # docs/llm-context.md # frontend/public/llm-context.md
Bojo jako apka na ekranie głównym (PWA, etap 1)
Zachęta do dodania Bojo na ekran główny (PWA, etap 1b)
Backlog: katalog zrobiony, nowa przesłanka strategiczna, plan PWA
…kuje graczy Zakładka "Ustawienia" na stronie meczu znika teraz razem z treścią (przycisk nie był gated na canManageEvent). Ikona "Grupy" na dolnej nawigacji nosi dwie kropki: różową z lewej (nieprzeczytane wiadomości), pomarańczową z prawej (nowy mecz w ekipie). Filtr "tylko z nieprzeczytanymi" na /moje-gry przeniesiony na wysokość "Brakuje graczy". Zaktualizowano zrzut kreatora w karuzeli landingu.
…ny-obszar # Conflicts: # docs/llm-context.md # frontend/public/llm-context.md
Zgloszone ze zrzutu z zainstalowanej apki: dolny pasek siedzi za nisko, a podpis "Nowy" przecina kreska gestow iPhone'a. PRZYCZYNA: brak `viewport-fit=cover`. Bez niego `env(safe-area-inset-*)` zwraca ZERO — a repo liczy na te wartosci w kilku miejscach: BottomNav ma `paddingBottom: env(safe-area-inset-bottom)`, `--bottom-nav-h` dodaje ten sam inset, karty na mapie sie od niego odsuwaja. Wszystkie te wywolania byly martwe. W karcie przegladarki nie bylo tego widac, bo miejsce na pasek gestow rezerwowal sam Safari; po instalacji jako apka nie robi tego nikt. Przy okazji dwa miejsca, ktore odsuwaly sie WYLACZNIE o wysokosc nawigacji: - baner cookies i zacheta do instalacji uzywaly `var(--bottom-nav-h)`, ktore wynosi 0, gdy paska nie ma (wylogowany, schowany pasek) — wtedy lezaly tuz nad kreska gestow. Nowa zmienna `--dol-bezpieczny` bierze `max` z wysokosci paska i samego insetu. Max, nie suma: `--bottom-nav-h` juz zawiera inset, wiec dodanie go drugi raz zostawialoby zbedna dziure. - pasek "Dolacz" na stronie meczu CHOWA nawigacje (HideBottomNav), wiec `--bottom-nav-h` jest tam zerem, a samo `pb-6` konczylo sie przyciskiem tuz nad kreska. Ta galaz niesie tez tresc PR-a #190 (zacheta do instalacji), ktora przez zla kolejnosc merge'owania wyladowala na galezi #188 zamiast w masterze. UWAGA: szesc zrzutow tras (strona glowna, dlaczego-bojo, jak-dziala-bojo, faq, grupy, cykliczne) rozni sie od wzorcow — sprawdzone na CZYSTYM masterze w osobnym worktree: pada tak samo bez tej zmiany. To zalegle wzorce po ostatnich rundach UI, nie skutek tej poprawki. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017dvpk3tbb8nsot5XNTaS8C
…e", dymki wyjaśniające EventBrowseCard w ogóle nie renderowała plakietki nieprzeczytanych dla rozegranych meczów - naprawione. Filtr nieprzeczytanych na /moje-gry próbuje trzech miejsc po kolei zamiast zajmować pusty wiersz na sztywno. Nazwa ekipy w belce /grupy/[id] rozwija listę pozostałych ekip. Nowa sekcja "Twoja ekipa gra wkrótce" na pulpicie. Pomarańczowa kropka na konkretnym meczu (nie tylko zbiorczo) na /wydarzenia i w zakładce Mecze ekipy. Krótkie dymki tłumaczące znaczenie kropek na dolnej nawigacji, max 5 razy na typ.
…kundy (#194) Cztery zapytania w BottomNav mogły nadpisać świeży stan przestarzałą odpowiedzią z poprzedniej trasy - teraz każde ignoruje wynik, jeśli komponent zdążył się przełączyć w trakcie oczekiwania. Dymki wyjaśniające kropki pokazują się teraz pojedynczo z globalnej kolejki (zamiast niezależnie per ikona) i trzymają się 4 sekundy zamiast 1.5. Claude-Session: https://claude.ai/code/session_0143mqBziP9dyccKubhT1BtN Co-authored-by: Claude <noreply@anthropic.com>
…nie wystaje poza ekran (#195) Poprzednia naprawa wyścigu nie wystarczyła - każdy .catch(() => {}) w BottomNav.tsx zostawiał poprzednią wartość stanu przy błędzie zapytania, więc jedno nieudane zapytanie po udanym "są nieprzeczytane" trzymało różową kropkę zapaloną bez związku z rzeczywistością. catch ustawia teraz jawnie false/null. Dymek nad pierwszą i ostatnią z pięciu ikon wyśrodkowywał się blisko krawędzi ekranu i wystawał poza nią - skrajne kolumny przypinają go teraz do swojej wewnętrznej krawędzi. Claude-Session: https://claude.ai/code/session_0143mqBziP9dyccKubhT1BtN Co-authored-by: Claude <noreply@anthropic.com>
…bazy Trzy zgloszenia z telefonu, dwa maja wspolna przyczyne. 1. PRZYPISYWANIE DO DRUZYN "NIC NIE ROBILO". Ani przesuniecie gracza w lewo i prawo, ani przyciski N i C. `updateParticipantTeam` robilo gole `.update()` — a przy niepasujacej polityce RLS Postgres zmienia ZERO wierszy i zwraca SUKCES. Zadnego bledu, zadnego komunikatu, `load()` przerysowuje ten sam stan. Dokladnie pulapka opisana w AGENTS.md, dla ktorej istnieje `zaktualizujJedenWiersz()` — teraz uzyta tu i przy zapisie platnosci. 2. PRZELACZNIK ADMIN/UZYTKOWNIK przelaczal sie na ekranie i wracal po odswiezeniu. Ta sama cisza, ale z prawdziwa odmowa pod spodem: polityka z migracji 022 sprawdzala uprawnienie podzapytaniem o `profiles` WEWNATRZ polityki na `profiles`. Podzapytanie samo podlega RLS tej tabeli, wiec warunek wychodzil falsz i UPDATE nie ruszal nic. Migracja 098 wynosi sprawdzenie do `czy_admin()` (SECURITY DEFINER, STABLE, ustawiony search_path) i przepina na nia takze polityke z 005. 3. ZAKLADKI. Podzial na druzyny mieszkal w zakladce "Wynik", wiec zeby poukladac sklady PRZED meczem trzeba bylo wejsc w wynik, ktorego jeszcze nie ma. Teraz "Sklady" to wlasna zakladka obok "Skladu" (lista zapisanych), a "Wynik" pojawia sie dopiero po rozpoczeciu meczu i zawiera sam formularz. Wczesniej zakladka Wynik istniala od utworzenia meczu i po klknieciu mowila tylko, ze wyniku jeszcze nie ma — zajmowala miejsce w pasku, nie dajac nic w zamian. Zwijana kopia druzyn w zakladce Sklad zamieniona na odnosnik, zeby nie bylo dwoch wejsc do tego samego. MIGRACJA 098 DO URUCHOMIENIA RECZNIE w Supabase — bez niej punkt 2 zostaje zepsuty, tyle ze teraz z widocznym komunikatem zamiast ciszy. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017dvpk3tbb8nsot5XNTaS8C
…ny-obszar # Conflicts: # docs/llm-context.md # frontend/public/llm-context.md
Poprawka wlasnej poprzedniej wersji, po obejrzeniu jej przez wlasciciela. DRUZYNY WRACAJA DO SKLADU. Probowalem dwoch gorszych ukladow: najpierw zwijana sekcja w Skladzie (chowala rzecz, po ktora sie tam wchodzi), potem osobna zakladka "Sklady" (rozdzielala sklad od jego podzialu). Teraz podzial jest widoczny WPROST w zakladce Sklad, bez klikania. ROZLICZENIA znikaja z paska, gdy mecz jest za darmo. `platnosciSection` renderuje sie wylacznie przy `costGrosze > 0`, wiec przy darmowym meczu zakladka otwierala sie PUSTA — sam naglowek i nic pod spodem. Zgloszone wprost ze zrzutu. WYNIK bez zmian wobec poprzedniej wersji: pojawia sie dopiero po rozpoczeciu meczu i zawiera sam formularz. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017dvpk3tbb8nsot5XNTaS8C
…ny-obszar # Conflicts: # docs/llm-context.md # frontend/public/llm-context.md
Pasek nawigacji pod kreską gestów iOS + zachęta do instalacji (dogranie #190)
Awaria u uzytkownika nie zostawiala ZADNEGO sladu. app/error.tsx wypisywal blad do konsoli przegladarki, ktorej nikt nie oglada, a zgloszenie "cos mi wywalilo" przychodzilo zrzutem ekranu bez adresu strony, wersji i tresci bledu — czyli w formie drozszej do odtworzenia niz sama naprawa. DLA UZYTKOWNIKA: /zglos-blad, jedno pole. Kazde kolejne (kategoria, powtarzalnosc, priorytet) odsiewa zglaszajacych i tak czy siak wypelnia sie je byle jak, a to, co naprawde potrzebne, doklejamy sami: adres, przegladarka, wersja, id uzytkownika. Dziala bez logowania — awaria na stronie meczu otwartej z linku jest dokladnie tym przypadkiem, o ktorym chcemy wiedziec. Odnosnik w stopce, czyli na kazdej stronie: awaria rzadko zdarza sie tam, gdzie akurat wisi przycisk. AUTOMATYCZNIE: window.onerror i unhandledrejection (ten drugi to najczestszy sposob, w jaki psuje sie apka rozmawiajaca z baza — await bez catch, zapytanie pada, ekran zostaje pusty). Plus samo app/error.tsx, razem z `digest`, ktorym Next laczy blad z logiem serwerowym. ZEBY TO NIE BYL SMIETNIK, cztery rzeczy: - GRUPOWANIE po odcisku: komunikat + pierwsza ramka stosu, z wycietym hashem builda i numerami linii. Bez tego jeden zepsuty widok daje setki kopii, a licznik wystapien — najwazniejsza liczba przy awarii, bo mowi czy dotyczy jednej osoby czy wszystkich — w ogole nie istnieje. Wyciecie hashy sprawia, ze ten sam blad nie zaklada nowego wiersza po kazdym wdrozeniu. - JEDEN BLAD NA SESJE plus twardy limit 10. Petla renderowania w Reakcie potrafi rzucic ten sam blad kilkadziesiat razy na sekunde. - ZGLOSZENIE NIGDY NIE WYWRACA APLIKACJI — awaria mechanizmu raportowania awarii nie moze byc kolejna awaria widoczna dla uzytkownika. - CZYTA WYLACZNIE ADMIN. To nie ostroznosc na wyrost: w kolumnie `adres` laduje link, ktory bywa linkiem do prywatnego meczu. Zapis idzie wylacznie przez RPC (SECURITY DEFINER) — tabela nie ma polityki INSERT, wiec klient nie decyduje o statusie, liczniku ani user_id; tozsamosc bierzemy z auth.uid(), nie z tego, co przyszlo z przegladarki. PANEL /admin/bledy: lista po ostatnim wystapieniu (blad sprzed tygodnia, ktory wciaz sie dzieje, jest pilniejszy od wczorajszego, ktory ucichl), filtry po statusie, stos w szczegolach, trzy stany. Zamkniety blad, ktory wraca, sam wraca na "nowe". MIGRACJA 099 DO URUCHOMIENIA RECZNIE. Wymaga 098 (czy_admin). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017dvpk3tbb8nsot5XNTaS8C
…amej stopki STOPKA BYLA ZLYM MIEJSCEM. SiteFooter jest importowany tylko w app/page.tsx i w StronaTresci — czyli renderuje sie na landingu i stronach tresci, a NIE na ekranach, na ktorych cos realnie pada: strona meczu, moje gry, mapa, ekipy. Odnosnik w stopce zostaje (nic nie kosztuje), ale glowne wejscie jest teraz w profilu, do ktorego zalogowany trafia z kazdego ekranu — tam, gdzie repo trzyma juz panel admina, i z tego samego powodu. BLAD W DANYCH OBIEKTU jako trzeci rodzaj zgloszenia. Osobny od bledu aplikacji, bo ma innego odbiorce i inny cykl zycia: katalog pochodzi z OpenStreetMap i NIE jestesmy jego wlascicielem. Stad dwie drogi na stronie obiektu i obie maja sens: - „Zglos poprawke" (bylo juz wczesniej) — notatka w OSM, naprawia dane U ZRODLA, z pozytkiem dla calego OSM, - „Zglos blad w danych" (nowe) — trafia DO NAS, bo tylko my mozemy ukryc obiekt, ktorego w rzeczywistosci nie ma. Lista zamknieta pieciu powodow zamiast pola tekstowego: pole daje „nie wiem", a te piec pokrywa to, co ludzie realnie zglaszaja. Zgloszenie SWIADOMIE nie zmienia zadnych danych — jedno kliknieciezlosliwej osoby nie moze wywrocic katalogu. Progi, kolumny `override_*` i odsylanie poprawek do OSM zostaja otwarte w backlogu, tak jak byly. Migracja 099 rozszerzona (nie byla jeszcze uruchomiona): rodzaj `obiekt`, kolumna `field_id` z ON DELETE CASCADE i indeks po niej — backlog zaklada, ze dopiero kilka niezaleznych zgloszen uzasadnia zmiane bez moderacji, wiec liczenie ich per obiekt musi byc tanie. W panelu admina zgloszenie o obiekcie ma wlasna ikone i odnosnik „Otwórz obiekt": przy takim zgloszeniu liczy sie jedno — dojsc tam jednym klknieciem. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017dvpk3tbb8nsot5XNTaS8C
Zgłaszanie błędów: formularz dla ludzi i automatyczny log awarii
…anie sie Nad licznikiem miejsc — najwazniejsza informacja na tej stronie — stalo pol ekranu rzeczy drugorzednych. GORNE „UDOSTEPNIJ / KOPIUJ" USUNIETE. Ta sama para stoi nizej, w karcie „Wyslij link znajomym", gdzie ma naglowek i zdanie tlumaczace, po co to klikac. Dwa wejscia do tej samej akcji na jednym ekranie kosztowaly miejsce nad trescia, po ktora sie tu wchodzi. DWA WIERSZE ZAMIAST CZTERECH. Zasada: pigulka jest elementem dla ETYKIETY — krotkiej, powtarzalnej, w rodzaju „Za darmo". Data i nazwa boiska to nie etykiety, tylko tresc o zmiennej dlugosci, a kazda tracila kilkadziesiat pikseli na sama ramke i dopelnienie. Wiec: - wiersz 1 (pigulki): status w meczu, cena, widocznosc, wymaga akceptacji, stala gierka, grupa — same krotkie etykiety, - wiersz 2 (zwykly tekst z ikonami): data i godzina, czas trwania doklejony do godziny (bo to ta sama informacja, nie dwa fakty), miejsce. Nazwa boiska ma dzieki temu dosc szerokosci, zeby nie urywac sie po trzech slowach. WYPISZ SIE — CZERWONE OD RAZU. Przycisk byl szary i czerwienial dopiero na hover, czyli na telefonie NIGDY. Teraz czerwona ramka i czerwony tekst na bialym tle. Swiadomie nie pelna czerwien: wypisanie sie jest odwracalne, a pelna czerwien zostaje dla akcji nieodwracalnych typu „Usun na stale". Przy okazji „Zapros z grupy" wychodzi wyzej samo — nad licznikiem ubylo okolo polowy dotychczasowej wysokosci. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017dvpk3tbb8nsot5XNTaS8C
fix: strona meczu — mniej pigulek nad licznikiem, czytelniejsze wypis…
…ekt→grupa
DWIE RZECZY, obie z dzisiejszego zgloszenia.
1. ROZMOWA — CZEGO JESZCZE NIE WIEM, POWIEDZIANE WPROST.
Blad "new row violates row-level security policy for table event_comments"
przy usuwaniu WLASNEJ wiadomosci jest wobec polityk z repo LOGICZNIE
NIEMOZLIWY. Migracja 026 daje:
USING (auth.uid() = user_id) WITH CHECK (auth.uid() = user_id)
Komunikat "new row violates" pochodzi z WITH CHECK, a ten odpala sie dopiero,
gdy USING przepuscil wiersz. Skoro USING przepuscil, to auth.uid() = user_id
bylo prawda — i ten sam warunek nie ma jak byc falszem sekunde pozniej na tym
samym wierszu, ktorego user_id nie ruszamy.
Wniosek: polityki na produkcji SA INNE niz w repo. To dokladnie ta rozbieznosc,
o ktorej ostrzega docs/baza-danych.md ("historia migracji w repo != historia
w Supabase"). Nie zgaduje wiec nowej polityki — do zgloszenia dolaczam
zapytanie diagnostyczne, ktore wypisze prawdziwy stan.
Co robie tym commitem, bo jest sluszne niezaleznie od przyczyny:
- deleteComment idzie przez zaktualizujJedenWiersz(). Kasowanie jest MIEKKIE
(ustawia deleted_at), wiec niepasujaca polityka dalaby zero zmienionych
wierszy i sukces: wiadomosc znikalaby z ekranu i wracala po odswiezeniu.
- nowy helper zPonowieniemPoOdswiezeniu(): zapis, ktory padl na wygaslej
sesji, jest ponawiany raz po odswiezeniu tokenu. To osobna, realna pulapka
na ekranach, gdzie karta wisi otwarta godzinami — token dostepu zyje godzine,
aplikacja dalej wyglada na zalogowana, a baza odsyla komunikat o polityce
bezpieczenstwa, z ktora piszacy nie ma nic wspolnego. Druga proba jest
ostatnia, zeby nie zapetlic sie na czyms, czego odswiezanie nie naprawia.
Bledy NIEZWIAZANE z sesja leca dalej nietkniete.
- podpiete tez pod tablice ekipy (groupPosts) — ten sam wzorzec uzycia.
2. SKRYPT obiekt→grupa (supabase/zadania/obiekt-do-grupy.sql).
Przypisuje wszystkie mecze z jednego boiska do grupy i dopisuje do niej
kazdego, kto zagral tam min. 2 razy. DWUCZESCIOWY: czesc A to same SELECT-y
i pokazuje, co sie stanie (w tym mecze, ktore zostalyby PRZEPIETE z innej
grupy); czesc B jest zakomentowana i wykonuje sie w jednej transakcji.
"Zagral" liczy waska definicja i jest to swiadome: bez gosci bez konta, bez
rezerwowych, bez nieakceptowanych prosb. Identyfikatory wpisane wprost —
edytor SQL w Supabase to nie psql i nie zna \set ani :nazwa.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017dvpk3tbb8nsot5XNTaS8C
Rozmowa: głośne błędy i ponowienie po wygasłej sesji + skrypt obiekt→grupa
Na liście składu ekipy każdy członek miał plakietkę Współorganizator. Powód: warunek w SkladGrupy sprawdzał cztery flagi na OR, a dwie z nich (can_create_events, can_invite) mają w bazie DEFAULT true — to prawa zwykłego członka, istniejące po to, żeby dało się je komuś odebrać. Wyróżnienie, które dostaje każdy, nie wyróżnia nikogo. Odznakę liczy teraz czyWspolorganizator() z lib/groups.ts na tych samych dwóch uprawnieniach, z których trigger ustaw_role_czlonka (migracja 092) wylicza role = 'admin': zarządzanie składem i moderowanie tablicy. Etykieta w UI i rola w bazie przestają się rozjeżdżać. Nadawanie uprawnień bez zmian: panel widzi wyłącznie założyciel (polityka UPDATE na group_members z 092). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017dvpk3tbb8nsot5XNTaS8C
fpudelko
force-pushed
the
claude/kind-ptolemy-9Mvh0
branch
from
August 17, 2026 20:34
45726f0 to
5873e54
Compare
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.