Przejdź do głównej zawartości

15. Dziennik treningowy

Zbudujesz aplikację do śledzenia aktywności fizycznej — planowanie i rejestrowanie treningów, baza ćwiczeń i śledzenie postępów (ciężar, powtórzenia, czas).

Czego się nauczycie?

  • Złożona struktura danych (trening → serie → ćwiczenia)
  • Praca z licznikiem i timerem w React
  • Wykresy postępu (ciężar w czasie)
  • Baza danych ćwiczeń z kategoriami
  • Praca zespołowa — jeden robi bazę ćwiczeń i planowanie, drugi rejestrowanie i statystyki
  1. Baza ćwiczeń — lista ćwiczeń z kategorią (klatka, plecy, nogi), opisem i instrukcją

  2. Tworzenie treningu — dodawanie ćwiczeń do treningu, ilość serii i powtórzeń

  3. Rejestrowanie treningu — odhaczanie serii, wpisywanie ciężaru użytego w danym ćwiczeniu

  4. Historia treningów — lista minionych treningów z datą i podsumowaniem

  5. Postępy — wykres ciężaru dla wybranego ćwiczenia w czasie

{
"workouts": [
{
"id": "wk-001",
"name": "Poniedziałek — Push",
"date": "2025-03-10",
"duration": 72,
"exercises": [
{
"exerciseId": "ex-bench-press",
"sets": [
{ "reps": 8, "weight": 80, "completed": true },
{ "reps": 8, "weight": 80, "completed": true },
{ "reps": 6, "weight": 80, "completed": true }
]
}
]
}
],
"exercises": [
{
"id": "ex-bench-press",
"name": "Wyciskanie na ławce",
"category": "chest",
"muscleGroup": ["Klatka piersiowa", "Triceps", "Barki"]
}
]
}
  • Baza ćwiczeń (minimum 10, z kategorią)
  • Tworzenie treningu przez wybór ćwiczeń
  • Rejestrowanie serii (ciężar + powtórzenia)
  • Historia treningów (lista z datami)
  • Zapis w localStorage
Ocena: 3.0
function useWorkoutTimer() {
const [seconds, setSeconds] = useState(0);
const [isRunning, setIsRunning] = useState(false);
useEffect(() => {
if (!isRunning) return;
const interval = setInterval(() => setSeconds((s) => s + 1), 1000);
return () => clearInterval(interval);
}, [isRunning]);
function formatTime(totalSeconds) {
const hours = Math.floor(totalSeconds / 3600);
const minutes = Math.floor((totalSeconds % 3600) / 60);
const secs = totalSeconds % 60;
return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
}
return {
time: formatTime(seconds),
seconds,
isRunning,
start: () => setIsRunning(true),
stop: () => setIsRunning(false),
reset: () => { setIsRunning(false); setSeconds(0); },
};
}

Powodzenia!

Dziennik treningowy to projekt z bogatą strukturą danych — relacja ćwiczenie ↔ serie w treningu ↔ historia. Zaplanujcie strukturę danych PRZED pisaniem kodu. Zły model danych na początku to dużo refaktoringu potem!