diff --git a/src/app/lib/storage/workoutStorage.ts b/src/app/lib/storage/workoutStorage.ts index bfdb2ea..ed263c0 100644 --- a/src/app/lib/storage/workoutStorage.ts +++ b/src/app/lib/storage/workoutStorage.ts @@ -1,309 +1,99 @@ -/** - * Workout and metrics data persistence layer - * Handles saving and retrieving workout data from localStorage - */ - -export interface WorkoutSet { - reps: number; - weight: number; - timestamp: number; -} +// This file contains workout storage utilities export interface WorkoutSession { id: string; - exerciseName: string; date: string; - sets: WorkoutSet[]; - duration: number; // in seconds - caloriesBurned: number; - notes?: string; + duration: number; + exercises: Exercise[]; + totalCalories: number; } -export interface CardioSession { +export interface Exercise { id: string; - type: 'running' | 'walking' | 'cycling'; - date: string; - distance: number; // in km - duration: number; // in seconds - caloriesBurned: number; - pace: number; // km/h - steps?: number; - route?: string; + name: string; + sets: number; + reps: number; + weight: number; } export interface NutritionLog { id: string; date: string; + meals: Meal[]; + totalCalories: number; +} + +export interface Meal { + id: string; + name: string; calories: number; - protein: number; - carbs: number; - fats: number; - meals: string[]; + macros: { + protein: number; + carbs: number; + fats: number; + }; } -export interface UserMetrics { - totalWorkouts: number; - totalCardioDistance: number; - totalCaloriesBurned: number; - currentStreak: number; - personalRecords: Record; - lastUpdated: number; -} +export const workoutStorage = { + // Store workout session + saveWorkout: (session: WorkoutSession): void => { + const workouts = JSON.parse(localStorage.getItem('workouts') || '[]'); + workouts.push(session); + localStorage.setItem('workouts', JSON.stringify(workouts)); + }, -const STORAGE_KEYS = { - WORKOUT_SESSIONS: 'fitflow_workout_sessions', - CARDIO_SESSIONS: 'fitflow_cardio_sessions', - NUTRITION_LOGS: 'fitflow_nutrition_logs', - USER_METRICS: 'fitflow_user_metrics', -}; + // Get all workouts + getAllWorkouts: (): WorkoutSession[] => { + const workouts = localStorage.getItem('workouts'); + return workouts ? JSON.parse(workouts) : []; + }, -/** - * Save a workout session to localStorage - */ -export const saveWorkoutSession = (session: WorkoutSession): void => { - if (typeof window === 'undefined') return; - - try { - const sessions = getWorkoutSessions(); - sessions.push(session); - localStorage.setItem(STORAGE_KEYS.WORKOUT_SESSIONS, JSON.stringify(sessions)); - updateUserMetrics(); - } catch (error) { - console.error('Error saving workout session:', error); - } -}; - -/** - * Get all workout sessions from localStorage - */ -export const getWorkoutSessions = (): WorkoutSession[] => { - if (typeof window === 'undefined') return []; - - try { - const data = localStorage.getItem(STORAGE_KEYS.WORKOUT_SESSIONS); - return data ? JSON.parse(data) : []; - } catch (error) { - console.error('Error retrieving workout sessions:', error); - return []; - } -}; - -/** - * Save a cardio session to localStorage - */ -export const saveCardioSession = (session: CardioSession): void => { - if (typeof window === 'undefined') return; - - try { - const sessions = getCardioSessions(); - sessions.push(session); - localStorage.setItem(STORAGE_KEYS.CARDIO_SESSIONS, JSON.stringify(sessions)); - updateUserMetrics(); - } catch (error) { - console.error('Error saving cardio session:', error); - } -}; - -/** - * Get all cardio sessions from localStorage - */ -export const getCardioSessions = (): CardioSession[] => { - if (typeof window === 'undefined') return []; - - try { - const data = localStorage.getItem(STORAGE_KEYS.CARDIO_SESSIONS); - return data ? JSON.parse(data) : []; - } catch (error) { - console.error('Error retrieving cardio sessions:', error); - return []; - } -}; - -/** - * Save a nutrition log to localStorage - */ -export const saveNutritionLog = (log: NutritionLog): void => { - if (typeof window === 'undefined') return; - - try { - const logs = getNutritionLogs(); - logs.push(log); - localStorage.setItem(STORAGE_KEYS.NUTRITION_LOGS, JSON.stringify(logs)); - updateUserMetrics(); - } catch (error) { - console.error('Error saving nutrition log:', error); - } -}; - -/** - * Get all nutrition logs from localStorage - */ -export const getNutritionLogs = (): NutritionLog[] => { - if (typeof window === 'undefined') return []; - - try { - const data = localStorage.getItem(STORAGE_KEYS.NUTRITION_LOGS); - return data ? JSON.parse(data) : []; - } catch (error) { - console.error('Error retrieving nutrition logs:', error); - return []; - } -}; - -/** - * Get user metrics from localStorage - */ -export const getUserMetrics = (): UserMetrics => { - if (typeof window === 'undefined') { - return { - totalWorkouts: 0, - totalCardioDistance: 0, - totalCaloriesBurned: 0, - currentStreak: 0, - personalRecords: {}, - lastUpdated: Date.now(), - }; - } - - try { - const data = localStorage.getItem(STORAGE_KEYS.USER_METRICS); - return data - ? JSON.parse(data) - : { - totalWorkouts: 0, - totalCardioDistance: 0, - totalCaloriesBurned: 0, - currentStreak: 0, - personalRecords: {}, - lastUpdated: Date.now(), - }; - } catch (error) { - console.error('Error retrieving user metrics:', error); - return { - totalWorkouts: 0, - totalCardioDistance: 0, - totalCaloriesBurned: 0, - currentStreak: 0, - personalRecords: {}, - lastUpdated: Date.now(), - }; - } -}; - -/** - * Update user metrics based on saved sessions - */ -export const updateUserMetrics = (): void => { - if (typeof window === 'undefined') return; - - try { - const workoutSessions = getWorkoutSessions(); - const cardioSessions = getCardioSessions(); - const nutritionLogs = getNutritionLogs(); - - let totalWorkouts = workoutSessions.length; - let totalCardioDistance = cardioSessions.reduce((sum, session) => sum + session.distance, 0); - let totalCaloriesBurned = workoutSessions.reduce((sum, session) => sum + session.caloriesBurned, 0) - + cardioSessions.reduce((sum, session) => sum + session.caloriesBurned, 0); - - // Calculate streak (consecutive days with activity) - const currentStreak = calculateStreak([...workoutSessions, ...cardioSessions]); - - // Extract personal records from workouts - const personalRecords: Record = {}; - workoutSessions.forEach((session) => { - const maxWeight = Math.max(...session.sets.map((s) => s.weight)); - const key = `${session.exerciseName}_pr`; - if (!personalRecords[key] || maxWeight > personalRecords[key]) { - personalRecords[key] = maxWeight; - } + // Get workouts by date range + getWorkoutsByDateRange: (startDate: Date, endDate: Date): WorkoutSession[] => { + const allWorkouts = workoutStorage.getAllWorkouts(); + return allWorkouts.filter(w => { + const workoutDate = new Date(w.date); + return workoutDate >= startDate && workoutDate <= endDate; }); + }, - const metrics: UserMetrics = { + // Delete workout + deleteWorkout: (id: string): void => { + const workouts = JSON.parse(localStorage.getItem('workouts') || '[]'); + const filtered = workouts.filter((w: WorkoutSession) => w.id !== id); + localStorage.setItem('workouts', JSON.stringify(filtered)); + }, + + // Get statistics + getStatistics: (): { totalWorkouts: number; totalCardioDistance: number; totalCaloriesBurned: number } => { + const allWorkouts = workoutStorage.getAllWorkouts(); + const totalWorkouts = allWorkouts.length; + const totalCardioDistance = allWorkouts.reduce((sum, w) => sum + (w.duration * 0.15), 0); + const totalCaloriesBurned = allWorkouts.reduce((sum, w) => sum + w.totalCalories, 0); + + return { totalWorkouts, totalCardioDistance, totalCaloriesBurned, - currentStreak, - personalRecords, - lastUpdated: Date.now(), }; + }, - localStorage.setItem(STORAGE_KEYS.USER_METRICS, JSON.stringify(metrics)); - } catch (error) { - console.error('Error updating user metrics:', error); - } -}; - -/** - * Calculate consecutive days with activity - */ -const calculateStreak = (sessions: Array): number => { - if (sessions.length === 0) return 0; - - const dates = sessions.map((session) => new Date(session.date).toDateString()).filter((date, index, self) => self.indexOf(date) === index).sort((a, b) => new Date(b).getTime() - new Date(a).getTime()); - - let streak = 1; - for (let i = 1; i < dates.length; i++) { - const currentDate = new Date(dates[i]); - const previousDate = new Date(dates[i - 1]); - const diffTime = Math.abs(previousDate.getTime() - currentDate.getTime()); - const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)); - - if (diffDays === 1) { - streak++; - } else { - break; - } - } - - return streak; -}; - -/** - * Clear all stored data - */ -export const clearAllData = (): void => { - if (typeof window === 'undefined') return; - - try { - localStorage.removeItem(STORAGE_KEYS.WORKOUT_SESSIONS); - localStorage.removeItem(STORAGE_KEYS.CARDIO_SESSIONS); - localStorage.removeItem(STORAGE_KEYS.NUTRITION_LOGS); - localStorage.removeItem(STORAGE_KEYS.USER_METRICS); - } catch (error) { - console.error('Error clearing data:', error); - } -}; - -/** - * Export data as JSON for backup - */ -export const exportData = (): string => { - const data = { - workouts: getWorkoutSessions(), - cardio: getCardioSessions(), - nutrition: getNutritionLogs(), - metrics: getUserMetrics(), - exportDate: new Date().toISOString(), - }; - return JSON.stringify(data, null, 2); -}; - -/** - * Import data from JSON backup - */ -export const importData = (jsonData: string): boolean => { - if (typeof window === 'undefined') return false; - - try { - const data = JSON.parse(jsonData); - if (data.workouts) localStorage.setItem(STORAGE_KEYS.WORKOUT_SESSIONS, JSON.stringify(data.workouts)); - if (data.cardio) localStorage.setItem(STORAGE_KEYS.CARDIO_SESSIONS, JSON.stringify(data.cardio)); - if (data.nutrition) localStorage.setItem(STORAGE_KEYS.NUTRITION_LOGS, JSON.stringify(data.nutrition)); - if (data.metrics) localStorage.setItem(STORAGE_KEYS.USER_METRICS, JSON.stringify(data.metrics)); - return true; - } catch (error) { - console.error('Error importing data:', error); - return false; - } + // Save nutrition log + saveNutritionLog: (log: NutritionLog): void => { + const logs = JSON.parse(localStorage.getItem('nutritionLogs') || '[]'); + logs.push(log); + localStorage.setItem('nutritionLogs', JSON.stringify(logs)); + }, + + // Get nutrition logs + getNutritionLogs: (): NutritionLog[] => { + const logs = localStorage.getItem('nutritionLogs'); + return logs ? JSON.parse(logs) : []; + }, + + // Clear all data + clearAll: (): void => { + localStorage.removeItem('workouts'); + localStorage.removeItem('nutritionLogs'); + }, };