279 lines
7.0 KiB
TypeScript
279 lines
7.0 KiB
TypeScript
import AuthHeader from '@/components/ui/AuthHeader';
|
||
import { auth_api } from '@/screens/auth/login/lib/api';
|
||
import { products_api } from '@/screens/home/lib/api';
|
||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||
import { useMutation, useQuery } from '@tanstack/react-query';
|
||
import { AxiosError } from 'axios';
|
||
import { LinearGradient } from 'expo-linear-gradient';
|
||
import { Stack, useLocalSearchParams, useRouter } from 'expo-router';
|
||
import { ChevronLeft } from 'lucide-react-native';
|
||
import React, { useState } from 'react';
|
||
import { useTranslation } from 'react-i18next';
|
||
import {
|
||
ActivityIndicator,
|
||
Alert,
|
||
ScrollView,
|
||
StyleSheet,
|
||
Text,
|
||
TouchableOpacity,
|
||
View,
|
||
} from 'react-native';
|
||
|
||
interface Category {
|
||
id: number;
|
||
name: string;
|
||
is_leaf: boolean;
|
||
}
|
||
|
||
export default function CategorySelectScreen() {
|
||
const router = useRouter();
|
||
const { t } = useTranslation();
|
||
const { phone, stir, person_type, director_full_name, referal, first_name, last_name, middle_name } = useLocalSearchParams<{
|
||
phone: string;
|
||
stir: string;
|
||
person_type: 'band' | 'ytt';
|
||
referal: string;
|
||
director_full_name: string;
|
||
first_name: string;
|
||
last_name: string;
|
||
middle_name: string;
|
||
}>();
|
||
|
||
const [selected, setSelected] = useState<number | null>(null);
|
||
const [categories, setCategories] = useState<Category[]>([]);
|
||
const [history, setHistory] = useState<Category[][]>([]);
|
||
|
||
/** ROOT categories */
|
||
const { isLoading } = useQuery({
|
||
queryKey: ['categories-root'],
|
||
queryFn: () => products_api.getCategorys(),
|
||
select: (res) => {
|
||
setCategories(res.data.data);
|
||
},
|
||
});
|
||
|
||
/** CHILD categories */
|
||
const childMutation = useMutation({
|
||
mutationFn: (id: number) => products_api.getCategorys({ parent: id }),
|
||
onSuccess: (res) => {
|
||
setHistory((prev) => [...prev, categories]);
|
||
setCategories(res.data.data);
|
||
},
|
||
});
|
||
|
||
/** REGISTER */
|
||
const registerMutation = useMutation({
|
||
mutationFn: (body: {
|
||
phone: string;
|
||
stir: string;
|
||
person_type: string;
|
||
activate_types: number[];
|
||
director_full_name: string;
|
||
referal: string;
|
||
first_name: string;
|
||
last_name: string;
|
||
}) => auth_api.register(body),
|
||
onSuccess: async () => {
|
||
router.replace('/(auth)/register-confirm');
|
||
await AsyncStorage.setItem('phone', phone);
|
||
},
|
||
onError: (err: AxiosError) => {
|
||
const errMessage = (err.response?.data as { data: { stir: string[] } }).data.stir[0];
|
||
const errMessageDetail = (err.response?.data as { data: { detail: string } }).data.detail;
|
||
|
||
const errrAlert = errMessage ? errMessage : errMessageDetail;
|
||
|
||
Alert.alert(t('Xatolik yuz berdi'), errMessage || errrAlert || t('erroXatolik yuz berdi'));
|
||
},
|
||
});
|
||
|
||
const onCategoryPress = (cat: Category) => {
|
||
if (cat.is_leaf) {
|
||
setSelected(cat.id);
|
||
} else {
|
||
childMutation.mutate(cat.id);
|
||
}
|
||
};
|
||
|
||
const goBack = () => {
|
||
if (history.length === 0) return;
|
||
const prev = history[history.length - 1];
|
||
setCategories(prev);
|
||
setHistory((h) => h.slice(0, -1));
|
||
setSelected(null);
|
||
};
|
||
|
||
const full_name = first_name.length > 0 ? first_name + ' ' + last_name + ' ' + middle_name : director_full_name;
|
||
|
||
return (
|
||
<View style={styles.safeArea}>
|
||
<AuthHeader />
|
||
<Stack.Screen options={{ title: t('Yo‘nalishni tanlang') }} />
|
||
|
||
<LinearGradient colors={['#0f172a', '#1e293b']} style={StyleSheet.absoluteFill} />
|
||
|
||
<ScrollView contentContainerStyle={styles.container}>
|
||
{history.length > 0 && (
|
||
<TouchableOpacity onPress={goBack} style={styles.backBtn}>
|
||
<ChevronLeft size={20} color="#3b82f6" />
|
||
<Text style={styles.backText}>{t('Orqaga')}</Text>
|
||
</TouchableOpacity>
|
||
)}
|
||
<Text style={styles.title}>{t("Yo'nalishni tanlang")}</Text>
|
||
|
||
{isLoading || childMutation.isPending ? (
|
||
<ActivityIndicator color="#3b82f6" />
|
||
) : (
|
||
categories.map((c) => {
|
||
const active = selected === c.id;
|
||
return (
|
||
<TouchableOpacity
|
||
key={c.id}
|
||
style={[styles.item, active && styles.itemActive]}
|
||
onPress={() => onCategoryPress(c)}
|
||
>
|
||
<Text style={[styles.text, active && styles.textActive]}>{c.name}</Text>
|
||
</TouchableOpacity>
|
||
);
|
||
})
|
||
)}
|
||
</ScrollView>
|
||
|
||
<TouchableOpacity
|
||
disabled={!selected || registerMutation.isPending}
|
||
style={[styles.bottom, (!selected || registerMutation.isPending) && styles.bottomDisabled]}
|
||
onPress={() => {
|
||
if (!selected) return;
|
||
registerMutation.mutate({
|
||
activate_types: [selected],
|
||
person_type,
|
||
phone: `998${phone}`,
|
||
stir,
|
||
referal: referal,
|
||
director_full_name: director_full_name,
|
||
first_name: full_name,
|
||
last_name: last_name,
|
||
});
|
||
}}
|
||
>
|
||
<Text style={styles.bottomText} disabled={registerMutation.isPending}>
|
||
{t('Tadiqlash')}
|
||
</Text>
|
||
</TouchableOpacity>
|
||
</View>
|
||
);
|
||
}
|
||
|
||
const styles = StyleSheet.create({
|
||
title: {
|
||
fontSize: 18,
|
||
fontWeight: '700',
|
||
color: '#ffffff',
|
||
marginBottom: 12,
|
||
},
|
||
safeArea: {
|
||
flex: 1,
|
||
backgroundColor: '#0f172a',
|
||
},
|
||
|
||
container: {
|
||
paddingHorizontal: 20,
|
||
paddingTop: 16,
|
||
paddingBottom: 70,
|
||
gap: 12,
|
||
},
|
||
|
||
backBtn: {
|
||
flexDirection: 'row',
|
||
alignItems: 'center',
|
||
gap: 6,
|
||
marginBottom: 12,
|
||
},
|
||
|
||
backText: {
|
||
fontSize: 14,
|
||
color: '#3b82f6',
|
||
fontWeight: '600',
|
||
},
|
||
|
||
item: {
|
||
paddingVertical: 18,
|
||
paddingHorizontal: 18,
|
||
borderRadius: 16,
|
||
flexDirection: 'row',
|
||
justifyContent: 'space-between',
|
||
alignItems: 'center',
|
||
backgroundColor: 'rgba(255,255,255,0.06)',
|
||
borderWidth: 1,
|
||
borderColor: 'rgba(255,255,255,0.12)',
|
||
},
|
||
|
||
itemActive: {
|
||
backgroundColor: 'rgba(59,130,246,0.15)',
|
||
borderColor: 'rgba(59,130,246,0.6)',
|
||
},
|
||
|
||
text: {
|
||
fontSize: 15,
|
||
fontWeight: '600',
|
||
color: '#cbd5f5',
|
||
},
|
||
|
||
textActive: {
|
||
color: '#ffffff',
|
||
fontWeight: '800',
|
||
},
|
||
|
||
arrow: {
|
||
fontSize: 18,
|
||
color: '#94a3b8',
|
||
},
|
||
|
||
bottom: {
|
||
position: 'absolute',
|
||
bottom: 20,
|
||
left: 16,
|
||
right: 16,
|
||
height: 54,
|
||
borderRadius: 16,
|
||
backgroundColor: '#3b82f6',
|
||
alignItems: 'center',
|
||
justifyContent: 'center',
|
||
shadowColor: '#3b82f6',
|
||
shadowOffset: { width: 0, height: 8 },
|
||
shadowOpacity: 0.35,
|
||
shadowRadius: 12,
|
||
elevation: 10,
|
||
},
|
||
|
||
bottomDisabled: {
|
||
backgroundColor: '#64748b',
|
||
},
|
||
|
||
bottomText: {
|
||
color: '#ffffff',
|
||
fontWeight: '800',
|
||
fontSize: 16,
|
||
},
|
||
|
||
decorCircle1: {
|
||
position: 'absolute',
|
||
top: -120,
|
||
right: -80,
|
||
width: 300,
|
||
height: 300,
|
||
borderRadius: 150,
|
||
backgroundColor: 'rgba(59,130,246,0.12)',
|
||
},
|
||
|
||
decorCircle2: {
|
||
position: 'absolute',
|
||
bottom: -120,
|
||
left: -100,
|
||
width: 280,
|
||
height: 280,
|
||
borderRadius: 140,
|
||
backgroundColor: 'rgba(16,185,129,0.1)',
|
||
},
|
||
});
|