import React, { useState, useCallback } from "react"; import { View, Text, StyleSheet, ScrollView, RefreshControl, TouchableOpacity, ActivityIndicator, Alert, } from "react-native"; import { Ionicons } from "@expo/vector-icons"; import { useUser } from "@clerk/clerk-expo"; import { useFocusEffect } from "expo-router"; import { useTheme } from "../../contexts/ThemeContext"; import { MinimalCard } from "../../components/MinimalCard"; import { SectionHeader } from "../../components/SectionHeader"; import { MinimalButton } from "../../components/MinimalButton"; import { Badge } from "../../components/Badge"; import { IconContainer } from "../../components/IconContainer"; import { useRecommendations } from "../../contexts/RecommendationsContext"; import { useNotifications } from "../../contexts/NotificationsContext"; import { NotificationsModal } from "../../components/NotificationsModal"; import type { Recommendation } from "../../api/recommendations"; import log from "../../utils/logger"; export default function RecommendationsScreen() { const { user } = useUser(); const { colors, typography } = useTheme(); const { recommendations: allRecommendations, loading, refetchRecommendations, generateNewRecommendation, } = useRecommendations(); const { unreadCount, refetchNotifications } = useNotifications(); const [generating, setGenerating] = useState(false); const [refreshing, setRefreshing] = useState(false); const [notificationsVisible, setNotificationsVisible] = useState(false); const handleOpenNotifications = () => { log.debug("Opening notifications modal", { unreadCount }); setNotificationsVisible(true); }; const handleCloseNotifications = () => { log.debug("Closing notifications modal"); setNotificationsVisible(false); }; // Filter to show only approved recommendations const recommendations = allRecommendations.filter( (rec) => rec.status === "approved", ); useFocusEffect( useCallback(() => { refetchRecommendations(); refetchNotifications(); }, [refetchRecommendations, refetchNotifications]), ); const onRefresh = async () => { setRefreshing(true); await Promise.all([refetchRecommendations(), refetchNotifications()]); setRefreshing(false); }; const handleGenerateRecommendation = async () => { if (!user?.id) return; Alert.alert( "Generate AI Recommendation", "Generate a personalized fitness and nutrition plan based on your profile and goals?", [ { text: "Cancel", style: "cancel" }, { text: "Generate", onPress: async () => { try { setGenerating(true); await generateNewRecommendation({ userId: user.id, modelProvider: "deepseek", useExternalModel: true, }); Alert.alert( "Success", "AI recommendation generated! It will appear here once approved by your trainer.", ); await refetchRecommendations(); } catch (error) { log.error("Failed to generate recommendation", error); Alert.alert( "Error", "Failed to generate recommendation. Please try again.", ); } finally { setGenerating(false); } }, }, ], ); }; if (loading && recommendations.length === 0) { return ( ); } return ( } > {/* Header */} Recommendations {recommendations.length === 0 ? "Let's create your perfect plan!" : `${recommendations.length} plan${recommendations.length !== 1 ? "s" : ""} ready for you!`} {unreadCount > 0 && ( {unreadCount} )} {/* Generate Button */} {/* Recommendations List */} 0 ? `${recommendations.length} active plan${recommendations.length !== 1 ? "s" : ""}` : undefined } /> {recommendations.length === 0 ? ( 🤖 No Recommendations Yet Tap "Generate New Plan" to get personalized AI-powered fitness and nutrition recommendations! 🎯 ) : ( {recommendations.map((recommendation) => ( ))} )} {/* Bottom Spacer */} ); } interface RecommendationCardProps { recommendation: Recommendation; } function RecommendationCard({ recommendation }: RecommendationCardProps) { const { colors, typography } = useTheme(); const [expanded, setExpanded] = useState(false); return ( {/* Header */} setExpanded(!expanded)} activeOpacity={0.7} style={styles.cardHeader} > ✨ AI Fitness Plan {new Date(recommendation.generatedAt).toLocaleDateString()} {/* Summary */} {recommendation.recommendationText} {/* Expanded Content */} {expanded && ( {/* Activity Plan */} 💪 Activity Plan {recommendation.activityPlan} {/* Diet Plan */} 🍽️ Diet Plan {recommendation.dietPlan} )} ); } const styles = StyleSheet.create({ container: { flex: 1, }, centered: { flex: 1, justifyContent: "center", alignItems: "center", }, scrollContent: { paddingBottom: 20, }, header: { flexDirection: "row", justifyContent: "space-between", alignItems: "flex-start", paddingHorizontal: 24, paddingTop: 60, paddingBottom: 24, }, notificationButton: { position: "relative", }, notificationBadge: { position: "absolute", top: -4, right: -4, minWidth: 18, height: 18, borderRadius: 9, justifyContent: "center", alignItems: "center", paddingHorizontal: 4, }, notificationBadgeText: { color: "#fff", fontSize: 11, fontWeight: "700", }, section: { paddingHorizontal: 24, marginBottom: 24, }, emptyState: { alignItems: "center", paddingVertical: 40, paddingHorizontal: 20, }, recommendationsList: { gap: 12, }, cardHeader: { flexDirection: "row", justifyContent: "space-between", alignItems: "center", }, cardHeaderLeft: { flexDirection: "row", alignItems: "center", flex: 1, }, cardSummary: { marginTop: 12, paddingTop: 12, borderTopWidth: 1, borderTopColor: "rgba(0, 0, 0, 0.05)", }, expandedContent: { marginTop: 16, gap: 12, }, planSection: { padding: 16, borderRadius: 16, }, planHeader: { flexDirection: "row", alignItems: "center", }, });