bug fixed
This commit is contained in:
6
app.json
6
app.json
@@ -11,12 +11,16 @@
|
||||
"ios": {
|
||||
"supportsTablet": true,
|
||||
"infoPlist": {
|
||||
"UIBackgroundModes": ["remote-notification"]
|
||||
"UIBackgroundModes": [
|
||||
"remote-notification"
|
||||
],
|
||||
"UIViewControllerBasedStatusBarAppearance": true
|
||||
},
|
||||
"bundleIdentifier": "com.felix.infotarget"
|
||||
},
|
||||
"android": {
|
||||
"useNextNotificationsApi": true,
|
||||
"softwareKeyboardLayoutMode": "resize",
|
||||
"adaptiveIcon": {
|
||||
"backgroundColor": "#E6F4FE",
|
||||
"foregroundImage": "./assets/images/logo.png"
|
||||
|
||||
@@ -5,18 +5,30 @@ import { useHomeStore } from '@/screens/home/lib/hook';
|
||||
import { BottomSheetModalProvider } from '@gorhom/bottom-sheet';
|
||||
import { router, Tabs } from 'expo-router';
|
||||
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 { 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 { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||
|
||||
export default function TabsLayout() {
|
||||
const { isDark } = useTheme();
|
||||
const { t } = useTranslation();
|
||||
const { setShowFilter, setStep } = useHomeStore();
|
||||
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(() => {
|
||||
Animated.loop(
|
||||
@@ -54,6 +66,7 @@ export default function TabsLayout() {
|
||||
headerShadowVisible: false,
|
||||
tabBarStyle: {
|
||||
position: 'absolute',
|
||||
display: keyboard ? "none" : "flex",
|
||||
left: 16,
|
||||
right: 16,
|
||||
bottom: 8,
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import { useTheme } from '@/components/ThemeContext';
|
||||
import { FilterProvider } from '@/components/ui/FilterContext';
|
||||
import { CustomHeader } from '@/components/ui/Header';
|
||||
import CreateAdsScreens from '@/screens/create-ads/ui/CreateAdsScreens';
|
||||
|
||||
export default function CreateAnnouncements() {
|
||||
const { isDark } = useTheme();
|
||||
return (
|
||||
<FilterProvider>
|
||||
<CustomHeader />
|
||||
|
||||
@@ -15,17 +15,13 @@ function AppContent() {
|
||||
useNotifications();
|
||||
|
||||
return (
|
||||
<SafeAreaView style={{ flex: 1 }}>
|
||||
<StatusBar
|
||||
style="dark"
|
||||
backgroundColor="#fff"
|
||||
translucent={false}
|
||||
/>
|
||||
|
||||
<SafeAreaView style={{ flex: 1, backgroundColor: "#000" }}>
|
||||
<StatusBar style='light' backgroundColor='#000' />
|
||||
<Stack screenOptions={{ headerShown: false }} />
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
|
||||
export default function RootLayout() {
|
||||
return (
|
||||
<I18nextProvider i18n={i18n}>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import { router } from 'expo-router';
|
||||
import { createContext, useContext, useEffect, useState } from 'react';
|
||||
|
||||
type AuthContextType = {
|
||||
@@ -32,6 +33,7 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
|
||||
await AsyncStorage.removeItem('access_token');
|
||||
await AsyncStorage.removeItem('refresh_token');
|
||||
setIsAuthenticated(false);
|
||||
router.replace('/(auth)');
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -20,7 +20,6 @@ import {
|
||||
View
|
||||
} from 'react-native';
|
||||
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import { Toast } from 'toastify-react-native';
|
||||
import { auth_api } from '../login/lib/api';
|
||||
import useTokenStore from '../login/lib/hook';
|
||||
@@ -130,10 +129,10 @@ const ConfirmScreen = () => {
|
||||
<View style={styles.decorCircle1} />
|
||||
<View style={styles.decorCircle2} />
|
||||
<AuthHeader />
|
||||
<SafeAreaView style={{ flex: 1 }}>
|
||||
<KeyboardAwareScrollView
|
||||
contentContainerStyle={styles.scrollContent}
|
||||
showsVerticalScrollIndicator={false}
|
||||
enableOnAndroid
|
||||
extraScrollHeight={120}
|
||||
keyboardShouldPersistTaps="handled"
|
||||
>
|
||||
<View style={styles.header}>
|
||||
@@ -195,7 +194,6 @@ const ConfirmScreen = () => {
|
||||
</Text>
|
||||
</View> */}
|
||||
</KeyboardAwareScrollView>
|
||||
</SafeAreaView>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -26,12 +26,10 @@ import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
ActivityIndicator,
|
||||
Keyboard,
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TextInput,
|
||||
TouchableOpacity,
|
||||
TouchableWithoutFeedback,
|
||||
View
|
||||
} from 'react-native';
|
||||
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
|
||||
@@ -110,6 +108,7 @@ export default function RegisterFormScreen() {
|
||||
});
|
||||
|
||||
const openCountrySheet = useCallback(() => {
|
||||
Keyboard.dismiss();
|
||||
setTimeout(() => {
|
||||
countrySheetRef.current?.snapToIndex(0);
|
||||
}, 100);
|
||||
@@ -162,7 +161,6 @@ export default function RegisterFormScreen() {
|
||||
onSuccess: (res) => {
|
||||
setInfo(res.data.data);
|
||||
setLoading(false);
|
||||
// INN o'zgarganda director ma'lumotlarini tozalash
|
||||
setDirectorJshshr('');
|
||||
setDirectorInfo(null);
|
||||
setErrorDirectorInfo(null);
|
||||
@@ -180,26 +178,16 @@ export default function RegisterFormScreen() {
|
||||
mutationFn: (body: { value: string }) => auth_api.get_director_info(body),
|
||||
onSuccess: (res) => {
|
||||
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 innMatch = rows.some((row) => row.inn === inn);
|
||||
|
||||
if (!innMatch) {
|
||||
// Director bu tashkilotga tegishli emas
|
||||
setDirectorInfo(null);
|
||||
setErrorDirectorInfo(t("Bu direktor ko'rsatilgan tashkilotga tegishli emas"));
|
||||
setDirectorLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// INN mos keldi — director ma'lumotini saqlash
|
||||
setDirectorInfo(directorData);
|
||||
setDirectorLoading(false);
|
||||
setErrorDirectorInfo(null);
|
||||
@@ -326,7 +314,7 @@ export default function RegisterFormScreen() {
|
||||
inn.length === 9 &&
|
||||
info &&
|
||||
directorJshshr.length === 14 &&
|
||||
directorInfo // faqat INN mos kelganda to'ldiriladi
|
||||
directorInfo
|
||||
);
|
||||
}
|
||||
|
||||
@@ -334,7 +322,6 @@ export default function RegisterFormScreen() {
|
||||
})();
|
||||
|
||||
const handleContinue = () => {
|
||||
// Director to'liq ismi directorInfo dan olinadi
|
||||
const directorFullName = isLegal
|
||||
? (directorInfo?.data?.entrepreneur?.rows[0]?.entrepreneur ?? '')
|
||||
: `${info?.firstname ?? ''} ${info?.lastname ?? ''} ${info?.middlename ?? ''}`.trim();
|
||||
@@ -361,14 +348,22 @@ export default function RegisterFormScreen() {
|
||||
};
|
||||
|
||||
return (
|
||||
// ✅ Fragment — BottomSheet tashqarida bo'lishi uchun
|
||||
<>
|
||||
<KeyboardAwareScrollView
|
||||
showsVerticalScrollIndicator={false}
|
||||
keyboardShouldPersistTaps="handled"
|
||||
enableOnAndroid
|
||||
enableAutomaticScroll
|
||||
extraScrollHeight={120}
|
||||
style={styles.keyboardScroll}
|
||||
>
|
||||
{/* ✅ TouchableWithoutFeedback yo'q — onStartShouldSetResponder ishlatildi */}
|
||||
<View
|
||||
style={styles.container}
|
||||
onStartShouldSetResponder={() => {
|
||||
Keyboard.dismiss();
|
||||
return false; // false — child elementlar (buttonlar) ham ishlaydi
|
||||
}}
|
||||
>
|
||||
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
|
||||
<View style={styles.container}>
|
||||
<LinearGradient
|
||||
colors={['#0f172a', '#1e293b', '#334155']}
|
||||
start={{ x: 0, y: 0 }}
|
||||
@@ -380,13 +375,9 @@ export default function RegisterFormScreen() {
|
||||
|
||||
<AuthHeader />
|
||||
|
||||
{/* ✅ SafeAreaView va ichki ScrollView yo'q — to'g'ridan View */}
|
||||
<SafeAreaView style={{ flex: 1 }} edges={['bottom']}>
|
||||
|
||||
<ScrollView
|
||||
contentContainerStyle={styles.scrollContent}
|
||||
showsVerticalScrollIndicator={false}
|
||||
keyboardShouldPersistTaps="handled"
|
||||
>
|
||||
<View style={styles.scrollContent}>
|
||||
<View style={styles.header}>
|
||||
<View style={styles.iconContainer}>
|
||||
<LinearGradient
|
||||
@@ -408,43 +399,6 @@ export default function RegisterFormScreen() {
|
||||
|
||||
<View style={styles.card}>
|
||||
<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 ---- */}
|
||||
{isYattOrBand && (
|
||||
<>
|
||||
@@ -544,7 +498,7 @@ export default function RegisterFormScreen() {
|
||||
</View>
|
||||
))}
|
||||
|
||||
{/* ---- LEGAL ENTITY: Direktor JSHSHR — faqat info kelganda ko'rinadi ---- */}
|
||||
{/* ---- LEGAL ENTITY: Direktor JSHSHR ---- */}
|
||||
{isLegal && info && (
|
||||
<View>
|
||||
<Text style={styles.label}>{t('Direktor JSHSHR')}</Text>
|
||||
@@ -565,7 +519,6 @@ export default function RegisterFormScreen() {
|
||||
)}
|
||||
</View>
|
||||
|
||||
{/* ---- Direktor ma'lumoti (INN mos kelgan holda) ---- */}
|
||||
{directorInfo && (
|
||||
<View style={[styles.infoBox, { marginTop: 8 }]}>
|
||||
<Text style={styles.infoLabel}>{t('Direktor')}</Text>
|
||||
@@ -575,7 +528,6 @@ export default function RegisterFormScreen() {
|
||||
</View>
|
||||
)}
|
||||
|
||||
{/* ---- Xato: INN mos kelmasa yoki server xatosi ---- */}
|
||||
{directorInfoError && (
|
||||
<View style={[styles.errorBox, { marginTop: 8 }]}>
|
||||
<Text style={styles.errorText}>{directorInfoError}</Text>
|
||||
@@ -648,10 +600,12 @@ export default function RegisterFormScreen() {
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
</ScrollView>
|
||||
</View>
|
||||
</SafeAreaView>
|
||||
</View>
|
||||
</KeyboardAwareScrollView>
|
||||
|
||||
{/* ---- Country BottomSheet ---- */}
|
||||
{/* ✅ BottomSheet KeyboardAwareScrollView TASHQARISIDA */}
|
||||
<BottomSheet
|
||||
ref={countrySheetRef}
|
||||
index={-1}
|
||||
@@ -670,7 +624,6 @@ export default function RegisterFormScreen() {
|
||||
<Text style={styles.sheetTitle}>{t('Davlat')}</Text>
|
||||
</View>
|
||||
|
||||
{/* Search input */}
|
||||
<View style={styles.searchContainer}>
|
||||
<Search size={16} color="#94a3b8" />
|
||||
<BottomSheetTextInput
|
||||
@@ -730,16 +683,20 @@ export default function RegisterFormScreen() {
|
||||
}}
|
||||
/>
|
||||
</BottomSheet>
|
||||
</View>
|
||||
</TouchableWithoutFeedback>
|
||||
</KeyboardAwareScrollView>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
// ✅ KeyboardAwareScrollView uchun style
|
||||
keyboardScroll: {
|
||||
flex: 1,
|
||||
backgroundColor: '#0f172a',
|
||||
},
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: '#0f172a',
|
||||
minHeight: '100%',
|
||||
},
|
||||
scrollContent: {
|
||||
flexGrow: 1,
|
||||
@@ -969,15 +926,6 @@ const styles = StyleSheet.create({
|
||||
fontWeight: '800' as const,
|
||||
fontSize: 16,
|
||||
},
|
||||
footer: {
|
||||
marginTop: 20,
|
||||
alignItems: 'center',
|
||||
},
|
||||
footerText: {
|
||||
color: '#94a3b8',
|
||||
fontSize: 14,
|
||||
fontWeight: '600' as const,
|
||||
},
|
||||
decorCircle1: {
|
||||
position: 'absolute',
|
||||
top: -150,
|
||||
@@ -997,7 +945,7 @@ const styles = StyleSheet.create({
|
||||
backgroundColor: 'rgba(16, 185, 129, 0.08)',
|
||||
},
|
||||
inputDisabled: {
|
||||
backgroundColor: '#f1f5f9', // disabled bo'lganda fon rangi
|
||||
borderColor: '#e2e8f0', // disabled bo'lganda border rangi
|
||||
backgroundColor: '#f1f5f9',
|
||||
borderColor: '#e2e8f0',
|
||||
},
|
||||
});
|
||||
@@ -1,5 +1,5 @@
|
||||
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 { AxiosError } from 'axios';
|
||||
import { router, useFocusEffect } from 'expo-router';
|
||||
@@ -9,17 +9,17 @@ import {
|
||||
Image,
|
||||
Keyboard,
|
||||
Linking,
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
TouchableWithoutFeedback,
|
||||
View
|
||||
} from 'react-native';
|
||||
|
||||
import OneClick from '@/assets/images/one_click.png';
|
||||
import PAYME from '@/assets/images/Payme_NEW.png';
|
||||
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 { CreateAdsResponse } from '../lib/types';
|
||||
import StepFour from './StepFour';
|
||||
@@ -213,12 +213,16 @@ export default function CreateAdsScreens() {
|
||||
<KeyboardAwareScrollView
|
||||
showsVerticalScrollIndicator={false}
|
||||
keyboardShouldPersistTaps="handled"
|
||||
enableOnAndroid
|
||||
extraScrollHeight={120}
|
||||
style={[styles.safeArea, isDark ? styles.darkBg : styles.lightBg]}
|
||||
>
|
||||
<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
|
||||
source={OneClick}
|
||||
style={{ width: 180, height: 56, marginBottom: 10 }}
|
||||
@@ -281,11 +285,8 @@ export default function CreateAdsScreens() {
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</ScrollView>
|
||||
|
||||
{/* FOOTER */}
|
||||
|
||||
{/* PAYMENT BOTTOM SHEET */}
|
||||
</View>
|
||||
</TouchableWithoutFeedback>
|
||||
<BottomSheetModal
|
||||
ref={bottomSheetModalRef}
|
||||
index={0}
|
||||
@@ -329,7 +330,6 @@ export default function CreateAdsScreens() {
|
||||
</View>
|
||||
</BottomSheetScrollView>
|
||||
</BottomSheetModal>
|
||||
</TouchableWithoutFeedback>
|
||||
</KeyboardAwareScrollView>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -60,8 +60,6 @@ export default function CreateReferrals() {
|
||||
const validate = () => {
|
||||
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)
|
||||
e.description = 'Tavsif kamida 5 ta belgidan iborat bo‘lishi kerak';
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ export function ReferralsTab() {
|
||||
|
||||
// Clipboard + Share funksiyasi
|
||||
const handleCopyAndShare = async (code: string) => {
|
||||
const referralLink = `https://t.me/infotargetbot/join?startapp=${code}`;
|
||||
const referralLink = `${code}`;
|
||||
|
||||
// Clipboard-ga nusxa olish
|
||||
await Clipboard.setStringAsync(referralLink);
|
||||
|
||||
Reference in New Issue
Block a user