Historia logowań w panelu
Kafelek Liczba logowań i wiersz Ostatnie logowanie na profilu klienta oraz pracownika w panelu administracyjnym.
👤 Instrukcja dla pracownika
Na karcie klienta (Klienci → profil) i pracownika (Pracownicy → profil)
widać dwie informacje o korzystaniu z konta:
- Liczba logowań — ile razy właściciel konta się zalogował,
- Ostatnie logowanie — data i godzina ostatniego wejścia, albo „Nigdy".
Przydaje się przy pytaniu „czy ten klient w ogóle używa aplikacji?" — na przykład zanim wyśle się mu instrukcję albo zanim uzna się, że nie odbiera powiadomień, bo nigdy nie wszedł na konto.
Dwa zastrzeżenia, o których warto wiedzieć:
- Klient bez konta (kartoteka założona przez recepcję, rezerwacja z
publicznego kalendarza) pokazuje
0i „Nigdy" — i to jest prawda, bo takie konto nie istnieje, więc nie ma się czym logować. Rozpoznasz go po plakietce „Brak konta". - Licznik sięga do migracji logowania (koniec lipca 2026). Konto założone wcześniej ma policzone tylko logowania od tamtej pory, więc dla starych klientów liczba bywa zaniżona. Data ostatniego logowania jest dokładna.
🔧 Dokumentacja techniczna
Skąd biorą się liczby
Better Auth zakłada jeden wiersz w tabeli session na każde zalogowanie
(session.createdAt; updatedAt zmienia się przy odświeżeniu sesji, ale nowego
wiersza nie tworzy). To jedyna historia logowań, jaką aplikacja ma.
Od września 2026 cotygodniowy cron usuwa sesje wygasłe ponad 30 dni temu, więc
wiersze nie zostają w nieskończoność. Żeby licznik tego nie odczuł, sprzątanie
najpierw dopisuje sumę usuwanych logowań do tabeli session_login_archive
(migracja 0253), a odczyt sumuje archiwum z tym, co wciąż jest w session —
patrz Czas trwania sesji.
lib/actions/users-db.ts:
getSessionActivityByUserIds(userIds)— jedno zapytanieGROUP BY userIdnadUNION ALLżywych sesji (COUNT(*),MAX(createdAt)) i zarchiwizowanego salda, korzysta z istniejącego indeksusession_userId_idx. Gdysession_login_archivejest niedostępne (worker wdrożony przed migracją, baza bez niej), zapytanie schodzi do samych żywych sesji i loguje ostrzeżenie — licznik jest wtedy zaniżony, ale lista klientów i pracowników nadal się otwiera, zamiast zwracać 500,getSessionActivity(userId)— wariant dla jednego konta,withSessionActivity(users)— doklejalogins_countilast_logindo całej strony listy jednym zapytaniem (używane przezgetUsersigetEmployees).
Dlaczego to w ogóle powstało
Do sierpnia 2026 oba pola były zahardkodowane na logins_count: 0 i
last_login: null — pozostałość po Auth0, które dostarczało je w tokenie.
Panel pokazywał więc „0 logowań / Nigdy" dla każdego użytkownika, łącznie z
takimi, którzy logowali się co tydzień. Wartość nie była pusta, tylko
nieprawdziwa, co jest gorsze: na jej podstawie dało się wyciągnąć wniosek, że
klient nigdy nie wszedł do aplikacji.
Puste wartości zostały tam, gdzie są prawdziwe — w gałęziach budujących profil użytkownika lokalnego i klienta bez konta.
Pliki
| Plik | Rola |
|---|---|
lib/actions/users-db.ts | odczyt z session |
app/(dashboard)/dashboard/user/[email]/profile/page.tsx | profil klienta |
app/(dashboard)/dashboard/employee/[employeeId]/profile/page.tsx | profil pracownika |
lib/actions/users.ts | getUsers, getEmployees — listy |
lib/session-cleanup.ts | sprzątanie sesji + zapis do archiwum |
Testy
__tests__/lib/actions/session-activity.test.ts — liczba i data z sesji, konto
bez sesji, konto nieistniejące, jedno zapytanie na całą stronę listy.
__tests__/lib/session-cleanup.test.ts — regresja na prawdziwym SQLite: licznik
logowań przeżywa sprzątanie, także przy kolejnych przebiegach.