Strona /firmy, CTA jako linki i testy Playwright routingu
Nowa trasa:
- /firmy - lista firm i uslug na istniejacych komponentach (.directory-card)
i stylistyce sekcji uslug; filtr kategorii w query stringu (/firmy?kategoria=remonty)
- serviceCategories dostaly slug, nowa baza companyDirectory pokrywa wszystkie
8 kategorii, wiec filtrowanie dziala na realnych danych
- "Zobacz firmy" prowadzi do listy z wybrana kategoria, "Zobacz wszystkie"
do pelnej listy - ostatnie dwie atrapy href="#" usuniete
CTA zamienione na <Link> (wylacznie czysta nawigacja, bez akcji):
- 35 przyciskow onClick={() => navigate(x)} zamienionych automatycznie
- 5 skrotow panelu admina (setTab) -> Link do /admin/*
- karty narzedzi konta i kafelek poradnika: zamiast role="button" prawdziwy link
- pozycje menu konta i popovera powiadomien -> Link + zamkniecie popovera
- karty ofert: link rozciagniety na cala karte (.card-stretched-link) zamiast
role="button", bez zagniezdzania przyciskow w <a>
- bez zmian zostaly przyciski wykonujace akcje: publikacja, zapis draftu,
wyszukiwanie, oznaczanie powiadomien, bramki logowania
Wyglad 1:1 - rozszerzone selektory kontenerow o warianty <a>, reset :where(a)
o zerowej specyficznosci oraz odtworzenie centrowania tam, gdzie <button>
robil to domyslnie. Zweryfikowane zrzutami ekranu i pomiarem geometrii.
Naprawa: kazdy blad /auth/me (takze chwilowy timeout albo 5xx) kasowal token
i wylogowywal uzytkownika. Teraz sesje konczy tylko odrzucenie tokenu (401/403),
pozostale bledy sa ponawiane raz.
Testy: frontend/tests/routing.spec.ts (41 testow) + playwright.config.ts,
skrypt npm run test:e2e. E2E_BASE_URL pozwala uruchomic je na buildzie
produkcyjnym za nginx.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+27
-6
@@ -104,21 +104,42 @@ export function AuthProvider({ children }: { children: ReactNode }) {
|
||||
}
|
||||
let cancelled = false;
|
||||
setLoading(true);
|
||||
apiFetch<AuthUser>('/auth/me')
|
||||
.then((me) => {
|
||||
|
||||
// Sesje konczymy wylacznie wtedy, gdy backend odrzuci token (401/403).
|
||||
// Chwilowy blad sieci albo 5xx nie moze wylogowywac uzytkownika - taki blad
|
||||
// ponawiamy raz, a token zostaje, wiec kolejne wejscie na strone go odzyska.
|
||||
const loadProfile = async (canRetry: boolean): Promise<void> => {
|
||||
try {
|
||||
const me = await apiFetch<AuthUser>('/auth/me');
|
||||
if (!cancelled) {
|
||||
setUser(me);
|
||||
setLoading(false);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
if (!cancelled) {
|
||||
} catch (error) {
|
||||
if (cancelled) {
|
||||
return;
|
||||
}
|
||||
const status = (error as { status?: number }).status;
|
||||
if (status === 401 || status === 403) {
|
||||
window.localStorage.removeItem(TOKEN_KEY);
|
||||
setToken(null);
|
||||
setUser(null);
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
});
|
||||
if (canRetry) {
|
||||
await new Promise((resolve) => { window.setTimeout(resolve, 400); });
|
||||
if (!cancelled) {
|
||||
await loadProfile(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
setUser(null);
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
void loadProfile(true);
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user