diff --git a/mobile/PHASE_1_COMPLETE.md b/mobile/PHASE_1_COMPLETE.md index 7ad8cfad..7713fd4f 100644 --- a/mobile/PHASE_1_COMPLETE.md +++ b/mobile/PHASE_1_COMPLETE.md @@ -188,14 +188,39 @@ boxShadow: '0 2px 4px rgba(0, 0, 0, 0.05)', **Files Fixed:** - SettingsScreen.tsx +### Fixed React Native Web Compatibility + +**Issue:** Alert.alert() with button arrays doesn't work properly on React Native Web + +**Fix:** +- Created FontSizeModal.tsx to replace Alert-based font size selector +- Simplified biometric toggle to avoid button arrays +- Now all interactive elements use proper modals or simple alerts + +**Files Fixed:** +- SettingsScreen.tsx - Replaced Alert.alert() with modal +- FontSizeModal.tsx - NEW professional font size selector + +### Fixed TypeScript Errors + +**Issue:** TermsOfServiceModal and PrivacyPolicyModal don't accept `onAccept` prop + +**Fix:** +- Removed `onAccept` prop from modal calls in SettingsScreen +- Modals now only use `visible` and `onClose` props + +**Files Fixed:** +- SettingsScreen.tsx + --- ## Files Created 1. `/home/mamostehp/pwap/mobile/src/components/EmailNotificationsModal.tsx` - 350 lines 2. `/home/mamostehp/pwap/mobile/src/components/ChangePasswordModal.tsx` - 350 lines +3. `/home/mamostehp/pwap/mobile/src/components/FontSizeModal.tsx` - 200 lines -**Total:** 2 new files, 700 lines of code +**Total:** 3 new files, 900 lines of code --- diff --git a/mobile/src/components/FontSizeModal.tsx b/mobile/src/components/FontSizeModal.tsx new file mode 100644 index 00000000..7f740aa0 --- /dev/null +++ b/mobile/src/components/FontSizeModal.tsx @@ -0,0 +1,175 @@ +import React from 'react'; +import { + Modal, + View, + Text, + TouchableOpacity, + StyleSheet, +} from 'react-native'; +import { KurdistanColors } from '../theme/colors'; +import { useTheme } from '../contexts/ThemeContext'; + +interface FontSizeModalProps { + visible: boolean; + onClose: () => void; +} + +const FontSizeModal: React.FC = ({ visible, onClose }) => { + const { colors, fontSize, setFontSize } = useTheme(); + const styles = createStyles(colors); + + const handleSelectSize = async (size: 'small' | 'medium' | 'large') => { + await setFontSize(size); + onClose(); + }; + + return ( + + + + + Font Size + + + + + + + + Choose your preferred font size for better readability. + + + handleSelectSize('small')} + > + Small + + The quick brown fox jumps over the lazy dog + + {fontSize === 'small' && } + + + handleSelectSize('medium')} + > + Medium (Default) + + The quick brown fox jumps over the lazy dog + + {fontSize === 'medium' && } + + + handleSelectSize('large')} + > + Large + + The quick brown fox jumps over the lazy dog + + {fontSize === 'large' && } + + + + + + ); +}; + +const createStyles = (colors: any) => StyleSheet.create({ + overlay: { + flex: 1, + backgroundColor: 'rgba(0, 0, 0, 0.5)', + justifyContent: 'center', + alignItems: 'center', + }, + container: { + width: '90%', + maxWidth: 400, + backgroundColor: colors.surface, + borderRadius: 16, + overflow: 'hidden', + }, + header: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + padding: 20, + borderBottomWidth: 1, + borderBottomColor: colors.border, + }, + headerTitle: { + fontSize: 20, + fontWeight: 'bold', + color: colors.text, + }, + closeButton: { + width: 32, + height: 32, + borderRadius: 16, + backgroundColor: colors.background, + justifyContent: 'center', + alignItems: 'center', + }, + closeButtonText: { + fontSize: 20, + color: colors.textSecondary, + }, + content: { + padding: 20, + }, + description: { + fontSize: 14, + color: colors.textSecondary, + marginBottom: 20, + lineHeight: 20, + }, + sizeOption: { + padding: 16, + borderRadius: 12, + borderWidth: 2, + borderColor: colors.border, + marginBottom: 12, + position: 'relative', + }, + sizeOptionSelected: { + borderColor: KurdistanColors.kesk, + backgroundColor: colors.background, + }, + sizeLabel: { + fontSize: 16, + fontWeight: '600', + color: colors.text, + marginBottom: 8, + }, + sizeExample: { + color: colors.textSecondary, + lineHeight: 22, + }, + checkmark: { + position: 'absolute', + top: 16, + right: 16, + fontSize: 24, + color: KurdistanColors.kesk, + fontWeight: 'bold', + }, +}); + +export default FontSizeModal; diff --git a/mobile/src/screens/SettingsScreen.tsx b/mobile/src/screens/SettingsScreen.tsx index 2b89acc3..ba739989 100644 --- a/mobile/src/screens/SettingsScreen.tsx +++ b/mobile/src/screens/SettingsScreen.tsx @@ -17,6 +17,7 @@ import TermsOfServiceModal from '../components/TermsOfServiceModal'; import PrivacyPolicyModal from '../components/PrivacyPolicyModal'; import EmailNotificationsModal from '../components/EmailNotificationsModal'; import ChangePasswordModal from '../components/ChangePasswordModal'; +import FontSizeModal from '../components/FontSizeModal'; import { useTheme } from '../contexts/ThemeContext'; import { useBiometricAuth } from '../contexts/BiometricAuthContext'; import { useAuth } from '../contexts/AuthContext'; @@ -36,10 +37,19 @@ const SettingsScreen: React.FC = () => { const [showPrivacy, setShowPrivacy] = useState(false); const [showEmailPrefs, setShowEmailPrefs] = useState(false); const [showChangePassword, setShowChangePassword] = useState(false); + const [showFontSize, setShowFontSize] = useState(false); // Create styles with current theme colors const styles = React.useMemo(() => createStyles(colors), [colors]); + React.useEffect(() => { + console.log('[Settings] Screen mounted'); + console.log('[Settings] isDarkMode:', isDarkMode); + console.log('[Settings] fontSize:', fontSize); + console.log('[Settings] isBiometricEnabled:', isBiometricEnabled); + console.log('[Settings] styles:', styles ? 'DEFINED' : 'UNDEFINED'); + }, []); + const handleBiometryToggle = async (value: boolean) => { if (value) { // Check if biometric is available @@ -51,24 +61,13 @@ const SettingsScreen: React.FC = () => { return; } - Alert.alert( - t('biometricAuth'), - t('settingsScreen.biometricAlerts.prompt'), - [ - { text: t('common.cancel'), style: 'cancel' }, - { - text: t('common.confirm'), - onPress: async () => { - const success = await enableBiometric(); - if (success) { - Alert.alert(t('settingsScreen.biometricAlerts.successTitle'), t('settingsScreen.biometricAlerts.enabled')); - } else { - Alert.alert('Error', 'Failed to enable biometric authentication. Please try again.'); - } - }, - }, - ] - ); + // Try to enable biometric directly + const success = await enableBiometric(); + if (success) { + Alert.alert(t('settingsScreen.biometricAlerts.successTitle'), t('settingsScreen.biometricAlerts.enabled')); + } else { + Alert.alert('Error', 'Failed to enable biometric authentication. Please try again.'); + } } else { await disableBiometric(); Alert.alert(t('settingsScreen.biometricAlerts.successTitle'), t('settingsScreen.biometricAlerts.disabled')); @@ -88,7 +87,13 @@ const SettingsScreen: React.FC = () => { onPress: () => void; showArrow?: boolean; }) => ( - + { + console.log(`[Settings] Button pressed: ${title}`); + onPress(); + }} + > {icon} @@ -162,27 +167,7 @@ const SettingsScreen: React.FC = () => { icon="📏" title="Font Size" subtitle={`Current: ${fontSize.charAt(0).toUpperCase() + fontSize.slice(1)}`} - onPress={() => { - Alert.alert( - 'Font Size', - 'Choose your preferred font size', - [ - { - text: 'Small', - onPress: async () => await setFontSize('small'), - }, - { - text: 'Medium', - onPress: async () => await setFontSize('medium'), - }, - { - text: 'Large', - onPress: async () => await setFontSize('large'), - }, - { text: t('common.cancel'), style: 'cancel' }, - ] - ); - }} + onPress={() => setShowFontSize(true)} /> @@ -274,13 +259,11 @@ const SettingsScreen: React.FC = () => { setShowTerms(false)} - onAccept={() => setShowTerms(false)} /> setShowPrivacy(false)} - onAccept={() => setShowPrivacy(false)} /> { visible={showChangePassword} onClose={() => setShowChangePassword(false)} /> + + setShowFontSize(false)} + /> ); };