232 lines
6.5 KiB
TypeScript
232 lines
6.5 KiB
TypeScript
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';
|
|
|
|
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[];
|
|
age: number | null;
|
|
gender: 'male' | 'female' | null;
|
|
}) => 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 (
|
|
<View 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'} />
|
|
</View>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<View 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,
|
|
age: me.data.data.age,
|
|
gender: me.data.data.gender,
|
|
});
|
|
}
|
|
}}
|
|
>
|
|
{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>
|
|
</View>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
flex: 1,
|
|
paddingBottom: 30,
|
|
},
|
|
tabsList: {
|
|
maxHeight: 56,
|
|
},
|
|
tabsContainer: {
|
|
alignItems: 'center',
|
|
marginBottom: 10,
|
|
},
|
|
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' },
|
|
});
|