Files
info-target-mobile/app/profile/categories.tsx
Samandar Turgunboyev 124798419b fitst commit
2026-01-28 18:26:50 +05:00

228 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';
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' },
});