/** * Settings Screen * * User settings and app configuration */ import { View, Text, StyleSheet, ScrollView, TouchableOpacity, Alert, Switch } from 'react-native'; import { useState, useEffect } from 'react'; import { Ionicons } from '@expo/vector-icons'; import { useAuthStore } from '@/stores'; import { useNotifications, useBiometrics } from '@/hooks'; import { useOfflineStore, syncManager } from '@/services/offline'; interface SettingItemProps { icon: keyof typeof Ionicons.glyphMap; title: string; subtitle?: string; onPress?: () => void; trailing?: React.ReactNode; danger?: boolean; } function SettingItem({ icon, title, subtitle, onPress, trailing, danger }: SettingItemProps) { return ( {title} {subtitle && {subtitle}} {trailing || (onPress && )} ); } export default function SettingsScreen() { const { user, token, logout } = useAuthStore(); const [darkMode, setDarkMode] = useState(false); // Notifications const { isPermissionGranted: notificationsGranted, requestPermission: requestNotificationPermission, unreadCount, } = useNotifications(); // Biometrics const { isAvailable: biometricsAvailable, isEnrolled: biometricsEnrolled, isEnabled: biometricsEnabled, biometricTypeName, enableBiometricLogin, disableBiometricLogin, isLoading: biometricsLoading, } = useBiometrics(); // Offline const { isOnline, syncQueue } = useOfflineStore(); const pendingSyncCount = syncQueue.filter((s) => s.status === 'pending').length; const handleNotificationsToggle = async (value: boolean) => { if (value && !notificationsGranted) { const granted = await requestNotificationPermission(); if (!granted) { Alert.alert( 'Permisos Requeridos', 'Necesitamos permiso para enviar notificaciones. Por favor, habilítalas en la configuración del dispositivo.' ); } } }; const handleBiometricsToggle = async (value: boolean) => { if (value) { if (!biometricsAvailable) { Alert.alert('No Disponible', 'Tu dispositivo no soporta autenticación biométrica.'); return; } if (!biometricsEnrolled) { Alert.alert('No Configurado', 'No hay datos biométricos registrados en tu dispositivo.'); return; } if (token) { const success = await enableBiometricLogin(token); if (!success) { Alert.alert('Error', 'No se pudo habilitar el inicio de sesión biométrico.'); } } } else { await disableBiometricLogin(); } }; const handleLogout = () => { Alert.alert( 'Cerrar Sesión', '¿Estás seguro que deseas cerrar sesión?', [ { text: 'Cancelar', style: 'cancel' }, { text: 'Cerrar Sesión', style: 'destructive', onPress: () => logout(), }, ] ); }; const handleChangePassword = () => { Alert.alert('Próximamente', 'Esta función estará disponible pronto'); }; const handleHelp = () => { Alert.alert('Ayuda', 'Contacta soporte en: soporte@erp-generic.com'); }; const handleSyncNow = () => { if (!isOnline) { Alert.alert('Sin Conexión', 'No hay conexión a internet para sincronizar.'); return; } if (pendingSyncCount === 0) { Alert.alert('Todo Sincronizado', 'No hay cambios pendientes por sincronizar.'); return; } Alert.alert('Sincronizando', `Sincronizando ${pendingSyncCount} cambios...`); }; return ( {/* Profile Section */} {user?.fullName?.charAt(0).toUpperCase() || 'U'} {user?.fullName || 'Usuario'} {user?.email || 'email@ejemplo.com'} {/* Account Section */} Cuenta {}} /> {/* Preferences Section */} Preferencias } /> } /> } /> {}} /> {}} /> {/* Sync Section */} Sincronización 0 ? `${pendingSyncCount} por sincronizar` : 'Todo sincronizado'} onPress={handleSyncNow} /> {/* Support Section */} Soporte {}} /> {}} /> {/* Logout Section */} {/* Version */} ERP Generic Mobile v0.1.0 © 2026 ERP Generic ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#f8fafc', }, content: { padding: 16, paddingBottom: 32, }, section: { marginBottom: 24, }, sectionTitle: { fontSize: 13, fontWeight: '600', color: '#64748b', textTransform: 'uppercase', letterSpacing: 0.5, marginBottom: 8, marginLeft: 4, }, sectionContent: { backgroundColor: '#ffffff', borderRadius: 12, overflow: 'hidden', }, profileCard: { backgroundColor: '#ffffff', borderRadius: 12, padding: 20, flexDirection: 'row', alignItems: 'center', }, profileAvatar: { width: 64, height: 64, borderRadius: 32, backgroundColor: '#1e40af', justifyContent: 'center', alignItems: 'center', }, profileInitial: { fontSize: 24, fontWeight: '700', color: '#ffffff', }, profileInfo: { marginLeft: 16, flex: 1, }, profileName: { fontSize: 20, fontWeight: '600', color: '#1f2937', }, profileEmail: { fontSize: 14, color: '#64748b', marginTop: 2, }, settingItem: { flexDirection: 'row', alignItems: 'center', padding: 16, borderBottomWidth: 1, borderBottomColor: '#f1f5f9', }, settingIcon: { width: 36, height: 36, borderRadius: 8, backgroundColor: '#eff6ff', justifyContent: 'center', alignItems: 'center', marginRight: 12, }, settingIconDanger: { backgroundColor: '#fef2f2', }, settingContent: { flex: 1, }, settingTitle: { fontSize: 16, color: '#1f2937', }, settingTitleDanger: { color: '#dc2626', }, settingSubtitle: { fontSize: 13, color: '#9ca3af', marginTop: 2, }, footer: { alignItems: 'center', paddingTop: 16, }, version: { fontSize: 13, color: '#9ca3af', }, copyright: { fontSize: 12, color: '#d1d5db', marginTop: 4, }, });