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