Add src/lib/storage/workoutStorage.ts
This commit is contained in:
185
src/lib/storage/workoutStorage.ts
Normal file
185
src/lib/storage/workoutStorage.ts
Normal file
@@ -0,0 +1,185 @@
|
||||
// Workout and metrics persistence layer
|
||||
|
||||
interface WorkoutSession {
|
||||
id: string;
|
||||
type: 'cardio' | 'training' | 'nutrition';
|
||||
date: string;
|
||||
data: Record<string, any>;
|
||||
createdAt: number;
|
||||
}
|
||||
|
||||
interface UserMetrics {
|
||||
totalWorkouts: number;
|
||||
totalDistance: number;
|
||||
totalCalories: number;
|
||||
totalWeight: number;
|
||||
consistency: number; // days in a row
|
||||
lastUpdated: number;
|
||||
}
|
||||
|
||||
const STORAGE_KEYS = {
|
||||
WORKOUTS: 'fitflow_workouts',
|
||||
METRICS: 'fitflow_metrics',
|
||||
USER_PROFILE: 'fitflow_user_profile',
|
||||
} as const;
|
||||
|
||||
export class WorkoutStorageService {
|
||||
// Workout Session Management
|
||||
static saveWorkoutSession(session: Omit<WorkoutSession, 'id' | 'createdAt'>): WorkoutSession {
|
||||
try {
|
||||
const sessions = this.getWorkoutSessions();
|
||||
const newSession: WorkoutSession = {
|
||||
id: `workout_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
||||
...session,
|
||||
createdAt: Date.now(),
|
||||
};
|
||||
sessions.push(newSession);
|
||||
localStorage.setItem(STORAGE_KEYS.WORKOUTS, JSON.stringify(sessions));
|
||||
return newSession;
|
||||
} catch (error) {
|
||||
console.error('Error saving workout session:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
static getWorkoutSessions(): WorkoutSession[] {
|
||||
try {
|
||||
const data = localStorage.getItem(STORAGE_KEYS.WORKOUTS);
|
||||
return data ? JSON.parse(data) : [];
|
||||
} catch (error) {
|
||||
console.error('Error retrieving workout sessions:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
static getWorkoutSessionsByType(type: WorkoutSession['type']): WorkoutSession[] {
|
||||
const sessions = this.getWorkoutSessions();
|
||||
return sessions.filter(session => session.type === type);
|
||||
}
|
||||
|
||||
static getWorkoutSessionsByDate(date: string): WorkoutSession[] {
|
||||
const sessions = this.getWorkoutSessions();
|
||||
return sessions.filter(session => session.date === date);
|
||||
}
|
||||
|
||||
static updateWorkoutSession(id: string, updates: Partial<WorkoutSession>): WorkoutSession | null {
|
||||
try {
|
||||
const sessions = this.getWorkoutSessions();
|
||||
const index = sessions.findIndex(s => s.id === id);
|
||||
if (index === -1) return null;
|
||||
|
||||
const updated = { ...sessions[index], ...updates, id: sessions[index].id, createdAt: sessions[index].createdAt };
|
||||
sessions[index] = updated;
|
||||
localStorage.setItem(STORAGE_KEYS.WORKOUTS, JSON.stringify(sessions));
|
||||
return updated;
|
||||
} catch (error) {
|
||||
console.error('Error updating workout session:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static deleteWorkoutSession(id: string): boolean {
|
||||
try {
|
||||
const sessions = this.getWorkoutSessions();
|
||||
const filtered = sessions.filter(s => s.id !== id);
|
||||
localStorage.setItem(STORAGE_KEYS.WORKOUTS, JSON.stringify(filtered));
|
||||
return filtered.length < sessions.length;
|
||||
} catch (error) {
|
||||
console.error('Error deleting workout session:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Metrics Management
|
||||
static saveMetrics(metrics: UserMetrics): void {
|
||||
try {
|
||||
localStorage.setItem(STORAGE_KEYS.METRICS, JSON.stringify(metrics));
|
||||
} catch (error) {
|
||||
console.error('Error saving metrics:', error);
|
||||
}
|
||||
}
|
||||
|
||||
static getMetrics(): UserMetrics {
|
||||
try {
|
||||
const data = localStorage.getItem(STORAGE_KEYS.METRICS);
|
||||
if (!data) {
|
||||
return {
|
||||
totalWorkouts: 0,
|
||||
totalDistance: 0,
|
||||
totalCalories: 0,
|
||||
totalWeight: 0,
|
||||
consistency: 0,
|
||||
lastUpdated: Date.now(),
|
||||
};
|
||||
}
|
||||
return JSON.parse(data);
|
||||
} catch (error) {
|
||||
console.error('Error retrieving metrics:', error);
|
||||
return {
|
||||
totalWorkouts: 0,
|
||||
totalDistance: 0,
|
||||
totalCalories: 0,
|
||||
totalWeight: 0,
|
||||
consistency: 0,
|
||||
lastUpdated: Date.now(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
static updateMetrics(updates: Partial<UserMetrics>): UserMetrics {
|
||||
const current = this.getMetrics();
|
||||
const updated: UserMetrics = { ...current, ...updates, lastUpdated: Date.now() };
|
||||
this.saveMetrics(updated);
|
||||
return updated;
|
||||
}
|
||||
|
||||
// Calculated Metrics
|
||||
static calculateMetricsFromSessions(): UserMetrics {
|
||||
const sessions = this.getWorkoutSessions();
|
||||
let totalDistance = 0;
|
||||
let totalCalories = 0;
|
||||
let totalWeight = 0;
|
||||
|
||||
sessions.forEach(session => {
|
||||
if (session.data.distance) totalDistance += Number(session.data.distance) || 0;
|
||||
if (session.data.calories) totalCalories += Number(session.data.calories) || 0;
|
||||
if (session.data.weight) totalWeight += Number(session.data.weight) || 0;
|
||||
});
|
||||
|
||||
return this.updateMetrics({
|
||||
totalWorkouts: sessions.length,
|
||||
totalDistance,
|
||||
totalCalories,
|
||||
totalWeight,
|
||||
});
|
||||
}
|
||||
|
||||
// Batch Operations
|
||||
static clearAllData(): void {
|
||||
try {
|
||||
localStorage.removeItem(STORAGE_KEYS.WORKOUTS);
|
||||
localStorage.removeItem(STORAGE_KEYS.METRICS);
|
||||
localStorage.removeItem(STORAGE_KEYS.USER_PROFILE);
|
||||
} catch (error) {
|
||||
console.error('Error clearing data:', error);
|
||||
}
|
||||
}
|
||||
|
||||
static exportData(): { workouts: WorkoutSession[]; metrics: UserMetrics } {
|
||||
return {
|
||||
workouts: this.getWorkoutSessions(),
|
||||
metrics: this.getMetrics(),
|
||||
};
|
||||
}
|
||||
|
||||
static importData(data: { workouts: WorkoutSession[]; metrics: UserMetrics }): void {
|
||||
try {
|
||||
localStorage.setItem(STORAGE_KEYS.WORKOUTS, JSON.stringify(data.workouts));
|
||||
this.saveMetrics(data.metrics);
|
||||
} catch (error) {
|
||||
console.error('Error importing data:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export type { WorkoutSession, UserMetrics };
|
||||
Reference in New Issue
Block a user