native_convex_CRM/app/features/profile/profile.screen.tsx
2026-07-24 13:15:31 +05:30

277 lines
8.4 KiB
TypeScript

import React, { useState } from 'react';
import {
Text,
View,
TouchableOpacity,
ScrollView,
Switch,
Image,
} from 'react-native';
import { useNavigation } from '@react-navigation/native';
import Icon from 'react-native-vector-icons/Ionicons';
import { getStyles } from './profile.styles';
import { useTheme } from '../../theme';
import { ProfileInfoRow } from '@components';
import { useAppDispatch, useAppSelector, logout, RootState } from '@store';
export const ProfileScreen = () => {
const navigation = useNavigation<any>();
const { theme: colors, isDark, toggleTheme } = useTheme();
const styles = getStyles(colors);
const dispatch = useAppDispatch();
const [pushEnabled, setPushEnabled] = useState(true);
const userData = useAppSelector((state: RootState) => state.auth.user_data);
const handleLogout = async () => {
try {
dispatch(logout());
} catch (e) {
console.error(e);
}
navigation.reset({
index: 0,
routes: [{ name: 'AuthStack' }],
});
};
// Derive user info
const fullName =
userData?.full_name ||
`${userData?.firstname || ''} ${userData?.lastname || ''}`.trim() ||
'User Profile';
const email = userData?.email || 'N/A';
const phone = userData?.phonenumber || 'N/A';
const staffId = userData?.staffid ? `#${userData.staffid}` : 'N/A';
const isAdmin = userData?.admin === '1';
const roleText = isAdmin ? 'Administrator' : 'Staff Member';
const isActive = userData?.active === '1';
const hasProfileImage =
userData?.profile_image && userData.profile_image.startsWith('http');
// Derive initials
const initials = fullName
.split(' ')
.filter(Boolean)
.map(n => n[0])
.join('')
.substring(0, 2)
.toUpperCase() || 'U';
const hasSocials =
Boolean(userData?.linkedin) ||
Boolean(userData?.facebook) ||
Boolean(userData?.skype);
return (
<ScrollView style={styles.container} contentContainerStyle={styles.content}>
{/* ── Header Card ── */}
<View style={styles.headerCard}>
<View style={styles.avatarWrapper}>
{hasProfileImage ? (
<Image
source={{ uri: userData!.profile_image }}
style={styles.avatarImage}
/>
) : (
<View style={styles.avatarCircle}>
<Text style={styles.avatarInitial}>{initials}</Text>
</View>
)}
{isActive && <View style={styles.onlineDot} />}
</View>
<Text style={styles.profileName}>{fullName}</Text>
<Text style={styles.profileEmail}>{email}</Text>
<View style={styles.roleBadge}>
<Text style={styles.roleBadgeText}>{roleText}</Text>
</View>
</View>
{/* ── Stats Summary Row ── */}
<View style={styles.statsRow}>
<View style={styles.statBox}>
<Text style={styles.statValue}>{userData?.staffid || '—'}</Text>
<Text style={styles.statLabel}>Staff ID</Text>
</View>
<View style={styles.statBox}>
<Text style={styles.statValue}>
{userData?.total_unfinished_todos ?? '0'}
</Text>
<Text style={styles.statLabel}>Pending Todos</Text>
</View>
<View style={styles.statBox}>
<Text style={styles.statValue}>
{userData?.total_unread_notifications ?? '0'}
</Text>
<Text style={styles.statLabel}>Unread Alerts</Text>
</View>
</View>
{/* ── Personal Details ── */}
<View style={styles.sectionCard}>
<Text style={styles.sectionHeader}>Personal Details</Text>
<ProfileInfoRow
icon="person-outline"
label="Name"
value={fullName}
/>
<ProfileInfoRow
icon="card-outline"
label="Staff ID"
value={staffId}
/>
<ProfileInfoRow
icon="mail-outline"
label="Email"
value={email}
/>
<ProfileInfoRow
icon="call-outline"
label="Phone"
value={phone}
/>
<ProfileInfoRow
icon="shield-checkmark-outline"
label="Role"
value={roleText}
isLast
/>
</View>
{/* ── System & Account ── */}
<View style={styles.sectionCard}>
<Text style={styles.sectionHeader}>System &amp; Account</Text>
<ProfileInfoRow
icon="checkmark-circle-outline"
label="Account Status"
value={isActive ? 'Active' : 'Inactive'}
valueColor={isActive ? '#10B981' : '#EF4444'}
isBadge
badgeBgColor={isActive ? '#10B98120' : '#EF444420'}
/>
<ProfileInfoRow
icon="key-outline"
label="Two-Factor Auth"
value={
userData?.two_factor_auth_enabled === '1'
? 'Enabled'
: 'Disabled'
}
/>
{userData?.default_language ? (
<ProfileInfoRow
icon="language-outline"
label="Default Language"
value={userData.default_language.toUpperCase()}
/>
) : null}
<ProfileInfoRow
icon="time-outline"
label="Last Login"
value={userData?.last_login || 'N/A'}
isLast
/>
</View>
{/* ── Social Profiles ── */}
{hasSocials && (
<View style={styles.sectionCard}>
<Text style={styles.sectionHeader}>Social Profiles</Text>
{userData?.linkedin ? (
<ProfileInfoRow
icon="logo-linkedin"
label="LinkedIn"
value={userData.linkedin}
/>
) : null}
{userData?.facebook ? (
<ProfileInfoRow
icon="logo-facebook"
label="Facebook"
value={userData.facebook}
/>
) : null}
{userData?.skype ? (
<ProfileInfoRow
icon="logo-skype"
label="Skype"
value={userData.skype}
isLast
/>
) : null}
</View>
)}
{/* ── Preferences ── */}
<View style={styles.sectionCard}>
<Text style={styles.sectionHeader}>Preferences</Text>
<View style={styles.preferenceRow}>
<View style={styles.preferenceLabelGroup}>
<View style={styles.iconWrapper}>
<Icon
name={isDark ? 'moon' : 'moon-outline'}
size={18}
color={colors.icon}
/>
</View>
<Text style={styles.preferenceText}>Dark Mode</Text>
</View>
<Switch
value={isDark}
onValueChange={toggleTheme}
trackColor={{ false: '#767577', true: colors.icon }}
thumbColor={isDark ? '#ffffff' : '#f4f3f4'}
/>
</View>
{/* <TouchableOpacity style={styles.preferenceRow} activeOpacity={0.7}>
<View style={styles.preferenceLabelGroup}>
<View style={styles.iconWrapper}>
<Icon
name="notifications-outline"
size={18}
color={colors.icon}
/>
</View>
<Text style={styles.preferenceText}>Push Notifications</Text>
</View>
<Icon name="chevron-forward" size={18} color={colors.textMuted} />
</TouchableOpacity> */}
<View style={[styles.preferenceRow, styles.noBorder]}>
<View style={styles.preferenceLabelGroup}>
<View style={styles.iconWrapper}>
<Icon name="notifications-outline" size={18} color={colors.icon} />
</View>
<Text style={styles.preferenceText}>Push Notifications</Text>
</View>
<Switch
value={pushEnabled}
onValueChange={setPushEnabled}
trackColor={{ false: '#767577', true: colors.icon }}
thumbColor={pushEnabled ? '#ffffff' : '#f4f3f4'}
/>
</View>
</View>
{/* ── Sign Out ── */}
<TouchableOpacity
style={styles.signOutButton}
activeOpacity={0.8}
onPress={handleLogout}>
<Icon
name="log-out-outline"
size={20}
color="#FFFFFF"
style={styles.buttonIcon}
/>
<Text style={styles.signOutButtonText}>Sign Out</Text>
</TouchableOpacity>
</ScrollView>
);
};