"use client" import { useAuth } from "@/context/auth-context" import { getFoods } from "@/services/data/foods" import { getBookmarkedPosts } from "@/services/data/bookmarks" import { getLikedPosts } from "@/services/data/likes" import { getProfile, updateProfile } from "@/services/data/profile" import { supabase } from "@/services/supabase" import { useIsFocused, useNavigation } from "@react-navigation/native" import { useQuery, useQueryClient } from "@tanstack/react-query" import * as ImagePicker from "expo-image-picker" import { useEffect, useState } from "react" import { ActivityIndicator, Image, Modal, Pressable, ScrollView, Text, TextInput, TouchableOpacity, View, } from "react-native" import { SafeAreaView } from "react-native-safe-area-context" import uuid from "react-native-uuid" // Define the Food type based on your database structure type Food = { id: number name: string description: string time_to_cook_minutes: number skill_level: string ingredient_count: number calories: number image_url: string is_shared: boolean created_by: string created_at: string } export default function ProfileScreen() { const [activeTab, setActiveTab] = useState("My Recipes") const { isAuthenticated } = useAuth() const isFocused = useIsFocused() const queryClient = useQueryClient() const navigation = useNavigation() const { data: userData, isLoading: isUserLoading, error: userError, } = useQuery({ queryKey: ["auth-user"], queryFn: async () => { const { data, error } = await supabase.auth.getUser() if (error) throw error return data?.user }, enabled: isAuthenticated, staleTime: 0, }) const userId = userData?.id const { data: profileData, error, isLoading, } = useQuery({ queryKey: ["profile", userId], queryFn: async () => { if (!userId) throw new Error("No user id") return getProfile(userId) }, enabled: !!userId, staleTime: 0, subscribed: isFocused, }) // My Recipes Query const { data: myRecipesData, isLoading: isMyRecipesLoading, error: myRecipesError, refetch: refetchMyRecipes, } = useQuery({ queryKey: ["my-recipes", userId], queryFn: async () => { if (!userId) throw new Error("No user id") return getFoods(userId) }, enabled: !!userId, staleTime: 1000 * 60, // 1 minute }) // Likes Query const { data: likesData, isLoading: isLikesLoading, error: likesError, refetch: refetchLikes, } = useQuery({ queryKey: ["liked-posts", userId], queryFn: async () => { if (!userId) throw new Error("No user id") return getLikedPosts(userId) }, enabled: !!userId, staleTime: 1000 * 60, // 1 minute }) // Bookmarks Query const { data: bookmarksData, isLoading: isBookmarksLoading, error: bookmarksError, refetch: refetchBookmarks, } = useQuery({ queryKey: ["bookmarked-posts", userId], queryFn: async () => { if (!userId) throw new Error("No user id") return getBookmarkedPosts(userId) }, enabled: !!userId, staleTime: 1000 * 60, // 1 minute }) // Navigate to post detail const handleFoodPress = (foodId: number) => { // @ts-ignore - Navigation typing might be different in your app navigation.navigate("post-detail", { id: foodId }) } // Refetch data when tab changes const handleTabChange = (tab: string) => { setActiveTab(tab) // Refetch data for the selected tab if (tab === "My Recipes") { refetchMyRecipes() } else if (tab === "Likes") { refetchLikes() } else if (tab === "Bookmarks") { refetchBookmarks() } } // Refetch all data when the screen comes into focus useEffect(() => { if (isFocused && userId) { refetchMyRecipes() refetchLikes() refetchBookmarks() } }, [isFocused, userId]) const [modalVisible, setModalVisible] = useState(false) const [editUsername, setEditUsername] = useState("") const [editImage, setEditImage] = useState(null) const [editLoading, setEditLoading] = useState(false) const [editError, setEditError] = useState(null) const pickImage = async () => { const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync() if (status !== "granted") { setEditError("Permission to access media library is required.") return } const result = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ["images"], quality: 0.7, allowsEditing: true, }) if (!result.canceled) { setEditImage(result.assets[0].uri) } } const uploadImageToSupabase = async (uri: string): Promise => { const fileName = `${userId}/${uuid.v4()}.jpg` const response = await fetch(uri) const blob = await response.blob() const { error: uploadError } = await supabase.storage.from("avatars").upload(fileName, blob, { contentType: "image/jpeg", upsert: true, }) if (uploadError) throw uploadError const { data } = supabase.storage.from("avatars").getPublicUrl(fileName) return data.publicUrl } const handleSaveProfile = async () => { setEditLoading(true) setEditError(null) try { if (!editUsername.trim()) throw new Error("Username cannot be empty") let avatarUrl = profileData?.data?.avatar_url ?? null if (editImage && editImage !== avatarUrl) { avatarUrl = await uploadImageToSupabase(editImage) } const { error: updateError } = await updateProfile(userId!, editUsername.trim(), avatarUrl) if (updateError) throw updateError setModalVisible(false) await queryClient.invalidateQueries({ queryKey: ["profile", userId] }) } catch (err: any) { setEditError(err.message || "Failed to update profile") } finally { setEditLoading(false) } } // Get the active data based on the current tab const getActiveData = () => { switch (activeTab) { case "My Recipes": return { data: myRecipesData, isLoading: isMyRecipesLoading, error: myRecipesError } case "Likes": return { data: likesData, isLoading: isLikesLoading, error: likesError } case "Bookmarks": return { data: bookmarksData, isLoading: isBookmarksLoading, error: bookmarksError } default: return { data: myRecipesData, isLoading: isMyRecipesLoading, error: myRecipesError } } } const { data: activeData, isLoading: isActiveLoading, error: activeError } = getActiveData() if (isUserLoading) { return ( ) } if (userError) { return ( {userError.message || "Failed to load user data."} ) } return ( {isLoading ? ( ) : error ? ( {error.message || error.toString()} ) : ( {profileData?.data?.username ?? "-"} )} { setEditUsername(profileData?.data?.username ?? "") setEditImage(profileData?.data?.avatar_url ?? null) setEditError(null) setModalVisible(true) }} > Edit {/* Edit Modal */} setModalVisible(false)}> Edit Profile Change Photo Username {editError && {editError}} setModalVisible(false)} disabled={editLoading} > Cancel {editLoading ? ( ) : ( Save )} {/* Tab Navigation */} {["My Recipes", "Likes", "Bookmarks"].map((tab) => ( handleTabChange(tab)} > {tab} ))} {/* Tab Content */} {isActiveLoading ? ( ) : activeError ? ( {activeError.message || "Failed to load data"} ) : !activeData?.data?.length ? ( No items found ) : ( {activeData.data.map((item: Food) => ( handleFoodPress(item.id)} activeOpacity={0.7} > {item.name} ))} )} ) }