import type { Activity, ProcessedData } from '@/types'; /** * Format date to YYYY-MM-DD in local timezone (not UTC) */ function formatDateLocal(date: Date): string { const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); return `${year}-${month}-${day}`; } export function processActivities(activities: Activity[], dateRange?: { start: Date; end: Date }): ProcessedData { if (activities.length === 0 && !dateRange) { return { activities: [], dates: [], distances: [], durations: [], tss: [], }; } // Sort activities by date const sortedActivities = [...activities].sort((a, b) => a.date.getTime() - b.date.getTime()); // Get date range const startDate = dateRange?.start || (sortedActivities.length > 0 ? new Date(sortedActivities[0].date) : new Date()); const endDate = dateRange?.end || (sortedActivities.length > 0 ? new Date(sortedActivities[sortedActivities.length - 1].date) : new Date()); // Create a map of date -> activities const activityMap = new Map(); sortedActivities.forEach(activity => { const dateStr = formatDateLocal(activity.date); if (!activityMap.has(dateStr)) { activityMap.set(dateStr, []); } activityMap.get(dateStr)!.push(activity); }); // Generate all dates in range const dates: string[] = []; const distances: (number | null)[] = []; const durations: (number | null)[] = []; const tss: (number | null)[] = []; for (let d = new Date(startDate); d <= endDate; d.setDate(d.getDate() + 1)) { const dateStr = formatDateLocal(d); dates.push(dateStr); const dayActivities = activityMap.get(dateStr) || []; if (dayActivities.length === 0) { // No activity this day distances.push(null); durations.push(null); tss.push(null); } else { // Sum up activities for the day let totalDistance = 0; let totalDuration = 0; let totalTss = 0; let hasDistance = false; let hasDuration = false; let hasTss = false; dayActivities.forEach(activity => { if (activity.distance !== undefined) { totalDistance += activity.distance; hasDistance = true; } if (activity.duration !== undefined) { totalDuration += activity.duration; hasDuration = true; } if (activity.trainingStressScore !== undefined) { totalTss += activity.trainingStressScore; hasTss = true; } }); distances.push(hasDistance ? totalDistance : null); durations.push(hasDuration ? totalDuration : null); tss.push(hasTss ? totalTss : null); } } return { activities: sortedActivities, dates, distances, durations, tss, }; }