Smart Fitness App: Client Architecture Spec
ArtefaktJest to artefakt używany w odcinku 3: „Give Your App a Brain” i odcinku 4: „The No-Code App Implementation Plan”. Możesz używać tej specyfikacji jako odniesienia do widoków frontendu, komponentów interfejsu wielokrotnego użytku, zarządzania stanem klienta i przypadków testowych w prostym języku angielskim.
Zaloguj się, aby uzyskać dostęp do tego artefaktu
Zaloguj się za pomocą profilu dewelopera w Google, aby wyświetlić i skopiować pełny artefakt używany w serii Build It!
Wymagany jest profil dewelopera
Nie kwalifikujesz się do utworzenia profilu dewelopera. Poproś administratora Workspace o włączenie tej funkcji.
Utwórz profil dewelopera
Utwórz bezpłatny profil dewelopera w Google, aby odblokować wszystkie prompty i artefakty w Build It!
Dołącz do Builder Central, aby odblokować
Odbierz bezpłatną plakietkę wspierającego programu Builder jednym kliknięciem, aby odblokować wszystkie prompty i artefakty Build It!
Stan: gotowy do sesji planowania (tworzenie wersji roboczej z pomocą towarzysza planowania klienta)
Dokument towarzyszący: specyfikacja architektury danych
Cel architektury: czysta, łatwa w utrzymaniu, modułowa i testowalna przebudowa frontendu prototypu inteligentnego fitnessu AI Studio.
0. Podstawowy stos techniczny i standardy inżynieryjne
- Środowisko wykonawcze: Next.js (App Router, React 19) + buforowanie zasobów offline w progresywnej aplikacji internetowej (PWA).
- Styling Architecture: Tailwind CSS v4 + Tailwind Variants (for deterministic component styling) + Lucide React (icons).
- Client State Division:
- Zustand (sesja lokalna): zarządza zmiennym stanem na siłowni (
useActiveSessionStore), stoperami, aktywnymi buforami serii i wstępnie obliczoną sekwencją kroków. Zsynchronizowano z kontemlocalStoragena potrzeby odzyskiwania blokady telefonu. - TanStack Query (stan serwera): zarządza buforowaniem dokumentów Firestore, ponowną weryfikacją w tle i optymistycznymi aktualizacjami w przypadku
weekly_plans,user_profiles,prsiworkout_logs.
- Zustand (sesja lokalna): zarządza zmiennym stanem na siłowni (
- Wizualizacja wykresów: Recharts (stylizowane za pomocą niestandardowych tokenów trybu ciemnego).
- Uwierzytelnianie: Uwierzytelnianie Firebase z nagłówkiem uwierzytelniania tokena okaziciela przekazywanym do wszystkich punktów końcowych serwera.
1. Zasady i założenia dotyczące frontendu
- Ergonomia dostosowana do ćwiczeń: urządzenie zostało zaprojektowane z myślą o obsłudze jedną ręką podczas treningu, nawet gdy dłonie są spocone. Duże elementy do kliknięcia (co najmniej 48 x 48 dp), wysoki kontrast i minimalna ilość wymaganego tekstu.
- Optymistyczny interfejs i odporność na brak połączenia: zapisywanie serii, uruchamianie minutników odpoczynku i zamiana ćwiczeń muszą być natychmiastowe (<16 ms) w interfejsie. Synchronizacja w tle obsługuje trwałość serwera w
POST /api/workouts/logbez blokowania użytkownika. - Ścisłe rozdzielenie zadań: komponenty Dumb/Presentational otrzymują dane i emitują zdarzenia za pomocą właściwości, a widoki kontenerów Smart zarządzają logiką biznesową, magazynami stanów i koordynacją interfejsów API.
- Interfejs etapowej mutacji UX: propozycje generowane przez trenera AI (
POST /api/coach/chat) są renderowane jako interaktywne karty podglądu etapowego z wyraźnymi elementami sterującymi [Zaakceptuj plan] i [Modyfikuj], zanim zmiany zostaną zatwierdzone w aplikacji. - Jakość oparta na zachowaniu: każda strona, komponent i interakcja są powiązane z elementami testowania w prostym języku angielskim, które jednoznacznie definiują oczekiwane zachowanie.
2. Nawigacja po aplikacji i hierarchia widoków
| Ścieżka trasy | Nazwa widoku | Cel główny | Kluczowe komponenty |
|---|---|---|---|
/ |
Przekierowanie katalogu głównego | Natychmiastowe przekierowanie do: /today. |
(Router redirect) |
/today |
Podgląd dzisiejszego treningu | Widok domyślny. Automatycznie rozpoznaje bieżący dzień tygodnia i wyświetla podgląd dzisiejszego treningu. | <BackButton />, <WorkoutHeader />, <CoachNoteCard />, <WorkoutExerciseSummary />, <WorkoutBlock />, <ExerciseCard />, <EmptyDayPlaceholder />, <ModifyWithCoachCard /> |
/workouts/:day |
Podgląd codziennego treningu | Wyświetla podgląd treningu na dany dzień tygodnia (np. /workouts/monday, /workouts/thursday). |
<BackButton />, <WorkoutHeader />, <CoachNoteCard />, <WorkoutExerciseSummary />, <WorkoutBlock />, <ExerciseCard />, <EmptyDayPlaceholder />, <ModifyWithCoachCard /> |
/workout/active |
Śledzenie aktywnej sesji aktywności | Ekran wykonywania treningu o wysokiej intensywności (serie, powtórzenia, minutnik). Dolny pasek nawigacyjny pozostaje widoczny. | <ActiveSessionStickyHeader />, <ActiveExerciseCardHeader />, <CoachTipCard />, <CurrentSetTargetCard />, <SetNavigationRow />, <ExerciseSetsTable />, <ActiveRestTimerDock />, <SessionExerciseOverview />, <ActiveSessionControlsDock />, <SwapExerciseModal />, <FinishConfirmationModal /> |
/week |
Harmonogram treningów / Widok tygodnia | Pełny przegląd harmonogramu na 7 dni z tygodniowymi danymi zbiorczymi dotyczącymi głośności i czasu. | <WeekHeader />, <WeeklyStatsSummary />, <DayScheduleCardList />, <DayScheduleCard />, <ModifyWeekWithCoachCard /> |
/coach |
Czat z trenerem AI | Wskazówki konwersacyjne z elementami kontekstowymi i propozycjami treningów etapowych. | <CoachHeader />, <ChatMessageList />, <ChatBubble />, <StagedProposalCard />, <ContextualPromptsBar />, <ChatInputDock />, <ContextBanner />, <ChatInputBar />, <SpeechToTextButton /> |
/progress |
Postępy i statystyki | historyczne dzienniki treningowe, osiągnięcia i wykresy objętości; | <ProgressHeader />, <PRShowcaseBanner />, <VolumeProgressChartCard />, <AllTimeStatsGrid />, <WorkoutHistorySection />, <HistorySessionCard />, <EmptyHistoryPlaceholder /> |
/settings |
Profil i ustawienia użytkownika | Profil sprzętu, powiadomienia i 3-poziomowe zarządzanie pamięcią. | <SettingsHeader />, <UserProfileCard />, <EquipmentSelectorCard />, <EquipmentToggleChip />, <PreferencesGroup />, <MemoryTierViewerCard />, <MemoryItemCard />, <AccountActionsGroup /> |
/exercises/:exerciseId |
Szczegóły encyklopedii ćwiczeń | Przewodnik po ćwiczeniach z możliwością precyzyjnego linkowania (np. /exercises/incline-db-bench-press) zawierający filmy i wskazówki dotyczące formy. |
<BackButton />, <ExerciseVideoPlayer />, <TargetMusclesCard />, <HowToPerformCard />, <FormTipsCard /> |
3. Specyfikacje stron i wyświetleń
Wyświetl: DailyWorkoutView (/today i /workouts/:day)
- Cel: wyświetla zaplanowany trening na dany dzień, w tym jego rodzaj, czas trwania, docelowe obciążenie mięśni, notatki trenera, bloki serii prostych i superserii. Jeśli nie zaplanowano żadnego treningu, wyświetla się pusty stan.
- Anatomia wizualna:
- Góra:
<BackButton label="Back to Week" targetRoute="/week" />. - Nagłówek: jednowierszowy tytuł (
"Today"lub dzień tygodnia) z warunkową plakietką"✓ Completed", pigułką czasu trwania ("⏱ 50 min") i paskami procentowymi intensywności docelowych mięśni. - Notatka trenera: karta z poradą kontekstową z ikoną i zielonym obramowaniem.
- Treść: przewijana lista bloków ćwiczeń z użyciem
<WorkoutExerciseSummary />(serie proste lub superserie z plakietkąborder-left: 3px solid #a3e635i🔁 SUPERSET BLOCK). - Pusty stan:
<EmptyDayPlaceholder message="Nothing scheduled for this day" />. - Działanie w stopce na dole:
<ModifyWithCoachCard />(prowadzi do:/coach?day=:day).
- Góra:
Wyświetl: WeekScheduleView (/week)
- Cel: wyświetla pełny 7-dniowy harmonogram treningów, w tym ogólne dane dotyczące tygodniowej objętości i czasu, wyselekcjonowaną listę dni z aktywnymi treningami (z wyłączeniem dni bez zaplanowanych treningów i dni odpoczynku) oraz bezpośredni skrót do zmiany planu tygodniowego za pomocą trenera AI.
- Anatomia wizualna:
<WeekHeader />, 3-kolumnowy<WeeklyStatsSummary />(łączny czas, łączna objętość, częstotliwość), lista zaplanowanych dni z użyciem<DayScheduleCard variant="normal" />(z neonowo-zieloną plakietkąTODAYna bieżącym dniu) i<ModifyWeekWithCoachCard />(prowadzi do/coach?context=week).
Wyświetl: CoachChatView (/coach)
- Cel: centrum coachingu konwersacyjnego z agentem trenera Gemini. Zapewnia motywacyjne i strategiczne porady treningowe, obsługuje zamianę mowy na tekst i umożliwia wprowadzanie etapowych zmian w treningu z udziałem człowieka i wyraźnymi elementami sterującymi akceptacją.
- Anatomia wizualna:
<CoachHeader />, przewijany<ChatMessageList />(<ChatBubble />i<StagedProposalCard />), warunkowy<ContextualPromptsBar />i zadokowany<ChatInputDock />(<ContextBanner />z[✕]przyciskiem zamknięcia +<ChatInputBar />+<SpeechToTextButton />).
Wyświetl: ExerciseDetailView (/exercises/:exerciseId)
- Cel: wpis encyklopedyczny z możliwością precyzyjnego linkowania, zawierający automatycznie zapętlony wyciszony film demonstracyjny (
<ExerciseVideoPlayer />), plakietki z głównymi i dodatkowymi mięśniami docelowymi (<TargetMusclesCard />), uporządkowane instrukcje wykonywania ćwiczenia krok po kroku (<HowToPerformCard />) oraz wskazówki dotyczące formy (<FormTipsCard />).
Wyświetl: ActiveWorkoutView (/workout/active)
- Cel: ekran do wykonywania treningów o wysokiej intensywności i rejestrowania serii. Zarządza stanem stopera sesji na żywo, bieżącymi celami serii, danymi wejściowymi dotyczącymi powtórzeń i obciążenia, natychmiastowym zaznaczaniem ukończenia (<16 ms), automatyczną zmianą superserii, odliczaniem czasu odpoczynku z wykorzystaniem sygnałów haptycznych i dźwiękowych, zamianą ćwiczeń i ostatecznym zapisywaniem w aplikacji
POST /api/workouts/log. - Anatomia wizualna:
<ActiveSessionStickyHeader />,<ActiveExerciseCardHeader />,<CoachTipCard />,<CurrentSetTargetCard />, pływający<ActiveRestTimerDock />(+30s,Skip),<SetNavigationRow />,<ExerciseSetsTable />(+ Add Set),<SessionExerciseOverview />, zadokowany<ActiveSessionControlsDock />([⇄ SWAP EXERCISE]+[▶ START WORKOUT]/[⏸ PAUSE]/[▶ RESUME]),<SwapExerciseModal />i<FinishConfirmationModal />.
Wyświetl: ProgressView (/progress)
- Cel: śledzenie postępów sportowych w czasie, świętowanie niedawnych rekordów życiowych (
<PRShowcaseBanner />), wizualizacja tygodniowych i miesięcznych trendów dotyczących objętości za pomocą interaktywnych wykresów Recharts (<VolumeProgressChartCard />z przełącznikami4W | 3M | 1Y), wyświetlanie<AllTimeStatsGrid />oraz archiwizowanie ukończonych sesji treningowych (<WorkoutHistorySection />/<HistorySessionCard />).
Wyświetl: SettingsView (/settings)
- Cel: zarządzanie informacjami o profilu sportowca (
<UserProfileCard />), wyposażeniem (<EquipmentSelectorCard />/<EquipmentToggleChip />), preferencjami dotyczącymi treningu (<PreferencesGroup />dlaLBS / KG, haptyka, dźwięk) oraz zapewnienie przejrzystego zarządzania użytkownikami i usuwania 3-poziomowej pamięci aktywnej trenera AI (<MemoryTierViewerCard />/<MemoryItemCard />).
4. Katalog i interfejsy komponentów wielokrotnego użytku
Kluczowe umowy dotyczące właściwości komponentów TypeScript w aplikacji:
// src/components/workout/WorkoutExerciseSummary.tsx
interface WorkoutExerciseSummaryProps {
blocks: Array<{
label?: string;
category?: string;
exercises: Array<{
exercise_id: string; // Canonical slug (e.g. 'incline-db-bench-press')
name: string; // Denormalized display name (e.g. 'Incline DB Bench Press')
target_sets: number;
target_reps: string | number;
rest_seconds?: number;
}>;
}>;
activeExerciseId?: string;
onSelectExercise?: (exerciseId: string) => void;
}
// src/components/week/DayScheduleCard.tsx
interface DayScheduleCardProps {
dayName: string;
dayShort: string;
subtitleLabel?: string;
isToday?: boolean;
title: string;
focusBadge: string;
durationMin: number;
volumeLbs?: number;
targetMuscles: string[];
variant?: 'normal' | 'condensed';
onPress: (dayName: string) => void;
}
// src/components/coach/StagedProposalCard.tsx
interface StagedProposalCardProps {
proposalId: string;
type: 'UPDATE_DAY' | 'UPDATE_WEEK';
targetDay?: string;
summaryDiff: string;
proposalData: any;
isApplied?: boolean;
onAccept: (proposalId: string, data: any) => void;
onModify: (summaryDiff: string) => void;
}
// src/components/workout/CurrentSetTargetCard.tsx
interface CurrentSetTargetCardProps {
setNumber: number;
targetWeightLbs: number;
targetReps: number;
isCompleted: boolean;
onWeightChange: (weight: number) => void;
onRepsChange: (reps: number) => void;
onToggleComplete: () => void;
}5. Zarządzanie stanem klienta i macierz przepływu danych
5.1 Zasady dotyczące opóźnień i wczytywania: silnik o 2 prędkościach
- Optymistyczny interfejs użytkownika na siłowni (<16 ms): działania na siłowni, takie jak odznaczanie serii, zwiększanie obciążenia lub liczby powtórzeń, przełączanie kart i zmiana sprzętu, aktualizują stan lokalny i ponownie renderują się w ciągu 16 milisekund. Użytkownicy nie są blokowani przez wskaźniki ładowania podczas trzymania obciążników.
- Wyraźne wskaźniki ładowania i wskaźniki operacji asynchronicznych:
- Rozmowy z trenerem AI (
POST /api/coach/chat): po wysłaniu wiadomości na czacie natychmiast pojawia się animowany dymek z wirującym kółkiem oznaczającym, że trener myśli. Jest on widoczny w strumieniu czatu, dopóki Gemini nie udzieli odpowiedzi lub nie zaproponuje treningu. - Początkowe uruchomienie na zimno i synchronizacja sieciowa: kontenery widoku wyświetlają szkieletowe elementy wczytywania i wysokokontrastowe ikony ładowania podczas pobierania
weekly_planslubhistorical_workouts. - Przesyłanie treningu (
[Finish]): okno potwierdzenia zakończenia wyświetla aktywny wskaźnik ładowania, gdy ładunek sesji jest zatwierdzany wPOST /api/workouts/logw Cloud Firestore.
- Rozmowy z trenerem AI (
5.2 Architektura magazynu klienta i granice domeny
| Warstwa sklepu | Domena stanu i kluczowe właściwości | Zasady dotyczące trwałości i pamięci podręcznej | Skoordynowana umowa dotycząca backendu |
|---|---|---|---|
useActiveSessionStore (Zustand) |
sessionState (unstarted, running, paused), elapsedSeconds, currentStepIndex, steps: WorkoutStep[], loggedExercises. |
Synchronizacja z localStorage co sekundę, aby zapewnić niezawodne odzyskiwanie danych po zablokowaniu lub odświeżeniu telefonu. |
Przesyła ukończony ładunek do POST /api/workouts/log. |
useWeeklyPlanQuery (TanStack Query) |
Bieżący 7-dniowy harmonogram, obiekty treningu dziennego, bloki superserii, stany ukończenia (scheduled, completed). |
Zapisane w pamięci podręcznej w TanStack Query (staleTime: 5 min); pobrane wstępnie przy uruchomieniu. |
Zatwierdzane, gdy użytkownik kliknie [Accept Plan] w przypadku propozycji od: POST /api/coach/chat. |
useCoachChatStore (Zustand + TanStack) |
Dymki z wiadomościami w porządku chronologicznym, activeContext, elementy z promptami, isCoachTyping: boolean, propozycje na etapie przygotowania. |
Zsynchronizowano z cotygodniowym zasobnikiem czatu Firestore za pomocą subskrypcji w czasie rzeczywistym (onSnapshot). |
Wysyła zapytania do: POST /api/coach/chat. |
useProgressQuery (TanStack Query) |
Archiwum historycznych treningów, tablica rekordów życiowych (/users/{userId}/prs), zagregowane dane o objętości treningowej, filtr przedziału czasu (4W, 3M, 1Y). |
Zapisano w pamięci podręcznej w TanStack Query (staleTime: 10 min). |
Aktualizowane natychmiast po zakończeniu sesji treningowej. |
useUserProfileStore (TanStack Query) |
Ekwipunek, jednostki (LBS/KG), przełączniki dźwięku/haptyki, 3-poziomowa pamięć żywa (podstawowa, fizjologiczna, sytuacyjna). |
Dane są przechowywane w pamięci podręcznej w TanStack Query z dwukierunkową synchronizacją z Firestore user_profiles. |
Zaktualizowano automatycznie za pomocą memory_mutations z: POST /api/coach/chat. |
useExerciseLibraryQuery (TanStack Query) |
Statyczne wpisy encyklopedyczne, adresy URL filmów, główne/dodatkowe mięśnie, kroki, wskazówki dotyczące formy. | Agresywne korzystanie z pamięci podręcznej z nieskończonym czasem życia danych (staleTime: Infinity). |
Tylko do odczytu z niezmiennej kolekcji Firestore exercises. |
5.3 Wstępnie obliczony wykres kroków aktywnej sesji
export interface WorkoutStep {
stepIndex: number; // 1-based index (e.g. 1 to 13)
totalSteps: number; // Total sets in the session
blockIndex: number; // Index of block in day plan
blockType: 'straight' | 'superset';
exerciseId: string; // Canonical slug
exerciseName: string; // Display name
setNumber: number; // Set index for this exercise (1, 2, 3...)
targetWeightLbs: number; // Target weight in lbs
targetReps: string | number; // Target reps (e.g. "8-10")
restSecondsAfter: number; // Prescribed rest duration
isCompleted: boolean; // Completion checkmark status
actualWeightLbs?: number; // User entered weight
actualRepsCompleted?: number; // User entered reps
}5.4 Kompleksowy przepływ danych i macierz mutacji
| Aktywator użytkownika | Widok źródłowy | Zmieniono magazyn klienta | Opóźnienie interfejsu / stan wczytywania | Koordynacja backendu | Wycofanie / obsługa awarii |
|---|---|---|---|---|---|
Kliknij [✓] Zakończ serię |
/workout/active |
useActiveSessionStore |
<16ms (optymistyczny) |
Zaktualizowano bufor sesji lokalnej; brak oczekiwania na sieć. | Zapis w pamięci lokalnej z niezawodną trwałością lokalną. |
Kliknij [Finish Workout]. |
/workout/active |
useActiveSessionStore, useWeeklyPlanStore, useProgressStore |
Podczas synchronizacji na przycisku wyświetla się wskaźnik postępu wczytywania | Przesyła do: POST /api/workouts/log. Oznacza dzień Firestore jako completed. |
Jeśli urządzenie jest offline, ładunek jest umieszczany w kolejce w lokalnym buforze synchronizacji i ponownie wysyłany po ponownym połączeniu. |
Kliknij [Accept Plan]. |
/coach |
useWeeklyPlanStore, useCoachChatStore |
Znaczek interfejsu błyskawicznego ("✓ Plan Applied") |
Zatwierdza proposal.data w Firestore weekly_plans. |
Jeśli wystąpi błąd sieci, użytkownik otrzyma powiadomienie, a przyciski pozostaną aktywne, aby można było spróbować ponownie. |
| Wysyłanie wiadomości w Google Chat | /coach |
useCoachChatStore, useUserProfileStore |
Optymistyczne dodanie dymka + wskaźnik postępu myślenia trenera | Połączenia telefoniczne: POST /api/coach/chat. Zatwierdzenia zwróciły wartość memory_mutations. |
Zastępuje ikonę ładowania komunikatem „Nie udało się wysłać. Dotknij, aby spróbować jeszcze raz”. |
| Przełączanie elementu dotyczącego sprzętu | /settings |
useUserProfileStore |
Przełącznik błyskawiczny (<16ms) |
Wysyła zapis w tle do Firestore user_profiles. |
Cofa wybór elementu i wyświetla komunikat o błędzie, jeśli zapis się nie powiedzie. |
Usuwanie elementu z pamięci AI [🗑] |
/settings |
useUserProfileStore |
Natychmiastowe usunięcie (<16ms) |
Wysyła mutację usuwania do Firestore user_profiles. |
Przywraca element pamięci i ostrzega użytkownika, jeśli usunięcie się nie powiedzie. |
6. Kompleksowe ścieżki użytkownika i zestaw testów w prostym języku angielskim
- Zestaw 1. Powłoka aplikacji, nawigacja i obsługa tras (testy 1.1–1.6: przekierowanie po uruchomieniu z katalogu głównego, stały dok, szybki powrót do aktywnej sesji, zastępczy dzień tygodnia w przypadku nieprawidłowego dnia, zastępcza strona 404 w przypadku nieznanej trasy, zastępczy precyzyjny link do ćwiczenia w przypadku nieprawidłowego linku).
- Zestaw 2. Widok codziennego treningu i renderowanie bloków (testy 2.1–2.7: dynamiczne rozpoznawanie tytułu dnia, trasa konkretnego dnia i przycisk Wstecz, traktowanie pojedynczego bloku i superserii, obiekt zastępczy pustego dnia, oznaczenie ukończonego treningu, czysta nawigacja na środkowym przycisku odtwarzania, modyfikacja z załącznikiem kontekstowym trenera).
- Zestaw 3. Widok harmonogramu tygodniowego i karta harmonogramu dziennego (testy 3.1–3.6: renderowanie statystyk tygodniowych, filtr tylko zaplanowanych dni, wizualne wyróżnienie dnia dzisiejszego, nawigacja po karcie dnia, modyfikowanie nawigacji po tygodniu, renderowanie wersji skróconej).
- Pakiet 4. Czat z trenerem i etapowa mutacja (testy 4.1–4.7: renderowanie strumienia wiadomości na czacie, dołączanie i odrzucanie banera kontekstowego, wstępne wypełnianie elementu z promptem, przełącznik dyktowania mowy, izolacja etapowej mutacji, akceptacja i zatwierdzenie propozycji, podgląd i zatwierdzenie propozycji cotygodniowej zmiany).
- Zestaw 5. Szczegóły ćwiczenia i encyklopedia (testy 5.1–5.5: renderowanie szczegółów ćwiczenia, automatyczne odtwarzanie w pętli z wyciszonym dźwiękiem, przełącznik wstrzymywania filmu, tagi mięśni głównych i pomocniczych, przechodzenie wstecz w historii i opcja zastępcza).
- Pakiet 6. Aktywny moduł śledzenia treningu i rejestrowanie (testy 6.1–6.7: stan początkowy przed rozpoczęciem i ręczne rozpoczęcie, wstrzymanie i wznowienie stopera, dotykowe rejestrowanie serii i przełączanie znacznika wyboru, naprzemienne wykonywanie kroków superserii, modalne okno zamiany ćwiczenia i zamiana, potwierdzenie zakończenia i synchronizacja z serwerem, przywracanie stanu sesji po ponownym załadowaniu).
- Zestaw 7. Postępy i dane historyczne (testy 7.1–7.5: renderowanie podsumowania panelu postępów, wyświetlanie banera Showcase PR, przełączanie przedziału czasowego wykresu, stan pustej historii, kliknięcie historii poprzedniej sesji).
- Zestaw 8. Ustawienia użytkownika, sprzęt i pamięć AI (testy 8.1–8.4: renderowanie widoku ustawień, aktualizacja przełącznika sprzętu, przełączanie jednostek, usuwanie elementów z pamięci AI).