Code maintainability fixes

This commit is contained in:
AG
2025-12-06 11:32:40 +02:00
parent a13ef9f479
commit 4106f3b783
23 changed files with 1775 additions and 796 deletions

208
src/context/DataContext.tsx Normal file
View File

@@ -0,0 +1,208 @@
import React, { createContext, useContext, useState, useEffect } from 'react';
import { WorkoutSession, WorkoutPlan, WorkoutSet } from '../types';
import { useAuth } from './AuthContext';
import {
getSessions,
getPlans,
getActiveSession,
saveSession,
deleteSession,
updateActiveSession,
deleteActiveSession,
deleteSetFromActiveSession,
updateSetInActiveSession
} from '../services/storage';
import { getCurrentUserProfile, getMe } from '../services/auth';
import { generateId } from '../utils/uuid';
import { logWeight } from '../services/weight';
import { useNavigate } from 'react-router-dom';
interface DataContextType {
sessions: WorkoutSession[];
plans: WorkoutPlan[];
activeSession: WorkoutSession | null;
activePlan: WorkoutPlan | null;
startSession: (plan?: WorkoutPlan, startWeight?: number) => Promise<void>;
endSession: () => Promise<void>;
quitSession: () => Promise<void>;
addSet: (set: WorkoutSet) => void;
removeSet: (setId: string) => Promise<void>;
updateSet: (updatedSet: WorkoutSet) => Promise<void>;
updateSession: (updatedSession: WorkoutSession) => void;
deleteSessionById: (sessionId: string) => void;
refreshData: () => Promise<void>;
}
const DataContext = createContext<DataContextType | undefined>(undefined);
export const DataProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const { currentUser, updateUser } = useAuth();
const navigate = useNavigate();
const [sessions, setSessions] = useState<WorkoutSession[]>([]);
const [plans, setPlans] = useState<WorkoutPlan[]>([]);
const [activeSession, setActiveSession] = useState<WorkoutSession | null>(null);
const [activePlan, setActivePlan] = useState<WorkoutPlan | null>(null);
const refreshData = async () => {
if (currentUser) {
const s = await getSessions(currentUser.id);
setSessions(s);
const p = await getPlans(currentUser.id);
setPlans(p);
} else {
setSessions([]);
setPlans([]);
}
};
useEffect(() => {
refreshData();
}, [currentUser]);
// Restore active session
useEffect(() => {
const restoreActive = async () => {
if (currentUser) {
const session = await getActiveSession(currentUser.id);
if (session) {
setActiveSession(session);
if (session.planId) {
// Ensure plans are loaded or fetch specifically
const currentPlans = plans.length > 0 ? plans : await getPlans(currentUser.id);
const plan = currentPlans.find(p => p.id === session.planId);
if (plan) setActivePlan(plan);
}
}
}
};
restoreActive();
}, [currentUser]); // Dependency logic might need tuning, but this matches App.tsx roughly
const startSession = async (plan?: WorkoutPlan, startWeight?: number) => {
if (!currentUser || activeSession) return;
const profile = getCurrentUserProfile(currentUser.id);
const currentWeight = startWeight || profile?.weight || 70;
const newSession: WorkoutSession = {
id: generateId(),
startTime: Date.now(),
type: 'STANDARD',
userBodyWeight: currentWeight,
sets: [],
planId: plan?.id,
planName: plan?.name
};
setActivePlan(plan || null);
setActiveSession(newSession);
navigate('/');
await saveSession(currentUser.id, newSession);
if (startWeight) {
await logWeight(startWeight);
}
};
const endSession = async () => {
if (activeSession && currentUser) {
const finishedSession = { ...activeSession, endTime: Date.now() };
await updateActiveSession(currentUser.id, finishedSession);
setSessions(prev => [finishedSession, ...prev]);
setActiveSession(null);
setActivePlan(null);
const res = await getMe();
if (res.success && res.user) {
updateUser(res.user);
}
}
};
const quitSession = async () => {
if (currentUser) {
await deleteActiveSession(currentUser.id);
setActiveSession(null);
setActivePlan(null);
}
};
const addSet = (set: WorkoutSet) => {
if (activeSession) {
const updatedSession = { ...activeSession, sets: [...activeSession.sets, set] };
setActiveSession(updatedSession);
// Context update is optimistic, actual save usually happens in hooks or components?
// In App.tsx handleAddSet only updated local state.
// Wait, useTracker usually handles saving sets via API?
// In App.tsx: handleAddSet just set state.
// useTracker.ts calls onSetAdded, but ALSO calls api to save it?
// Let's look at useTracker.ts.
// handleLogSet in useTracker calls API then onSetAdded.
// So this state update is mainly for UI sync in App.
}
};
const removeSet = async (setId: string) => {
if (activeSession && currentUser) {
await deleteSetFromActiveSession(currentUser.id, setId);
const updatedSession = {
...activeSession,
sets: activeSession.sets.filter(s => s.id !== setId)
};
setActiveSession(updatedSession);
}
};
const updateSet = async (updatedSet: WorkoutSet) => {
if (activeSession && currentUser) {
const response = await updateSetInActiveSession(currentUser.id, updatedSet.id, updatedSet);
const updatedSession = {
...activeSession,
sets: activeSession.sets.map(s => s.id === updatedSet.id ? response : s)
};
setActiveSession(updatedSession);
}
};
const updateSession = (updatedSession: WorkoutSession) => {
if (!currentUser) return;
saveSession(currentUser.id, updatedSession);
setSessions(prev => prev.map(s => s.id === updatedSession.id ? updatedSession : s));
};
const deleteSessionById = (sessionId: string) => {
if (!currentUser) return;
deleteSession(currentUser.id, sessionId);
setSessions(prev => prev.filter(s => s.id !== sessionId));
};
return (
<DataContext.Provider value={{
sessions,
plans,
activeSession,
activePlan,
startSession,
endSession,
quitSession,
addSet,
removeSet,
updateSet,
updateSession,
deleteSessionById,
refreshData
}}>
{children}
</DataContext.Provider>
);
};
export const useData = () => {
const context = useContext(DataContext);
if (context === undefined) {
throw new Error('useData must be used within a DataProvider');
}
return context;
};