Update src/lib/storage/workoutStorage.ts

This commit is contained in:
2026-03-11 19:33:41 +00:00
parent bb58f2b1f7
commit 00d4a3cc07

View File

@@ -1,285 +1,64 @@
// User data persistence layer for workouts and metrics
'use client';
export interface ExerciseLog {
id: string;
name: string;
sets: number;
reps: number;
weight?: number;
}
export interface WorkoutSession {
id: string;
date: string;
type: 'cardio' | 'training' | 'nutrition';
duration?: number;
distance?: number;
calories?: number;
duration: number;
pace?: string;
calories?: number;
steps?: number;
exercises?: ExerciseLog[];
meals?: MealLog[];
meals?: Array<{
id: string;
name: string;
calories: number;
protein: number;
carbs: number;
fats: number;
timestamp: string;
}>;
notes?: string;
}
export interface ExerciseLog {
id: string;
name: string;
muscleGroup: string;
sets: SetLog[];
totalVolume?: number;
}
const STORAGE_KEY = 'workout_sessions';
export interface SetLog {
reps: number;
weight: number;
restTime?: number;
}
export const workoutStorage = {
getSessions: (): WorkoutSession[] => {
if (typeof window === 'undefined') return [];
const stored = localStorage.getItem(STORAGE_KEY);
return stored ? JSON.parse(stored) : [];
},
export interface MealLog {
id: string;
name: string;
calories: number;
protein: number;
carbs: number;
fats: number;
timestamp: string;
}
export interface UserMetrics {
totalSteps: number;
totalDistance: number;
totalCalories: number;
totalVolume: number;
workoutStreak: number;
lastWorkoutDate?: string;
personalRecords: Record<string, number>;
}
const STORAGE_KEY = 'fitflow_workouts';
const METRICS_KEY = 'fitflow_metrics';
// Workout Session Management
export const saveWorkoutSession = (session: WorkoutSession): boolean => {
try {
const existing = getWorkoutSessions();
const updated = [...existing, { ...session, id: session.id || Date.now().toString() }];
localStorage.setItem(STORAGE_KEY, JSON.stringify(updated));
return true;
} catch (error) {
console.error('Error saving workout session:', error);
return false;
}
};
export const getWorkoutSessions = (): WorkoutSession[] => {
try {
const data = localStorage.getItem(STORAGE_KEY);
return data ? JSON.parse(data) : [];
} catch (error) {
console.error('Error retrieving workout sessions:', error);
return [];
}
};
export const getWorkoutById = (id: string): WorkoutSession | null => {
try {
const sessions = getWorkoutSessions();
return sessions.find(s => s.id === id) || null;
} catch (error) {
console.error('Error retrieving workout by id:', error);
return null;
}
};
export const updateWorkoutSession = (id: string, updates: Partial<WorkoutSession>): boolean => {
try {
const sessions = getWorkoutSessions();
const index = sessions.findIndex(s => s.id === id);
if (index === -1) return false;
sessions[index] = { ...sessions[index], ...updates, id };
localStorage.setItem(STORAGE_KEY, JSON.stringify(sessions));
return true;
} catch (error) {
console.error('Error updating workout session:', error);
return false;
}
};
export const deleteWorkoutSession = (id: string): boolean => {
try {
const sessions = getWorkoutSessions();
const filtered = sessions.filter(s => s.id !== id);
localStorage.setItem(STORAGE_KEY, JSON.stringify(filtered));
return true;
} catch (error) {
console.error('Error deleting workout session:', error);
return false;
}
};
export const getWorkoutsByType = (type: 'cardio' | 'training' | 'nutrition'): WorkoutSession[] => {
try {
const sessions = getWorkoutSessions();
return sessions.filter(s => s.type === type);
} catch (error) {
console.error('Error filtering workouts by type:', error);
return [];
}
};
export const getWorkoutsByDateRange = (startDate: string, endDate: string): WorkoutSession[] => {
try {
const sessions = getWorkoutSessions();
return sessions.filter(s => {
const sessionDate = new Date(s.date);
return sessionDate >= new Date(startDate) && sessionDate <= new Date(endDate);
});
} catch (error) {
console.error('Error filtering workouts by date range:', error);
return [];
}
};
// Metrics Management
export const saveUserMetrics = (metrics: UserMetrics): boolean => {
try {
localStorage.setItem(METRICS_KEY, JSON.stringify(metrics));
return true;
} catch (error) {
console.error('Error saving user metrics:', error);
return false;
}
};
export const getUserMetrics = (): UserMetrics => {
try {
const data = localStorage.getItem(METRICS_KEY);
return data ? JSON.parse(data) : getDefaultMetrics();
} catch (error) {
console.error('Error retrieving user metrics:', error);
return getDefaultMetrics();
}
};
export const updateUserMetrics = (updates: Partial<UserMetrics>): boolean => {
try {
const current = getUserMetrics();
const updated = { ...current, ...updates };
return saveUserMetrics(updated);
} catch (error) {
console.error('Error updating user metrics:', error);
return false;
}
};
export const calculateMetricsFromSessions = (): UserMetrics => {
try {
const sessions = getWorkoutSessions();
let totalSteps = 0;
let totalDistance = 0;
let totalCalories = 0;
let totalVolume = 0;
const personalRecords: Record<string, number> = {};
sessions.forEach(session => {
if (session.steps) totalSteps += session.steps;
if (session.distance) totalDistance += session.distance;
if (session.calories) totalCalories += session.calories;
if (session.exercises) {
session.exercises.forEach(ex => {
ex.sets.forEach(set => {
totalVolume += set.weight * set.reps;
const key = ex.name;
if (!personalRecords[key] || set.weight > personalRecords[key]) {
personalRecords[key] = set.weight;
}
});
});
}
});
const metrics: UserMetrics = {
totalSteps,
totalDistance,
totalCalories,
totalVolume,
workoutStreak: calculateWorkoutStreak(sessions),
lastWorkoutDate: sessions.length > 0 ? sessions[sessions.length - 1].date : undefined,
personalRecords
addSession: (session: Omit<WorkoutSession, 'id'>): WorkoutSession => {
const sessions = workoutStorage.getSessions();
const newSession: WorkoutSession = {
...session,
id: `session-${Date.now()}`,
};
return metrics;
} catch (error) {
console.error('Error calculating metrics:', error);
return getDefaultMetrics();
}
};
export const calculateWorkoutStreak = (sessions: WorkoutSession[]): number => {
if (sessions.length === 0) return 0;
const sortedSessions = [...sessions].sort((a, b) =>
new Date(b.date).getTime() - new Date(a.date).getTime()
);
let streak = 0;
let currentDate = new Date();
currentDate.setHours(0, 0, 0, 0);
for (const session of sortedSessions) {
const sessionDate = new Date(session.date);
sessionDate.setHours(0, 0, 0, 0);
const dayDiff = Math.floor((currentDate.getTime() - sessionDate.getTime()) / (1000 * 60 * 60 * 24));
if (dayDiff === streak) {
streak++;
} else {
break;
sessions.push(newSession);
if (typeof window !== 'undefined') {
localStorage.setItem(STORAGE_KEY, JSON.stringify(sessions));
}
}
return newSession;
},
return streak;
};
const getDefaultMetrics = (): UserMetrics => ({
totalSteps: 0,
totalDistance: 0,
totalCalories: 0,
totalVolume: 0,
workoutStreak: 0,
personalRecords: {}
});
// Bulk operations
export const exportWorkoutData = (): string => {
try {
const sessions = getWorkoutSessions();
const metrics = getUserMetrics();
const data = { sessions, metrics, exportDate: new Date().toISOString() };
return JSON.stringify(data, null, 2);
} catch (error) {
console.error('Error exporting data:', error);
return '';
}
};
export const importWorkoutData = (jsonData: string): boolean => {
try {
const data = JSON.parse(jsonData);
if (data.sessions) {
localStorage.setItem(STORAGE_KEY, JSON.stringify(data.sessions));
}
if (data.metrics) {
localStorage.setItem(METRICS_KEY, JSON.stringify(data.metrics));
}
return true;
} catch (error) {
console.error('Error importing data:', error);
return false;
}
};
export const clearAllData = (): boolean => {
try {
localStorage.removeItem(STORAGE_KEY);
localStorage.removeItem(METRICS_KEY);
return true;
} catch (error) {
console.error('Error clearing data:', error);
return false;
}
getSessionsByDate: (date: string): WorkoutSession[] => {
const sessions = workoutStorage.getSessions();
return sessions.filter((s) => s.date.startsWith(date));
},
getTodaysSessions: (): WorkoutSession[] => {
const currentDate = new Date().toISOString().split('T')[0];
return workoutStorage.getSessionsByDate(currentDate);
},
};