bug fixed
This commit is contained in:
8
app.json
8
app.json
@@ -11,12 +11,16 @@
|
|||||||
"ios": {
|
"ios": {
|
||||||
"supportsTablet": true,
|
"supportsTablet": true,
|
||||||
"infoPlist": {
|
"infoPlist": {
|
||||||
"UIBackgroundModes": ["remote-notification"]
|
"UIBackgroundModes": [
|
||||||
|
"remote-notification"
|
||||||
|
],
|
||||||
|
"UIViewControllerBasedStatusBarAppearance": true
|
||||||
},
|
},
|
||||||
"bundleIdentifier": "com.felix.infotarget"
|
"bundleIdentifier": "com.felix.infotarget"
|
||||||
},
|
},
|
||||||
"android": {
|
"android": {
|
||||||
"useNextNotificationsApi": true,
|
"useNextNotificationsApi": true,
|
||||||
|
"softwareKeyboardLayoutMode": "resize",
|
||||||
"adaptiveIcon": {
|
"adaptiveIcon": {
|
||||||
"backgroundColor": "#E6F4FE",
|
"backgroundColor": "#E6F4FE",
|
||||||
"foregroundImage": "./assets/images/logo.png"
|
"foregroundImage": "./assets/images/logo.png"
|
||||||
@@ -86,4 +90,4 @@
|
|||||||
},
|
},
|
||||||
"owner": "samandar111"
|
"owner": "samandar111"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,18 +5,30 @@ import { useHomeStore } from '@/screens/home/lib/hook';
|
|||||||
import { BottomSheetModalProvider } from '@gorhom/bottom-sheet';
|
import { BottomSheetModalProvider } from '@gorhom/bottom-sheet';
|
||||||
import { router, Tabs } from 'expo-router';
|
import { router, Tabs } from 'expo-router';
|
||||||
import { Home, Megaphone, PlusCircle, User } from 'lucide-react-native';
|
import { Home, Megaphone, PlusCircle, User } from 'lucide-react-native';
|
||||||
import { useEffect, useRef } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Animated, Easing, Platform, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
|
import { Animated, Easing, Keyboard, Platform, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
|
||||||
import { GestureHandlerRootView } from 'react-native-gesture-handler';
|
import { GestureHandlerRootView } from 'react-native-gesture-handler';
|
||||||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
||||||
|
|
||||||
export default function TabsLayout() {
|
export default function TabsLayout() {
|
||||||
const { isDark } = useTheme();
|
const { isDark } = useTheme();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { setShowFilter, setStep } = useHomeStore();
|
const { setShowFilter, setStep } = useHomeStore();
|
||||||
const rotateAnim = useRef(new Animated.Value(0)).current;
|
const rotateAnim = useRef(new Animated.Value(0)).current;
|
||||||
const insets = useSafeAreaInsets();
|
const [keyboard, setKeyboard] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const showSub = Keyboard.addListener('keyboardDidShow', () => setKeyboard(true));
|
||||||
|
const hideSub = Keyboard.addListener('keyboardDidHide', () => setKeyboard(false));
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
showSub.remove();
|
||||||
|
hideSub.remove();
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
console.log(keyboard);
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
Animated.loop(
|
Animated.loop(
|
||||||
@@ -54,6 +66,7 @@ export default function TabsLayout() {
|
|||||||
headerShadowVisible: false,
|
headerShadowVisible: false,
|
||||||
tabBarStyle: {
|
tabBarStyle: {
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
|
display: keyboard ? "none" : "flex",
|
||||||
left: 16,
|
left: 16,
|
||||||
right: 16,
|
right: 16,
|
||||||
bottom: 8,
|
bottom: 8,
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
import { useTheme } from '@/components/ThemeContext';
|
|
||||||
import { FilterProvider } from '@/components/ui/FilterContext';
|
import { FilterProvider } from '@/components/ui/FilterContext';
|
||||||
import { CustomHeader } from '@/components/ui/Header';
|
import { CustomHeader } from '@/components/ui/Header';
|
||||||
import CreateAdsScreens from '@/screens/create-ads/ui/CreateAdsScreens';
|
import CreateAdsScreens from '@/screens/create-ads/ui/CreateAdsScreens';
|
||||||
|
|
||||||
export default function CreateAnnouncements() {
|
export default function CreateAnnouncements() {
|
||||||
const { isDark } = useTheme();
|
|
||||||
return (
|
return (
|
||||||
<FilterProvider>
|
<FilterProvider>
|
||||||
<CustomHeader />
|
<CustomHeader />
|
||||||
|
|||||||
@@ -15,17 +15,13 @@ function AppContent() {
|
|||||||
useNotifications();
|
useNotifications();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SafeAreaView style={{ flex: 1 }}>
|
<SafeAreaView style={{ flex: 1, backgroundColor: "#000" }}>
|
||||||
<StatusBar
|
<StatusBar style='light' backgroundColor='#000' />
|
||||||
style="dark"
|
|
||||||
backgroundColor="#fff"
|
|
||||||
translucent={false}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Stack screenOptions={{ headerShown: false }} />
|
<Stack screenOptions={{ headerShown: false }} />
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function RootLayout() {
|
export default function RootLayout() {
|
||||||
return (
|
return (
|
||||||
<I18nextProvider i18n={i18n}>
|
<I18nextProvider i18n={i18n}>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||||
|
import { router } from 'expo-router';
|
||||||
import { createContext, useContext, useEffect, useState } from 'react';
|
import { createContext, useContext, useEffect, useState } from 'react';
|
||||||
|
|
||||||
type AuthContextType = {
|
type AuthContextType = {
|
||||||
@@ -32,6 +33,7 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
|
|||||||
await AsyncStorage.removeItem('access_token');
|
await AsyncStorage.removeItem('access_token');
|
||||||
await AsyncStorage.removeItem('refresh_token');
|
await AsyncStorage.removeItem('refresh_token');
|
||||||
setIsAuthenticated(false);
|
setIsAuthenticated(false);
|
||||||
|
router.replace('/(auth)');
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import {
|
|||||||
View
|
View
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
|
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
|
||||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
|
||||||
import { Toast } from 'toastify-react-native';
|
import { Toast } from 'toastify-react-native';
|
||||||
import { auth_api } from '../login/lib/api';
|
import { auth_api } from '../login/lib/api';
|
||||||
import useTokenStore from '../login/lib/hook';
|
import useTokenStore from '../login/lib/hook';
|
||||||
@@ -130,72 +129,71 @@ const ConfirmScreen = () => {
|
|||||||
<View style={styles.decorCircle1} />
|
<View style={styles.decorCircle1} />
|
||||||
<View style={styles.decorCircle2} />
|
<View style={styles.decorCircle2} />
|
||||||
<AuthHeader />
|
<AuthHeader />
|
||||||
<SafeAreaView style={{ flex: 1 }}>
|
<KeyboardAwareScrollView
|
||||||
<KeyboardAwareScrollView
|
contentContainerStyle={styles.scrollContent}
|
||||||
contentContainerStyle={styles.scrollContent}
|
enableOnAndroid
|
||||||
showsVerticalScrollIndicator={false}
|
extraScrollHeight={120}
|
||||||
keyboardShouldPersistTaps="handled"
|
keyboardShouldPersistTaps="handled"
|
||||||
>
|
>
|
||||||
<View style={styles.header}>
|
<View style={styles.header}>
|
||||||
<View style={styles.iconContainer}>
|
<View style={styles.iconContainer}>
|
||||||
<LinearGradient colors={['#3b82f6', '#2563eb']} style={styles.iconGradient}>
|
<LinearGradient colors={['#3b82f6', '#2563eb']} style={styles.iconGradient}>
|
||||||
<ShieldCheck size={32} color="#ffffff" strokeWidth={2.2} />
|
<ShieldCheck size={32} color="#ffffff" strokeWidth={2.2} />
|
||||||
</LinearGradient>
|
</LinearGradient>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<Text style={styles.title}>{t('Kodni tasdiqlash')}</Text>
|
<Text style={styles.title}>{t('Kodni tasdiqlash')}</Text>
|
||||||
<Text style={styles.subtitle}>
|
<Text style={styles.subtitle}>
|
||||||
{t("Tasdiqlash kodi sizning Telegram botingizga yuboriladi. Botni ko'rish")}
|
{t("Tasdiqlash kodi sizning Telegram botingizga yuboriladi. Botni ko'rish")}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<View style={styles.phoneBadge}>
|
<View style={styles.phoneBadge}>
|
||||||
<Text style={styles.phoneText}>+{phoneOTP}</Text>
|
<Text style={styles.phoneText}>+{phoneOTP}</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* Telegram Button */}
|
{/* Telegram Button */}
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={styles.telegramBanner}
|
style={styles.telegramBanner}
|
||||||
onPress={openBotLink}
|
onPress={openBotLink}
|
||||||
activeOpacity={0.8}
|
activeOpacity={0.8}
|
||||||
|
>
|
||||||
|
<LinearGradient
|
||||||
|
colors={['#0088cc', '#00a2ed']}
|
||||||
|
style={styles.telegramGradient}
|
||||||
|
start={{ x: 0, y: 0 }}
|
||||||
|
end={{ x: 1, y: 0 }}
|
||||||
>
|
>
|
||||||
<LinearGradient
|
<View style={styles.botIconCircle}>
|
||||||
colors={['#0088cc', '#00a2ed']}
|
<MessageCircle size={20} color="#0088cc" fill="#fff" />
|
||||||
style={styles.telegramGradient}
|
</View>
|
||||||
start={{ x: 0, y: 0 }}
|
<View style={{ flex: 1 }}>
|
||||||
end={{ x: 1, y: 0 }}
|
<Text style={styles.telegramTitle}>{t('Botni ochish')}</Text>
|
||||||
>
|
<Text style={styles.telegramSub}>
|
||||||
<View style={styles.botIconCircle}>
|
{t('Telegram botni ochish uchun tugmani bosing va kodni oling')}
|
||||||
<MessageCircle size={20} color="#0088cc" fill="#fff" />
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={{ flex: 1 }}>
|
<ArrowLeft size={20} color="#fff" style={{ transform: [{ rotate: '180deg' }] }} />
|
||||||
<Text style={styles.telegramTitle}>{t('Botni ochish')}</Text>
|
</LinearGradient>
|
||||||
<Text style={styles.telegramSub}>
|
</TouchableOpacity>
|
||||||
{t('Telegram botni ochish uchun tugmani bosing va kodni oling')}
|
</View>
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
<ArrowLeft size={20} color="#fff" style={{ transform: [{ rotate: '180deg' }] }} />
|
|
||||||
</LinearGradient>
|
|
||||||
</TouchableOpacity>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<View style={styles.card}>
|
<View style={styles.card}>
|
||||||
<ConfirmForm
|
<ConfirmForm
|
||||||
onSubmit={(otp) => mutate({ code: otp, phone: phoneOTP || '' })}
|
onSubmit={(otp) => mutate({ code: otp, phone: phoneOTP || '' })}
|
||||||
isLoading={isPending}
|
isLoading={isPending}
|
||||||
error={error}
|
error={error}
|
||||||
onResendPress={() => resendMutation.mutate({ phone: phoneOTP || '' })}
|
onResendPress={() => resendMutation.mutate({ phone: phoneOTP || '' })}
|
||||||
resendTimer={resendTimer}
|
resendTimer={resendTimer}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* <View style={styles.infoBox}>
|
{/* <View style={styles.infoBox}>
|
||||||
<Text style={styles.infoText}>
|
<Text style={styles.infoText}>
|
||||||
<Text style={{ fontWeight: '700' }}>Eslatma:</Text> Kod SMS orqali kelmaydi. Agar
|
<Text style={{ fontWeight: '700' }}>Eslatma:</Text> Kod SMS orqali kelmaydi. Agar
|
||||||
botni ishga tushirmagan bo'lsangiz, yuqoridagi tugmani bosing.
|
botni ishga tushirmagan bo'lsangiz, yuqoridagi tugmani bosing.
|
||||||
</Text>
|
</Text>
|
||||||
</View> */}
|
</View> */}
|
||||||
</KeyboardAwareScrollView>
|
</KeyboardAwareScrollView>
|
||||||
</SafeAreaView>
|
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -26,12 +26,10 @@ import { useTranslation } from 'react-i18next';
|
|||||||
import {
|
import {
|
||||||
ActivityIndicator,
|
ActivityIndicator,
|
||||||
Keyboard,
|
Keyboard,
|
||||||
ScrollView,
|
|
||||||
StyleSheet,
|
StyleSheet,
|
||||||
Text,
|
Text,
|
||||||
TextInput,
|
TextInput,
|
||||||
TouchableOpacity,
|
TouchableOpacity,
|
||||||
TouchableWithoutFeedback,
|
|
||||||
View
|
View
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
|
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
|
||||||
@@ -110,6 +108,7 @@ export default function RegisterFormScreen() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const openCountrySheet = useCallback(() => {
|
const openCountrySheet = useCallback(() => {
|
||||||
|
Keyboard.dismiss();
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
countrySheetRef.current?.snapToIndex(0);
|
countrySheetRef.current?.snapToIndex(0);
|
||||||
}, 100);
|
}, 100);
|
||||||
@@ -162,7 +161,6 @@ export default function RegisterFormScreen() {
|
|||||||
onSuccess: (res) => {
|
onSuccess: (res) => {
|
||||||
setInfo(res.data.data);
|
setInfo(res.data.data);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
// INN o'zgarganda director ma'lumotlarini tozalash
|
|
||||||
setDirectorJshshr('');
|
setDirectorJshshr('');
|
||||||
setDirectorInfo(null);
|
setDirectorInfo(null);
|
||||||
setErrorDirectorInfo(null);
|
setErrorDirectorInfo(null);
|
||||||
@@ -180,26 +178,16 @@ export default function RegisterFormScreen() {
|
|||||||
mutationFn: (body: { value: string }) => auth_api.get_director_info(body),
|
mutationFn: (body: { value: string }) => auth_api.get_director_info(body),
|
||||||
onSuccess: (res) => {
|
onSuccess: (res) => {
|
||||||
const directorData = res.data;
|
const directorData = res.data;
|
||||||
|
|
||||||
// -------------------------------------------------------
|
|
||||||
// INN TEKSHIRUVI
|
|
||||||
// Director response strukturasi:
|
|
||||||
// data.entity.name.rows = [{ inn: "123456789", ... }, ...]
|
|
||||||
// Shu rows ichida joriy inn bor-yo'qligini tekshiramiz
|
|
||||||
// -------------------------------------------------------
|
|
||||||
const rows: Array<{ inn: string }> = directorData?.data?.entity?.name?.rows ?? [];
|
const rows: Array<{ inn: string }> = directorData?.data?.entity?.name?.rows ?? [];
|
||||||
|
|
||||||
const innMatch = rows.some((row) => row.inn === inn);
|
const innMatch = rows.some((row) => row.inn === inn);
|
||||||
|
|
||||||
if (!innMatch) {
|
if (!innMatch) {
|
||||||
// Director bu tashkilotga tegishli emas
|
|
||||||
setDirectorInfo(null);
|
setDirectorInfo(null);
|
||||||
setErrorDirectorInfo(t("Bu direktor ko'rsatilgan tashkilotga tegishli emas"));
|
setErrorDirectorInfo(t("Bu direktor ko'rsatilgan tashkilotga tegishli emas"));
|
||||||
setDirectorLoading(false);
|
setDirectorLoading(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// INN mos keldi — director ma'lumotini saqlash
|
|
||||||
setDirectorInfo(directorData);
|
setDirectorInfo(directorData);
|
||||||
setDirectorLoading(false);
|
setDirectorLoading(false);
|
||||||
setErrorDirectorInfo(null);
|
setErrorDirectorInfo(null);
|
||||||
@@ -326,7 +314,7 @@ export default function RegisterFormScreen() {
|
|||||||
inn.length === 9 &&
|
inn.length === 9 &&
|
||||||
info &&
|
info &&
|
||||||
directorJshshr.length === 14 &&
|
directorJshshr.length === 14 &&
|
||||||
directorInfo // faqat INN mos kelganda to'ldiriladi
|
directorInfo
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -334,7 +322,6 @@ export default function RegisterFormScreen() {
|
|||||||
})();
|
})();
|
||||||
|
|
||||||
const handleContinue = () => {
|
const handleContinue = () => {
|
||||||
// Director to'liq ismi directorInfo dan olinadi
|
|
||||||
const directorFullName = isLegal
|
const directorFullName = isLegal
|
||||||
? (directorInfo?.data?.entrepreneur?.rows[0]?.entrepreneur ?? '')
|
? (directorInfo?.data?.entrepreneur?.rows[0]?.entrepreneur ?? '')
|
||||||
: `${info?.firstname ?? ''} ${info?.lastname ?? ''} ${info?.middlename ?? ''}`.trim();
|
: `${info?.firstname ?? ''} ${info?.lastname ?? ''} ${info?.middlename ?? ''}`.trim();
|
||||||
@@ -361,14 +348,22 @@ export default function RegisterFormScreen() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<KeyboardAwareScrollView
|
// ✅ Fragment — BottomSheet tashqarida bo'lishi uchun
|
||||||
showsVerticalScrollIndicator={false}
|
<>
|
||||||
keyboardShouldPersistTaps="handled"
|
<KeyboardAwareScrollView
|
||||||
enableOnAndroid
|
enableOnAndroid
|
||||||
extraScrollHeight={120}
|
enableAutomaticScroll
|
||||||
>
|
extraScrollHeight={120}
|
||||||
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
|
style={styles.keyboardScroll}
|
||||||
<View style={styles.container}>
|
>
|
||||||
|
{/* ✅ TouchableWithoutFeedback yo'q — onStartShouldSetResponder ishlatildi */}
|
||||||
|
<View
|
||||||
|
style={styles.container}
|
||||||
|
onStartShouldSetResponder={() => {
|
||||||
|
Keyboard.dismiss();
|
||||||
|
return false; // false — child elementlar (buttonlar) ham ishlaydi
|
||||||
|
}}
|
||||||
|
>
|
||||||
<LinearGradient
|
<LinearGradient
|
||||||
colors={['#0f172a', '#1e293b', '#334155']}
|
colors={['#0f172a', '#1e293b', '#334155']}
|
||||||
start={{ x: 0, y: 0 }}
|
start={{ x: 0, y: 0 }}
|
||||||
@@ -380,13 +375,9 @@ export default function RegisterFormScreen() {
|
|||||||
|
|
||||||
<AuthHeader />
|
<AuthHeader />
|
||||||
|
|
||||||
|
{/* ✅ SafeAreaView va ichki ScrollView yo'q — to'g'ridan View */}
|
||||||
<SafeAreaView style={{ flex: 1 }} edges={['bottom']}>
|
<SafeAreaView style={{ flex: 1 }} edges={['bottom']}>
|
||||||
|
<View style={styles.scrollContent}>
|
||||||
<ScrollView
|
|
||||||
contentContainerStyle={styles.scrollContent}
|
|
||||||
showsVerticalScrollIndicator={false}
|
|
||||||
keyboardShouldPersistTaps="handled"
|
|
||||||
>
|
|
||||||
<View style={styles.header}>
|
<View style={styles.header}>
|
||||||
<View style={styles.iconContainer}>
|
<View style={styles.iconContainer}>
|
||||||
<LinearGradient
|
<LinearGradient
|
||||||
@@ -408,43 +399,6 @@ export default function RegisterFormScreen() {
|
|||||||
|
|
||||||
<View style={styles.card}>
|
<View style={styles.card}>
|
||||||
<View style={styles.formGap}>
|
<View style={styles.formGap}>
|
||||||
{/* ---- Davlat (Country) ---- */}
|
|
||||||
{/* <View>
|
|
||||||
<Text style={styles.label}>{t('Davlat')}</Text>
|
|
||||||
<TouchableOpacity
|
|
||||||
style={[
|
|
||||||
styles.input,
|
|
||||||
styles.inputDisabled,
|
|
||||||
]}
|
|
||||||
onPress={openCountrySheet}
|
|
||||||
activeOpacity={0.7}
|
|
||||||
testID="country-select"
|
|
||||||
disabled
|
|
||||||
>
|
|
||||||
{countryLoading ? (
|
|
||||||
<ActivityIndicator size="small" color="#3b82f6" style={{ flex: 1 }} />
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<Image
|
|
||||||
source={{ uri: `https://flagcdn.com/w320/${selectedCountry.toLowerCase()}.png` }}
|
|
||||||
style={{ width: 30, height: 15 }}
|
|
||||||
resizeMode="cover"
|
|
||||||
/>
|
|
||||||
<Text
|
|
||||||
style={[
|
|
||||||
styles.textInput,
|
|
||||||
// { color: selectedCountry === 'all' ? '#94a3b8' : '#1e293b' },
|
|
||||||
{ color: '#94a3b8' },
|
|
||||||
]}
|
|
||||||
numberOfLines={1}
|
|
||||||
>
|
|
||||||
{selectedCountryName}
|
|
||||||
</Text>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
<ChevronDown size={18} color={'#cbd5e1'} />
|
|
||||||
</TouchableOpacity>
|
|
||||||
</View> */}
|
|
||||||
{/* ---- YATT / BAND ---- */}
|
{/* ---- YATT / BAND ---- */}
|
||||||
{isYattOrBand && (
|
{isYattOrBand && (
|
||||||
<>
|
<>
|
||||||
@@ -544,7 +498,7 @@ export default function RegisterFormScreen() {
|
|||||||
</View>
|
</View>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
{/* ---- LEGAL ENTITY: Direktor JSHSHR — faqat info kelganda ko'rinadi ---- */}
|
{/* ---- LEGAL ENTITY: Direktor JSHSHR ---- */}
|
||||||
{isLegal && info && (
|
{isLegal && info && (
|
||||||
<View>
|
<View>
|
||||||
<Text style={styles.label}>{t('Direktor JSHSHR')}</Text>
|
<Text style={styles.label}>{t('Direktor JSHSHR')}</Text>
|
||||||
@@ -565,7 +519,6 @@ export default function RegisterFormScreen() {
|
|||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* ---- Direktor ma'lumoti (INN mos kelgan holda) ---- */}
|
|
||||||
{directorInfo && (
|
{directorInfo && (
|
||||||
<View style={[styles.infoBox, { marginTop: 8 }]}>
|
<View style={[styles.infoBox, { marginTop: 8 }]}>
|
||||||
<Text style={styles.infoLabel}>{t('Direktor')}</Text>
|
<Text style={styles.infoLabel}>{t('Direktor')}</Text>
|
||||||
@@ -575,7 +528,6 @@ export default function RegisterFormScreen() {
|
|||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* ---- Xato: INN mos kelmasa yoki server xatosi ---- */}
|
|
||||||
{directorInfoError && (
|
{directorInfoError && (
|
||||||
<View style={[styles.errorBox, { marginTop: 8 }]}>
|
<View style={[styles.errorBox, { marginTop: 8 }]}>
|
||||||
<Text style={styles.errorText}>{directorInfoError}</Text>
|
<Text style={styles.errorText}>{directorInfoError}</Text>
|
||||||
@@ -648,98 +600,103 @@ export default function RegisterFormScreen() {
|
|||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</ScrollView>
|
</View>
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
|
|
||||||
{/* ---- Country BottomSheet ---- */}
|
|
||||||
<BottomSheet
|
|
||||||
ref={countrySheetRef}
|
|
||||||
index={-1}
|
|
||||||
snapPoints={snapPoints}
|
|
||||||
enablePanDownToClose={true}
|
|
||||||
enableDynamicSizing={false}
|
|
||||||
enableOverDrag={false}
|
|
||||||
backdropComponent={renderBackdrop}
|
|
||||||
backgroundStyle={styles.bottomSheetBg}
|
|
||||||
handleIndicatorStyle={styles.handleIndicator}
|
|
||||||
android_keyboardInputMode="adjustResize"
|
|
||||||
keyboardBehavior="interactive"
|
|
||||||
keyboardBlurBehavior="restore"
|
|
||||||
>
|
|
||||||
<View style={styles.sheetHeader}>
|
|
||||||
<Text style={styles.sheetTitle}>{t('Davlat')}</Text>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
{/* Search input */}
|
|
||||||
<View style={styles.searchContainer}>
|
|
||||||
<Search size={16} color="#94a3b8" />
|
|
||||||
<BottomSheetTextInput
|
|
||||||
value={countrySearch}
|
|
||||||
onChangeText={setCountrySearch}
|
|
||||||
placeholder={t('Qidirish...')}
|
|
||||||
placeholderTextColor="#94a3b8"
|
|
||||||
style={styles.searchInput}
|
|
||||||
clearButtonMode="while-editing"
|
|
||||||
autoCorrect={false}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<BottomSheetFlatList
|
|
||||||
data={filteredCountries}
|
|
||||||
keyExtractor={(item: any) => item.id?.toString()}
|
|
||||||
contentContainerStyle={styles.listContainer}
|
|
||||||
showsVerticalScrollIndicator={false}
|
|
||||||
keyboardShouldPersistTaps="handled"
|
|
||||||
ListEmptyComponent={
|
|
||||||
<View style={styles.emptyList}>
|
|
||||||
<Text style={styles.emptyListText}>{t('Natija topilmadi')}</Text>
|
|
||||||
</View>
|
|
||||||
}
|
|
||||||
renderItem={({ item }: { item: any }) => {
|
|
||||||
const isSelected = item.flag?.toUpperCase() === selectedCountry;
|
|
||||||
const flagCode = item.flag ? item.flag.toLowerCase() : '';
|
|
||||||
return (
|
|
||||||
<TouchableOpacity
|
|
||||||
style={[styles.listItem, isSelected && styles.selectedListItem]}
|
|
||||||
onPress={() => {
|
|
||||||
setSelectedCountry(item.flag?.toUpperCase());
|
|
||||||
closeCountrySheet();
|
|
||||||
}}
|
|
||||||
activeOpacity={0.7}
|
|
||||||
>
|
|
||||||
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 10, flex: 1 }}>
|
|
||||||
{flagCode ? (
|
|
||||||
<Image
|
|
||||||
source={{ uri: `https://flagcdn.com/w320/${flagCode}.png` }}
|
|
||||||
style={{ width: 34, height: 22, borderRadius: 2 }}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<Globe size={20} color={isSelected ? '#2563eb' : '#94a3b8'} />
|
|
||||||
)}
|
|
||||||
<Text style={[styles.listItemText, isSelected && styles.selectedListItemText]}>
|
|
||||||
{item.name}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
{isSelected && (
|
|
||||||
<View style={styles.checkmark}>
|
|
||||||
<CheckIcon color="#3b82f6" strokeWidth={2.5} size={16} />
|
|
||||||
</View>
|
|
||||||
)}
|
|
||||||
</TouchableOpacity>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</BottomSheet>
|
|
||||||
</View>
|
</View>
|
||||||
</TouchableWithoutFeedback>
|
</KeyboardAwareScrollView>
|
||||||
</KeyboardAwareScrollView>
|
|
||||||
|
{/* ✅ BottomSheet KeyboardAwareScrollView TASHQARISIDA */}
|
||||||
|
<BottomSheet
|
||||||
|
ref={countrySheetRef}
|
||||||
|
index={-1}
|
||||||
|
snapPoints={snapPoints}
|
||||||
|
enablePanDownToClose={true}
|
||||||
|
enableDynamicSizing={false}
|
||||||
|
enableOverDrag={false}
|
||||||
|
backdropComponent={renderBackdrop}
|
||||||
|
backgroundStyle={styles.bottomSheetBg}
|
||||||
|
handleIndicatorStyle={styles.handleIndicator}
|
||||||
|
android_keyboardInputMode="adjustResize"
|
||||||
|
keyboardBehavior="interactive"
|
||||||
|
keyboardBlurBehavior="restore"
|
||||||
|
>
|
||||||
|
<View style={styles.sheetHeader}>
|
||||||
|
<Text style={styles.sheetTitle}>{t('Davlat')}</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.searchContainer}>
|
||||||
|
<Search size={16} color="#94a3b8" />
|
||||||
|
<BottomSheetTextInput
|
||||||
|
value={countrySearch}
|
||||||
|
onChangeText={setCountrySearch}
|
||||||
|
placeholder={t('Qidirish...')}
|
||||||
|
placeholderTextColor="#94a3b8"
|
||||||
|
style={styles.searchInput}
|
||||||
|
clearButtonMode="while-editing"
|
||||||
|
autoCorrect={false}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<BottomSheetFlatList
|
||||||
|
data={filteredCountries}
|
||||||
|
keyExtractor={(item: any) => item.id?.toString()}
|
||||||
|
contentContainerStyle={styles.listContainer}
|
||||||
|
showsVerticalScrollIndicator={false}
|
||||||
|
keyboardShouldPersistTaps="handled"
|
||||||
|
ListEmptyComponent={
|
||||||
|
<View style={styles.emptyList}>
|
||||||
|
<Text style={styles.emptyListText}>{t('Natija topilmadi')}</Text>
|
||||||
|
</View>
|
||||||
|
}
|
||||||
|
renderItem={({ item }: { item: any }) => {
|
||||||
|
const isSelected = item.flag?.toUpperCase() === selectedCountry;
|
||||||
|
const flagCode = item.flag ? item.flag.toLowerCase() : '';
|
||||||
|
return (
|
||||||
|
<TouchableOpacity
|
||||||
|
style={[styles.listItem, isSelected && styles.selectedListItem]}
|
||||||
|
onPress={() => {
|
||||||
|
setSelectedCountry(item.flag?.toUpperCase());
|
||||||
|
closeCountrySheet();
|
||||||
|
}}
|
||||||
|
activeOpacity={0.7}
|
||||||
|
>
|
||||||
|
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 10, flex: 1 }}>
|
||||||
|
{flagCode ? (
|
||||||
|
<Image
|
||||||
|
source={{ uri: `https://flagcdn.com/w320/${flagCode}.png` }}
|
||||||
|
style={{ width: 34, height: 22, borderRadius: 2 }}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<Globe size={20} color={isSelected ? '#2563eb' : '#94a3b8'} />
|
||||||
|
)}
|
||||||
|
<Text style={[styles.listItemText, isSelected && styles.selectedListItemText]}>
|
||||||
|
{item.name}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
{isSelected && (
|
||||||
|
<View style={styles.checkmark}>
|
||||||
|
<CheckIcon color="#3b82f6" strokeWidth={2.5} size={16} />
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
</TouchableOpacity>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</BottomSheet>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
|
// ✅ KeyboardAwareScrollView uchun style
|
||||||
|
keyboardScroll: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: '#0f172a',
|
||||||
|
},
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
backgroundColor: '#0f172a',
|
backgroundColor: '#0f172a',
|
||||||
|
minHeight: '100%',
|
||||||
},
|
},
|
||||||
scrollContent: {
|
scrollContent: {
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
@@ -969,15 +926,6 @@ const styles = StyleSheet.create({
|
|||||||
fontWeight: '800' as const,
|
fontWeight: '800' as const,
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
},
|
},
|
||||||
footer: {
|
|
||||||
marginTop: 20,
|
|
||||||
alignItems: 'center',
|
|
||||||
},
|
|
||||||
footerText: {
|
|
||||||
color: '#94a3b8',
|
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: '600' as const,
|
|
||||||
},
|
|
||||||
decorCircle1: {
|
decorCircle1: {
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
top: -150,
|
top: -150,
|
||||||
@@ -997,7 +945,7 @@ const styles = StyleSheet.create({
|
|||||||
backgroundColor: 'rgba(16, 185, 129, 0.08)',
|
backgroundColor: 'rgba(16, 185, 129, 0.08)',
|
||||||
},
|
},
|
||||||
inputDisabled: {
|
inputDisabled: {
|
||||||
backgroundColor: '#f1f5f9', // disabled bo'lganda fon rangi
|
backgroundColor: '#f1f5f9',
|
||||||
borderColor: '#e2e8f0', // disabled bo'lganda border rangi
|
borderColor: '#e2e8f0',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useTheme } from '@/components/ThemeContext';
|
import { useTheme } from '@/components/ThemeContext';
|
||||||
import { BottomSheetBackdrop, BottomSheetModal, BottomSheetScrollView, TouchableWithoutFeedback } from '@gorhom/bottom-sheet';
|
import { BottomSheetBackdrop, BottomSheetModal, BottomSheetScrollView } from '@gorhom/bottom-sheet';
|
||||||
import { useMutation, useQuery } from '@tanstack/react-query';
|
import { useMutation, useQuery } from '@tanstack/react-query';
|
||||||
import { AxiosError } from 'axios';
|
import { AxiosError } from 'axios';
|
||||||
import { router, useFocusEffect } from 'expo-router';
|
import { router, useFocusEffect } from 'expo-router';
|
||||||
@@ -9,17 +9,17 @@ import {
|
|||||||
Image,
|
Image,
|
||||||
Keyboard,
|
Keyboard,
|
||||||
Linking,
|
Linking,
|
||||||
ScrollView,
|
|
||||||
StyleSheet,
|
StyleSheet,
|
||||||
Text,
|
Text,
|
||||||
TouchableOpacity,
|
TouchableOpacity,
|
||||||
|
TouchableWithoutFeedback,
|
||||||
View
|
View
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
|
|
||||||
import OneClick from '@/assets/images/one_click.png';
|
import OneClick from '@/assets/images/one_click.png';
|
||||||
import PAYME from '@/assets/images/Payme_NEW.png';
|
import PAYME from '@/assets/images/Payme_NEW.png';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
|
import { KeyboardAwareScrollView, } from 'react-native-keyboard-aware-scroll-view';
|
||||||
import { price_calculation } from '../lib/api';
|
import { price_calculation } from '../lib/api';
|
||||||
import { CreateAdsResponse } from '../lib/types';
|
import { CreateAdsResponse } from '../lib/types';
|
||||||
import StepFour from './StepFour';
|
import StepFour from './StepFour';
|
||||||
@@ -213,12 +213,16 @@ export default function CreateAdsScreens() {
|
|||||||
<KeyboardAwareScrollView
|
<KeyboardAwareScrollView
|
||||||
showsVerticalScrollIndicator={false}
|
showsVerticalScrollIndicator={false}
|
||||||
keyboardShouldPersistTaps="handled"
|
keyboardShouldPersistTaps="handled"
|
||||||
enableOnAndroid
|
|
||||||
extraScrollHeight={120}
|
|
||||||
style={[styles.safeArea, isDark ? styles.darkBg : styles.lightBg]}
|
style={[styles.safeArea, isDark ? styles.darkBg : styles.lightBg]}
|
||||||
>
|
>
|
||||||
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
|
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
|
||||||
<ScrollView contentContainerStyle={[styles.container, { paddingBottom: 90 }]}>
|
<View
|
||||||
|
style={[styles.container, { marginBottom: Keyboard.isVisible() ? 10 : 90 }]}
|
||||||
|
onStartShouldSetResponder={() => {
|
||||||
|
Keyboard.dismiss();
|
||||||
|
return false;
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Image
|
<Image
|
||||||
source={OneClick}
|
source={OneClick}
|
||||||
style={{ width: 180, height: 56, marginBottom: 10 }}
|
style={{ width: 180, height: 56, marginBottom: 10 }}
|
||||||
@@ -281,55 +285,51 @@ export default function CreateAdsScreens() {
|
|||||||
</Text>
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
</ScrollView>
|
</View>
|
||||||
|
|
||||||
{/* FOOTER */}
|
|
||||||
|
|
||||||
{/* PAYMENT BOTTOM SHEET */}
|
|
||||||
<BottomSheetModal
|
|
||||||
ref={bottomSheetModalRef}
|
|
||||||
index={0}
|
|
||||||
snapPoints={['70%', '95%']}
|
|
||||||
backdropComponent={renderBackdrop}
|
|
||||||
handleIndicatorStyle={{ backgroundColor: '#94a3b8', width: 50 }}
|
|
||||||
backgroundStyle={{ backgroundColor: isDark ? '#0f172a' : '#ffffff' }}
|
|
||||||
enablePanDownToClose
|
|
||||||
>
|
|
||||||
<BottomSheetScrollView
|
|
||||||
style={styles.sheetContent}
|
|
||||||
contentContainerStyle={styles.sheetContentContainer}
|
|
||||||
>
|
|
||||||
<View style={{ padding: 20 }}>
|
|
||||||
<Text style={[styles.sheetTitle, isDark ? styles.darkText : styles.lightText]}>
|
|
||||||
{t("To'lov turini tanlang")}
|
|
||||||
</Text>
|
|
||||||
|
|
||||||
<TouchableOpacity
|
|
||||||
style={[
|
|
||||||
styles.paymentItem,
|
|
||||||
isDark ? styles.darkPaymentItem : styles.lightPaymentItem,
|
|
||||||
{ flexDirection: 'row', justifyContent: 'flex-start', alignItems: 'center' },
|
|
||||||
]}
|
|
||||||
onPress={() => sendPayment('payme')}
|
|
||||||
>
|
|
||||||
<Image source={PAYME} style={{ width: 80, height: 80 }} />
|
|
||||||
</TouchableOpacity>
|
|
||||||
|
|
||||||
<TouchableOpacity
|
|
||||||
style={[
|
|
||||||
styles.paymentItem,
|
|
||||||
isDark ? styles.darkPaymentItem : styles.lightPaymentItem,
|
|
||||||
]}
|
|
||||||
onPress={() => sendPayment('referral')}
|
|
||||||
>
|
|
||||||
<Text style={[styles.paymentText, isDark ? styles.darkText : styles.lightText]}>
|
|
||||||
{t('Referal orqali')}
|
|
||||||
</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
</View>
|
|
||||||
</BottomSheetScrollView>
|
|
||||||
</BottomSheetModal>
|
|
||||||
</TouchableWithoutFeedback>
|
</TouchableWithoutFeedback>
|
||||||
|
<BottomSheetModal
|
||||||
|
ref={bottomSheetModalRef}
|
||||||
|
index={0}
|
||||||
|
snapPoints={['70%', '95%']}
|
||||||
|
backdropComponent={renderBackdrop}
|
||||||
|
handleIndicatorStyle={{ backgroundColor: '#94a3b8', width: 50 }}
|
||||||
|
backgroundStyle={{ backgroundColor: isDark ? '#0f172a' : '#ffffff' }}
|
||||||
|
enablePanDownToClose
|
||||||
|
>
|
||||||
|
<BottomSheetScrollView
|
||||||
|
style={styles.sheetContent}
|
||||||
|
contentContainerStyle={styles.sheetContentContainer}
|
||||||
|
>
|
||||||
|
<View style={{ padding: 20 }}>
|
||||||
|
<Text style={[styles.sheetTitle, isDark ? styles.darkText : styles.lightText]}>
|
||||||
|
{t("To'lov turini tanlang")}
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<TouchableOpacity
|
||||||
|
style={[
|
||||||
|
styles.paymentItem,
|
||||||
|
isDark ? styles.darkPaymentItem : styles.lightPaymentItem,
|
||||||
|
{ flexDirection: 'row', justifyContent: 'flex-start', alignItems: 'center' },
|
||||||
|
]}
|
||||||
|
onPress={() => sendPayment('payme')}
|
||||||
|
>
|
||||||
|
<Image source={PAYME} style={{ width: 80, height: 80 }} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
|
||||||
|
<TouchableOpacity
|
||||||
|
style={[
|
||||||
|
styles.paymentItem,
|
||||||
|
isDark ? styles.darkPaymentItem : styles.lightPaymentItem,
|
||||||
|
]}
|
||||||
|
onPress={() => sendPayment('referral')}
|
||||||
|
>
|
||||||
|
<Text style={[styles.paymentText, isDark ? styles.darkText : styles.lightText]}>
|
||||||
|
{t('Referal orqali')}
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</BottomSheetScrollView>
|
||||||
|
</BottomSheetModal>
|
||||||
</KeyboardAwareScrollView>
|
</KeyboardAwareScrollView>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,8 +60,6 @@ export default function CreateReferrals() {
|
|||||||
const validate = () => {
|
const validate = () => {
|
||||||
const e: any = {};
|
const e: any = {};
|
||||||
|
|
||||||
if (!form.code || form.code.length !== 9)
|
|
||||||
e.code = 'Kod aynan 9 ta belgidan iborat bo‘lishi kerak';
|
|
||||||
if (!form.description || form.description.length < 5)
|
if (!form.description || form.description.length < 5)
|
||||||
e.description = 'Tavsif kamida 5 ta belgidan iborat bo‘lishi kerak';
|
e.description = 'Tavsif kamida 5 ta belgidan iborat bo‘lishi kerak';
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ export function ReferralsTab() {
|
|||||||
|
|
||||||
// Clipboard + Share funksiyasi
|
// Clipboard + Share funksiyasi
|
||||||
const handleCopyAndShare = async (code: string) => {
|
const handleCopyAndShare = async (code: string) => {
|
||||||
const referralLink = `https://t.me/infotargetbot/join?startapp=${code}`;
|
const referralLink = `${code}`;
|
||||||
|
|
||||||
// Clipboard-ga nusxa olish
|
// Clipboard-ga nusxa olish
|
||||||
await Clipboard.setStringAsync(referralLink);
|
await Clipboard.setStringAsync(referralLink);
|
||||||
|
|||||||
Reference in New Issue
Block a user