NeoScan_Physician/app/modules/Settings/screens/SettingsScreen.tsx
2025-08-14 20:16:03 +05:30

530 lines
14 KiB
TypeScript

/*
* File: SettingsScreen.tsx
* Description: Main settings screen with profile management and app preferences
* Design & Developed by Tech4Biz Solutions
* Copyright (c) Spurrin Innovations. All rights reserved.
*/
import React, { useState, useEffect } from 'react';
import {
View,
Text,
StyleSheet,
ScrollView,
Alert,
RefreshControl,
Image,
} from 'react-native';
import { theme } from '../../../theme/theme';
import {
SettingsSection,
SettingsSectionData,
SettingsItem
} from '../../../shared/types';
import { SettingsHeader } from '../components/SettingsHeader';
import { SettingsSectionComponent } from '../components/SettingsSectionComponent';
import { ProfileCard } from '../components/ProfileCard';
import { CustomModal } from '../../../shared/components';
import { useAppDispatch, useAppSelector } from '../../../store/hooks';
import { logoutUser } from '../../Auth/redux/authActions';
import {
selectUser,
selectUserDisplayName,
selectUserEmail,
selectUserFirstName,
selectUserLastName,
selectUserProfilePhoto,
selectDashboardSettings
} from '../../Auth/redux/authSelectors';
/**
* SettingsScreenProps Interface
*
* Purpose: Defines the props required by the SettingsScreen component
*
* Props:
* - navigation: React Navigation object for screen navigation
*/
interface SettingsScreenProps {
navigation: any;
}
/**
* SettingsScreen Component
*
* Purpose: Main settings screen for user profile management and app preferences
*
* Features:
* 1. User profile overview and quick access
* 2. Comprehensive settings sections
* 3. Navigation to detailed settings screens
* 4. Pull-to-refresh functionality
* 5. Mock data generation for demonstration
*
* Settings Sections:
* - Profile: Personal and professional information
* - Notifications: Alert and notification preferences
* - Clinical: Clinical workflow preferences
* - Privacy: Security and privacy settings
* - Accessibility: Accessibility features
* - About: App information and help
* - Logout: Sign out functionality
*/
export const SettingsScreen: React.FC<SettingsScreenProps> = ({
navigation,
}) => {
// ============================================================================
// STATE MANAGEMENT
// ============================================================================
// Settings sections state
const [settingsSections, setSettingsSections] = useState<SettingsSectionData[]>([]);
// UI state
const [refreshing, setRefreshing] = useState(false);
// Modal state
const [modalVisible, setModalVisible] = useState(false);
const [modalConfig, setModalConfig] = useState({
title: '',
message: '',
type: 'info' as 'success' | 'error' | 'warning' | 'info' | 'confirm',
onConfirm: () => {},
showCancel: false,
icon: '',
});
// Redux dispatch and selectors
const dispatch = useAppDispatch();
// User data from Redux
const user = useAppSelector(selectUser);
const userDisplayName = useAppSelector(selectUserDisplayName);
const userEmail = useAppSelector(selectUserEmail);
const userFirstName = useAppSelector(selectUserFirstName);
const userLastName = useAppSelector(selectUserLastName);
const userProfilePhoto = useAppSelector(selectUserProfilePhoto);
const dashboardSettings = useAppSelector(selectDashboardSettings);
// ============================================================================
// SETTINGS SECTIONS GENERATION
// ============================================================================
/**
* generateSettingsSections Function
*
* Purpose: Generate settings sections with items for the settings screen
*
* Returns: Array of SettingsSectionData with navigation and action items
*/
const generateSettingsSections = (): SettingsSectionData[] => [
{
id: 'PROFILE',
title: 'Profile & Account',
items: [
{
id: 'edit-profile',
title: 'Edit Profile',
subtitle: 'Update personal and professional information',
icon: 'user',
type: 'NAVIGATION',
onPress: () => handleNavigation('PROFILE'),
},
{
id: 'change-password',
title: 'Change Password',
subtitle: 'Update your account password',
icon: 'lock',
type: 'NAVIGATION',
onPress: () => handleNavigation('CHANGE_PASSWORD'),
},
],
},
{
id: 'ABOUT',
title: 'About & Support',
items: [
{
id: 'app-info',
title: 'App Information',
subtitle: 'Version, build number, and details',
icon: 'smartphone',
type: 'NAVIGATION',
onPress: () => handleNavigation('APP_INFO'),
},
{
id: 'help-support',
title: 'Help & Support',
subtitle: 'Contact support and view documentation',
icon: 'help',
type: 'NAVIGATION',
onPress: () => handleNavigation('HELP'),
},
],
},
{
id: 'LOGOUT',
title: 'Account',
items: [
{
id: 'logout',
title: 'Sign Out',
subtitle: 'Sign out of your account',
icon: 'log-out',
type: 'ACTION',
onPress: handleLogout,
},
],
},
];
// ============================================================================
// EFFECTS
// ============================================================================
/**
* useEffect for initial settings sections generation
*
* Purpose: Generate settings sections when component mounts or user data changes
*/
useEffect(() => {
setSettingsSections(generateSettingsSections());
}, [user, dashboardSettings]);
// ============================================================================
// EVENT HANDLERS
// ============================================================================
/**
* handleRefresh Function
*
* Purpose: Handle pull-to-refresh functionality to update settings data
*
* Flow:
* 1. Set refreshing state to true (show loading indicator)
* 2. Simulate API call with delay
* 3. Regenerate settings sections with current user data
* 4. Set refreshing state to false (hide loading indicator)
*/
const handleRefresh = async () => {
setRefreshing(true);
// Simulate API call with 1-second delay
await new Promise<void>(resolve => setTimeout(() => resolve(), 1000));
// Regenerate settings sections with current user data
setSettingsSections(generateSettingsSections());
setRefreshing(false);
};
/**
* handleNavigation Function
*
* Purpose: Handle navigation to different settings screens
*
* @param screen - Screen to navigate to
*/
const handleNavigation = (screen: string) => {
switch (screen) {
case 'APP_INFO':
navigation.navigate('AppInfoScreen');
break;
case 'PROFILE':
navigation.navigate('EditProfileScreen');
break;
case 'CHANGE_PASSWORD':
navigation.navigate('ChangePasswordScreen');
break;
case 'HELP':
// TODO: Implement help and support
setModalConfig({
title: 'Help & Support',
message: 'Help and support functionality coming soon!',
type: 'info',
onConfirm: () => {},
showCancel: false,
icon: 'info',
});
setModalVisible(true);
break;
default:
console.log('Navigate to:', screen);
setModalConfig({
title: 'Navigation',
message: `Navigate to ${screen} screen`,
type: 'info',
onConfirm: () => {},
showCancel: false,
icon: 'info',
});
setModalVisible(true);
}
};
/**
* handleToggleSetting Function
*
* Purpose: Handle toggle settings changes
*
* @param setting - Setting to toggle
*/
const handleToggleSetting = (setting: string) => {
// TODO: Implement setting toggle logic
console.log('Toggle setting:', setting);
setModalConfig({
title: 'Setting Toggle',
message: `Toggle ${setting} setting`,
type: 'info',
icon: 'info',
onConfirm: () => {},
showCancel: false,
});
setModalVisible(true);
};
/**
* handleLogout Function
*
* Purpose: Handle user logout with Redux integration
*
* Flow:
* 1. Show confirmation dialog
* 2. Dispatch logout action to Redux
* 3. Clear authentication state
* 4. Show success message
* 5. Automatically navigate to login screen via Redux state change
*/
const handleLogout = () => {
setModalConfig({
title: 'Sign Out',
message: 'Are you sure you want to sign out?',
type: 'confirm',
icon: 'log-out',
onConfirm: async () => {
try {
// Dispatch logout thunk to Redux
await dispatch(logoutUser());
// Log the logout action
console.log('User logged out successfully');
} catch (error) {
console.error('Logout error:', error);
setModalConfig({
title: 'Error',
message: 'Failed to sign out. Please try again.',
type: 'error',
icon: 'info',
onConfirm: () => {},
showCancel: false,
});
setModalVisible(true);
}
},
showCancel: true,
});
setModalVisible(true);
};
// ============================================================================
// MAIN RENDER
// ============================================================================
return (
<View style={styles.container}>
{/* Settings header with title */}
<SettingsHeader title="Settings" />
{/* Scrollable settings content */}
<ScrollView
style={styles.scrollView}
contentContainerStyle={styles.scrollContent}
refreshControl={
<RefreshControl
refreshing={refreshing}
onRefresh={handleRefresh}
colors={[theme.colors.primary]}
tintColor={theme.colors.primary}
/>
}
showsVerticalScrollIndicator={false}
>
{/* Profile card section */}
{user && (
<View style={styles.profileCard}>
<View style={styles.profileHeader}>
<View style={styles.profileImageContainer}>
{user.profile_photo_url ? (
<Image
source={{ uri: user.profile_photo_url }}
style={styles.profileImage}
resizeMode="cover"
/>
) : (
<View style={styles.fallbackAvatar}>
<Text style={styles.fallbackText}>
{user.first_name.charAt(0)}{user.last_name.charAt(0)}
</Text>
</View>
)}
</View>
<View style={styles.profileInfo}>
<Text style={styles.profileName}>
{user.display_name || `${user.first_name} ${user.last_name}`}
</Text>
<Text style={styles.profileEmail}>{user.email}</Text>
<Text style={styles.profileRole}>Radiologist</Text>
</View>
</View>
</View>
)}
{/* Settings sections */}
{settingsSections.map((section) => (
<SettingsSectionComponent
key={section.id}
section={section}
/>
))}
{/* Bottom spacing for tab bar */}
<View style={styles.bottomSpacing} />
</ScrollView>
{/* Custom Modal */}
<CustomModal
visible={modalVisible}
title={modalConfig.title}
message={modalConfig.message}
type={modalConfig.type}
onConfirm={modalConfig.onConfirm}
showCancel={modalConfig.showCancel}
icon={modalConfig.icon}
confirmText={modalConfig.type === 'confirm' ? 'Sign Out' : 'OK'}
cancelText="Cancel"
onClose={() => setModalVisible(false)}
/>
</View>
);
};
// ============================================================================
// STYLES SECTION
// ============================================================================
const styles = StyleSheet.create({
// Main container for the settings screen
container: {
flex: 1,
backgroundColor: theme.colors.background,
},
// Loading container for initial data loading
loadingContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: theme.colors.background,
},
// Loading text styling
loadingText: {
fontSize: theme.typography.fontSize.bodyLarge,
color: theme.colors.textSecondary,
fontFamily: theme.typography.fontFamily.medium,
},
// Scroll view styling
scrollView: {
flex: 1,
},
// Scroll content styling
scrollContent: {
paddingHorizontal: theme.spacing.md,
},
// Bottom spacing for tab bar
bottomSpacing: {
height: theme.spacing.xl,
},
// Profile card styles
profileCard: {
backgroundColor: theme.colors.background,
borderRadius: theme.borderRadius.medium,
padding: theme.spacing.md,
marginBottom: theme.spacing.md,
...theme.shadows.primary,
},
profileHeader: {
flexDirection: 'row',
alignItems: 'center',
},
profileImageContainer: {
marginRight: theme.spacing.md,
},
profileImage: {
width: 60,
height: 60,
borderRadius: 30,
},
fallbackAvatar: {
width: 60,
height: 60,
borderRadius: 30,
backgroundColor: theme.colors.primary,
justifyContent: 'center',
alignItems: 'center',
},
fallbackText: {
color: theme.colors.background,
fontSize: theme.typography.fontSize.bodyLarge,
fontFamily: theme.typography.fontFamily.bold,
},
profileInfo: {
flex: 1,
},
profileName: {
fontSize: theme.typography.fontSize.bodyLarge,
fontFamily: theme.typography.fontFamily.bold,
color: theme.colors.textPrimary,
marginBottom: theme.spacing.xs,
},
profileEmail: {
fontSize: theme.typography.fontSize.bodyMedium,
fontFamily: theme.typography.fontFamily.regular,
color: theme.colors.textSecondary,
marginBottom: theme.spacing.xs,
},
profileRole: {
fontSize: theme.typography.fontSize.bodySmall,
fontFamily: theme.typography.fontFamily.medium,
color: theme.colors.primary,
},
});
/*
* End of File: SettingsScreen.tsx
* Design & Developed by Tech4Biz Solutions
* Copyright (c) Spurrin Innovations. All rights reserved.
*/