/** * Health Profile Card Component * * Shows profile status using the /api/profile/me endpoint: * - First-time user (exists=false or is_completed=false): "Complete your health profile" CTA * - In-progress: Resume wizard prompt * - Completed (is_completed=true): Success state with "Edit Profile" button -> Settings * * Once profile is completed, user is NEVER asked to fill again. */ import { useState, useEffect, useCallback } from 'react'; import { useNavigate } from 'react-router-dom'; import { motion } from 'framer-motion'; import { CheckCircle2, ChevronRight, Activity, Heart, Loader2, Settings } from 'lucide-react'; import { fetchProfileMe, ProfileMeResponse, fetchFullProfile, FullProfile } from '../../services/profileApi'; import './HealthProfileCard.css'; interface HealthProfileCardProps { onProfileUpdated?: () => void; } export default function HealthProfileCard({ onProfileUpdated: _onProfileUpdated }: HealthProfileCardProps) { const navigate = useNavigate(); const [loading, setLoading] = useState(true); const [profileStatus, setProfileStatus] = useState(null); const [fullProfile, setFullProfile] = useState(null); const loadProfile = useCallback(async () => { setLoading(true); try { // Use the simpler /me endpoint for status check const status = await fetchProfileMe(); setProfileStatus(status); // If profile exists and is complete, also fetch full profile for display if (status.exists && status.is_completed) { const full = await fetchFullProfile(); setFullProfile(full); } } catch (error) { console.error('Error loading profile:', error); } finally { setLoading(false); } }, []); useEffect(() => { loadProfile(); }, [loadProfile]); const handleGetStarted = () => { navigate('/health-profile'); }; const handleEditProfile = () => { // Navigate to Settings page for editing completed profile navigate('/settings'); }; // Determine profile state from /me response const exists = profileStatus?.exists || false; const isCompleted = profileStatus?.is_completed || false; const completionScore = profileStatus?.completion?.score || 0; // Check if in progress (has profile but not completed, and has made some progress) const wizardStep = profileStatus?.profile?.wizard_current_step || 1; const inProgress = exists && !isCompleted && wizardStep > 1; // Loading state if (loading) { return (
Loading profile...
); } // COMPLETED - Show success state with Edit button (routes to Settings) if (isCompleted) { const profile = fullProfile?.profile || profileStatus?.profile; return (

Health Profile Complete ✅

Profile saved

{profile?.full_name && (
Name {profile.full_name}
)} {profile?.sex_at_birth && (
Sex {profile.sex_at_birth}
)} {(profile?.date_of_birth || profile?.age_years) && (
Age {profile?.date_of_birth ? calculateAge(profile.date_of_birth as string) : profile?.age_years }
)} {profile?.height_cm && profile?.weight_kg && (
BMI {(profile.weight_kg / Math.pow(profile.height_cm / 100, 2)).toFixed(1)}
)}
); } // IN-PROGRESS - Show resume prompt if (inProgress) { return (

Continue your health profile

You're {completionScore.toFixed(0)}% complete

); } // NOT STARTED - Show CTA return (

Complete your health profile

Get personalized health insights and recommendations

  • Personalized health recommendations
  • Better analysis of your reports
  • Track health trends over time
); } function calculateAge(dateOfBirth: string): number { const dob = new Date(dateOfBirth); const today = new Date(); let age = today.getFullYear() - dob.getFullYear(); const monthDiff = today.getMonth() - dob.getMonth(); if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < dob.getDate())) { age--; } return age; }