import React, { useState, useEffect } from 'react'; import { View, Text, StyleSheet, FlatList, TouchableOpacity, ActivityIndicator, RefreshControl, Image, } from 'react-native'; import { Ionicons } from '@expo/vector-icons'; import { SafeAreaView } from 'react-native-safe-area-context'; import { router } from 'expo-router'; import { useAuth } from '@/contexts/AuthContext'; import { useBeneficiary } from '@/contexts/BeneficiaryContext'; import { api } from '@/services/api'; import { AppColors, BorderRadius, FontSizes, FontWeights, Spacing, Shadows, AvatarSizes, } from '@/constants/theme'; import type { Beneficiary } from '@/types'; // Simplified beneficiary card: Avatar + Name + Warning (if no subscription) interface BeneficiaryCardProps { beneficiary: Beneficiary; onPress: () => void; } function BeneficiaryCard({ beneficiary, onPress }: BeneficiaryCardProps) { // Check if subscription is missing or expired const hasNoSubscription = !beneficiary.subscription || beneficiary.subscription.status !== 'active'; return ( {/* Avatar */} {beneficiary.avatar ? ( ) : ( {beneficiary.name.charAt(0).toUpperCase()} )} {/* Name */} {beneficiary.name} {/* Warning icon if no subscription */} {hasNoSubscription && ( )} {/* Arrow */} ); } export default function HomeScreen() { const { user } = useAuth(); const { currentBeneficiary, setCurrentBeneficiary, localBeneficiaries } = useBeneficiary(); const [isLoading, setIsLoading] = useState(true); const [isRefreshing, setIsRefreshing] = useState(false); const [beneficiaries, setBeneficiaries] = useState([]); const [error, setError] = useState(null); // Load beneficiaries from API and combine with local ones useEffect(() => { loadBeneficiaries(); }, [localBeneficiaries]); const loadBeneficiaries = async () => { setIsLoading(true); setError(null); try { const onboardingCompleted = await api.isOnboardingCompleted(); const response = await api.getAllBeneficiaries(); let allBeneficiaries: Beneficiary[] = []; if (response.ok && response.data) { allBeneficiaries = [...response.data]; } allBeneficiaries = [...allBeneficiaries, ...localBeneficiaries]; setBeneficiaries(allBeneficiaries); if (!currentBeneficiary && allBeneficiaries.length > 0) { setCurrentBeneficiary(allBeneficiaries[0]); } if (allBeneficiaries.length === 0 && !onboardingCompleted) { router.replace({ pathname: '/(auth)/add-loved-one', params: { email: user?.email || '' }, }); return; } } catch (err) { console.error('Failed to load beneficiaries:', err); if (localBeneficiaries.length > 0) { setBeneficiaries(localBeneficiaries); } else { setError('Failed to load beneficiaries'); } } finally { setIsLoading(false); } }; const handleRefresh = async () => { setIsRefreshing(true); await loadBeneficiaries(); setIsRefreshing(false); }; const handleBeneficiaryPress = (beneficiary: Beneficiary) => { setCurrentBeneficiary(beneficiary); router.push(`/(tabs)/beneficiaries/${beneficiary.id}/dashboard`); }; const getDisplayName = () => { if (user?.user_name) return user.user_name; if (user?.email) return user.email.split('@')[0]; return 'User'; }; const displayName = getDisplayName(); const greeting = new Date().getHours() < 12 ? 'Good morning' : new Date().getHours() < 18 ? 'Good afternoon' : 'Good evening'; if (isLoading) { return ( {greeting}, {displayName} Loading... ); } return ( {/* Header */} {greeting}, {displayName} {/* Section Title */} {beneficiaries.length > 0 && ( My Loved Ones {beneficiaries.length} )} {/* Content */} {beneficiaries.length === 0 ? ( No loved ones yet Add a loved one to start monitoring their wellbeing and stay connected. router.push('/(tabs)/beneficiaries/add')} > Add Loved One ) : ( <> item.id.toString()} renderItem={({ item }) => ( handleBeneficiaryPress(item)} /> )} contentContainerStyle={styles.listContent} showsVerticalScrollIndicator={false} refreshControl={ } /> {/* Floating Add Button */} router.push('/(tabs)/beneficiaries/add')} activeOpacity={0.9} > )} ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: AppColors.background, }, header: { paddingHorizontal: Spacing.lg, paddingTop: Spacing.md, paddingBottom: Spacing.lg, backgroundColor: AppColors.background, }, headerContent: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', }, greeting: { fontSize: FontSizes.base, color: AppColors.textSecondary, fontWeight: FontWeights.medium, }, displayName: { fontSize: FontSizes['2xl'], fontWeight: FontWeights.bold, color: AppColors.textPrimary, marginTop: 2, }, headerAction: { width: 44, height: 44, borderRadius: BorderRadius.lg, backgroundColor: AppColors.primaryLighter, justifyContent: 'center', alignItems: 'center', }, sectionHeader: { flexDirection: 'row', alignItems: 'center', paddingHorizontal: Spacing.lg, marginBottom: Spacing.md, }, sectionTitle: { fontSize: FontSizes.lg, fontWeight: FontWeights.semibold, color: AppColors.textPrimary, }, sectionCount: { fontSize: FontSizes.sm, fontWeight: FontWeights.semibold, color: AppColors.primary, backgroundColor: AppColors.primaryLighter, paddingHorizontal: Spacing.sm, paddingVertical: 2, borderRadius: BorderRadius.full, marginLeft: Spacing.sm, overflow: 'hidden', }, loadingContainer: { flex: 1, justifyContent: 'center', alignItems: 'center', }, loadingText: { marginTop: Spacing.md, fontSize: FontSizes.base, color: AppColors.textSecondary, }, emptyContainer: { flex: 1, justifyContent: 'center', alignItems: 'center', paddingHorizontal: Spacing.xl, }, emptyIconContainer: { width: 96, height: 96, borderRadius: BorderRadius['2xl'], backgroundColor: AppColors.primaryLighter, justifyContent: 'center', alignItems: 'center', marginBottom: Spacing.lg, }, emptyTitle: { fontSize: FontSizes.xl, fontWeight: FontWeights.bold, color: AppColors.textPrimary, marginBottom: Spacing.sm, }, emptyText: { fontSize: FontSizes.base, color: AppColors.textSecondary, textAlign: 'center', lineHeight: 24, marginBottom: Spacing.xl, }, addButtonLarge: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', backgroundColor: AppColors.primary, paddingVertical: Spacing.md, paddingHorizontal: Spacing.xl, borderRadius: BorderRadius.lg, gap: Spacing.sm, ...Shadows.primary, }, addButtonText: { fontSize: FontSizes.base, fontWeight: FontWeights.semibold, color: AppColors.white, }, listContent: { paddingHorizontal: Spacing.lg, paddingBottom: 100, }, // Card styles card: { backgroundColor: AppColors.surface, borderRadius: BorderRadius.xl, marginBottom: Spacing.md, padding: Spacing.md, flexDirection: 'row', alignItems: 'center', ...Shadows.sm, }, avatarWrapper: { position: 'relative', }, avatar: { width: AvatarSizes.md, height: AvatarSizes.md, borderRadius: AvatarSizes.md / 2, backgroundColor: AppColors.primaryLighter, justifyContent: 'center', alignItems: 'center', }, avatarImage: { width: AvatarSizes.md, height: AvatarSizes.md, borderRadius: AvatarSizes.md / 2, }, avatarText: { fontSize: FontSizes.xl, fontWeight: FontWeights.bold, color: AppColors.primary, }, info: { flex: 1, marginLeft: Spacing.md, marginRight: Spacing.sm, }, name: { fontSize: FontSizes.lg, fontWeight: FontWeights.semibold, color: AppColors.textPrimary, }, warningContainer: { marginRight: Spacing.sm, }, arrowContainer: { width: 32, height: 32, borderRadius: BorderRadius.md, backgroundColor: AppColors.surfaceSecondary, justifyContent: 'center', alignItems: 'center', }, // Floating Action Button fab: { position: 'absolute', bottom: Spacing.xl, right: Spacing.lg, width: 60, height: 60, borderRadius: 30, backgroundColor: AppColors.primary, justifyContent: 'center', alignItems: 'center', ...Shadows.lg, }, });