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, Spacing } from '@/constants/theme'; import type { Beneficiary } from '@/types'; // Patient card component interface PatientCardProps { patient: Beneficiary; onPress: () => void; } function PatientCard({ patient, onPress }: PatientCardProps) { const wellnessColor = patient.wellness_score && patient.wellness_score >= 70 ? AppColors.success : patient.wellness_score && patient.wellness_score >= 40 ? '#F59E0B' : AppColors.error; return ( {/* Avatar */} {patient.avatar ? ( ) : ( {patient.name.charAt(0).toUpperCase()} )} {/* Info */} {patient.name} {patient.last_location && ( {patient.last_location} )} {patient.last_activity && ( {patient.last_activity} )} {/* Wellness Score */} {patient.wellness_score !== undefined && ( {patient.wellness_score}% Wellness )} {/* Arrow */} ); } export default function HomeScreen() { const { user } = useAuth(); const { currentBeneficiary, setCurrentBeneficiary } = useBeneficiary(); const [isLoading, setIsLoading] = useState(true); const [isRefreshing, setIsRefreshing] = useState(false); const [patients, setPatients] = useState([]); const [error, setError] = useState(null); // Load patients from API useEffect(() => { loadPatients(); }, []); const loadPatients = async () => { setIsLoading(true); setError(null); try { const response = await api.getAllPatients(); if (response.ok && response.data) { setPatients(response.data); // Auto-select first beneficiary if none selected if (!currentBeneficiary && response.data.length > 0) { setCurrentBeneficiary(response.data[0]); } } else { setError(response.error?.message || 'Failed to load patients'); } } catch (err) { console.error('Failed to load patients:', err); setError('Failed to load patients'); } finally { setIsLoading(false); } }; const handleRefresh = async () => { setIsRefreshing(true); await loadPatients(); setIsRefreshing(false); }; const handlePatientPress = (patient: Beneficiary) => { // Set current beneficiary in context setCurrentBeneficiary(patient); // Navigate to patient dashboard with deployment_id router.push(`/(tabs)/beneficiaries/${patient.id}/dashboard`); }; if (isLoading) { return ( Hello, {user?.user_name || 'User'} My Beneficiaries Loading patients... ); } return ( {/* Header */} Hello, {user?.user_name || 'User'} My Beneficiaries {/* Patient List */} {patients.length === 0 ? ( No Patients You don't have any patients assigned yet. ) : ( item.id.toString()} renderItem={({ item }) => ( handlePatientPress(item)} /> )} contentContainerStyle={styles.listContent} showsVerticalScrollIndicator={false} refreshControl={ } /> )} ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: AppColors.background, }, 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, }, refreshButton: { padding: Spacing.xs, }, loadingContainer: { flex: 1, justifyContent: 'center', alignItems: 'center', }, loadingText: { marginTop: Spacing.md, fontSize: FontSizes.base, color: AppColors.textSecondary, }, emptyContainer: { flex: 1, justifyContent: 'center', alignItems: 'center', padding: Spacing.xl, }, emptyTitle: { fontSize: FontSizes.lg, fontWeight: '600', color: AppColors.textPrimary, marginTop: Spacing.md, }, emptyText: { fontSize: FontSizes.base, color: AppColors.textSecondary, textAlign: 'center', marginTop: Spacing.xs, }, listContent: { padding: Spacing.lg, paddingBottom: Spacing.xxl, }, // Card styles card: { backgroundColor: AppColors.white, borderRadius: BorderRadius.lg, marginBottom: Spacing.md, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.05, shadowRadius: 4, elevation: 2, }, cardContent: { flexDirection: 'row', alignItems: 'center', padding: Spacing.md, }, avatarWrapper: { width: 56, height: 56, borderRadius: 28, position: 'relative', overflow: 'hidden', }, avatar: { width: 56, height: 56, borderRadius: 28, backgroundColor: AppColors.primaryLight, justifyContent: 'center', alignItems: 'center', }, avatarImage: { width: 56, height: 56, borderRadius: 28, }, avatarText: { fontSize: FontSizes.xl, fontWeight: '600', color: AppColors.white, }, info: { flex: 1, marginLeft: Spacing.md, }, name: { fontSize: FontSizes.lg, fontWeight: '600', color: AppColors.textPrimary, }, relationship: { fontSize: FontSizes.sm, color: AppColors.textSecondary, marginTop: 2, }, lastActivity: { fontSize: FontSizes.xs, color: AppColors.textMuted, marginLeft: Spacing.sm, }, locationRow: { flexDirection: 'row', alignItems: 'center', marginTop: 2, }, locationText: { fontSize: FontSizes.xs, color: AppColors.textSecondary, marginLeft: 4, }, wellnessContainer: { alignItems: 'center', marginRight: Spacing.sm, }, wellnessScore: { fontSize: FontSizes.lg, fontWeight: '700', }, wellnessLabel: { fontSize: FontSizes.xs, color: AppColors.textMuted, }, });