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,
},
});