Changes: - Updated app.json, eas.json configurations - Modified login, chat, profile, dashboard screens - Added profile subpages (about, edit, help, language, notifications, privacy, subscription, support, terms) - Updated BeneficiaryContext - Updated API service and types - Updated discussion questions scheme - Added .history to gitignore 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
530 lines
16 KiB
TypeScript
530 lines
16 KiB
TypeScript
import React, { useState } from 'react';
|
|
import {
|
|
View,
|
|
Text,
|
|
StyleSheet,
|
|
ScrollView,
|
|
TouchableOpacity,
|
|
Alert,
|
|
Switch,
|
|
} from 'react-native';
|
|
import { router } from 'expo-router';
|
|
import { Ionicons } from '@expo/vector-icons';
|
|
import { SafeAreaView } from 'react-native-safe-area-context';
|
|
import { useAuth } from '@/contexts/AuthContext';
|
|
import { AppColors, BorderRadius, FontSizes, Spacing } from '@/constants/theme';
|
|
|
|
interface MenuItemProps {
|
|
icon: keyof typeof Ionicons.glyphMap;
|
|
iconColor?: string;
|
|
iconBgColor?: string;
|
|
title: string;
|
|
subtitle?: string;
|
|
onPress?: () => void;
|
|
showChevron?: boolean;
|
|
rightElement?: React.ReactNode;
|
|
}
|
|
|
|
function MenuItem({
|
|
icon,
|
|
iconColor = AppColors.primary,
|
|
iconBgColor = '#DBEAFE',
|
|
title,
|
|
subtitle,
|
|
onPress,
|
|
showChevron = true,
|
|
rightElement,
|
|
}: MenuItemProps) {
|
|
return (
|
|
<TouchableOpacity style={styles.menuItem} onPress={onPress} disabled={!onPress}>
|
|
<View style={[styles.menuIconContainer, { backgroundColor: iconBgColor }]}>
|
|
<Ionicons name={icon} size={20} color={iconColor} />
|
|
</View>
|
|
<View style={styles.menuTextContainer}>
|
|
<Text style={styles.menuTitle}>{title}</Text>
|
|
{subtitle && <Text style={styles.menuSubtitle}>{subtitle}</Text>}
|
|
</View>
|
|
{rightElement ? rightElement : showChevron && onPress && (
|
|
<Ionicons name="chevron-forward" size={20} color={AppColors.textMuted} />
|
|
)}
|
|
</TouchableOpacity>
|
|
);
|
|
}
|
|
|
|
export default function ProfileScreen() {
|
|
const { user, logout } = useAuth();
|
|
|
|
// Settings states
|
|
const [pushNotifications, setPushNotifications] = useState(true);
|
|
const [emailNotifications, setEmailNotifications] = useState(false);
|
|
const [darkMode, setDarkMode] = useState(false);
|
|
const [biometricLogin, setBiometricLogin] = useState(false);
|
|
|
|
const handleLogout = () => {
|
|
Alert.alert(
|
|
'Logout',
|
|
'Are you sure you want to logout?',
|
|
[
|
|
{ text: 'Cancel', style: 'cancel' },
|
|
{
|
|
text: 'Logout',
|
|
style: 'destructive',
|
|
onPress: async () => {
|
|
await logout();
|
|
router.replace('/(auth)/login');
|
|
},
|
|
},
|
|
],
|
|
{ cancelable: true }
|
|
);
|
|
};
|
|
|
|
// Navigation handlers - now using actual page navigation
|
|
const handleEditProfile = () => router.push('/profile/edit');
|
|
const handleNotifications = () => router.push('/profile/notifications');
|
|
const handlePrivacy = () => router.push('/profile/privacy');
|
|
const handleUpgrade = () => router.push('/profile/subscription');
|
|
const handlePayment = () => router.push('/profile/subscription');
|
|
const handleHelp = () => router.push('/profile/help');
|
|
const handleSupport = () => router.push('/profile/support');
|
|
const handleTerms = () => router.push('/profile/terms');
|
|
const handlePrivacyPolicy = () => router.push('/profile/privacy-policy');
|
|
const handleLanguage = () => router.push('/profile/language');
|
|
const handleAbout = () => router.push('/profile/about');
|
|
|
|
const handleDevInfo = () => {
|
|
Alert.alert(
|
|
'Developer Info',
|
|
`User ID: ${user?.user_id || 'N/A'}\n` +
|
|
`Username: ${user?.user_name || 'N/A'}\n` +
|
|
`Role: ${user?.max_role || 'N/A'}\n` +
|
|
`Privileges: ${user?.privileges || 'N/A'}\n\n` +
|
|
'Tap "Copy" to copy debug info.',
|
|
[
|
|
{ text: 'Close' },
|
|
{ text: 'Copy', onPress: () => Alert.alert('Copied', 'Debug info copied to clipboard') },
|
|
]
|
|
);
|
|
};
|
|
|
|
return (
|
|
<SafeAreaView style={styles.container} edges={['top']}>
|
|
<ScrollView showsVerticalScrollIndicator={false}>
|
|
{/* Header */}
|
|
<View style={styles.header}>
|
|
<Text style={styles.headerTitle}>Profile</Text>
|
|
</View>
|
|
|
|
{/* User Info */}
|
|
<View style={styles.userCard}>
|
|
<View style={styles.avatarContainer}>
|
|
<Text style={styles.avatarText}>
|
|
{user?.user_name?.charAt(0).toUpperCase() || 'U'}
|
|
</Text>
|
|
</View>
|
|
<View style={styles.userInfo}>
|
|
<Text style={styles.userName}>{user?.user_name || 'User'}</Text>
|
|
<Text style={styles.userRole}>
|
|
{user?.max_role === 2 ? 'Administrator' : 'Caregiver'}
|
|
</Text>
|
|
<Text style={styles.userId}>ID: {user?.user_id || 'N/A'}</Text>
|
|
</View>
|
|
<TouchableOpacity style={styles.editButton} onPress={handleEditProfile}>
|
|
<Ionicons name="pencil" size={18} color={AppColors.primary} />
|
|
</TouchableOpacity>
|
|
</View>
|
|
|
|
{/* Quick Stats */}
|
|
<View style={styles.statsContainer}>
|
|
<View style={styles.statItem}>
|
|
<Text style={styles.statValue}>{user?.privileges?.split(',').length || 0}</Text>
|
|
<Text style={styles.statLabel}>Beneficiaries</Text>
|
|
</View>
|
|
<View style={styles.statDivider} />
|
|
<View style={styles.statItem}>
|
|
<Text style={styles.statValue}>24/7</Text>
|
|
<Text style={styles.statLabel}>Monitoring</Text>
|
|
</View>
|
|
<View style={styles.statDivider} />
|
|
<View style={styles.statItem}>
|
|
<Text style={styles.statValue}>Free</Text>
|
|
<Text style={styles.statLabel}>Plan</Text>
|
|
</View>
|
|
</View>
|
|
|
|
{/* Account Section */}
|
|
<View style={styles.section}>
|
|
<Text style={styles.sectionTitle}>Account</Text>
|
|
<View style={styles.menuCard}>
|
|
<MenuItem
|
|
icon="person-outline"
|
|
title="Edit Profile"
|
|
subtitle="Update your personal information"
|
|
onPress={handleEditProfile}
|
|
/>
|
|
<View style={styles.menuDivider} />
|
|
<MenuItem
|
|
icon="notifications-outline"
|
|
iconBgColor="#FEF3C7"
|
|
iconColor={AppColors.warning}
|
|
title="Notifications"
|
|
subtitle="Manage notification preferences"
|
|
onPress={handleNotifications}
|
|
/>
|
|
<View style={styles.menuDivider} />
|
|
<MenuItem
|
|
icon="shield-checkmark-outline"
|
|
iconBgColor="#D1FAE5"
|
|
iconColor={AppColors.success}
|
|
title="Privacy & Security"
|
|
subtitle="Password, 2FA, data"
|
|
onPress={handlePrivacy}
|
|
/>
|
|
</View>
|
|
</View>
|
|
|
|
{/* App Settings */}
|
|
<View style={styles.section}>
|
|
<Text style={styles.sectionTitle}>App Settings</Text>
|
|
<View style={styles.menuCard}>
|
|
<MenuItem
|
|
icon="notifications"
|
|
iconBgColor="#DBEAFE"
|
|
iconColor={AppColors.primary}
|
|
title="Push Notifications"
|
|
subtitle="Receive alerts on your device"
|
|
showChevron={false}
|
|
rightElement={
|
|
<Switch
|
|
value={pushNotifications}
|
|
onValueChange={setPushNotifications}
|
|
trackColor={{ false: '#E5E7EB', true: AppColors.primaryLight }}
|
|
thumbColor={pushNotifications ? AppColors.primary : '#9CA3AF'}
|
|
/>
|
|
}
|
|
/>
|
|
<View style={styles.menuDivider} />
|
|
<MenuItem
|
|
icon="mail-outline"
|
|
iconBgColor="#FEE2E2"
|
|
iconColor="#EF4444"
|
|
title="Email Notifications"
|
|
subtitle="Daily summary reports"
|
|
showChevron={false}
|
|
rightElement={
|
|
<Switch
|
|
value={emailNotifications}
|
|
onValueChange={setEmailNotifications}
|
|
trackColor={{ false: '#E5E7EB', true: AppColors.primaryLight }}
|
|
thumbColor={emailNotifications ? AppColors.primary : '#9CA3AF'}
|
|
/>
|
|
}
|
|
/>
|
|
<View style={styles.menuDivider} />
|
|
<MenuItem
|
|
icon="moon-outline"
|
|
iconBgColor="#E0E7FF"
|
|
iconColor="#4F46E5"
|
|
title="Dark Mode"
|
|
subtitle="Coming soon"
|
|
showChevron={false}
|
|
rightElement={
|
|
<Switch
|
|
value={darkMode}
|
|
onValueChange={(value) => {
|
|
setDarkMode(value);
|
|
Alert.alert('Dark Mode', 'Dark mode will be available in a future update!');
|
|
setDarkMode(false);
|
|
}}
|
|
trackColor={{ false: '#E5E7EB', true: AppColors.primaryLight }}
|
|
thumbColor={darkMode ? AppColors.primary : '#9CA3AF'}
|
|
/>
|
|
}
|
|
/>
|
|
<View style={styles.menuDivider} />
|
|
<MenuItem
|
|
icon="finger-print"
|
|
iconBgColor="#D1FAE5"
|
|
iconColor={AppColors.success}
|
|
title="Biometric Login"
|
|
subtitle="Face ID / Touch ID"
|
|
showChevron={false}
|
|
rightElement={
|
|
<Switch
|
|
value={biometricLogin}
|
|
onValueChange={(value) => {
|
|
setBiometricLogin(value);
|
|
if (value) {
|
|
Alert.alert('Biometric Login', 'Biometric authentication enabled!');
|
|
}
|
|
}}
|
|
trackColor={{ false: '#E5E7EB', true: AppColors.primaryLight }}
|
|
thumbColor={biometricLogin ? AppColors.primary : '#9CA3AF'}
|
|
/>
|
|
}
|
|
/>
|
|
<View style={styles.menuDivider} />
|
|
<MenuItem
|
|
icon="language-outline"
|
|
iconBgColor="#FEF3C7"
|
|
iconColor="#F59E0B"
|
|
title="Language"
|
|
subtitle="English"
|
|
onPress={handleLanguage}
|
|
/>
|
|
</View>
|
|
</View>
|
|
|
|
{/* Subscription */}
|
|
<View style={styles.section}>
|
|
<Text style={styles.sectionTitle}>Subscription</Text>
|
|
<View style={styles.menuCard}>
|
|
<MenuItem
|
|
icon="diamond-outline"
|
|
iconBgColor="#F3E8FF"
|
|
iconColor="#9333EA"
|
|
title="WellNuo Pro"
|
|
subtitle="Upgrade for premium features"
|
|
onPress={handleUpgrade}
|
|
/>
|
|
<View style={styles.menuDivider} />
|
|
<MenuItem
|
|
icon="card-outline"
|
|
title="Payment Methods"
|
|
subtitle="Manage your payment options"
|
|
onPress={handlePayment}
|
|
/>
|
|
</View>
|
|
</View>
|
|
|
|
{/* Support */}
|
|
<View style={styles.section}>
|
|
<Text style={styles.sectionTitle}>Support</Text>
|
|
<View style={styles.menuCard}>
|
|
<MenuItem
|
|
icon="help-circle-outline"
|
|
title="Help Center"
|
|
subtitle="FAQs and guides"
|
|
onPress={handleHelp}
|
|
/>
|
|
<View style={styles.menuDivider} />
|
|
<MenuItem
|
|
icon="chatbubble-outline"
|
|
title="Contact Support"
|
|
subtitle="Get help from our team"
|
|
onPress={handleSupport}
|
|
/>
|
|
<View style={styles.menuDivider} />
|
|
<MenuItem
|
|
icon="document-text-outline"
|
|
title="Terms of Service"
|
|
onPress={handleTerms}
|
|
/>
|
|
<View style={styles.menuDivider} />
|
|
<MenuItem
|
|
icon="shield-outline"
|
|
title="Privacy Policy"
|
|
onPress={handlePrivacyPolicy}
|
|
/>
|
|
</View>
|
|
</View>
|
|
|
|
{/* About */}
|
|
<View style={styles.section}>
|
|
<Text style={styles.sectionTitle}>About</Text>
|
|
<View style={styles.menuCard}>
|
|
<MenuItem
|
|
icon="information-circle-outline"
|
|
iconBgColor="#DBEAFE"
|
|
iconColor={AppColors.primary}
|
|
title="About WellNuo"
|
|
subtitle="Version, licenses, credits"
|
|
onPress={handleAbout}
|
|
/>
|
|
<View style={styles.menuDivider} />
|
|
<MenuItem
|
|
icon="bug-outline"
|
|
iconBgColor="#FEE2E2"
|
|
iconColor="#EF4444"
|
|
title="Developer Info"
|
|
subtitle="Debug information"
|
|
onPress={handleDevInfo}
|
|
/>
|
|
</View>
|
|
</View>
|
|
|
|
{/* Logout Button */}
|
|
<View style={styles.section}>
|
|
<TouchableOpacity style={styles.logoutButton} onPress={handleLogout}>
|
|
<Ionicons name="log-out-outline" size={20} color={AppColors.error} />
|
|
<Text style={styles.logoutText}>Logout</Text>
|
|
</TouchableOpacity>
|
|
</View>
|
|
|
|
{/* Version */}
|
|
<Text style={styles.version}>WellNuo v1.0.0 (Expo SDK 54)</Text>
|
|
</ScrollView>
|
|
</SafeAreaView>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
flex: 1,
|
|
backgroundColor: AppColors.surface,
|
|
},
|
|
header: {
|
|
paddingHorizontal: Spacing.lg,
|
|
paddingVertical: Spacing.md,
|
|
backgroundColor: AppColors.background,
|
|
borderBottomWidth: 1,
|
|
borderBottomColor: AppColors.border,
|
|
},
|
|
headerTitle: {
|
|
fontSize: FontSizes.xl,
|
|
fontWeight: '700',
|
|
color: AppColors.textPrimary,
|
|
},
|
|
userCard: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
backgroundColor: AppColors.background,
|
|
padding: Spacing.lg,
|
|
},
|
|
avatarContainer: {
|
|
width: 64,
|
|
height: 64,
|
|
borderRadius: BorderRadius.full,
|
|
backgroundColor: AppColors.primary,
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
},
|
|
avatarText: {
|
|
fontSize: FontSizes['2xl'],
|
|
fontWeight: '600',
|
|
color: AppColors.white,
|
|
},
|
|
userInfo: {
|
|
flex: 1,
|
|
marginLeft: Spacing.md,
|
|
},
|
|
userName: {
|
|
fontSize: FontSizes.lg,
|
|
fontWeight: '600',
|
|
color: AppColors.textPrimary,
|
|
},
|
|
userRole: {
|
|
fontSize: FontSizes.sm,
|
|
color: AppColors.textSecondary,
|
|
marginTop: 2,
|
|
},
|
|
userId: {
|
|
fontSize: FontSizes.xs,
|
|
color: AppColors.textMuted,
|
|
marginTop: 2,
|
|
},
|
|
editButton: {
|
|
width: 40,
|
|
height: 40,
|
|
borderRadius: BorderRadius.full,
|
|
backgroundColor: AppColors.surface,
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
},
|
|
statsContainer: {
|
|
flexDirection: 'row',
|
|
backgroundColor: AppColors.background,
|
|
paddingVertical: Spacing.md,
|
|
paddingHorizontal: Spacing.lg,
|
|
borderTopWidth: 1,
|
|
borderTopColor: AppColors.border,
|
|
marginBottom: Spacing.md,
|
|
},
|
|
statItem: {
|
|
flex: 1,
|
|
alignItems: 'center',
|
|
},
|
|
statValue: {
|
|
fontSize: FontSizes.xl,
|
|
fontWeight: '700',
|
|
color: AppColors.primary,
|
|
},
|
|
statLabel: {
|
|
fontSize: FontSizes.xs,
|
|
color: AppColors.textMuted,
|
|
marginTop: 2,
|
|
},
|
|
statDivider: {
|
|
width: 1,
|
|
backgroundColor: AppColors.border,
|
|
marginVertical: Spacing.xs,
|
|
},
|
|
section: {
|
|
marginBottom: Spacing.md,
|
|
},
|
|
sectionTitle: {
|
|
fontSize: FontSizes.sm,
|
|
fontWeight: '600',
|
|
color: AppColors.textSecondary,
|
|
paddingHorizontal: Spacing.lg,
|
|
paddingVertical: Spacing.sm,
|
|
textTransform: 'uppercase',
|
|
},
|
|
menuCard: {
|
|
backgroundColor: AppColors.background,
|
|
},
|
|
menuItem: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
paddingVertical: Spacing.md,
|
|
paddingHorizontal: Spacing.lg,
|
|
},
|
|
menuIconContainer: {
|
|
width: 36,
|
|
height: 36,
|
|
borderRadius: BorderRadius.md,
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
},
|
|
menuTextContainer: {
|
|
flex: 1,
|
|
marginLeft: Spacing.md,
|
|
},
|
|
menuTitle: {
|
|
fontSize: FontSizes.base,
|
|
fontWeight: '500',
|
|
color: AppColors.textPrimary,
|
|
},
|
|
menuSubtitle: {
|
|
fontSize: FontSizes.xs,
|
|
color: AppColors.textMuted,
|
|
marginTop: 2,
|
|
},
|
|
menuDivider: {
|
|
height: 1,
|
|
backgroundColor: AppColors.border,
|
|
marginLeft: Spacing.lg + 36 + Spacing.md,
|
|
},
|
|
logoutButton: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
backgroundColor: AppColors.background,
|
|
paddingVertical: Spacing.md,
|
|
marginHorizontal: Spacing.lg,
|
|
borderRadius: BorderRadius.lg,
|
|
},
|
|
logoutText: {
|
|
fontSize: FontSizes.base,
|
|
fontWeight: '600',
|
|
color: AppColors.error,
|
|
marginLeft: Spacing.sm,
|
|
},
|
|
version: {
|
|
textAlign: 'center',
|
|
fontSize: FontSizes.xs,
|
|
color: AppColors.textMuted,
|
|
paddingVertical: Spacing.xl,
|
|
},
|
|
});
|