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';
// Dev email - only this account has real beneficiaries
const DEV_EMAIL = 'serter2069@gmail.com';
// Beneficiary card component
interface BeneficiaryCardProps {
beneficiary: Beneficiary;
onPress: () => void;
}
function BeneficiaryCard({ beneficiary, onPress }: BeneficiaryCardProps) {
const wellnessColor = beneficiary.wellness_score && beneficiary.wellness_score >= 70
? AppColors.success
: beneficiary.wellness_score && beneficiary.wellness_score >= 40
? '#F59E0B'
: AppColors.error;
return (
{/* Avatar */}
{beneficiary.avatar ? (
) : (
{beneficiary.name.charAt(0).toUpperCase()}
)}
{/* Info */}
{beneficiary.name}
{beneficiary.last_location && (
{beneficiary.last_location}
)}
{beneficiary.last_activity && (
{beneficiary.last_activity}
)}
{/* Wellness Score */}
{beneficiary.wellness_score !== undefined && (
{beneficiary.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 [beneficiaries, setBeneficiaries] = useState([]);
const [error, setError] = useState(null);
const [onboardingChecked, setOnboardingChecked] = useState(false);
// Check if user is dev account (has real beneficiaries)
const isDevAccount = user?.email?.toLowerCase() === DEV_EMAIL.toLowerCase();
// Load beneficiaries from API
useEffect(() => {
loadBeneficiaries();
}, []);
const loadBeneficiaries = async () => {
setIsLoading(true);
setError(null);
try {
// First check if onboarding was already completed (persisted in SecureStore)
const onboardingCompleted = await api.isOnboardingCompleted();
const response = await api.getAllBeneficiaries();
if (response.ok && response.data) {
setBeneficiaries(response.data);
// Auto-select first beneficiary if none selected
if (!currentBeneficiary && response.data.length > 0) {
setCurrentBeneficiary(response.data[0]);
}
// Redirect to onboarding only if:
// 1. No beneficiaries
// 2. Not a dev account
// 3. Onboarding wasn't completed before (persistent check)
if (response.data.length === 0 && !isDevAccount && !onboardingCompleted) {
router.replace({
pathname: '/(auth)/add-loved-one',
params: { email: user?.email || '' },
});
return;
}
} else {
setError(response.error?.message || 'Failed to load beneficiaries');
}
} catch (err) {
console.error('Failed to load beneficiaries:', err);
setError('Failed to load beneficiaries');
} finally {
setIsLoading(false);
setOnboardingChecked(true);
}
};
const handleRefresh = async () => {
setIsRefreshing(true);
await loadBeneficiaries();
setIsRefreshing(false);
};
const handleBeneficiaryPress = (beneficiary: Beneficiary) => {
// Set current beneficiary in context
setCurrentBeneficiary(beneficiary);
// Navigate to beneficiary dashboard with deployment_id
router.push(`/(tabs)/beneficiaries/${beneficiary.id}/dashboard`);
};
// Get display name from user data
const getDisplayName = () => {
// For dev account, show "Developer"
if (isDevAccount) return 'Developer';
// Otherwise use email prefix or user_name as fallback
if (user?.email) {
return user.email.split('@')[0];
}
return user?.user_name || 'User';
};
const displayName = getDisplayName();
if (isLoading) {
return (
Hello, {displayName}
My Beneficiaries
Loading beneficiaries...
);
}
return (
{/* Header */}
Hello, {displayName}
My Beneficiaries
{/* Beneficiary List */}
{beneficiaries.length === 0 ? (
No Beneficiaries
Add a loved one to start monitoring their wellbeing.
router.push('/(auth)/add-loved-one')}
>
Add Loved One
) : (
item.id.toString()}
renderItem={({ item }) => (
handleBeneficiaryPress(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,
},
addButton: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: AppColors.primary,
paddingVertical: Spacing.md,
paddingHorizontal: Spacing.xl,
borderRadius: BorderRadius.md,
marginTop: Spacing.lg,
gap: Spacing.xs,
},
addButtonText: {
fontSize: FontSizes.base,
fontWeight: '600',
color: AppColors.white,
},
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,
},
});