"use client"
import { useState, useMemo } from "react"
import { Sidebar } from "@/components/sidebar"
import { ChatWindow } from "@/components/chat-window"
import { WorkoutTracker } from "@/components/workout-tracker"
import { MealTracker } from "@/components/meal-tracker"
import { FloatingActionButton } from "@/components/floating-action-button"
import { LogModal } from "@/components/log-modal"
import { Header } from "@/components/header"
import { useFitnessData } from "@/hooks/useFitnessData"
export default function FitnessApp() {
const [activeTab, setActiveTab] = useState("Workouts")
const [showLogModal, setShowLogModal] = useState(false)
// Connect to MCP server
const {
context,
progressData,
loading,
error,
isLogging,
isGeneratingPlan,
refreshContext,
logNewEntry,
generateNewPlan,
markExerciseComplete,
clearError,
} = useFitnessData()
const handleLogActivity = () => {
setShowLogModal(true)
}
const handleActivityLogged = async (data: { entryType: 'workout' | 'nutrition' | 'feedback' | 'activity'; entryData: any }) => {
const result = await logNewEntry(data.entryType, data.entryData)
if (result.success) {
setShowLogModal(false)
}
// Error handling is managed by the hook
}
// Memoize props to prevent infinite re-renders
const memoizedLoggedWorkouts = useMemo(() => {
return context?.recentEntries?.workouts?.map(workout => ({
id: workout.id || Date.now().toString(),
name: workout.name || 'Unknown Exercise',
type: workout.type || 'strength',
completed: workout.completed || false,
timestamp: workout.timestamp || new Date().toISOString(),
duration: workout.duration || 0
})) || []
}, [context?.recentEntries?.workouts])
const memoizedLoggedNutrition = useMemo(() => {
return context?.recentEntries?.nutrition?.map(nutrition => ({
id: nutrition.id || Date.now().toString(),
foodItem: nutrition.foodItem || 'Unknown Food',
mealType: nutrition.mealType || 'snack',
calories: nutrition.calories || 0,
protein: nutrition.protein || 0,
carbs: nutrition.carbs || 0,
fat: nutrition.fat || 0,
timestamp: nutrition.timestamp || new Date().toISOString()
})) || []
}, [context?.recentEntries?.nutrition])
const memoizedCurrentPlan = useMemo(() => {
return context?.currentPlan?.workouts || []
}, [context?.currentPlan?.workouts])
if (loading && !context) {
return (
<div className="min-h-screen bg-gradient-to-br from-slate-50 via-blue-50 to-green-50 flex items-center justify-center">
<div className="flex flex-col items-center gap-4">
<div className="w-12 h-12 animate-spin rounded-full border-2 border-lime-200 border-t-lime-500" />
<p className="text-sm text-slate-600">Loading your fitness data...</p>
</div>
</div>
)
}
return (
<div className="min-h-screen bg-gradient-to-br from-slate-50 via-blue-50 to-green-50">
{/* Heartbeat Pattern Background */}
<div className="fixed inset-0 opacity-5 pointer-events-none">
<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="heartbeat" x="0" y="0" width="200" height="40" patternUnits="userSpaceOnUse">
<path
d="M0,20 Q10,10 20,20 T40,20 L60,20 L80,5 L100,35 L120,20 L140,20 Q150,10 160,20 T180,20 L200,20"
stroke="currentColor"
strokeWidth="1"
fill="none"
/>
</pattern>
</defs>
<rect width="100%" height="100%" fill="url(#heartbeat)" />
</svg>
</div>
<div className="relative z-10">
<Header />
{/* Error Message */}
{error && (
<div className="mx-6 mt-6 bg-red-50 border border-red-200 rounded-2xl p-4 flex items-center gap-3">
<div className="flex-1">
<p className="text-sm text-red-800">{error}</p>
{context && context.todaysProgress && (
<p className="text-xs text-red-600 mt-1">
Note: Some data is still loading correctly (showing {context.todaysProgress.workoutMinutes} workout minutes)
</p>
)}
</div>
<button onClick={clearError} className="text-red-500 hover:text-red-700">
✕
</button>
</div>
)}
<div className="flex h-[calc(100vh-80px)]">
{/* Sidebar - Always visible */}
<div className="w-80">
<Sidebar
activeTab={activeTab}
setActiveTab={setActiveTab}
progressData={progressData}
/>
</div>
{/* Main Content */}
<main className="flex-1 flex flex-col lg:flex-row gap-6 p-6 overflow-hidden">
{/* Chat Interface */}
<div className="flex-1 min-w-0">
<ChatWindow />
</div>
{/* Right Panel - Content based on active tab */}
<div className="w-full lg:w-96 space-y-6 overflow-y-auto">
{activeTab === "Workouts" && (
<WorkoutTracker
loggedWorkouts={memoizedLoggedWorkouts}
currentPlan={memoizedCurrentPlan}
/>
)}
{activeTab === "Nutrition" && (
<MealTracker
loggedNutrition={memoizedLoggedNutrition}
/>
)}
{activeTab === "Feedback" && (
<div className="bg-white/80 backdrop-blur-sm rounded-3xl shadow-lg border border-white/20 p-6">
<h3 className="text-lg font-bold text-slate-800 mb-4">Feedback & Progress</h3>
<div className="space-y-4">
<div className="bg-gradient-to-r from-green-50 to-emerald-50 rounded-2xl p-4 border border-green-200/50">
<h4 className="font-semibold text-green-800 mb-2">Recent Achievements</h4>
<ul className="space-y-2 text-sm text-green-700">
{context?.recentEntries.feedback
.filter(f => f.type === 'progress')
.slice(0, 3)
.map(feedback => (
<li key={feedback.id}>• {feedback.notes}</li>
)) || [
<li key="1">• Completed 3 strength training sessions this week</li>,
<li key="2">• Maintained calorie goal for 5 days straight</li>,
<li key="3">• Increased workout duration by 15 minutes</li>
]}
</ul>
</div>
<div className="bg-gradient-to-r from-blue-50 to-indigo-50 rounded-2xl p-4 border border-blue-200/50">
<h4 className="font-semibold text-blue-800 mb-2">Recommendations</h4>
<ul className="space-y-2 text-sm text-blue-700">
{context?.currentPlan?.recommendations?.slice(0, 3).map((rec, index) => (
<li key={index}>• {rec}</li>
)) || [
<li key="1">• Add more cardio sessions to improve endurance</li>,
<li key="2">• Increase protein intake by 20g daily</li>,
<li key="3">• Focus on proper form during strength exercises</li>
]}
</ul>
</div>
</div>
</div>
)}
{/* Mobile Progress Cards - Only show on small screens */}
<div className="lg:hidden">
<div className="bg-white/80 backdrop-blur-sm rounded-3xl p-6 shadow-lg border border-white/20">
<h3 className="text-lg font-semibold text-slate-800 mb-4">Today's Progress</h3>
<div className="grid grid-cols-3 gap-4">
<div className="text-center">
<div className="text-2xl font-bold text-lime-600">{progressData.workoutMinutes}</div>
<div className="text-sm text-slate-600">Minutes</div>
</div>
<div className="text-center">
<div className="text-2xl font-bold text-orange-500">{progressData.caloriesConsumed}</div>
<div className="text-sm text-slate-600">Calories</div>
</div>
<div className="text-center">
<div className="text-2xl font-bold text-blue-500">{progressData.stepsTaken}</div>
<div className="text-sm text-slate-600">Steps</div>
</div>
</div>
</div>
</div>
</div>
</main>
</div>
{/* Floating Action Button */}
<FloatingActionButton onClick={handleLogActivity} />
{/* Log Modal */}
<LogModal
isOpen={showLogModal}
onClose={() => setShowLogModal(false)}
onActivityLogged={handleActivityLogged}
/>
</div>
</div>
)
}