diff --git a/frontend/src/screens/LanguageSettingsScreen.tsx b/frontend/src/screens/LanguageSettingsScreen.tsx new file mode 100644 index 00000000..74ffb619 --- /dev/null +++ b/frontend/src/screens/LanguageSettingsScreen.tsx @@ -0,0 +1,173 @@ +import React, { useState } from 'react'; +import { + View, + Text, + StyleSheet, + ScrollView, + TouchableOpacity, + Alert, +} from 'react-native'; +import { Ionicons } from '@expo/vector-icons'; +import { useSafeAreaInsets } from 'react-native-safe-area-context'; + +const LANGUAGES = [ + { code: 'en', name: 'English', nativeName: 'English', flag: '🇺🇸' }, + { code: 'ku-sorani', name: 'Kurdish Sorani', nativeName: 'کوردی سۆرانی', flag: '🟥' }, + { code: 'ku-kurmanji', name: 'Kurdish Kurmanji', nativeName: 'Kurdî Kurmancî', flag: '🟨' }, + { code: 'ar', name: 'Arabic', nativeName: 'العربية', flag: '🇸🇦' }, + { code: 'tr', name: 'Turkish', nativeName: 'Türkçe', flag: '🇹🇷' }, + { code: 'fa', name: 'Persian', nativeName: 'فارسی', flag: '🇮🇷' }, +]; + +export default function LanguageSettingsScreen({ navigation }: any) { + const insets = useSafeAreaInsets(); + const [selectedLanguage, setSelectedLanguage] = useState('en'); + + const handleLanguageChange = (languageCode: string) => { + setSelectedLanguage(languageCode); + // TODO: Save to backend and apply i18n + Alert.alert( + 'Language Changed', + 'Language preference has been saved. Full translation will be available in the next update.', + [ + { + text: 'OK', + onPress: () => navigation.goBack(), + }, + ] + ); + }; + + return ( + + + navigation.goBack()} style={styles.backButton}> + + + Language + + + + + + + + 6 languages fully supported. Other languages use Google Translator. + + + + {LANGUAGES.map((language) => ( + handleLanguageChange(language.code)} + > + + {language.flag} + + {language.name} + {language.nativeName} + + + {selectedLanguage === language.code && ( + + )} + + ))} + + + ); +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: '#F8F9FA', + }, + header: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + paddingHorizontal: 16, + paddingVertical: 16, + backgroundColor: '#FFF', + borderBottomWidth: 1, + borderBottomColor: '#E5E7EB', + }, + backButton: { + width: 40, + height: 40, + borderRadius: 20, + backgroundColor: '#F3F4F6', + alignItems: 'center', + justifyContent: 'center', + }, + headerTitle: { + fontSize: 18, + fontWeight: '700', + color: '#1F2937', + }, + scrollContent: { + padding: 16, + paddingBottom: 80, + }, + infoBox: { + flexDirection: 'row', + alignItems: 'center', + backgroundColor: '#DBEAFE', + padding: 12, + borderRadius: 8, + marginBottom: 16, + }, + infoText: { + fontSize: 14, + color: '#1E40AF', + marginLeft: 8, + flex: 1, + }, + languageCard: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + backgroundColor: '#FFF', + padding: 16, + borderRadius: 12, + marginBottom: 12, + borderWidth: 2, + borderColor: '#E5E7EB', + shadowColor: '#000', + shadowOffset: { width: 0, height: 1 }, + shadowOpacity: 0.05, + shadowRadius: 4, + elevation: 2, + }, + languageCardSelected: { + borderColor: '#EE2A35', + backgroundColor: '#FEE2E2', + }, + languageCardLeft: { + flexDirection: 'row', + alignItems: 'center', + flex: 1, + }, + flag: { + fontSize: 32, + marginRight: 12, + }, + languageInfo: { + flex: 1, + }, + languageName: { + fontSize: 16, + fontWeight: '600', + color: '#1F2937', + marginBottom: 2, + }, + languageNative: { + fontSize: 14, + color: '#6B7280', + }, +}); \ No newline at end of file diff --git a/frontend/src/screens/WalletAddressScreen.tsx b/frontend/src/screens/WalletAddressScreen.tsx new file mode 100644 index 00000000..f4bbcac4 --- /dev/null +++ b/frontend/src/screens/WalletAddressScreen.tsx @@ -0,0 +1,286 @@ +import React, { useState, useEffect } from 'react'; +import { + View, + Text, + StyleSheet, + TouchableOpacity, + TextInput, + ScrollView, + Alert, + ActivityIndicator, + Clipboard, +} from 'react-native'; +import { Ionicons } from '@expo/vector-icons'; +import { useSafeAreaInsets } from 'react-native-safe-area-context'; +import { useAuth } from '../contexts/AuthContext'; +import { API_ENDPOINTS } from '../config/api'; + +export default function WalletAddressScreen({ navigation }: any) { + const insets = useSafeAreaInsets(); + const { user } = useAuth(); + const [loading, setLoading] = useState(false); + const [walletAddress, setWalletAddress] = useState(''); + const [isEditing, setIsEditing] = useState(false); + + useEffect(() => { + loadWalletAddress(); + }, []); + + const loadWalletAddress = async () => { + try { + const response = await fetch(`${API_ENDPOINTS.AUTH_USER(user?.user_id || '')}`); + if (response.ok) { + const data = await response.json(); + setWalletAddress(data.wallet_address || ''); + } + } catch (error) { + console.error('Error loading wallet address:', error); + } + }; + + const handleSave = async () => { + if (!walletAddress.trim()) { + Alert.alert('Error', 'Wallet address cannot be empty'); + return; + } + + setLoading(true); + try { + const backendUrl = process.env.EXPO_PUBLIC_BACKEND_URL || 'http://localhost:8001'; + const response = await fetch(`${backendUrl}/api/auth/profile`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + user_id: user?.user_id, + wallet_address: walletAddress, + }), + }); + + if (response.ok) { + Alert.alert('Success', 'Wallet address updated successfully!'); + setIsEditing(false); + } else { + Alert.alert('Error', 'Failed to update wallet address'); + } + } catch (error) { + Alert.alert('Error', 'Network error occurred'); + } finally { + setLoading(false); + } + }; + + const copyToClipboard = () => { + Clipboard.setString(walletAddress); + Alert.alert('Copied', 'Wallet address copied to clipboard'); + }; + + return ( + + + navigation.goBack()} style={styles.backButton}> + + + Wallet Address + + + + + + + + Your wallet address is used to receive HEZ and PEZ tokens. Make sure it's correct. + + + + + Wallet Address + {isEditing ? ( + + ) : ( + + + {walletAddress || 'No wallet address set'} + + + + + + )} + + + {isEditing ? ( + + { + setIsEditing(false); + loadWalletAddress(); + }} + > + Cancel + + + {loading ? ( + + ) : ( + Save + )} + + + ) : ( + setIsEditing(true)} + > + + Edit Wallet Address + + )} + + + ); +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: '#F8F9FA', + }, + header: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + paddingHorizontal: 16, + paddingVertical: 16, + backgroundColor: '#FFF', + borderBottomWidth: 1, + borderBottomColor: '#E5E7EB', + }, + backButton: { + width: 40, + height: 40, + borderRadius: 20, + backgroundColor: '#F3F4F6', + alignItems: 'center', + justifyContent: 'center', + }, + headerTitle: { + fontSize: 18, + fontWeight: '700', + color: '#1F2937', + }, + scrollContent: { + padding: 16, + paddingBottom: 80, + }, + infoBox: { + flexDirection: 'row', + alignItems: 'center', + backgroundColor: '#DBEAFE', + padding: 12, + borderRadius: 8, + marginBottom: 24, + }, + infoText: { + fontSize: 14, + color: '#1E40AF', + marginLeft: 8, + flex: 1, + }, + section: { + marginBottom: 20, + }, + label: { + fontSize: 14, + fontWeight: '600', + color: '#374151', + marginBottom: 8, + }, + input: { + backgroundColor: '#FFF', + padding: 16, + borderRadius: 12, + fontSize: 14, + borderWidth: 1, + borderColor: '#E5E7EB', + minHeight: 80, + textAlignVertical: 'top', + }, + addressContainer: { + flexDirection: 'row', + alignItems: 'center', + backgroundColor: '#FFF', + padding: 16, + borderRadius: 12, + borderWidth: 1, + borderColor: '#E5E7EB', + }, + addressText: { + flex: 1, + fontSize: 14, + color: '#374151', + fontFamily: 'monospace', + }, + copyButton: { + padding: 8, + marginLeft: 8, + }, + buttonRow: { + flexDirection: 'row', + gap: 12, + marginTop: 24, + }, + button: { + flex: 1, + padding: 16, + borderRadius: 12, + alignItems: 'center', + }, + cancelButton: { + backgroundColor: '#F3F4F6', + }, + cancelButtonText: { + fontSize: 16, + fontWeight: '600', + color: '#6B7280', + }, + saveButton: { + backgroundColor: '#EE2A35', + }, + saveButtonDisabled: { + opacity: 0.6, + }, + saveButtonText: { + fontSize: 16, + fontWeight: '600', + color: '#FFF', + }, + editButton: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + backgroundColor: '#EE2A35', + padding: 16, + borderRadius: 12, + marginTop: 24, + }, + editButtonText: { + fontSize: 16, + fontWeight: '600', + color: '#FFF', + marginLeft: 8, + }, +}); \ No newline at end of file