152 lines
4.1 KiB
TypeScript
152 lines
4.1 KiB
TypeScript
import { languages } from '@/constants/languages';
|
|
import { getLang, saveLang } from '@/hooks/storage.native';
|
|
import { useLanguage } from '@/i18n/useLanguage';
|
|
import { useQueryClient } from '@tanstack/react-query';
|
|
import { useRouter } from 'expo-router';
|
|
import { ArrowLeft, Check, ChevronDown, Globe } from 'lucide-react-native';
|
|
import React, { useEffect, useState } from 'react';
|
|
import { useTranslation } from 'react-i18next';
|
|
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
|
|
|
|
export default function AuthHeader({ back = true }: { back?: boolean }) {
|
|
const router = useRouter();
|
|
const { language, changeLanguage, getLanguageName } = useLanguage();
|
|
const { i18n } = useTranslation();
|
|
const [open, setOpen] = useState(false);
|
|
const queryClient = useQueryClient();
|
|
|
|
useEffect(() => {
|
|
const loadLanguage = async () => {
|
|
const lang = await getLang();
|
|
if (lang === 'uz' || lang === 'ru' || lang === 'en') {
|
|
changeLanguage(lang);
|
|
}
|
|
};
|
|
|
|
loadLanguage();
|
|
}, [language]);
|
|
|
|
const selectLanguage = async (lang: string) => {
|
|
changeLanguage(lang as any);
|
|
queryClient.invalidateQueries();
|
|
await i18n.changeLanguage(lang);
|
|
await saveLang(lang);
|
|
setOpen(false);
|
|
};
|
|
|
|
return (
|
|
<View style={{ ...styles.header, justifyContent: back ? 'space-between' : 'flex-end' }}>
|
|
{/* Back */}
|
|
{back && (
|
|
<TouchableOpacity style={styles.back} onPress={() => router.back()} activeOpacity={0.7}>
|
|
<ArrowLeft size={22} color="#fff" />
|
|
</TouchableOpacity>
|
|
)}
|
|
|
|
{/* Language */}
|
|
<View>
|
|
<TouchableOpacity style={styles.langBtn} onPress={() => setOpen(!open)} activeOpacity={0.7}>
|
|
<Globe size={18} color="#94a3b8" />
|
|
<Text style={styles.langText}>{getLanguageName()}</Text>
|
|
<ChevronDown size={16} color="#94a3b8" />
|
|
</TouchableOpacity>
|
|
|
|
{open && (
|
|
<View style={styles.dropdown}>
|
|
{languages.map((l) => {
|
|
const active = language === l.code;
|
|
return (
|
|
<TouchableOpacity
|
|
key={l.code}
|
|
style={[styles.option, active && styles.optionActive]}
|
|
onPress={() => selectLanguage(l.code)}
|
|
>
|
|
<Text style={[styles.optionText, active && styles.optionTextActive]}>
|
|
{l.name}
|
|
</Text>
|
|
{active && (
|
|
<View style={styles.check}>
|
|
<Check size={14} color="#fff" />
|
|
</View>
|
|
)}
|
|
</TouchableOpacity>
|
|
);
|
|
})}
|
|
</View>
|
|
)}
|
|
</View>
|
|
</View>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
header: {
|
|
flexDirection: 'row',
|
|
justifyContent: 'space-between',
|
|
alignItems: 'center',
|
|
paddingHorizontal: 24,
|
|
paddingVertical: 12,
|
|
zIndex: 50,
|
|
},
|
|
back: {
|
|
width: 44,
|
|
height: 44,
|
|
borderRadius: 12,
|
|
backgroundColor: 'rgba(255,255,255,0.1)',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
borderWidth: 1,
|
|
borderColor: 'rgba(255,255,255,0.15)',
|
|
},
|
|
langBtn: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
gap: 8,
|
|
backgroundColor: 'rgba(255,255,255,0.1)',
|
|
paddingHorizontal: 14,
|
|
paddingVertical: 10,
|
|
borderRadius: 12,
|
|
borderWidth: 1,
|
|
borderColor: 'rgba(255,255,255,0.15)',
|
|
},
|
|
langText: {
|
|
color: '#94a3b8',
|
|
fontWeight: '600',
|
|
fontSize: 14,
|
|
},
|
|
dropdown: {
|
|
position: 'absolute',
|
|
top: 52,
|
|
right: 0,
|
|
backgroundColor: '#fff',
|
|
borderRadius: 16,
|
|
padding: 8,
|
|
minWidth: 180,
|
|
elevation: 20,
|
|
},
|
|
option: {
|
|
flexDirection: 'row',
|
|
justifyContent: 'space-between',
|
|
padding: 12,
|
|
borderRadius: 12,
|
|
},
|
|
optionActive: {
|
|
backgroundColor: '#eff6ff',
|
|
},
|
|
optionText: {
|
|
color: '#475569',
|
|
fontWeight: '600',
|
|
},
|
|
optionTextActive: {
|
|
color: '#3b82f6',
|
|
},
|
|
check: {
|
|
width: 20,
|
|
height: 20,
|
|
borderRadius: 10,
|
|
backgroundColor: '#3b82f6',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
},
|
|
});
|