import React, { useState, useEffect, useCallback } from 'react'; import { View, Text, StyleSheet, FlatList, TouchableOpacity, RefreshControl, } from 'react-native'; import { router } from 'expo-router'; import { Ionicons } from '@expo/vector-icons'; import { SafeAreaView } from 'react-native-safe-area-context'; import { api } from '@/services/api'; import { useAuth } from '@/contexts/AuthContext'; import { useBeneficiary } from '@/contexts/BeneficiaryContext'; import { LoadingSpinner } from '@/components/ui/LoadingSpinner'; import { FullScreenError } from '@/components/ui/ErrorMessage'; import { AppColors, BorderRadius, FontSizes, Spacing } from '@/constants/theme'; import type { Beneficiary } from '@/types'; export default function BeneficiariesListScreen() { const { user } = useAuth(); const { setCurrentBeneficiary } = useBeneficiary(); const [beneficiaries, setBeneficiaries] = useState([]); const [isLoading, setIsLoading] = useState(true); const [isRefreshing, setIsRefreshing] = useState(false); const [error, setError] = useState(null); const loadBeneficiaries = useCallback(async (showLoading = true) => { if (showLoading) setIsLoading(true); setError(null); try { const response = await api.getBeneficiaries(); if (response.ok && response.data) { setBeneficiaries(response.data.beneficiaries); } else { setError(response.error?.message || 'Failed to load beneficiaries'); } } catch (err) { setError(err instanceof Error ? err.message : 'An error occurred'); } finally { setIsLoading(false); setIsRefreshing(false); } }, []); useEffect(() => { loadBeneficiaries(); }, [loadBeneficiaries]); const handleRefresh = useCallback(() => { setIsRefreshing(true); loadBeneficiaries(false); }, [loadBeneficiaries]); const handleBeneficiaryPress = (beneficiary: Beneficiary) => { // Set current beneficiary in context before navigating setCurrentBeneficiary(beneficiary); // Navigate directly to their dashboard router.push(`/beneficiaries/${beneficiary.id}/dashboard`); }; const renderBeneficiaryCard = ({ item }: { item: Beneficiary }) => ( handleBeneficiaryPress(item)} activeOpacity={0.7} > {item.name.charAt(0).toUpperCase()} {item.name} {item.relationship} {' '} {item.last_activity} {item.sensor_data && ( {item.sensor_data.motion_detected ? 'Active' : 'Inactive'} Motion {item.sensor_data.door_status === 'open' ? 'Open' : 'Closed'} Door {item.sensor_data.temperature}° Temp )} ); if (isLoading) { return ; } if (error) { return loadBeneficiaries()} />; } return ( {/* Header */} Hello, {user?.user_name || 'User'} Beneficiaries {/* Beneficiary List */} item.id.toString()} renderItem={renderBeneficiaryCard} contentContainerStyle={styles.listContent} showsVerticalScrollIndicator={false} refreshControl={ } ListEmptyComponent={ No beneficiaries yet Add your first beneficiary to start monitoring } /> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: AppColors.surface, }, header: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingHorizontal: Spacing.lg, paddingVertical: Spacing.md, backgroundColor: AppColors.background, borderBottomWidth: 1, borderBottomColor: AppColors.border, }, greeting: { fontSize: FontSizes.sm, color: AppColors.textSecondary, }, headerTitle: { fontSize: FontSizes.xl, fontWeight: '700', color: AppColors.textPrimary, }, addButton: { width: 44, height: 44, borderRadius: BorderRadius.full, backgroundColor: AppColors.primary, justifyContent: 'center', alignItems: 'center', }, listContent: { padding: Spacing.md, }, beneficiaryCard: { backgroundColor: AppColors.background, borderRadius: BorderRadius.lg, padding: Spacing.md, marginBottom: Spacing.md, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.05, shadowRadius: 4, elevation: 2, }, beneficiaryInfo: { flexDirection: 'row', alignItems: 'center', marginBottom: Spacing.md, }, avatarContainer: { width: 56, height: 56, borderRadius: BorderRadius.full, backgroundColor: AppColors.primaryLight, justifyContent: 'center', alignItems: 'center', marginRight: Spacing.md, }, avatarText: { fontSize: FontSizes.xl, fontWeight: '600', color: AppColors.white, }, statusIndicator: { position: 'absolute', bottom: 2, right: 2, width: 14, height: 14, borderRadius: BorderRadius.full, borderWidth: 2, borderColor: AppColors.background, }, online: { backgroundColor: AppColors.online, }, offline: { backgroundColor: AppColors.offline, }, beneficiaryDetails: { flex: 1, }, beneficiaryName: { fontSize: FontSizes.lg, fontWeight: '600', color: AppColors.textPrimary, }, beneficiaryRelationship: { fontSize: FontSizes.sm, color: AppColors.textSecondary, marginTop: 2, }, lastActivity: { fontSize: FontSizes.xs, color: AppColors.textMuted, marginTop: 4, }, sensorStats: { flexDirection: 'row', justifyContent: 'space-around', paddingTop: Spacing.md, borderTopWidth: 1, borderTopColor: AppColors.border, }, statItem: { alignItems: 'center', }, statValue: { fontSize: FontSizes.base, fontWeight: '600', color: AppColors.textPrimary, marginTop: Spacing.xs, }, statLabel: { fontSize: FontSizes.xs, color: AppColors.textMuted, }, chevron: { position: 'absolute', top: Spacing.md, right: Spacing.md, }, emptyContainer: { flex: 1, justifyContent: 'center', alignItems: 'center', paddingTop: Spacing.xxl * 2, }, emptyTitle: { fontSize: FontSizes.lg, fontWeight: '600', color: AppColors.textPrimary, marginTop: Spacing.md, }, emptyText: { fontSize: FontSizes.base, color: AppColors.textSecondary, textAlign: 'center', marginTop: Spacing.xs, }, });