import React, { useState, useEffect } from 'react'; import { View, Text, Image, TouchableOpacity, ScrollView, SafeAreaView, ActivityIndicator, TextInput, KeyboardAvoidingView, Platform, Alert } from 'react-native'; import { Feather, FontAwesome } from '@expo/vector-icons'; import { useLocalSearchParams, router } from 'expo-router'; import { useAuth } from '../../context/auth-context'; import { supabase } from '../../services/supabase'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { getFoods, getIngredients, getNutrients } from '../../services/data/foods'; import { createLike, deleteLike, createSave, deleteSave, getComments, createComment, getLikesCount, getSavesCount, getCommentsCount, checkUserLiked, checkUserSaved } from '../../services/data/forum'; import { getProfile } from '../../services/data/profile'; import { Food, Ingredient, Nutrient, FoodComment, Profile } from '../../types/index'; import { queryKeys, useLikeMutation, useSaveMutation } from '../../hooks/use-foods'; export default function PostDetailScreen() { const { id } = useLocalSearchParams(); const foodId = typeof id === 'string' ? id : ''; const queryClient = useQueryClient(); console.log('Post detail screen - Food ID:', foodId); const { isAuthenticated } = useAuth(); const [currentUserId, setCurrentUserId] = useState(null); const [commentText, setCommentText] = useState(''); const [submittingComment, setSubmittingComment] = useState(false); const [showReviews, setShowReviews] = useState(true); // Get current user ID from Supabase session useEffect(() => { async function getCurrentUser() { if (isAuthenticated) { const { data } = await supabase.auth.getSession(); const userId = data.session?.user?.id; console.log('Current user ID:', userId); setCurrentUserId(userId || null); } else { setCurrentUserId(null); } } getCurrentUser(); }, [isAuthenticated]); // Fetch food details const { data: food, isLoading: isLoadingFood, error: foodError } = useQuery({ queryKey: queryKeys.foodDetails(foodId), queryFn: async () => { const { data, error } = await supabase .from('foods') .select('*') .eq('id', foodId) .single(); if (error) throw error; return { ...data, description: data.description || '', ingredient_count: data.ingredient_count ?? 0, calories: data.calories ?? 0, image_url: data.image_url || '', }; }, enabled: !!foodId, }); // Fetch food creator const { data: foodCreator, isLoading: isLoadingCreator } = useQuery({ queryKey: ['food-creator', food?.created_by], queryFn: async () => { if (!food?.created_by) return null; const { data, error } = await getProfile(food.created_by); if (error) throw error; return data; }, enabled: !!food?.created_by, }); // Fetch food stats const { data: stats = { likes: 0, saves: 0, comments: 0 }, isLoading: isLoadingStats, refetch: refetchStats } = useQuery({ queryKey: ['food-stats', foodId], queryFn: async () => { const [likesRes, savesRes, commentsRes] = await Promise.all([ getLikesCount(foodId), getSavesCount(foodId), getCommentsCount(foodId) ]); return { likes: likesRes.count || 0, saves: savesRes.count || 0, comments: commentsRes.count || 0 }; }, enabled: !!foodId, }); // Fetch user interactions const { data: interactions = { liked: false, saved: false }, isLoading: isLoadingInteractions, refetch: refetchInteractions } = useQuery({ queryKey: ['user-interactions', foodId, currentUserId], queryFn: async () => { if (!currentUserId) return { liked: false, saved: false }; const [likedRes, savedRes] = await Promise.all([ checkUserLiked(foodId, currentUserId), checkUserSaved(foodId, currentUserId) ]); return { liked: !!likedRes.data, saved: !!savedRes.data }; }, enabled: !!foodId && !!currentUserId, }); // Fetch comments const { data: comments = [], isLoading: isLoadingComments, refetch: refetchComments } = useQuery({ queryKey: queryKeys.foodComments(foodId), queryFn: async () => { const { data, error } = await getComments(foodId); if (error) throw error; return data || []; }, enabled: !!foodId, }); // Set up mutations const likeMutation = useLikeMutation(); const saveMutation = useSaveMutation(); const commentMutation = useMutation({ mutationFn: async ({ foodId, userId, content }: { foodId: string, userId: string, content: string }) => { return createComment(foodId, userId, content); }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: queryKeys.foodComments(foodId) }); queryClient.invalidateQueries({ queryKey: ['food-stats', foodId] }); setCommentText(''); }, }); // Set up real-time subscription for comments useEffect(() => { if (!foodId) return; console.log(`Setting up real-time subscription for comments on food_id: ${foodId}`); const subscription = supabase .channel(`food_comments:${foodId}`) .on('postgres_changes', { event: '*', schema: 'public', table: 'food_comments', filter: `food_id=eq.${foodId}` }, () => { console.log('Comment change detected, refreshing comments'); refetchComments(); refetchStats(); }) .subscribe(); return () => { supabase.removeChannel(subscription); }; }, [foodId, refetchComments, refetchStats]); // Set up real-time subscription for likes and saves useEffect(() => { if (!foodId) return; const likesSubscription = supabase .channel(`food_likes:${foodId}`) .on('postgres_changes', { event: '*', schema: 'public', table: 'food_likes', filter: `food_id=eq.${foodId}` }, () => { console.log('Like change detected, refreshing stats and interactions'); refetchStats(); refetchInteractions(); }) .subscribe(); const savesSubscription = supabase .channel(`food_saves:${foodId}`) .on('postgres_changes', { event: '*', schema: 'public', table: 'food_saves', filter: `food_id=eq.${foodId}` }, () => { console.log('Save change detected, refreshing stats and interactions'); refetchStats(); refetchInteractions(); }) .subscribe(); return () => { supabase.removeChannel(likesSubscription); supabase.removeChannel(savesSubscription); }; }, [foodId, refetchStats, refetchInteractions]); const handleLike = async () => { if (!isAuthenticated || !currentUserId || !food) { Alert.alert('Authentication Required', 'Please log in to like posts.'); return; } try { likeMutation.mutate({ foodId, userId: currentUserId, isLiked: interactions.liked }); } catch (error) { console.error('Error toggling like:', error); Alert.alert('Error', 'Failed to update like. Please try again.'); } }; const handleSave = async () => { if (!isAuthenticated || !currentUserId || !food) { Alert.alert('Authentication Required', 'Please log in to save posts.'); return; } try { saveMutation.mutate({ foodId, userId: currentUserId, isSaved: interactions.saved }); } catch (error) { console.error('Error toggling save:', error); Alert.alert('Error', 'Failed to update save. Please try again.'); } }; const handleSubmitComment = async () => { if (!isAuthenticated || !currentUserId || !foodId || !commentText.trim()) { if (!isAuthenticated || !currentUserId) { Alert.alert('Authentication Required', 'Please log in to comment.'); } return; } setSubmittingComment(true); try { await commentMutation.mutateAsync({ foodId, userId: currentUserId, content: commentText.trim() }); } catch (error) { console.error('Error submitting comment:', error); Alert.alert('Error', 'Failed to submit comment. Please try again.'); } finally { setSubmittingComment(false); } }; const isLoading = isLoadingFood || isLoadingCreator || isLoadingStats || isLoadingInteractions || isLoadingComments; if (isLoading) { return ( ); } if (foodError || !food) { return ( Post not found router.back()} > Go Back ); } return ( {/* Header */} router.back()} > Post {/* User info and rating */} {foodCreator?.avatar_url ? ( ) : ( {foodCreator?.username?.charAt(0).toUpperCase() || food.created_by?.charAt(0).toUpperCase() || '?'} )} {foodCreator?.username || foodCreator?.full_name || 'Chef'} 4.2 {/* Food image */} {/* Food title and description */} {food.name} {food.description} {new Date(food.created_at).toLocaleDateString()} - {new Date(food.created_at).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })} {/* Interaction buttons */} {stats.likes} {stats.comments} {/* Reviews section */} setShowReviews(!showReviews)} > Review {showReviews && ( {comments.length > 0 ? ( comments.map((comment) => ( {comment.user?.avatar_url ? ( ) : ( {comment.user?.username?.charAt(0).toUpperCase() || comment.user_id?.charAt(0).toUpperCase() || '?'} )} {comment.user?.username || comment.user?.full_name || 'User'} {new Date(comment.created_at).toLocaleDateString()} {comment.content} )) ) : ( No reviews yet. Be the first to comment! )} )} {/* Bottom spacing */} {/* Comment input */} {!isAuthenticated && ( Please log in to comment )} ); }