import React, { useEffect, useRef } from "react"; import { View, Text, StyleSheet, TouchableOpacity, Alert, Animated, } from "react-native"; import { Ionicons } from "@expo/vector-icons"; import type { FitnessGoal } from "../services/fitnessGoals"; import { useTheme } from "../contexts/ThemeContext"; import { MinimalCard } from "./MinimalCard"; import { Badge } from "./Badge"; import { ProgressBar } from "./ProgressBar"; import { IconContainer } from "./IconContainer"; interface GoalProgressCardProps { goal: FitnessGoal; onPress?: () => void; onComplete?: () => void; onDelete?: () => void; } export function GoalProgressCard({ goal, onPress, onComplete, onDelete, }: GoalProgressCardProps) { const { colors, typography } = useTheme(); const isCompleted = goal.status === "completed"; const progress = (goal.progress || 0) / 100; // Convert to 0-1 scale const scaleAnim = useRef(new Animated.Value(1)).current; // Celebration animation when goal is completed useEffect(() => { if (isCompleted) { Animated.sequence([ Animated.spring(scaleAnim, { toValue: 1.05, friction: 3, tension: 40, useNativeDriver: true, }), Animated.spring(scaleAnim, { toValue: 1, friction: 3, tension: 40, useNativeDriver: true, }), ]).start(); } }, [isCompleted]); const handleComplete = () => { if (onComplete) { // Trigger celebration animation Animated.sequence([ Animated.spring(scaleAnim, { toValue: 1.1, friction: 3, tension: 40, useNativeDriver: true, }), Animated.spring(scaleAnim, { toValue: 1, friction: 3, tension: 40, useNativeDriver: true, }), ]).start(() => { onComplete(); }); } }; // Calculate days remaining const daysRemaining = goal.targetDate ? Math.ceil( (new Date(goal.targetDate).getTime() - Date.now()) / (1000 * 60 * 60 * 24), ) : null; const getGoalTypeIcon = (type: string) => { switch (type) { case "weight_target": return "scale-outline"; case "strength_milestone": return "barbell-outline"; case "endurance_target": return "bicycle-outline"; case "flexibility_goal": return "body-outline"; case "habit_building": return "calendar-outline"; default: return "flag-outline"; } }; const getPriorityColor = (priority: string) => { switch (priority) { case "high": return colors.danger; case "medium": return colors.warning; case "low": return colors.success; default: return colors.primary; } }; const handleDelete = () => { Alert.alert("Delete Goal", "Are you sure you want to delete this goal?", [ { text: "Cancel", style: "cancel" }, { text: "Delete", style: "destructive", onPress: onDelete }, ]); }; return ( {/* Header */} {goal.title} {goal.description && ( {goal.description} )} {/* Action Buttons */} {!isCompleted && onComplete && ( )} {onDelete && ( )} {/* Progress Section */} {goal.targetValue && ( {goal.currentValue || 0} / {goal.targetValue}{" "} {goal.unit || ""} {(progress * 100).toFixed(0)}% )} {/* Footer */} {isCompleted ? ( ) : ( {goal.priority === "high" && ( )} {goal.priority === "medium" && ( )} {goal.priority === "low" && ( )} )} {daysRemaining !== null && !isCompleted && ( {daysRemaining < 0 ? `${Math.abs(daysRemaining)} days overdue` : `${daysRemaining} days remaining`} )} {isCompleted && goal.completedDate && ( Completed {new Date(goal.completedDate).toLocaleDateString()} )} ); } const styles = StyleSheet.create({ card: { marginBottom: 16, borderRadius: 20, }, header: { flexDirection: "row", justifyContent: "space-between", alignItems: "flex-start", marginBottom: 16, }, titleRow: { flexDirection: "row", alignItems: "flex-start", flex: 1, }, titleContainer: { flex: 1, marginLeft: 14, }, actions: { flexDirection: "row", gap: 12, }, actionButton: { padding: 6, }, progressSection: { marginBottom: 16, }, progressInfo: { flexDirection: "row", justifyContent: "space-between", alignItems: "center", marginBottom: 10, }, footer: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", }, });