From 7a8f16c6246ff132730691d888933ec2315c09f3 Mon Sep 17 00:00:00 2001 From: Joseph D'Souza Date: Wed, 11 Feb 2026 13:18:03 +0100 Subject: [PATCH] refactor and modularise profile components --- mobile/src/hooks/useProfileLogic.ts | 62 +++++++++++++++++++++++++++ mobile/src/screens/ProfileScreen.tsx | 64 +++++++--------------------- 2 files changed, 77 insertions(+), 49 deletions(-) create mode 100644 mobile/src/hooks/useProfileLogic.ts diff --git a/mobile/src/hooks/useProfileLogic.ts b/mobile/src/hooks/useProfileLogic.ts new file mode 100644 index 0000000..a104185 --- /dev/null +++ b/mobile/src/hooks/useProfileLogic.ts @@ -0,0 +1,62 @@ +import { useState } from 'react'; +import { Alert } from 'react-native'; +import { useAuthStore } from '../store/useAuthStore'; +import { authService } from '../services/api'; + +export const useProfileLogic = () => { + const { user, logout } = useAuthStore(); + const [isResending, setIsResending] = useState(false); + const [isModalVisible, setIsModalVisible] = useState(false); + + const displayName = + (user?.user?.first_name && user?.user?.last_name) ? `${user.user.first_name} ${user.user.last_name}` : + user?.user?.username ? user.user.username : + user?.user?.email ? user.user.email.split('@')[0] : + 'User Name'; + + const handleResendVerification = async () => { + setIsResending(true); + const result = await authService.resendVerificationEmail(); + setIsResending(false); + + if (result.ok) { + Alert.alert('Email Sent', 'Please check your email (or server logs) for the verification link.'); + } else { + Alert.alert('Error', result.message || 'Failed to resend verification email'); + } + }; + + const handleDeleteAccount = () => { + Alert.alert( + 'Delete Account', + 'Are you sure you want to permanently delete your account? This action cannot be undone.', + [ + { text: 'Cancel', style: 'cancel' }, + { + text: 'Delete', + style: 'destructive', + onPress: async () => { + const result = await authService.deleteAccount(); + if (result.ok) { + logout(); + Alert.alert('Success', 'Your account has been deleted.'); + } else { + Alert.alert('Error', 'Failed to delete account.'); + } + } + }, + ] + ); + }; + + return { + user, + displayName, + isResending, + isModalVisible, + setIsModalVisible, + handleResendVerification, + handleDeleteAccount, + logout, + }; +}; diff --git a/mobile/src/screens/ProfileScreen.tsx b/mobile/src/screens/ProfileScreen.tsx index b608c5f..2245d1d 100644 --- a/mobile/src/screens/ProfileScreen.tsx +++ b/mobile/src/screens/ProfileScreen.tsx @@ -1,68 +1,34 @@ -import React, { useState } from 'react'; -import { View, Text, TouchableOpacity, useColorScheme, ScrollView, Alert, Image, ActivityIndicator, Modal } from 'react-native'; +import React from 'react'; +import { View, Text, TouchableOpacity, useColorScheme, ScrollView, Image, ActivityIndicator, Modal, Alert } from 'react-native'; import { Ionicons } from '@expo/vector-icons'; import { useNavigation } from '@react-navigation/native'; import { NativeStackNavigationProp } from '@react-navigation/native-stack'; import { RootStackParamList } from '../navigation/AppNavigator'; -import { getThemeStyles, commonStyles } from '../theme/styles'; -import { useAuthStore } from '../store/useAuthStore'; -import { authService } from '../services/api'; +import { getThemeStyles } from '../theme/styles'; import { COLORS } from '../theme/colors'; +import { useProfileLogic } from '../hooks/useProfileLogic'; import appConfig from '../../app.json'; export default function ProfileScreen() { const navigation = useNavigation>(); - const { user, logout } = useAuthStore(); - const [isResending, setIsResending] = useState(false); - const [isModalVisible, setIsModalVisible] = useState(false); const colorScheme = useColorScheme(); const isDark = colorScheme === 'dark'; const themeStyles = getThemeStyles(isDark); const themeColors = isDark ? COLORS.DARK : COLORS.LIGHT; + const { + user, + displayName, + isResending, + isModalVisible, + setIsModalVisible, + handleResendVerification, + handleDeleteAccount, + logout, + } = useProfileLogic(); + if (!user) return null; - const displayName = - (user.user?.first_name && user.user?.last_name) ? `${user.user.first_name} ${user.user.last_name}` : - user.user?.username ? user.user.username : - user.user?.email ? user.user.email.split('@')[0] : - 'User Name'; - - const handleResendVerification = async () => { - setIsResending(true); - const result = await authService.resendVerificationEmail(); - setIsResending(false); - - if (result.ok) { - Alert.alert('Email Sent', 'Please check your email (or server logs) for the verification link.'); - } else { - Alert.alert('Error', result.message || 'Failed to resend verification email'); - } - }; - - const handleDeleteAccount = () => { - Alert.alert( - 'Delete Account', - 'Are you sure you want to permanently delete your account? This action cannot be undone.', - [ - { text: 'Cancel', style: 'cancel' }, - { - text: 'Delete', - style: 'destructive', - onPress: async () => { - const result = await authService.deleteAccount(); - if (result.ok) { - logout(); - Alert.alert('Success', 'Your account has been deleted.'); - } else { - Alert.alert('Error', 'Failed to delete account.'); - } - } - }, - ] - ); - }; - const MenuItem = ({ icon, label, onPress, isDestructive = false }: { icon: string, label: string, onPress: () => void, isDestructive?: boolean }) => (