import { useState, useEffect } from 'react' import { useAuth } from '../context/AuthContext' import { Icon, getActivityIconName } from '../components/Icons' import Logo from '../components/Logo' import '../styles/kinetic-precision.css' const API_URL = '/api' // Coach greetings based on context const getCoachGreeting = (user, todayWorkout) => { const hour = new Date().getHours() const name = user?.name?.split(' ')[0] || 'du' if (todayWorkout) { if (hour < 10) { return `Godmorgon ${name}! Idag kör vi ${todayWorkout.name.toLowerCase()}. Redo?` } else if (hour < 14) { return `${todayWorkout.name} står på schemat idag. Dags att köra!` } else if (hour < 18) { return `Eftermiddagspass? ${todayWorkout.name} väntar på dig.` } else { return `Kvällspass ${name}? ${todayWorkout.name} – perfekt för att avsluta dagen.` } } else { if (hour < 10) { return `Godmorgon ${name}! Vilodag idag – perfekt för återhämtning.` } else if (hour < 14) { return `Ingen träning schemalagd. Ta en promenad eller stretcha lite?` } else if (hour < 18) { return `Vila är också träning! Lätt rörelse eller mobilitet idag?` } else { return `Lugn kväll ${name}. Ladda batterierna till nästa pass!` } } } const restDayTips = [ { iconName: 'walking', text: 'Promenad' }, { iconName: 'yoga', text: 'Stretching' }, { iconName: 'swimming', text: 'Simning' }, { iconName: 'cycling', text: 'Cykling' }, ] const weekdays = ['Mån', 'Tis', 'Ons', 'Tor', 'Fre', 'Lör', 'Sön'] // Format volume number function formatVolume(kg) { if (kg >= 1000) return `${(kg / 1000).toFixed(1).replace('.0', '')} 000` return `${kg}` } // Format session date function formatSessionDate(dateStr) { if (!dateStr) return '' const d = new Date(dateStr) return d.toLocaleDateString('sv-SE', { day: 'numeric', month: 'short' }) } // Placeholder recent sessions const PLACEHOLDER_SESSIONS = [ { id: 1, name: 'Bröst & Triceps', date: new Date(Date.now() - 2 * 86400000).toISOString(), duration: 52, exercise_count: 6, volume: 8750, is_pr: true }, { id: 2, name: 'Rygg & Biceps', date: new Date(Date.now() - 4 * 86400000).toISOString(), duration: 48, exercise_count: 7, volume: 11200, is_pr: false }, { id: 3, name: 'Ben & Axlar', date: new Date(Date.now() - 6 * 86400000).toISOString(), duration: 61, exercise_count: 8, volume: 14300, is_pr: false }, ] const PLACEHOLDER_MONTHLY = { stronger_pct: 15, streak: 14, total_volume: 124500, } function Dashboard({ onStartWorkout, onNavigate }) { const { user, logout } = useAuth() const [program, setProgram] = useState(null) const [todayWorkout, setTodayWorkout] = useState(null) const [loading, setLoading] = useState(true) const [currentWeekStart, setCurrentWeekStart] = useState(getWeekStart(new Date())) const [recentSessions, setRecentSessions] = useState(PLACEHOLDER_SESSIONS) const [monthlyStats, setMonthlyStats] = useState(PLACEHOLDER_MONTHLY) useEffect(() => { fetchData() }, []) const fetchData = async () => { try { const res = await fetch(`${API_URL}/programs/1`) const data = await res.json() setProgram(data) const dayOfWeek = new Date().getDay() const adjustedDay = dayOfWeek === 0 ? 7 : dayOfWeek const todayDay = data.days?.find(d => d.day_number === adjustedDay) setTodayWorkout(todayDay || null) setLoading(false) } catch (err) { console.error('Failed to fetch data:', err) setLoading(false) } // Fetch workout history (graceful fallback) try { const histRes = await fetch(`${API_URL}/user/workout-history?user_id=1&limit=5`) if (histRes.ok) { const histData = await histRes.json() if (Array.isArray(histData) && histData.length > 0) { setRecentSessions(histData.slice(0, 4)) // Calculate monthly stats from history const now = new Date() const monthStart = new Date(now.getFullYear(), now.getMonth(), 1) const monthSessions = histData.filter(s => new Date(s.date) >= monthStart) const totalVol = monthSessions.reduce((sum, s) => sum + (s.volume || 0), 0) setMonthlyStats(prev => ({ ...prev, total_volume: totalVol || prev.total_volume })) } } } catch (_) { // use placeholder data } } if (loading) { return (
) } const workoutDays = program?.days?.map(d => d.day_number) || [] return (
{/* TOP HEADER */}
KINETIC
{/* MONTHLY HERO */}
{/* Subtle lime glow top-right */}
{monthlyStats.stronger_pct}%{' '} STARKARE ÄN{' '} FÖRRA MÅNADEN
{/* Streak badge */}
{monthlyStats.streak} DAGARS STREAK
{/* Volume */}
Denna månad {formatVolume(monthlyStats.total_volume)} KG
{/* WEEK CALENDAR */}
{formatWeekRange(currentWeekStart)}
{weekdays.map((name, idx) => { const date = addDays(currentWeekStart, idx) const dayNum = idx + 1 const isToday = isSameDay(date, new Date()) const hasWorkout = workoutDays.includes(dayNum) const workout = program?.days?.find(d => d.day_number === dayNum) return (
hasWorkout && workout && onStartWorkout(workout)} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '0.25rem', padding: '0.5rem 0.25rem', borderRadius: '8px', background: isToday ? 'rgba(202,253,0,0.1)' : 'transparent', border: isToday ? '1px solid rgba(202,253,0,0.25)' : '1px solid transparent', cursor: hasWorkout ? 'pointer' : 'default', }} > {name} {date.getDate()} {hasWorkout && ( )}
) })}
{/* COACH GREETING */}

{getCoachGreeting(user, todayWorkout)}

{/* TODAY'S WORKOUT CARD */}
{todayWorkout ? (
onStartWorkout(todayWorkout)} style={{ background: 'linear-gradient(135deg, #1a1a1a 0%, #131313 100%)', border: '1px solid rgba(202,253,0,0.15)', borderRadius: '12px', padding: '1.25rem', cursor: 'pointer', position: 'relative', overflow: 'hidden', }} > {/* Accent bar */}
Dagens pass

{todayWorkout.name}

{todayWorkout.exercises?.filter(e => e.name).length || 0} övningar ~45 min
) : (

Vilodag

{restDayTips.map((tip, i) => ( {tip.text} ))}
)}
{/* RECENT SESSIONS */}

Senaste pass

{recentSessions.map((session) => (
{session.name} {session.is_pr && ( PR )}
{formatSessionDate(session.date)} · {session.duration} min · {session.exercise_count} övningar
{formatVolume(session.volume)} kg
))}
{/* BOTTOM GLASSMORPHISM NAV */}
) } // Helper functions function getWeekStart(date) { const d = new Date(date) const day = d.getDay() const diff = d.getDate() - day + (day === 0 ? -6 : 1) return new Date(d.setDate(diff)) } function addDays(date, days) { const d = new Date(date) d.setDate(d.getDate() + days) return d } function isSameDay(d1, d2) { return d1.getDate() === d2.getDate() && d1.getMonth() === d2.getMonth() && d1.getFullYear() === d2.getFullYear() } function formatWeekRange(weekStart) { const end = addDays(weekStart, 6) const startMonth = weekStart.toLocaleDateString('sv-SE', { month: 'short' }) const endMonth = end.toLocaleDateString('sv-SE', { month: 'short' }) if (startMonth === endMonth) { return `${weekStart.getDate()} - ${end.getDate()} ${startMonth}` } return `${weekStart.getDate()} ${startMonth} - ${end.getDate()} ${endMonth}` } export default Dashboard