137 lines
5.0 KiB
TypeScript
137 lines
5.0 KiB
TypeScript
|
||
import { WorkoutSession, ExerciseDef, ExerciseType, WorkoutSet, WorkoutPlan } from '../types';
|
||
import { updateUserProfile } from './auth';
|
||
|
||
// Helper to namespace keys
|
||
const getKey = (base: string, userId: string) => `${base}_${userId}`;
|
||
|
||
const SESSIONS_KEY = 'gymflow_sessions';
|
||
const EXERCISES_KEY = 'gymflow_exercises'; // Custom exercises are per user
|
||
const PLANS_KEY = 'gymflow_plans';
|
||
|
||
const DEFAULT_EXERCISES: ExerciseDef[] = [
|
||
{ id: 'bp', name: 'Жим лежа', type: ExerciseType.STRENGTH },
|
||
{ id: 'sq', name: 'Приседания со штангой', type: ExerciseType.STRENGTH },
|
||
{ id: 'dl', name: 'Становая тяга', type: ExerciseType.STRENGTH },
|
||
{ id: 'pu', name: 'Подтягивания', type: ExerciseType.BODYWEIGHT, bodyWeightPercentage: 100 },
|
||
{ id: 'run', name: 'Бег', type: ExerciseType.CARDIO },
|
||
{ id: 'plank', name: 'Планка', type: ExerciseType.STATIC, bodyWeightPercentage: 100 },
|
||
{ id: 'dip', name: 'Отжимания на брусьях', type: ExerciseType.BODYWEIGHT, bodyWeightPercentage: 100 },
|
||
{ id: 'pushup', name: 'Отжимания от пола', type: ExerciseType.BODYWEIGHT, bodyWeightPercentage: 65 },
|
||
{ id: 'air_sq', name: 'Приседания (свой вес)', type: ExerciseType.BODYWEIGHT, bodyWeightPercentage: 75 },
|
||
];
|
||
|
||
export const getSessions = (userId: string): WorkoutSession[] => {
|
||
try {
|
||
const data = localStorage.getItem(getKey(SESSIONS_KEY, userId));
|
||
return data ? JSON.parse(data) : [];
|
||
} catch (e) {
|
||
return [];
|
||
}
|
||
};
|
||
|
||
export const saveSession = (userId: string, session: WorkoutSession): void => {
|
||
const sessions = getSessions(userId);
|
||
const index = sessions.findIndex(s => s.id === session.id);
|
||
if (index >= 0) {
|
||
sessions[index] = session;
|
||
} else {
|
||
sessions.unshift(session);
|
||
}
|
||
localStorage.setItem(getKey(SESSIONS_KEY, userId), JSON.stringify(sessions));
|
||
|
||
// Auto-update user weight profile if present in session
|
||
if (session.userBodyWeight) {
|
||
updateUserProfile(userId, { weight: session.userBodyWeight });
|
||
}
|
||
};
|
||
|
||
export const deleteSession = (userId: string, id: string): void => {
|
||
let sessions = getSessions(userId);
|
||
sessions = sessions.filter(s => s.id !== id);
|
||
localStorage.setItem(getKey(SESSIONS_KEY, userId), JSON.stringify(sessions));
|
||
};
|
||
|
||
export const deleteAllUserData = (userId: string) => {
|
||
localStorage.removeItem(getKey(SESSIONS_KEY, userId));
|
||
localStorage.removeItem(getKey(EXERCISES_KEY, userId));
|
||
localStorage.removeItem(getKey(PLANS_KEY, userId));
|
||
};
|
||
|
||
export const getExercises = (userId: string): ExerciseDef[] => {
|
||
try {
|
||
const data = localStorage.getItem(getKey(EXERCISES_KEY, userId));
|
||
const savedExercises: ExerciseDef[] = data ? JSON.parse(data) : [];
|
||
|
||
// Create a map of saved exercises for easy lookup
|
||
const savedMap = new Map(savedExercises.map(ex => [ex.id, ex]));
|
||
|
||
// Start with defaults
|
||
const mergedExercises = DEFAULT_EXERCISES.map(defEx => {
|
||
// If user has a saved version of this default exercise (e.g. edited or archived), use that
|
||
if (savedMap.has(defEx.id)) {
|
||
const saved = savedMap.get(defEx.id)!;
|
||
savedMap.delete(defEx.id); // Remove from map so we don't add it again
|
||
return saved;
|
||
}
|
||
return defEx;
|
||
});
|
||
|
||
// Add remaining custom exercises (those that are not overrides of defaults)
|
||
return [...mergedExercises, ...Array.from(savedMap.values())];
|
||
} catch (e) {
|
||
return DEFAULT_EXERCISES;
|
||
}
|
||
};
|
||
|
||
export const saveExercise = (userId: string, exercise: ExerciseDef): void => {
|
||
try {
|
||
const data = localStorage.getItem(getKey(EXERCISES_KEY, userId));
|
||
let list: ExerciseDef[] = data ? JSON.parse(data) : [];
|
||
|
||
const index = list.findIndex(e => e.id === exercise.id);
|
||
if (index >= 0) {
|
||
list[index] = exercise;
|
||
} else {
|
||
list.push(exercise);
|
||
}
|
||
localStorage.setItem(getKey(EXERCISES_KEY, userId), JSON.stringify(list));
|
||
} catch {}
|
||
};
|
||
|
||
export const getLastSetForExercise = (userId: string, exerciseId: string): WorkoutSet | undefined => {
|
||
const sessions = getSessions(userId);
|
||
for (const session of sessions) {
|
||
for (let i = session.sets.length - 1; i >= 0; i--) {
|
||
if (session.sets[i].exerciseId === exerciseId) {
|
||
return session.sets[i];
|
||
}
|
||
}
|
||
}
|
||
return undefined;
|
||
}
|
||
|
||
export const getPlans = (userId: string): WorkoutPlan[] => {
|
||
try {
|
||
const data = localStorage.getItem(getKey(PLANS_KEY, userId));
|
||
return data ? JSON.parse(data) : [];
|
||
} catch {
|
||
return [];
|
||
}
|
||
};
|
||
|
||
export const savePlan = (userId: string, plan: WorkoutPlan): void => {
|
||
const plans = getPlans(userId);
|
||
const index = plans.findIndex(p => p.id === plan.id);
|
||
if (index >= 0) {
|
||
plans[index] = plan;
|
||
} else {
|
||
plans.push(plan);
|
||
}
|
||
localStorage.setItem(getKey(PLANS_KEY, userId), JSON.stringify(plans));
|
||
};
|
||
|
||
export const deletePlan = (userId: string, id: string): void => {
|
||
const plans = getPlans(userId).filter(p => p.id !== id);
|
||
localStorage.setItem(getKey(PLANS_KEY, userId), JSON.stringify(plans));
|
||
}; |