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