import { View, Text, StyleSheet, TouchableOpacity, Image, Alert, ScrollView, ActivityIndicator, } from "react-native"; import { useUser, useClerk, useAuth } from "@clerk/clerk-expo"; import { useRouter } from "expo-router"; import { Ionicons } from "@expo/vector-icons"; import { useState, useEffect } from "react"; import { useTheme } from "../../contexts/ThemeContext"; import { MinimalCard } from "../../components/MinimalCard"; import { ListItem } from "../../components/ListItem"; import { MinimalButton } from "../../components/MinimalButton"; import { Badge } from "../../components/Badge"; import { IconContainer } from "../../components/IconContainer"; import { fitnessProfileApi, FitnessProfile } from "../../api/fitnessProfile"; import { gymsApi, type Gym } from "../../api/gyms"; import { useMembership } from "../../hooks/useMembership"; import log from "../../utils/logger"; export default function ProfileScreen() { const { user } = useUser(); const { signOut } = useClerk(); const router = useRouter(); const { colors, typography, theme: activeTheme, setTheme } = useTheme(); const { getToken } = useAuth(); const { membershipType } = useMembership(); const [gyms, setGyms] = useState([]); const [gymsLoading, setGymsLoading] = useState(false); const [selectedGymId, setSelectedGymId] = useState(null); const [currentGymId, setCurrentGymId] = useState(null); const [currentGymName, setCurrentGymName] = useState(null); const [showGymDropdown, setShowGymDropdown] = useState(false); const [fitnessProfile, setFitnessProfile] = useState( null, ); const [profileLoading, setProfileLoading] = useState(false); useEffect(() => { const gid = ((user?.publicMetadata as any)?.gymId as string | undefined) ?? null; setCurrentGymId(gid ?? null); if (gid && gyms.length > 0) { const g = gyms.find((x) => x.id === gid); setCurrentGymName(g?.name ?? null); if (selectedGymId === null) setSelectedGymId(gid); } }, [user?.publicMetadata, gyms]); useEffect(() => { loadGyms(); loadFitnessProfile(); }, []); const loadFitnessProfile = async () => { try { setProfileLoading(true); const token = await getToken(); if (!token) return; const profile = await fitnessProfileApi.getFitnessProfile(token); setFitnessProfile(profile); } catch (error) { log.error("Failed to load fitness profile", error); } finally { setProfileLoading(false); } }; const loadGyms = async () => { try { setGymsLoading(true); const token = await getToken(); const list = await gymsApi.getGyms(token); setGyms(list); const gid = currentGymId ?? ((user?.publicMetadata as any)?.gymId as string | undefined) ?? null; if (gid) { const g = list.find((x) => x.id === gid); setCurrentGymId(gid); setCurrentGymName(g?.name ?? null); if (selectedGymId === null) setSelectedGymId(gid); } } catch (err) { log.error("Failed to fetch gyms", err); setGyms([]); } finally { setGymsLoading(false); } }; const handleApplyGym = async () => { try { const token = await getToken(); await gymsApi.updateUserGym(selectedGymId, token); setCurrentGymId(selectedGymId); setCurrentGymName( selectedGymId ? (gyms.find((g) => g.id === selectedGymId)?.name ?? null) : null, ); try { await (user as any)?.reload?.(); } catch (e) { log.debug("Failed to reload user after gym update", { error: e }); } Alert.alert( "Success", selectedGymId ? "Gym selected successfully" : "Proceeding without gym", ); } catch (err) { log.error("Failed to update gym selection", err); Alert.alert("Error", "Failed to update gym selection"); } }; const handleSignOut = async () => { try { await signOut(); } catch (err) { log.error("Failed to sign out", err); } }; const confirmSignOut = () => { Alert.alert("Sign Out", "Are you sure you want to sign out?", [ { text: "Cancel", style: "cancel" }, { text: "Sign Out", style: "destructive", onPress: handleSignOut }, ]); }; const handleThemeChange = () => { Alert.alert("Choose Theme", "Select your preferred theme", [ { text: "Light", onPress: () => setTheme("light"), }, { text: "Dark", onPress: () => setTheme("dark"), }, { text: "System", onPress: () => setTheme("system"), }, { text: "Cancel", style: "cancel" }, ]); }; const getThemeLabel = () => { if (activeTheme === "light") return "Light"; if (activeTheme === "dark") return "Dark"; return "System"; }; return ( {/* Header Card */} {user?.imageUrl ? ( ) : ( )} {user?.fullName || "User"} {user?.primaryEmailAddress?.emailAddress} {/* Theme Settings */} Appearance } rightElement={ } onPress={handleThemeChange} /> {/* Account Settings */} Account } rightElement={ } onPress={() => router.push("/personal-details")} /> {/* Fitness Profile Card */} router.push("/fitness-profile")} activeOpacity={0.85} > Fitness Profile {fitnessProfile ? "Tap to edit" : "Set up your profile"} {profileLoading ? ( ) : fitnessProfile ? ( {fitnessProfile.height || "-"} Height (cm) {fitnessProfile.weight || "-"} Weight (kg) {fitnessProfile.age || "-"} Age ) : ( Complete your fitness profile to get personalized recommendations router.push("/fitness-profile")} /> )} } rightElement={ } /> {/* Gym Selection */} Gym Selection setShowGymDropdown(!showGymDropdown)} activeOpacity={0.85} > Current Gym {currentGymName || "No gym selected"} {showGymDropdown && ( {gymsLoading ? ( ) : ( <> { setSelectedGymId(null); setShowGymDropdown(false); }} > No Gym {selectedGymId === null && ( )} {gyms.map((gym) => ( { setSelectedGymId(gym.id); setShowGymDropdown(false); }} > {gym.name} {gym.location && ( {gym.location} )} {selectedGymId === gym.id && ( )} ))} {selectedGymId !== currentGymId && ( )} )} )} {/* Support */} Support } rightElement={ } /> } rightElement={ } /> {/* Sign Out */} Version 1.0.0 ); } const styles = StyleSheet.create({ container: { flex: 1, }, content: { padding: 20, paddingTop: 60, paddingBottom: 100, }, profileCard: { alignItems: "center", paddingVertical: 32, marginBottom: 24, }, avatarContainer: { position: "relative", }, avatar: { width: 100, height: 100, borderRadius: 50, }, placeholderAvatar: { width: 100, height: 100, borderRadius: 50, justifyContent: "center", alignItems: "center", }, section: { marginBottom: 24, }, sectionHeader: { flexDirection: "row", justifyContent: "space-between", alignItems: "center", marginBottom: 12, }, divider: { height: 1, marginLeft: 52, }, currentGym: { marginBottom: 16, paddingBottom: 16, borderBottomWidth: 1, borderBottomColor: "rgba(0, 0, 0, 0.05)", }, loadingContainer: { paddingVertical: 20, alignItems: "center", }, gymScroll: { marginHorizontal: -16, }, gymScrollContent: { paddingHorizontal: 16, gap: 8, }, gymChip: { paddingHorizontal: 16, paddingVertical: 10, borderRadius: 20, borderWidth: 1.5, marginRight: 8, }, dropdownCard: { padding: 16, }, dropdownHeader: { flexDirection: "row", justifyContent: "space-between", alignItems: "center", }, dropdownIcon: { width: 36, height: 36, borderRadius: 10, justifyContent: "center", alignItems: "center", }, dropdownOptions: { marginTop: 8, padding: 8, }, dropdownOption: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", paddingVertical: 14, paddingHorizontal: 16, borderRadius: 12, marginBottom: 4, }, fitnessProfileCard: { padding: 16, }, fitnessProfileHeader: { flexDirection: "row", alignItems: "center", }, fitnessProfileIcon: { width: 48, height: 48, borderRadius: 14, justifyContent: "center", alignItems: "center", }, editButton: { width: 32, height: 32, borderRadius: 8, justifyContent: "center", alignItems: "center", }, profileLoading: { paddingVertical: 20, alignItems: "center", }, fitnessProfileStats: { flexDirection: "row", justifyContent: "space-around", marginTop: 20, paddingTop: 16, borderTopWidth: 1, }, profileStat: { alignItems: "center", flex: 1, }, profileStatDivider: { width: 1, height: 40, }, noProfile: { marginTop: 16, paddingTop: 16, borderTopWidth: 1, alignItems: "center", }, });