import React, { useState, useCallback } from "react"; import { View, Text, StyleSheet, ScrollView, RefreshControl, TouchableOpacity, ActivityIndicator, Alert, } from "react-native"; import { LinearGradient } from "expo-linear-gradient"; import { Ionicons } from "@expo/vector-icons"; import { useUser } from "@clerk/clerk-expo"; import { useFocusEffect } from "expo-router"; import { theme } from "../../styles/theme"; import { useRecommendations } from "../../contexts/RecommendationsContext"; import type { Recommendation } from "../../api/recommendations"; import log from "../../utils/logger"; export default function RecommendationsScreen() { const { user } = useUser(); const { recommendations: allRecommendations, loading, refetchRecommendations, generateNewRecommendation, } = useRecommendations(); const [generating, setGenerating] = useState(false); const [refreshing, setRefreshing] = useState(false); // Filter to show only approved recommendations for regular users const recommendations = allRecommendations.filter( (rec) => rec.status === "approved", ); useFocusEffect( useCallback(() => { refetchRecommendations(); }, [refetchRecommendations]), ); const onRefresh = async () => { setRefreshing(true); await refetchRecommendations(); 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: "openai", 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 */} AI Recommendations Personalized fitness & nutrition plans {/* Generate Button */} {generating ? ( ) : ( <> Generate New Plan )} {/* Recommendations List */} {recommendations.length === 0 ? ( No Recommendations Yet Tap "Generate New Plan" to get personalized AI-powered fitness and nutrition recommendations based on your profile and goals. ) : ( recommendations.map((recommendation) => ( )) )} ); } interface RecommendationCardProps { recommendation: Recommendation; } function RecommendationCard({ recommendation }: RecommendationCardProps) { const [expanded, setExpanded] = useState(false); return ( {/* Header */} AI Fitness Plan {new Date(recommendation.generatedAt).toLocaleDateString()} setExpanded(!expanded)}> {/* 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, backgroundColor: theme.colors.background, }, centered: { flex: 1, justifyContent: "center", alignItems: "center", backgroundColor: theme.colors.background, }, scrollContent: { paddingBottom: 100, }, header: { flexDirection: "row", justifyContent: "space-between", alignItems: "center", padding: 24, paddingTop: 60, paddingBottom: 24, marginBottom: 20, borderBottomLeftRadius: theme.borderRadius.xl, borderBottomRightRadius: theme.borderRadius.xl, }, headerTitle: { fontSize: theme.typography.fontSize["3xl"], fontWeight: theme.typography.fontWeight.bold, color: theme.colors.white, }, headerSubtitle: { fontSize: theme.typography.fontSize.base, color: "rgba(255, 255, 255, 0.9)", marginTop: 4, }, iconContainer: { backgroundColor: "rgba(255, 255, 255, 0.2)", width: 64, height: 64, borderRadius: 32, justifyContent: "center", alignItems: "center", }, actionContainer: { paddingHorizontal: 20, marginBottom: 20, }, generateButton: { flexDirection: "row", alignItems: "center", justifyContent: "center", paddingVertical: 16, paddingHorizontal: 24, borderRadius: theme.borderRadius.xl, }, generateButtonText: { fontSize: theme.typography.fontSize.lg, fontWeight: theme.typography.fontWeight.bold, color: theme.colors.white, }, section: { paddingHorizontal: 20, }, emptyState: { paddingVertical: 40, }, emptyCard: { borderRadius: theme.borderRadius["2xl"], padding: 32, alignItems: "center", }, emptyTitle: { fontSize: theme.typography.fontSize.xl, fontWeight: theme.typography.fontWeight.bold, color: theme.colors.gray700, marginTop: 16, marginBottom: 8, }, emptyText: { fontSize: theme.typography.fontSize.base, color: theme.colors.gray500, textAlign: "center", lineHeight: 24, }, card: { marginBottom: 16, }, cardContent: { borderRadius: theme.borderRadius["2xl"], padding: 20, }, cardHeader: { flexDirection: "row", justifyContent: "space-between", alignItems: "center", marginBottom: 16, }, cardHeaderLeft: { flexDirection: "row", alignItems: "center", gap: 12, }, cardIcon: { width: 40, height: 40, borderRadius: 20, justifyContent: "center", alignItems: "center", }, cardTitle: { fontSize: theme.typography.fontSize.lg, fontWeight: theme.typography.fontWeight.bold, color: theme.colors.gray800, }, cardDate: { fontSize: theme.typography.fontSize.sm, color: theme.colors.gray500, marginTop: 2, }, cardSummary: { marginBottom: 12, }, summaryText: { fontSize: theme.typography.fontSize.base, color: theme.colors.gray700, lineHeight: 24, }, expandedContent: { marginTop: 12, paddingTop: 16, borderTopWidth: 1, borderTopColor: theme.colors.gray200, }, planSection: { marginBottom: 16, }, planHeader: { flexDirection: "row", alignItems: "center", gap: 8, marginBottom: 8, }, planTitle: { fontSize: theme.typography.fontSize.base, fontWeight: theme.typography.fontWeight.bold, color: theme.colors.gray800, }, planText: { fontSize: theme.typography.fontSize.base, color: theme.colors.gray600, lineHeight: 22, }, });