bug fixed

This commit is contained in:
Samandar Turgunboyev
2026-03-05 11:49:56 +05:00
parent 382b214e3e
commit a34cf75c57
10 changed files with 249 additions and 292 deletions

View File

@@ -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"
} }
} }

View File

@@ -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,

View File

@@ -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 />

View File

@@ -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}>

View File

@@ -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 (

View File

@@ -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>
); );
}; };

View File

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

View File

@@ -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>
); );
} }

View File

@@ -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 bolishi kerak';
if (!form.description || form.description.length < 5) if (!form.description || form.description.length < 5)
e.description = 'Tavsif kamida 5 ta belgidan iborat bolishi kerak'; e.description = 'Tavsif kamida 5 ta belgidan iborat bolishi kerak';

View File

@@ -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);