WellNuo/app/(tabs)/profile/language.tsx
Sergei abcc380984 Sync all changes - profile restructure and scheme updates
- Restructured profile screens location
- Updated beneficiary detail page
- Updated API service
- Updated all scheme files (MainScheme, ENV API, Discussion, AppStore, SysAnal)
- Added PageHeader component

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-12 16:48:07 -08:00

339 lines
10 KiB
TypeScript

import React, { useState } from 'react';
import {
View,
Text,
StyleSheet,
ScrollView,
TouchableOpacity,
Alert,
} from 'react-native';
import { Ionicons } from '@expo/vector-icons';
import { SafeAreaView } from 'react-native-safe-area-context';
import { router } from 'expo-router';
import { AppColors, BorderRadius, FontSizes, Spacing } from '@/constants/theme';
import { PageHeader } from '@/components/PageHeader';
interface LanguageOptionProps {
code: string;
name: string;
nativeName: string;
flag: string;
isSelected: boolean;
isAvailable: boolean;
onSelect: () => void;
}
function LanguageOption({
code,
name,
nativeName,
flag,
isSelected,
isAvailable,
onSelect,
}: LanguageOptionProps) {
return (
<TouchableOpacity
style={[styles.languageOption, isSelected && styles.languageOptionSelected]}
onPress={onSelect}
disabled={!isAvailable}
>
<Text style={styles.flag}>{flag}</Text>
<View style={styles.languageInfo}>
<Text style={[styles.languageName, !isAvailable && styles.languageNameDisabled]}>
{name}
</Text>
<Text style={styles.languageNative}>{nativeName}</Text>
</View>
{!isAvailable ? (
<View style={styles.comingSoonBadge}>
<Text style={styles.comingSoonText}>Coming Soon</Text>
</View>
) : isSelected ? (
<Ionicons name="checkmark-circle" size={24} color={AppColors.primary} />
) : null}
</TouchableOpacity>
);
}
export default function LanguageScreen() {
const [selectedLanguage, setSelectedLanguage] = useState('en');
const languages = [
{ code: 'en', name: 'English', nativeName: 'English', flag: '🇺🇸', available: true },
{ code: 'es', name: 'Spanish', nativeName: 'Español', flag: '🇪🇸', available: false },
{ code: 'fr', name: 'French', nativeName: 'Français', flag: '🇫🇷', available: false },
{ code: 'de', name: 'German', nativeName: 'Deutsch', flag: '🇩🇪', available: false },
{ code: 'it', name: 'Italian', nativeName: 'Italiano', flag: '🇮🇹', available: false },
{ code: 'pt', name: 'Portuguese', nativeName: 'Português', flag: '🇵🇹', available: false },
{ code: 'nl', name: 'Dutch', nativeName: 'Nederlands', flag: '🇳🇱', available: false },
{ code: 'pl', name: 'Polish', nativeName: 'Polski', flag: '🇵🇱', available: false },
{ code: 'ru', name: 'Russian', nativeName: 'Русский', flag: '🇷🇺', available: false },
{ code: 'ja', name: 'Japanese', nativeName: '日本語', flag: '🇯🇵', available: false },
{ code: 'zh', name: 'Chinese', nativeName: '中文', flag: '🇨🇳', available: false },
{ code: 'ko', name: 'Korean', nativeName: '한국어', flag: '🇰🇷', available: false },
];
const handleSelectLanguage = (code: string, name: string, available: boolean) => {
if (!available) {
Alert.alert(
'Coming Soon',
`${name} translation is not available yet. We're working on adding more languages!`,
[{ text: 'OK' }]
);
return;
}
if (code === selectedLanguage) {
return;
}
Alert.alert(
'Change Language',
`Are you sure you want to change the app language to ${name}?`,
[
{ text: 'Cancel', style: 'cancel' },
{
text: 'Change',
onPress: () => {
setSelectedLanguage(code);
Alert.alert(
'Language Changed',
`The app language has been changed to ${name}. Some changes may require restarting the app.`,
[{ text: 'OK', onPress: () => router.back() }]
);
},
},
]
);
};
const availableLanguages = languages.filter(l => l.available);
const comingSoonLanguages = languages.filter(l => !l.available);
return (
<SafeAreaView style={styles.container} edges={['top', 'bottom']}>
<PageHeader title="Language" />
<ScrollView showsVerticalScrollIndicator={false}>
{/* Current Language */}
<View style={styles.section}>
<View style={styles.currentLanguageCard}>
<Ionicons name="globe" size={24} color={AppColors.primary} />
<View style={styles.currentLanguageInfo}>
<Text style={styles.currentLanguageLabel}>Current Language</Text>
<Text style={styles.currentLanguageName}>
{languages.find(l => l.code === selectedLanguage)?.name || 'English'}
</Text>
</View>
</View>
</View>
{/* Available Languages */}
<View style={styles.section}>
<Text style={styles.sectionTitle}>Available Languages</Text>
<View style={styles.languagesCard}>
{availableLanguages.map((lang, index) => (
<View key={lang.code}>
<LanguageOption
code={lang.code}
name={lang.name}
nativeName={lang.nativeName}
flag={lang.flag}
isSelected={selectedLanguage === lang.code}
isAvailable={lang.available}
onSelect={() => handleSelectLanguage(lang.code, lang.name, lang.available)}
/>
{index < availableLanguages.length - 1 && <View style={styles.divider} />}
</View>
))}
</View>
</View>
{/* Coming Soon Languages */}
<View style={styles.section}>
<Text style={styles.sectionTitle}>Coming Soon</Text>
<View style={styles.languagesCard}>
{comingSoonLanguages.map((lang, index) => (
<View key={lang.code}>
<LanguageOption
code={lang.code}
name={lang.name}
nativeName={lang.nativeName}
flag={lang.flag}
isSelected={false}
isAvailable={lang.available}
onSelect={() => handleSelectLanguage(lang.code, lang.name, lang.available)}
/>
{index < comingSoonLanguages.length - 1 && <View style={styles.divider} />}
</View>
))}
</View>
</View>
{/* Help Translate */}
<View style={styles.section}>
<TouchableOpacity
style={styles.helpTranslateCard}
onPress={() => Alert.alert(
'Help Us Translate',
'We\'d love your help translating WellNuo into more languages!\n\n' +
'If you\'re fluent in another language and would like to contribute, ' +
'please contact us at translations@wellnuo.com',
[{ text: 'OK' }]
)}
>
<View style={styles.helpTranslateIcon}>
<Ionicons name="language" size={24} color={AppColors.primary} />
</View>
<View style={styles.helpTranslateContent}>
<Text style={styles.helpTranslateTitle}>Help Us Translate</Text>
<Text style={styles.helpTranslateDescription}>
Want to see WellNuo in your language? Help us by contributing translations.
</Text>
</View>
<Ionicons name="chevron-forward" size={20} color={AppColors.textMuted} />
</TouchableOpacity>
</View>
{/* Note */}
<View style={styles.noteContainer}>
<Ionicons name="information-circle" size={16} color={AppColors.textMuted} />
<Text style={styles.noteText}>
Changing the language will translate the app interface. Beneficiary data and
system notifications may remain in the original language.
</Text>
</View>
</ScrollView>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: AppColors.surface,
},
section: {
marginTop: Spacing.md,
},
sectionTitle: {
fontSize: FontSizes.sm,
fontWeight: '600',
color: AppColors.textSecondary,
paddingHorizontal: Spacing.lg,
paddingVertical: Spacing.sm,
textTransform: 'uppercase',
},
currentLanguageCard: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: AppColors.background,
marginHorizontal: Spacing.lg,
padding: Spacing.md,
borderRadius: BorderRadius.lg,
},
currentLanguageInfo: {
marginLeft: Spacing.md,
},
currentLanguageLabel: {
fontSize: FontSizes.xs,
color: AppColors.textMuted,
},
currentLanguageName: {
fontSize: FontSizes.lg,
fontWeight: '600',
color: AppColors.textPrimary,
marginTop: 2,
},
languagesCard: {
backgroundColor: AppColors.background,
},
languageOption: {
flexDirection: 'row',
alignItems: 'center',
paddingVertical: Spacing.md,
paddingHorizontal: Spacing.lg,
},
languageOptionSelected: {
backgroundColor: '#DBEAFE',
},
flag: {
fontSize: 28,
},
languageInfo: {
flex: 1,
marginLeft: Spacing.md,
},
languageName: {
fontSize: FontSizes.base,
fontWeight: '500',
color: AppColors.textPrimary,
},
languageNameDisabled: {
color: AppColors.textMuted,
},
languageNative: {
fontSize: FontSizes.xs,
color: AppColors.textSecondary,
marginTop: 2,
},
comingSoonBadge: {
backgroundColor: AppColors.surface,
paddingHorizontal: Spacing.sm,
paddingVertical: 4,
borderRadius: BorderRadius.sm,
},
comingSoonText: {
fontSize: FontSizes.xs,
color: AppColors.textMuted,
},
divider: {
height: 1,
backgroundColor: AppColors.border,
marginLeft: Spacing.lg + 28 + Spacing.md,
},
helpTranslateCard: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: AppColors.background,
marginHorizontal: Spacing.lg,
padding: Spacing.md,
borderRadius: BorderRadius.lg,
},
helpTranslateIcon: {
width: 48,
height: 48,
borderRadius: BorderRadius.md,
backgroundColor: '#DBEAFE',
justifyContent: 'center',
alignItems: 'center',
},
helpTranslateContent: {
flex: 1,
marginLeft: Spacing.md,
},
helpTranslateTitle: {
fontSize: FontSizes.base,
fontWeight: '500',
color: AppColors.textPrimary,
},
helpTranslateDescription: {
fontSize: FontSizes.xs,
color: AppColors.textMuted,
marginTop: 2,
},
noteContainer: {
flexDirection: 'row',
alignItems: 'flex-start',
marginHorizontal: Spacing.lg,
marginVertical: Spacing.lg,
},
noteText: {
flex: 1,
fontSize: FontSizes.xs,
color: AppColors.textMuted,
marginLeft: Spacing.sm,
lineHeight: 18,
},
});