fitst commit

This commit is contained in:
Samandar Turgunboyev
2026-01-28 18:26:50 +05:00
parent 166a55b1e9
commit 124798419b
196 changed files with 26627 additions and 421 deletions

16
app/profile/_layout.tsx Normal file
View File

@@ -0,0 +1,16 @@
import { RefreshProvider } from '@/components/ui/RefreshContext';
import { BottomSheetModalProvider } from '@gorhom/bottom-sheet';
import { Stack } from 'expo-router';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
export default function TabsLayout() {
return (
<GestureHandlerRootView style={{ flex: 1 }}>
<RefreshProvider>
<BottomSheetModalProvider>
<Stack screenOptions={{ headerShown: false }} />
</BottomSheetModalProvider>
</RefreshProvider>
</GestureHandlerRootView>
);
}

5
app/profile/bonuses.tsx Normal file
View File

@@ -0,0 +1,5 @@
import BonusesScreen from '@/screens/profile/ui/BonusesScreen';
export default function Bonuses() {
return <BonusesScreen />;
}

227
app/profile/categories.tsx Normal file
View File

@@ -0,0 +1,227 @@
import { useTheme } from '@/components/ThemeContext';
import CategorySelection from '@/components/ui/IndustrySelection';
import { user_api } from '@/screens/profile/lib/api';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { useRouter } from 'expo-router';
import { ArrowLeft, XIcon } from 'lucide-react-native';
import { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import {
ActivityIndicator,
Alert,
FlatList,
Pressable,
ScrollView,
StyleSheet,
Text,
ToastAndroid,
TouchableOpacity,
View,
} from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
export default function PersonalInfoScreen() {
const router = useRouter();
const queryClient = useQueryClient();
const { isDark } = useTheme();
const { t } = useTranslation();
const theme = {
background: isDark ? '#0f172a' : '#f8fafc',
text: isDark ? '#ffffff' : '#0f172a',
textSecondary: isDark ? '#64748b' : '#94a3b8',
primary: '#3b82f6',
tabBg: isDark ? '#1e293b' : '#e0e7ff',
tabText: isDark ? '#ffffff' : '#4338ca',
deleteBg: isDark ? '#394e73' : '#cbd5e1',
deleteIcon: isDark ? '#f8fafc' : '#475569',
shadow: isDark ? '#000' : '#64748b',
};
const [selectedCategories, setSelectedCategories] = useState<any[]>([]);
const { data: me, isLoading } = useQuery({
queryKey: ['get_me'],
queryFn: () => user_api.getMe(),
});
useEffect(() => {
if (me?.data.data?.activate_types) {
setSelectedCategories(me.data.data.activate_types.map((a: any) => a));
}
}, [me]);
const updateMutation = useMutation({
mutationFn: (body: {
first_name: string;
industries: {
id: number;
name: string;
code: string;
external_id: null | number;
level: number;
is_leaf: boolean;
icon_name: null | string;
parent: {
id: number;
name: string;
code: string;
};
}[];
phone: string;
person_type: 'employee' | 'legal_entity' | 'ytt' | 'band';
activate_types: number[];
}) => user_api.updateMe(body),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['get_me'] });
router.push('/profile/personal-info');
ToastAndroid.show(t("Ma'lumotlar yangilandi"), ToastAndroid.TOP);
},
onError: () => {
Alert.alert(t('Xatolik yzu berdi'), t("Ma'lumotlarni yangilashda xatolik yuz berdi"));
},
});
const removeCategory = (id: string | number) => {
setSelectedCategories((prev) => prev.filter((c) => c.id !== id));
};
const renderTab = ({ item }: { item: any }) => (
<View style={[styles.tabWrapper, { backgroundColor: theme.tabBg, shadowColor: theme.shadow }]}>
<Text
style={[styles.tabText, { color: theme.tabText }]}
numberOfLines={1}
ellipsizeMode="tail"
>
{item.name}
</Text>
<TouchableOpacity
onPress={() => removeCategory(item.id)}
style={[styles.deleteTab, { backgroundColor: theme.deleteBg }]}
>
<XIcon size={15} color={theme.deleteIcon} />
</TouchableOpacity>
</View>
);
if (isLoading) {
return (
<SafeAreaView style={[styles.container, { backgroundColor: theme.background }]}>
<View style={styles.topHeader}>
<Pressable onPress={() => router.push('/profile/personal-info')}>
<ArrowLeft color={theme.text} />
</Pressable>
<Text style={[styles.headerTitle, { color: theme.text }]}>{t('Faoliyat sohalari')}</Text>
<Pressable>
<Text style={{ color: theme.primary, fontSize: 16 }}>{t('Tayyor')}</Text>
</Pressable>
</View>
<ActivityIndicator size={'large'} />
</SafeAreaView>
);
}
return (
<SafeAreaView style={[styles.container, { backgroundColor: theme.background }]}>
<View style={styles.topHeader}>
<Pressable onPress={() => router.push('/profile/personal-info')}>
<ArrowLeft color={theme.text} />
</Pressable>
<Text style={[styles.headerTitle, { color: theme.text }]}>{t('Faoliyat sohalari')}</Text>
<Pressable
onPress={() => {
if (me) {
const activate_types = selectedCategories.map((e) => e.id) ?? [];
updateMutation.mutate({
person_type: me?.data.data.person_type,
first_name: me?.data.data.first_name,
phone: me.data.data.phone,
industries: selectedCategories,
activate_types,
});
}
}}
>
{updateMutation.isPending ? (
<ActivityIndicator size={'small'} />
) : (
<Text style={{ color: theme.primary, fontSize: 16 }}>{t('Tayyor')}</Text>
)}
</Pressable>
</View>
<ScrollView
style={{
padding: 16,
}}
>
{selectedCategories.length > 0 && (
<FlatList
data={selectedCategories}
keyExtractor={(item) => String(item.id)}
renderItem={renderTab}
horizontal
showsHorizontalScrollIndicator={false}
keyboardShouldPersistTaps="handled"
contentContainerStyle={styles.tabsContainer}
style={styles.tabsList}
ItemSeparatorComponent={() => <View style={{ width: 8 }} />}
/>
)}
<CategorySelection
selectedCategories={selectedCategories}
setSelectedCategories={setSelectedCategories}
/>
</ScrollView>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
tabsList: {
maxHeight: 56,
},
tabsContainer: {
alignItems: 'center',
marginBottom: 20,
},
tabWrapper: {
flexDirection: 'row',
alignItems: 'center',
paddingVertical: 8,
paddingHorizontal: 12,
borderRadius: 20,
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.2,
shadowRadius: 3,
elevation: 3,
},
tabText: {
fontSize: 14,
fontWeight: '600',
marginRight: 6,
maxWidth: 200,
flexShrink: 1,
},
deleteTab: {
padding: 4,
borderRadius: 12,
justifyContent: 'center',
alignItems: 'center',
},
loadingText: {
fontSize: 16,
textAlign: 'center',
marginTop: 40,
},
topHeader: {
flexDirection: 'row',
justifyContent: 'space-between',
padding: 16,
alignItems: 'center',
},
headerTitle: { fontSize: 18, fontWeight: '700' },
});

View File

@@ -0,0 +1,5 @@
import { EmployeesTab } from '@/screens/profile/ui/EmployeesTab';
export default function EmployeesScreen() {
return <EmployeesTab />;
}

View File

@@ -0,0 +1,5 @@
import { EmployeesTab } from '@/screens/profile/ui/EmployeesTab';
export default function EmployeeDetailScreen() {
return <EmployeesTab />;
}

View File

@@ -0,0 +1,9 @@
import AddEmployee from '@/screens/profile/ui/AddEmployee';
export default function AddEmployeeScreen() {
return (
<>
<AddEmployee />
</>
);
}

12
app/profile/my-ads.tsx Normal file
View File

@@ -0,0 +1,12 @@
import { useTheme } from '@/components/ThemeContext';
import { AnnouncementsTab } from '@/screens/profile/ui/AnnouncementsTab';
import { SafeAreaView } from 'react-native-safe-area-context';
export default function MyAds() {
const { isDark } = useTheme();
return (
<SafeAreaView style={{ flex: 1, backgroundColor: isDark ? '#0f172a' : '#f8fafc' }}>
<AnnouncementsTab />
</SafeAreaView>
);
}

View File

@@ -0,0 +1,346 @@
import { useTheme } from '@/components/ThemeContext';
import { formatNumber, formatPhone, normalizeDigits } from '@/constants/formatPhone';
import { user_api } from '@/screens/profile/lib/api';
import { UserInfoResponseData } from '@/screens/profile/lib/type';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { useRouter } from 'expo-router';
import { ArrowLeft, Edit2, Plus } from 'lucide-react-native';
import { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import {
ActivityIndicator,
Alert,
Image,
Pressable,
ScrollView,
StyleSheet,
Text,
TextInput,
ToastAndroid,
View,
} from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
export default function PersonalInfoScreen() {
const router = useRouter();
const queryClient = useQueryClient();
const { isDark } = useTheme();
const { t } = useTranslation();
const theme = {
background: isDark ? '#0f172a' : '#f8fafc',
cardBg: isDark ? '#1e293b' : '#ffffff',
text: isDark ? '#f8fafc' : '#0f172a',
textSecondary: isDark ? '#94a3b8' : '#64748b',
textTertiary: isDark ? '#64748b' : '#94a3b8',
inputBg: isDark ? '#1e293b' : '#f1f5f9',
inputBorder: isDark ? '#334155' : '#e2e8f0',
primary: '#3b82f6',
chipBg: isDark ? '#1e293b' : '#e0e7ff',
chipText: isDark ? '#f8fafc' : '#4338ca',
divider: isDark ? '#334155' : '#cbd5e1',
placeholder: isDark ? '#64748b' : '#94a3b8',
};
const [isEditing, setIsEditing] = useState(false);
const [editData, setEditData] = useState<UserInfoResponseData | null>(null);
const [phone, setPhone] = useState('');
const [focused, setFocused] = useState(false);
const [showCategories, setShowCategories] = useState(false);
const [selectedCategories, setSelectedCategories] = useState<any[]>([]);
const { data: me, isLoading } = useQuery({
queryKey: ['get_me'],
queryFn: () => user_api.getMe(),
});
useEffect(() => {
if (me?.data.data) {
setEditData(me.data);
const rawPhone = normalizeDigits(me.data.data.phone || '');
setPhone(rawPhone.startsWith('998') ? rawPhone.slice(3) : rawPhone);
setSelectedCategories(me.data.data.activate_types ?? []);
}
}, [me]);
const updateMutation = useMutation({
mutationFn: (body: any) => user_api.updateMe(body),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['get_me'] });
setIsEditing(false);
setShowCategories(false);
ToastAndroid.show(t("Ma'lumotlar yangilandi"), ToastAndroid.TOP);
},
onError: () => {
Alert.alert(t('Xatolik yuz berdi'), t('Yangilashda xatolik yuz berdi'));
},
});
const handleSave = () => {
if (!editData) return;
updateMutation.mutate({
first_name: editData.data.first_name,
phone: normalizeDigits(phone),
person_type: editData.data.person_type,
industries: editData.data.activate_types,
activate_types: editData.data.activate_types.map((e) => e.id),
company_name: editData.data.company_name,
stir: editData.data.stir,
director_full_name: editData.data.director_full_name,
address: editData.data.address,
});
};
const removeCategory = (id: number) => {
setSelectedCategories((prev) => prev.filter((c) => c.id !== id));
};
if (isLoading) {
return (
<SafeAreaView style={[styles.container, { backgroundColor: theme.background }]}>
<View style={styles.topHeader}>
<Pressable onPress={() => setIsEditing(false)}>
<ArrowLeft color={theme.text} />
</Pressable>
<Text style={[styles.headerTitle, { color: theme.text }]}>{t('Tahrirlash')}</Text>
<Pressable onPress={handleSave}>
<Text style={[styles.saveButton, { color: theme.primary }]}>{t('Saqlash')}</Text>
</Pressable>
</View>
<ActivityIndicator size={'large'} />
</SafeAreaView>
);
}
/* ===================== EDIT MODE ===================== */
if (isEditing && editData) {
return (
<SafeAreaView style={[styles.container, { backgroundColor: theme.background }]}>
<View style={styles.topHeader}>
<Pressable onPress={() => setIsEditing(false)}>
<ArrowLeft color={theme.text} />
</Pressable>
<Text style={[styles.headerTitle, { color: theme.text }]}>{t('Tahrirlash')}</Text>
<Pressable onPress={handleSave}>
{updateMutation.isPending ? (
<ActivityIndicator size={'small'} />
) : (
<Text style={[styles.saveButton, { color: theme.primary }]}>{t('Saqlash')}</Text>
)}
</Pressable>
</View>
<ScrollView style={styles.content}>
<View style={styles.editSection}>
<Text style={[styles.label, { color: theme.textSecondary }]}>{t('Ism')}</Text>
<TextInput
style={[styles.input, { backgroundColor: theme.inputBg, color: theme.text }]}
value={editData?.data.first_name}
onChangeText={(text) => setEditData((prev) => prev && { ...prev, first_name: text })}
placeholderTextColor={theme.placeholder}
/>
<Text style={[styles.label, { color: theme.textSecondary }]}>
{t('Telefon raqami')}
</Text>
<View style={[styles.phoneInputContainer, { backgroundColor: theme.inputBg }]}>
<View style={styles.prefixContainer}>
<Text
style={[styles.prefix, { color: theme.text }, focused && styles.prefixFocused]}
>
+998
</Text>
<View style={[styles.divider, { backgroundColor: theme.divider }]} />
</View>
<TextInput
style={[styles.phoneInput, { color: theme.text }]}
value={formatPhone(phone)}
onChangeText={(text) => setPhone(normalizeDigits(text))}
onFocus={() => setFocused(true)}
onBlur={() => setFocused(false)}
keyboardType="phone-pad"
placeholder="90 123 45 67"
maxLength={12}
placeholderTextColor={theme.placeholder}
/>
</View>
</View>
</ScrollView>
</SafeAreaView>
);
}
/* ===================== VIEW MODE ===================== */
return (
<SafeAreaView style={[styles.container, { backgroundColor: theme.background }]}>
<View style={styles.topHeader}>
<Pressable onPress={() => router.push('/profile')}>
<ArrowLeft color={theme.text} />
</Pressable>
<Text style={[styles.headerTitle, { color: theme.text }]}>{t("Shaxsiy ma'lumotlar")}</Text>
<Pressable onPress={() => setIsEditing(true)}>
<Edit2 color={theme.primary} />
</Pressable>
</View>
<ScrollView style={styles.content}>
<View style={[styles.infoCard, { backgroundColor: theme.cardBg }]}>
<Text style={[styles.infoLabel, { color: theme.textSecondary }]}>{t('Ism')}</Text>
<Text style={[styles.infoValue, { color: theme.text }]}>{me?.data.data.first_name}</Text>
<Text style={[styles.infoLabel, { color: theme.textSecondary }]}>
{t('Telefon raqami')}
</Text>
<Text style={[styles.infoValue, { color: theme.text }]}>
{me && formatNumber(me?.data.data.phone)}
</Text>
</View>
{me?.data.data.person_type !== 'employee' && (
<View style={[styles.infoCard, { backgroundColor: theme.cardBg }]}>
<Text style={[styles.sectionTitle, { color: theme.textTertiary }]}>
{t('Kompaniya')}
</Text>
{me?.data.data.company_image && (
<Image source={{ uri: me.data.data.company_image }} style={styles.companyImage} />
)}
<Text style={[styles.infoLabel, { color: theme.textSecondary }]}>{t('Nomi')}</Text>
<Text style={[styles.infoValue, { color: theme.text }]}>
{me?.data.data.company_name}
</Text>
<Text style={[styles.infoLabel, { color: theme.textSecondary }]}>{t('STIR')}</Text>
<Text style={[styles.infoValue, { color: theme.text }]}>{me?.data.data.stir}</Text>
<Text style={[styles.infoLabel, { color: theme.textSecondary }]}>{t('Direktor')}</Text>
<Text style={[styles.infoValue, { color: theme.text }]}>
{me?.data.data.director_full_name}
</Text>
{me?.data.data.address && (
<>
<Text style={[styles.infoLabel, { color: theme.textSecondary }]}>
{t('Manzil')}
</Text>
<Text style={[styles.infoValue, { color: theme.text }]}>
{me?.data.data.address}
</Text>
</>
)}
</View>
)}
<View style={styles.section}>
<View
style={{
flexDirection: 'row',
alignItems: 'flex-start',
justifyContent: 'space-between',
}}
>
<Text style={[styles.sectionTitle, { color: theme.textTertiary }]}>
{t('Faoliyat sohalari')}
</Text>
<Plus
color={theme.primary}
size={24}
onPress={() => router.push('/profile/categories')}
/>
</View>
<View style={styles.fieldsContainer}>
{me?.data.data.activate_types.map((field: any) => (
<View key={field.id} style={[styles.fieldChip, { backgroundColor: theme.chipBg }]}>
<Text style={[styles.fieldText, { color: theme.chipText }]}>{field.name}</Text>
</View>
))}
</View>
</View>
</ScrollView>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
fieldsContainer: { flexDirection: 'row', flexWrap: 'wrap', gap: 8 },
fieldChip: {
paddingHorizontal: 16,
paddingVertical: 10,
borderRadius: 16,
},
fieldText: { fontSize: 14, fontWeight: '600' },
section: {
padding: 10,
marginTop: 0,
},
content: {
padding: 16,
},
loadingText: {
textAlign: 'center',
marginTop: 40,
},
infoCard: {
borderRadius: 20,
padding: 16,
marginBottom: 16,
},
infoLabel: {
fontSize: 13,
marginTop: 8,
},
infoValue: {
fontSize: 16,
fontWeight: '600',
},
sectionTitle: {
fontWeight: '700',
fontSize: 16,
marginBottom: 12,
},
editSection: {
gap: 12,
},
label: {
fontSize: 13,
},
input: {
borderRadius: 14,
padding: 14,
},
phoneInputContainer: {
flexDirection: 'row',
borderRadius: 14,
padding: 14,
},
phoneInput: {
flex: 1,
},
saveButton: {
fontSize: 16,
fontWeight: '600',
},
companyImage: {
width: 90,
height: 90,
borderRadius: 45,
alignSelf: 'center',
marginBottom: 12,
},
topHeader: {
flexDirection: 'row',
justifyContent: 'space-between',
padding: 16,
alignItems: 'center',
},
headerTitle: { fontSize: 18, fontWeight: '700' },
prefixContainer: { flexDirection: 'row', alignItems: 'center', marginRight: 12 },
prefix: { fontSize: 17, fontWeight: '600' },
prefixFocused: {},
divider: { width: 1, height: 24, marginLeft: 12 },
});

5
app/profile/products.tsx Normal file
View File

@@ -0,0 +1,5 @@
import MyServicesScreen from '@/screens/profile/ui/MyServices';
export default function ProductsScreen() {
return <MyServicesScreen />;
}

View File

@@ -0,0 +1,5 @@
import AddService from '@/screens/profile/ui/AddService';
export default function AddProductScreen() {
return <AddService />;
}

View File

@@ -0,0 +1,5 @@
import EditServices from '@/screens/profile/ui/EditServices';
export default function EditProductScreen() {
return <EditServices />;
}

166
app/profile/settings.tsx Normal file
View File

@@ -0,0 +1,166 @@
import GB from '@/assets/images/GB.png';
import RU from '@/assets/images/RU.png';
import UZ from '@/assets/images/UZ.png';
import { useTheme } from '@/components/ThemeContext';
import { saveLang } from '@/hooks/storage.native';
import { useLanguage } from '@/i18n/useLanguage';
import { useQueryClient } from '@tanstack/react-query';
import { Image } from 'expo-image';
import { useRouter } from 'expo-router';
import { ChevronLeft, Moon, Sun } from 'lucide-react-native';
import { useTranslation } from 'react-i18next';
import { Pressable, ScrollView, StyleSheet, Switch, Text, View } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
export default function SettingsScreen() {
const router = useRouter();
const { language, changeLanguage } = useLanguage();
const { t, i18n } = useTranslation();
const queryClient = useQueryClient();
const selectLanguage = async (lang: string) => {
changeLanguage(lang as 'uz' | 'ru' | 'en');
await i18n.changeLanguage(lang);
queryClient.invalidateQueries();
await saveLang(lang);
};
const { isDark, toggleTheme } = useTheme();
const languages = [
{ code: 'uz', label: "O'zbek", icon: UZ },
{ code: 'ru', label: 'Русский', icon: RU },
{ code: 'en', label: 'English', icon: GB },
];
return (
<SafeAreaView style={[styles.container, isDark ? styles.darkBg : styles.lightBg]}>
<ScrollView contentContainerStyle={{ paddingBottom: 32 }}>
{/* Header */}
<View style={styles.header}>
<Pressable onPress={() => router.back()}>
<ChevronLeft size={26} color={isDark ? '#f8fafc' : '#0f172a'} />
</Pressable>
<Text style={[styles.headerTitle, isDark ? styles.darkText : styles.lightText]}>
{t('Sozlamalar')}
</Text>
<View style={{ width: 26 }} />
</View>
{/* Language Cards */}
<Text style={[styles.sectionTitle, isDark ? styles.darkText : styles.lightText]}>
{t('Tilni tanlang')}
</Text>
{languages.map((lang) => {
const active = language === lang.code;
return (
<Pressable
key={lang.code}
onPress={() => selectLanguage(lang.code)}
style={[
styles.langCard,
isDark ? styles.darkCard : styles.lightCard,
active && styles.langActiveCard,
]}
>
<View style={styles.row}>
<Image source={lang.icon} style={{ width: 32, height: 24 }} />
<Text
style={[
styles.label,
isDark ? styles.darkText : styles.lightText,
active && { color: '#fff' },
]}
>
{lang.label}
</Text>
</View>
</Pressable>
);
})}
{/* Theme */}
<View style={{ marginTop: 10 }}>
<Text style={[styles.sectionTitle, isDark ? styles.darkText : styles.lightText]}>
{t('Rejimni tanlang')}
</Text>
<View style={[styles.card, isDark ? styles.darkCard : styles.lightCard]}>
<View style={styles.row}>
{isDark ? <Moon size={22} color="#818cf8" /> : <Sun size={22} color="#f59e0b" />}
<Text style={[styles.label, isDark ? styles.darkText : styles.lightText]}>
{isDark ? t('Tungi rejim') : t("Yorug' rejim")}
</Text>
</View>
<Switch
value={isDark}
onValueChange={toggleTheme}
trackColor={{ false: '#d1d5db', true: '#6366f1' }}
thumbColor={isDark ? '#e5e7eb' : '#ffffff'}
/>
</View>
</View>
</ScrollView>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
/* Backgrounds */
lightBg: { backgroundColor: '#f9fafb' },
darkBg: { backgroundColor: '#0f172a' },
header: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
padding: 16,
},
headerTitle: {
fontSize: 18,
fontWeight: '600',
},
sectionTitle: {
fontSize: 16,
fontWeight: '600',
paddingHorizontal: 16,
marginBottom: 8,
},
card: {
borderRadius: 14,
padding: 16,
marginHorizontal: 16,
marginVertical: 8,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
},
lightCard: { backgroundColor: '#ffffff' },
darkCard: { backgroundColor: '#1e293b', borderWidth: 1, borderColor: '#334155' },
row: { flexDirection: 'row', alignItems: 'center', gap: 10 },
label: { fontSize: 15, fontWeight: '500' },
darkText: { color: '#f8fafc' },
lightText: { color: '#0f172a' },
/* Language Cards */
langCard: {
borderRadius: 14,
padding: 16,
marginHorizontal: 16,
marginVertical: 6,
flexDirection: 'row',
alignItems: 'center',
},
langActiveCard: { backgroundColor: '#3b82f6' },
});