This commit is contained in:
Samandar Turgunboyev
2025-10-02 17:05:40 +05:00
parent 38badbe3dd
commit 9aac17072f
27 changed files with 1636 additions and 1380 deletions

View File

@@ -5,7 +5,6 @@ import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { toastConfig } from 'components/CustomAlertModal'; import { toastConfig } from 'components/CustomAlertModal';
import { navigationRef } from 'components/NavigationRef'; import { navigationRef } from 'components/NavigationRef';
import SplashScreen from 'components/SplashScreen';
import i18n from 'i18n/i18n'; import i18n from 'i18n/i18n';
import React, { useEffect, useMemo, useRef, useState } from 'react'; import React, { useEffect, useMemo, useRef, useState } from 'react';
import { I18nextProvider } from 'react-i18next'; import { I18nextProvider } from 'react-i18next';
@@ -18,6 +17,7 @@ import {
View, View,
} from 'react-native'; } from 'react-native';
import Toast from 'react-native-toast-message'; import Toast from 'react-native-toast-message';
import SplashScreen from './src/components/SplashScreen';
// Screens // Screens
import Login from 'screens/auth/login/ui'; import Login from 'screens/auth/login/ui';

View File

@@ -85,8 +85,8 @@ android {
applicationId "uz.felix.cpost" applicationId "uz.felix.cpost"
minSdkVersion rootProject.ext.minSdkVersion minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 4 versionCode 5
versionName "0.4" versionName "0.5"
multiDexEnabled true multiDexEnabled true
vectorDrawables.useSupportLibrary = true vectorDrawables.useSupportLibrary = true

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -1 +1 @@
<resources xmlns:tools="http://schemas.android.com/tools" tools:keep="@drawable/assets_bootsplash_logo_512,@drawable/assets_bootsplash_ru,@drawable/assets_bootsplash_uz,@drawable/assets_bootsplash_avia,@drawable/assets_bootsplash_auto,@drawable/assets_bootsplash_logo,@drawable/assets_bootsplash_passportsample,@drawable/assets_bootsplash_local,@drawable/assets_bootsplash_step_1,@drawable/assets_bootsplash_step_2,@drawable/assets_bootsplash_step_3,@drawable/node_modules_reactnavigation_elements_lib_module_assets_searchicon,@drawable/node_modules_reactnavigation_elements_lib_module_assets_backicon,@drawable/node_modules_reactnavigation_elements_lib_module_assets_backiconmask,@drawable/node_modules_reactnavigation_elements_lib_module_assets_clearicon,@drawable/node_modules_reactnavigation_elements_lib_module_assets_closeicon" /> <resources xmlns:tools="http://schemas.android.com/tools" tools:keep="@drawable/assets_bootsplash_logo,@drawable/assets_bootsplash_logo_512,@drawable/assets_bootsplash_ru,@drawable/assets_bootsplash_uz,@drawable/assets_bootsplash_passportsample,@drawable/assets_bootsplash_telegram,@drawable/assets_bootsplash_local,@drawable/assets_bootsplash_avia,@drawable/assets_bootsplash_auto,@drawable/assets_bootsplash_shablon,@drawable/assets_bootsplash_step_1,@drawable/assets_bootsplash_step_2,@drawable/assets_bootsplash_step_3,@drawable/node_modules_reactnavigation_elements_lib_module_assets_searchicon,@drawable/node_modules_reactnavigation_elements_lib_module_assets_backicon,@drawable/node_modules_reactnavigation_elements_lib_module_assets_backiconmask,@drawable/node_modules_reactnavigation_elements_lib_module_assets_clearicon,@drawable/node_modules_reactnavigation_elements_lib_module_assets_closeicon" />

View File

@@ -29,7 +29,7 @@ export interface resendPayload {
export interface loginPayload { export interface loginPayload {
phoneNumber: string; phoneNumber: string;
passportSerial: string; passportSerial: string;
branchId: number; // branchId: number;
fcmToken: string; fcmToken: string;
deviceId: string; deviceId: string;
deviceType: string; deviceType: string;

View File

@@ -1,68 +1,86 @@
"use client" 'use client';
import React, { useEffect, useState, useCallback, useMemo } from "react" import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { type LayoutChangeEvent, View } from "react-native" import { type LayoutChangeEvent, View } from 'react-native';
import Animated, { import Animated, {
useSharedValue, cancelAnimation,
useAnimatedStyle,
withRepeat,
withTiming,
Easing, Easing,
useAnimatedStyle,
useSharedValue,
withRepeat,
withSequence, withSequence,
withDelay, withTiming,
} from "react-native-reanimated" } from 'react-native-reanimated';
import Auto from "svg/Auto" import Auto from 'svg/Auto';
import Avia from "svg/Avia" import Avia from 'svg/Avia';
type Props = { type Props = {
type: "auto" | "avia" type: 'AUTO' | 'AVIA';
} };
const AnimatedIcon = ({ type }: Props) => { const AnimatedIcon = ({ type }: Props) => {
const translateX = useSharedValue(0) const translateX = useSharedValue(0);
const translateY = useSharedValue(0) const translateY = useSharedValue(0);
const rotateY = useSharedValue(0) const rotateY = useSharedValue(0);
const direction = useSharedValue(1) const direction = useSharedValue(1);
const [containerWidth, setContainerWidth] = useState(0) const [containerWidth, setContainerWidth] = useState(0);
const iconSize = 40 const iconSize = 40;
const onLayout = useCallback((event: LayoutChangeEvent) => { const onLayout = useCallback((event: LayoutChangeEvent) => {
const { width } = event.nativeEvent.layout const { width } = event.nativeEvent.layout;
setContainerWidth(width) setContainerWidth(width);
}, []); }, []);
const animationConfig = useMemo(() => ({ const animationConfig = useMemo(
() => ({
duration: 4000, duration: 4000,
easing: Easing.linear, easing: Easing.linear,
rotationDuration: 300, rotationDuration: 300,
arcHeight: -30, arcHeight: -30,
}), []); }),
[],
);
const createXAnimation = useCallback((maxX: number) => { const createXAnimation = useCallback(
(maxX: number) => {
return withRepeat( return withRepeat(
withSequence( withSequence(
withTiming(maxX, { withTiming(
maxX,
{
duration: animationConfig.duration, duration: animationConfig.duration,
easing: animationConfig.easing easing: animationConfig.easing,
}, () => { },
() => {
direction.value = -1; direction.value = -1;
rotateY.value = withTiming(180, { duration: animationConfig.rotationDuration }); rotateY.value = withTiming(180, {
}), duration: animationConfig.rotationDuration,
withTiming(0, { });
duration: animationConfig.duration, },
easing: animationConfig.easing
}, () => {
direction.value = 1;
rotateY.value = withTiming(0, { duration: animationConfig.rotationDuration });
})
), ),
-1 withTiming(
0,
{
duration: animationConfig.duration,
easing: animationConfig.easing,
},
() => {
direction.value = 1;
rotateY.value = withTiming(0, {
duration: animationConfig.rotationDuration,
});
},
),
),
-1,
);
},
[animationConfig, direction, rotateY],
); );
}, [animationConfig, direction, rotateY]);
const createYAnimation = useCallback(() => { const createYAnimation = useCallback(() => {
if (type === "avia") { if (type === 'AVIA') {
return withRepeat( return withRepeat(
withSequence( withSequence(
withTiming(animationConfig.arcHeight, { withTiming(animationConfig.arcHeight, {
@@ -80,9 +98,9 @@ const AnimatedIcon = ({ type }: Props) => {
withTiming(0, { withTiming(0, {
duration: animationConfig.duration / 2, duration: animationConfig.duration / 2,
easing: Easing.in(Easing.quad), easing: Easing.in(Easing.quad),
}) }),
), ),
-1 -1,
); );
} }
return withTiming(0, { duration: 100 }); return withTiming(0, { duration: 100 });
@@ -93,9 +111,20 @@ const AnimatedIcon = ({ type }: Props) => {
const maxX = containerWidth - iconSize; const maxX = containerWidth - iconSize;
// eski animatsiyani toxtat
cancelAnimation(translateX);
cancelAnimation(translateY);
// qiymatlarni 0 ga reset qil
translateX.value = 0;
translateY.value = 0;
rotateY.value = 0;
direction.value = 1;
// keyin yangisini qayta boshlash
translateX.value = createXAnimation(maxX); translateX.value = createXAnimation(maxX);
translateY.value = createYAnimation(); translateY.value = createYAnimation();
}, [containerWidth, type, createXAnimation, createYAnimation, translateX, translateY]); }, [containerWidth, type]); // type = activeTab dan keladigan qiymat
const animatedStyle = useAnimatedStyle(() => { const animatedStyle = useAnimatedStyle(() => {
return { return {
@@ -104,34 +133,43 @@ const AnimatedIcon = ({ type }: Props) => {
{ translateY: translateY.value }, { translateY: translateY.value },
{ rotateY: `${rotateY.value}deg` }, { rotateY: `${rotateY.value}deg` },
], ],
} };
}); });
const containerStyle = useMemo(() => ({ const containerStyle = useMemo(
() => ({
height: 100, height: 100,
justifyContent: "center" as const, justifyContent: 'center' as const,
backgroundColor: "transparent" as const, backgroundColor: 'transparent' as const,
position: "relative" as const, position: 'relative' as const,
}), []); }),
[],
);
const trackStyle = useMemo(() => ({ const trackStyle = useMemo(
() => ({
height: 2, height: 2,
backgroundColor: "#28A7E850", backgroundColor: '#28A7E850',
position: "absolute" as const, position: 'absolute' as const,
top: 25, top: 25,
left: 0, left: 0,
right: 0, right: 0,
}), []); }),
[],
);
const iconContainerStyle = useMemo(() => ({ const iconContainerStyle = useMemo(
position: "absolute" as const, () => ({
position: 'absolute' as const,
top: 0, top: 0,
height: iconSize, height: iconSize,
width: iconSize, width: iconSize,
}), [iconSize]); }),
[iconSize],
);
const renderIcon = useMemo(() => { const renderIcon = useMemo(() => {
if (type === "auto") { if (type === 'AUTO') {
return <Auto color="#28A7E8" width={iconSize} height={iconSize} />; return <Auto color="#28A7E8" width={iconSize} height={iconSize} />;
} }
return <Avia color="#28A7E8" width={iconSize} height={iconSize} />; return <Avia color="#28A7E8" width={iconSize} height={iconSize} />;
@@ -144,7 +182,7 @@ const AnimatedIcon = ({ type }: Props) => {
{renderIcon} {renderIcon}
</Animated.View> </Animated.View>
</View> </View>
) );
} };
export default AnimatedIcon; export default AnimatedIcon;

View File

@@ -1,9 +1,18 @@
import React, { useCallback, useMemo, useState } from 'react'; import React, { useCallback, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { Alert, Image, StyleSheet, TouchableOpacity, View } from 'react-native'; import {
ActionSheetIOS,
Alert,
Image,
Platform,
StyleSheet,
TouchableOpacity,
View,
} from 'react-native';
import { import {
Asset, Asset,
ImagePickerResponse, ImagePickerResponse,
launchCamera,
launchImageLibrary, launchImageLibrary,
MediaType, MediaType,
} from 'react-native-image-picker'; } from 'react-native-image-picker';
@@ -20,9 +29,6 @@ export interface FileData {
export interface SingleFileDropProps { export interface SingleFileDropProps {
title: string; title: string;
onFileSelected?: (file: FileData) => void; onFileSelected?: (file: FileData) => void;
/**
* Ruxsat berilgan MIME tipi (masalan: "image/png" yoki "image/jpeg")
*/
type?: string; type?: string;
} }
@@ -44,7 +50,7 @@ const SingleFileDrop: React.FC<SingleFileDropProps> = ({
const handleImagePickerResponse = useCallback( const handleImagePickerResponse = useCallback(
(response: ImagePickerResponse) => { (response: ImagePickerResponse) => {
if (response.didCancel) return; // foydalanuvchi bekor qilsa if (response.didCancel) return;
if (response.errorCode) { if (response.errorCode) {
Alert.alert('Xato', response.errorMessage || 'Rasmni yuklashda xato'); Alert.alert('Xato', response.errorMessage || 'Rasmni yuklashda xato');
return; return;
@@ -53,7 +59,6 @@ const SingleFileDrop: React.FC<SingleFileDropProps> = ({
const asset: Asset | undefined = response.assets?.[0]; const asset: Asset | undefined = response.assets?.[0];
if (!asset || !asset.uri || !asset.type || !asset.base64) return; if (!asset || !asset.uri || !asset.type || !asset.base64) return;
// faqat belgilangan tipdagi fayllarni qabul qilish
if (!asset.type.startsWith('image/')) { if (!asset.type.startsWith('image/')) {
Alert.alert('Xato', 'Faqat rasm fayllarni yuklashingiz mumkin'); Alert.alert('Xato', 'Faqat rasm fayllarni yuklashingiz mumkin');
return; return;
@@ -77,6 +82,32 @@ const SingleFileDrop: React.FC<SingleFileDropProps> = ({
launchImageLibrary(imagePickerOptions, handleImagePickerResponse); launchImageLibrary(imagePickerOptions, handleImagePickerResponse);
}, [imagePickerOptions, handleImagePickerResponse]); }, [imagePickerOptions, handleImagePickerResponse]);
const openCamera = useCallback((): void => {
launchCamera(imagePickerOptions, handleImagePickerResponse);
}, [imagePickerOptions, handleImagePickerResponse]);
const openPicker = useCallback(() => {
if (Platform.OS === 'ios') {
ActionSheetIOS.showActionSheetWithOptions(
{
options: ['Bekor qilish', 'Kamera', 'Galereya'],
cancelButtonIndex: 0,
},
buttonIndex => {
if (buttonIndex === 1) openCamera();
else if (buttonIndex === 2) openGallery();
},
);
} else {
// Android uchun oddiy alert-style tanlov
Alert.alert(t('Fayl tanlash'), t('Qaysi usulda yuklamoqchisiz?'), [
{ text: t('Bekor qilish'), style: 'cancel' },
{ text: t('Kamera'), onPress: openCamera },
{ text: t('Galereya'), onPress: openGallery },
]);
}
}, [openCamera, openGallery]);
const UploadIcon = useMemo( const UploadIcon = useMemo(
() => () => () => () =>
( (
@@ -122,7 +153,7 @@ const SingleFileDrop: React.FC<SingleFileDropProps> = ({
}, [selectedImage, title, UploadIcon]); }, [selectedImage, title, UploadIcon]);
return ( return (
<TouchableOpacity style={styles.dropSection} onPress={openGallery}> <TouchableOpacity style={styles.dropSection} onPress={openPicker}>
{renderContent} {renderContent}
</TouchableOpacity> </TouchableOpacity>
); );

View File

@@ -230,5 +230,20 @@
"Xatolik yuz berdi": "Произошла ошибка", "Xatolik yuz berdi": "Произошла ошибка",
"Passport qo'shishda xatolik yuz berdi": "Ошибка добавления паспорта", "Passport qo'shishda xatolik yuz berdi": "Ошибка добавления паспорта",
"Kodsiz tovarlar": "Товары без кода", "Kodsiz tovarlar": "Товары без кода",
"Hech qanday ma'lumot topilmadi": "Нет данных" "Hech qanday ma'lumot topilmadi": "Нет данных",
"Foydalanish shartlari va qoidalari": "Условия и правила использования",
"Kamera": "Камера",
"Galereya": "Галерея",
"Fayl tanlash": "Выбрать файл",
"Qaysi usulda yuklamoqchisiz?": "Каким способом вы хотите загрузить?",
"Umumiy qoidalar": "Общие положения",
"Biz sizdan Xitoy xalq Respublikasi Davlatidan sotib olingan tovarlarni olib kelishda quyidagi tovarlarni jonatmaslikka rozilik so'raymiz.": "Мы просим Вашего согласия не отправлять следующие товары при ввозе товаров, приобретенных в Китайской Народной Республике.",
"Taqiqlangan tovarlar": "Запрещённые товары",
"Taqiqlangan tovarlar matni": "В соответствии с Указом Президента Республики Узбекистан от 25 декабря 1998 года No УП-2160 запрещается ввоз в Республику Узбекистан: брошюр, фотографий, видео, аудиопродукции, агитационных материалов и печатных изданий, направленных на нанесение ущерба государству и обществу; пропаганды нарушений порядка, территориальной целостности, политической независимости и государственного суверенитета, войны, терроризма, насилия, национальной идентичности и религиозной ненависти, расизма и его многообразия (антисемитизм, фашизм), а также порнографических материалов.",
"Tovarlar": "Запрещается ввоз: взрывчатых, ядовитых, легковоспламеняющихся, радиоактивных веществ, продуктов питания, лекарственных средств, медицинских изделий и оборудования, полиграфического оборудования, мобильных телефонов, зубной пасты (порошка), рационов, USB-флешек, различных флеш-карт и других аналогичных товаров.",
"Agar sizda savollar bolsa, quyidagi aloqa manzillaridan foydalanishingiz mumkin:": "Если у вас есть вопросы, вы можете воспользоваться следующими контактами:",
"Aloqa uchun": "Для связи",
"Email": "Электронная почта",
"Telegram": "Телеграм",
"Roziman": "Согласен"
} }

View File

@@ -42,13 +42,13 @@
"foydalanuvchi_majburiyatlari": "2. Foydalanuvchi majburiyatlari", "foydalanuvchi_majburiyatlari": "2. Foydalanuvchi majburiyatlari",
"foydalanuvchi_majburiyatlari_text": "• To'g'ri va aniq ma'lumotlar taqdim etish\n• Boshqa foydalanuvchilarning huquqlarini hurmat qilish\n• Tizimdan noto'g'ri maqsadlarda foydalanmaslik\n• Xavfsizlik qoidalariga rioya qilish", "foydalanuvchi_majburiyatlari_text": "• To'g'ri va aniq ma'lumotlar taqdim etish\n• Boshqa foydalanuvchilarning huquqlarini hurmat qilish\n• Tizimdan noto'g'ri maqsadlarda foydalanmaslik\n• Xavfsizlik qoidalariga rioya qilish",
"maxfiylik_siyosati": "3. Maxfiylik siyosati", "maxfiylik_siyosati": "3. Maxfiylik siyosati",
"maxfiylik_siyosati_text": "Sizning shaxsiy ma'lumotlaringiz maxfiylik siyosatimizga muvofiq himoyalanadi. Biz sizning ma'lumotlaringizni uchinchi shaxslarga bermaydi va xavfsiz saqlashni ta'minlaymiz.", "maxfiylik_siyosati_text": "Sizning shaxsiy ma'lumotlaringiz maxfiylik siyosatimizga muvofiq himoyalanadi. Biz sizning ma'lumotlaringizni uchinchi shaxslarga bermaymiz va xavfsiz saqlashni ta'minlaymiz.",
"javobgarlik": "4. Javobgarlik", "javobgarlik": "4. Javobgarlik",
"javobgarlik_text": "Kompaniya ilovadan foydalanish natijasida yuzaga kelishi mumkin bo'lgan zararlar uchun javobgar emas. Foydalanuvchi o'z harakatlari uchun to'liq javobgarlikni o'z zimmasiga oladi.", "javobgarlik_text": "Kompaniya ilovadan foydalanish natijasida yuzaga kelishi mumkin bo'lgan zararlar uchun javobgar emas. Foydalanuvchi o'z harakatlari uchun to'liq javobgarlikni o'z zimmasiga oladi.",
"shartlarni_ozgartirish": "5. Shartlarni o'zgartirish", "shartlarni_ozgartirish": "5. Shartlarni o'zgartirish",
"shartlarni_ozgartirish_text": "Kompaniya ushbu shartlarni istalgan vaqtda o'zgartirish huquqini o'zida saqlab qoladi. O'zgarishlar ilovada e'lon qilinadi va kuchga kirish sanasi ko'rsatiladi.", "shartlarni_ozgartirish_text": "Kompaniya ushbu shartlarni istalgan vaqtda o'zgartirish huquqini o'zida saqlab qoladi. O'zgarishlar ilovada e'lon qilinadi va kuchga kirish sanasi ko'rsatiladi.",
"aloqa": "6. Aloqa", "aloqa": "6. Aloqa",
"aloqa_text": "Savollar yoki takliflar bo'lsa, biz bilan quyidagi manzil orqali bog'laning:\nEmail: support@company.uz\nTelefon: +998 71 123 45 67", "aloqa_text": "Savollar yoki takliflar bo'lsa, biz bilan quyidagi manzil orqali bog'laning:",
"oxirgi_yangilanish": "Oxirgi yangilanish:", "oxirgi_yangilanish": "Oxirgi yangilanish:",
"roziman": "Roziman", "roziman": "Roziman",
"Shaxsiy maʼlumotlar": "Shaxsiy maʼlumotlar", "Shaxsiy maʼlumotlar": "Shaxsiy maʼlumotlar",
@@ -111,7 +111,7 @@
"Filiallarimiz ro'yhati ilovada mavjud": "Filiallarimiz ro'yhati ilovada mavjud", "Filiallarimiz ro'yhati ilovada mavjud": "Filiallarimiz ro'yhati ilovada mavjud",
"Agar siz yashayotgan hududda bizning filialimiz mavjud bo'lmasa, o'zingizga eng yaqin bo'lgan filialni tanlab, ro'yhatdan o'tishingiz mumkin.": "Agar siz yashayotgan hududda bizning filialimiz mavjud bo'lmasa, o'zingizga eng yaqin bo'lgan filialni tanlab, ro'yhatdan o'tishingiz mumkin.", "Agar siz yashayotgan hududda bizning filialimiz mavjud bo'lmasa, o'zingizga eng yaqin bo'lgan filialni tanlab, ro'yhatdan o'tishingiz mumkin.": "Agar siz yashayotgan hududda bizning filialimiz mavjud bo'lmasa, o'zingizga eng yaqin bo'lgan filialni tanlab, ro'yhatdan o'tishingiz mumkin.",
"ya'ni, qancha gramm mahsulot olsangiz, shuncha og'irligi (gramm) uchun to'lov qilasiz.": "ya'ni, qancha gramm mahsulot olsangiz, shuncha og'irligi (gramm) uchun to'lov qilasiz.", "ya'ni, qancha gramm mahsulot olsangiz, shuncha og'irligi (gramm) uchun to'lov qilasiz.": "ya'ni, qancha gramm mahsulot olsangiz, shuncha og'irligi (gramm) uchun to'lov qilasiz.",
"(Bu kargo narxini osishiga olib keladi. Seriyali buyularni avto kargo orqali olib kelish arzonga tushadi)": "(Bu kargo narxini osishiga olib keladi. Seriyali buyularni avto kargo orqali olib kelish arzonga tushadi)", "(Bu kargo narxini osishiga olib keladi. Seriyali buyularni avto kargo orqali olib kelish arzonga tushadi)": "(Bu kargo narxini osishiga olib keladi. Seriyali buyumlarni avto kargo orqali olib kelish arzonga tushadi)",
"Avto kargoda bir mahsulotdan seriyali ravishda, istalgan katta miqdorda xarid qilish mumkin. Doimiy ravishda kop yuk oluvchilar uchun maxsus chegirmali narxlarimiz mavjud.": "Avto kargoda bir mahsulotdan seriyali ravishda, istalgan katta miqdorda xarid qilish mumkin. Doimiy ravishda kop yuk oluvchilar uchun maxsus chegirmali narxlarimiz mavjud.", "Avto kargoda bir mahsulotdan seriyali ravishda, istalgan katta miqdorda xarid qilish mumkin. Doimiy ravishda kop yuk oluvchilar uchun maxsus chegirmali narxlarimiz mavjud.": "Avto kargoda bir mahsulotdan seriyali ravishda, istalgan katta miqdorda xarid qilish mumkin. Doimiy ravishda kop yuk oluvchilar uchun maxsus chegirmali narxlarimiz mavjud.",
"dan boshlab": "dan boshlab", "dan boshlab": "dan boshlab",
@@ -179,8 +179,8 @@
"Yopish": "Yopish", "Yopish": "Yopish",
"Passportlarim": "Passportlarim", "Passportlarim": "Passportlarim",
"Hali pasport qo'shilmagan": "Hali pasport qo'shilmagan", "Hali pasport qo'shilmagan": "Hali pasport qo'shilmagan",
"Yangi pasport qo'shish uchun tugmani bosing": "Yangi pasport qo'shish uchun tugmani bosing", "Yangi pasport qo'shish uchun tugmani bosing": "Yangi passport qo'shish uchun tugmani bosing",
"Yangi pasport qo'shish": "Yangi pasport qo'shish", "Yangi pasport qo'shish": "Yangi passport qo'shish",
"Passport malumotlarim": "Passport malumotlarim", "Passport malumotlarim": "Passport malumotlarim",
"Tez ID": "Tez ID", "Tez ID": "Tez ID",
"Toliq ismi": "Toliq ismi", "Toliq ismi": "Toliq ismi",
@@ -231,5 +231,20 @@
"Yuborish": "Yuborish", "Yuborish": "Yuborish",
"Passport qo'shishda xatolik yuz berdi": "Passport qo'shishda xatolik yuz berdi", "Passport qo'shishda xatolik yuz berdi": "Passport qo'shishda xatolik yuz berdi",
"Xatolik yuz berdi": "Xatolik yuz berdi", "Xatolik yuz berdi": "Xatolik yuz berdi",
"Kodsiz tovarlar": "Kodsiz tovarlar" "Kodsiz tovarlar": "Kodsiz tovarlar",
"Kamera": "Kamera",
"Galereya": "Galereya",
"Fayl tanlash": "Fayl tanlash",
"Qaysi usulda yuklamoqchisiz?": "Qaysi usulda yuklamoqchisiz?",
"Foydalanish shartlari va qoidalari": "Foydalanish shartlari va qoidalari",
"Umumiy qoidalar": "Umumiy qoidalar",
"Biz sizdan Xitoy xalq Respublikasi Davlatidan sotib olingan tovarlarni olib kelishda quyidagi tovarlarni jonatmaslikka rozilik so'raymiz.": "Biz sizdan Xitoy xalq Respublikasi Davlatidan sotib olingan tovarlarni olib kelishda quyidagi tovarlarni jonatmaslikka rozilik so'raymiz.",
"Taqiqlangan tovarlar": "Taqiqlangan tovarlar",
"Taqiqlangan tovarlar matni": " Ozbekiston Respublikasi Prezidentining 1998-yil 25-dekabrdagi UP-2160-son Farmoniga asosan Ozbekiston Respublikasiga olib kirish qudagilar taqiqlanadi: davlat va jamiyatga putur yetkazishga qaratilgan risolalar, fotosuratlar, videolar, audiomahsulotlar, tashviqot materiallari va bosma nashrlar; tartib, hududiy yaxlitlik, siyosiy mustaqillik va davlat suverenitetini buzish, urush, terrorizm, zoravonlik, milliy oziga xoslik va diniy nafrat, irqchilik va uning xilma-xilligini (antisemitizm, fashizm), shuningdek, pornografik materiallarga targib qilish.",
"Tovarlar": "Yonuvchan, tez yonuvchi, portlovchi, zaharli, radioaktiv moddalar, oziq-ovqat mahsulotlari, dori-darmonlar, tibbiy buyumlar, tibbiy asbob-uskunalar, poligrafiya uskunalari, uyali telefonlar, tish pastasi (chang), ratsionlar, USB flesh-disk, turli xil flesh-kartalar va boshqa shunga oxshash mahsulotlarni olib kirish taqiqlanadi.",
"Agar sizda savollar bolsa, quyidagi aloqa manzillaridan foydalanishingiz mumkin:": "Agar sizda savollar bolsa, quyidagi aloqa manzillaridan foydalanishingiz mumkin:",
"Aloqa uchun": "Aloqa uchun",
"Email": "Email",
"Telegram": "Telegram",
"Roziman": "Roziman"
} }

View File

@@ -5,7 +5,6 @@ export const loginSchema = z.object({
phone: z.string().min(12, 'Xato raqam kiritildi'), phone: z.string().min(12, 'Xato raqam kiritildi'),
passportSeriya: z.string().length(2, '2 ta harf kerak'), passportSeriya: z.string().length(2, '2 ta harf kerak'),
passportNumber: z.string().length(7, '7 ta raqam kerak'), passportNumber: z.string().length(7, '7 ta raqam kerak'),
branchId: z.number().min(1, 'Filialni tanlang'),
}); });
export type LoginFormType = z.infer<typeof loginSchema>; export type LoginFormType = z.infer<typeof loginSchema>;

View File

@@ -1,10 +1,9 @@
import { zodResolver } from '@hookform/resolvers/zod'; import { zodResolver } from '@hookform/resolvers/zod';
import { useNavigation } from '@react-navigation/native'; import { useNavigation } from '@react-navigation/native';
import { NativeStackNavigationProp } from '@react-navigation/native-stack'; import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import { useMutation, useQuery } from '@tanstack/react-query'; import { useMutation } from '@tanstack/react-query';
import { authApi } from 'api/auth'; import { authApi } from 'api/auth';
import { loginPayload } from 'api/auth/type'; import { loginPayload } from 'api/auth/type';
import { Branch, branchApi } from 'api/branch';
import AppText from 'components/AppText'; import AppText from 'components/AppText';
import formatPhone from 'helpers/formatPhone'; import formatPhone from 'helpers/formatPhone';
import React, { useCallback, useMemo, useRef, useState } from 'react'; import React, { useCallback, useMemo, useRef, useState } from 'react';
@@ -24,9 +23,7 @@ import { SafeAreaView } from 'react-native-safe-area-context';
import Logo from 'screens/../../assets/bootsplash/logo_512.png'; import Logo from 'screens/../../assets/bootsplash/logo_512.png';
import { LoginFormType, loginSchema } from 'screens/auth/login/lib/form'; import { LoginFormType, loginSchema } from 'screens/auth/login/lib/form';
import LanguageSelector from 'screens/auth/select-language/SelectLang'; import LanguageSelector from 'screens/auth/select-language/SelectLang';
import ArrowDown from 'svg/ArrowDown';
import ArrowLeft from 'svg/ArrowLeft'; import ArrowLeft from 'svg/ArrowLeft';
import ArrowUp from 'svg/ArrowUp';
import { useUserStore } from '../lib/userstore'; import { useUserStore } from '../lib/userstore';
import { Loginstyle } from './styled'; import { Loginstyle } from './styled';
@@ -46,10 +43,10 @@ const Login = () => {
const { setUser, setExpireTime } = useUserStore(state => state); const { setUser, setExpireTime } = useUserStore(state => state);
const [error, setError] = useState<string>(); const [error, setError] = useState<string>();
const [rawPhone, setRawPhone] = useState('+998'); const [rawPhone, setRawPhone] = useState('+998');
const { data: branchList } = useQuery({ // const { data: branchList } = useQuery({
queryKey: ['branchList'], // queryKey: ['branchList'],
queryFn: branchApi.branchList, // queryFn: branchApi.branchList,
}); // });
// const [firebaseToken, setFirebseToken] = useState<{ // const [firebaseToken, setFirebseToken] = useState<{
// fcmToken: string; // fcmToken: string;
// deviceId: string; // deviceId: string;
@@ -109,7 +106,6 @@ const Login = () => {
const onSubmit = (data: LoginFormType) => { const onSubmit = (data: LoginFormType) => {
mutate({ mutate({
branchId: data.branchId,
phoneNumber: data.phone, phoneNumber: data.phone,
passportSerial: `${data.passportSeriya.toUpperCase()}${ passportSerial: `${data.passportSeriya.toUpperCase()}${
data.passportNumber data.passportNumber
@@ -164,7 +160,7 @@ const Login = () => {
style={Loginstyle.container} style={Loginstyle.container}
behavior={keyboardBehavior} behavior={keyboardBehavior}
> >
<ScrollView style={{ flex: 1 }}> <ScrollView style={{ flex: 1 }} keyboardShouldPersistTaps="handled">
<View style={Loginstyle.scrollContainer}> <View style={Loginstyle.scrollContainer}>
<View style={Loginstyle.loginContainer}> <View style={Loginstyle.loginContainer}>
<AppText style={Loginstyle.title}> <AppText style={Loginstyle.title}>
@@ -251,7 +247,7 @@ const Login = () => {
)} )}
</View> </View>
<Controller {/* <Controller
control={control} control={control}
name="branchId" name="branchId"
render={({ field: { value } }) => ( render={({ field: { value } }) => (
@@ -314,7 +310,7 @@ const Login = () => {
)} )}
</View> </View>
)} )}
/> /> */}
<TouchableOpacity <TouchableOpacity
onPress={handleSubmit(onSubmit)} onPress={handleSubmit(onSubmit)}

View File

@@ -1,8 +1,6 @@
'use client'; 'use client';
import { zodResolver } from '@hookform/resolvers/zod'; import { zodResolver } from '@hookform/resolvers/zod';
// import { getApp } from '@react-native-firebase/app';
// import { getMessaging, getToken } from '@react-native-firebase/messaging';
import { import {
type RouteProp, type RouteProp,
useNavigation, useNavigation,
@@ -15,15 +13,15 @@ import { registerPayload } from 'api/auth/type';
import { Branch, branchApi } from 'api/branch'; import { Branch, branchApi } from 'api/branch';
import AppText from 'components/AppText'; import AppText from 'components/AppText';
import formatPhone from 'helpers/formatPhone'; import formatPhone from 'helpers/formatPhone';
import { useEffect, useState } from 'react'; import { useEffect, useRef, useState } from 'react';
import { Controller, useForm } from 'react-hook-form'; import { Controller, useForm } from 'react-hook-form';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { import {
ActivityIndicator, ActivityIndicator,
Animated, Animated,
ImageBackground, ImageBackground,
Keyboard,
KeyboardAvoidingView, KeyboardAvoidingView,
Platform,
ScrollView, ScrollView,
TextInput, TextInput,
TouchableOpacity, TouchableOpacity,
@@ -66,37 +64,6 @@ const FirstStep = ({ onNext }: { onNext: () => void }) => {
queryFn: branchApi.branchList, queryFn: branchApi.branchList,
}); });
// const [firebaseToken, setFirebseToken] = useState<{
// fcmToken: string;
// deviceId: string;
// deviceName: string;
// deviceType: string;
// } | null>();
// const app = getApp();
// const messaging = getMessaging(app);
// const getDeviceData = async () => {
// try {
// const fcmToken = await getToken(messaging);
// return {
// fcmToken,
// deviceId: await DeviceInfo.getUniqueId(),
// deviceName: await DeviceInfo.getDeviceName(),
// deviceType: await DeviceInfo.getDeviceType(),
// };
// } catch (e) {
// console.log('Xato:', e);
// return null;
// }
// };
// useEffect(() => {
// getDeviceData().then(data => {
// setFirebseToken(data);
// });
// }, []);
const { mutate, isPending } = useMutation({ const { mutate, isPending } = useMutation({
mutationFn: (payload: registerPayload) => authApi.register(payload), mutationFn: (payload: registerPayload) => authApi.register(payload),
onSuccess: res => { onSuccess: res => {
@@ -114,12 +81,12 @@ const FirstStep = ({ onNext }: { onNext: () => void }) => {
const navigation = useNavigation<LoginScreenNavigationProp>(); const navigation = useNavigation<LoginScreenNavigationProp>();
const [rawPhone, setRawPhone] = useState('+998'); const [rawPhone, setRawPhone] = useState('+998');
const route = useRoute<RouteProp<RootStackParamList, 'Register'>>(); const route = useRoute<RouteProp<RootStackParamList, 'Register'>>();
const { const {
control, control,
handleSubmit, handleSubmit,
setValue, setValue,
formState: { errors }, formState: { errors },
getValues,
} = useForm<FirstStepFormType>({ } = useForm<FirstStepFormType>({
resolver: zodResolver(FirstStepSchema), resolver: zodResolver(FirstStepSchema),
defaultValues: { defaultValues: {
@@ -130,6 +97,12 @@ const FirstStep = ({ onNext }: { onNext: () => void }) => {
}, },
}); });
// 🔑 Input ref'lar
const firstNameRef = useRef<TextInput>(null);
const lastNameRef = useRef<TextInput>(null);
const phoneRef = useRef<TextInput>(null);
const addressRef = useRef<TextInput>(null);
const onSubmit = (data: FirstStepFormType) => { const onSubmit = (data: FirstStepFormType) => {
setUser({ setUser({
firstName: data.firstName, firstName: data.firstName,
@@ -195,7 +168,7 @@ const FirstStep = ({ onNext }: { onNext: () => void }) => {
imageStyle={{ imageStyle={{
opacity: 0.1, opacity: 0.1,
height: '100%', height: '100%',
width: '100%', width: '90%',
transform: [{ scale: 1 }], transform: [{ scale: 1 }],
}} }}
> >
@@ -207,12 +180,13 @@ const FirstStep = ({ onNext }: { onNext: () => void }) => {
<LanguageSelector /> <LanguageSelector />
</View> </View>
<KeyboardAvoidingView <KeyboardAvoidingView
style={RegisterStyle.container} style={{ flex: 1 }}
behavior={Platform.OS === 'ios' ? 'padding' : 'height'} behavior="padding"
keyboardVerticalOffset={50}
> >
<ScrollView <ScrollView
showsVerticalScrollIndicator={false} contentContainerStyle={{ flexGrow: 1 }}
style={RegisterStyle.content} keyboardShouldPersistTaps="handled"
> >
<View style={RegisterStyle.scrollContainer}> <View style={RegisterStyle.scrollContainer}>
<View style={RegisterStyle.loginContainer}> <View style={RegisterStyle.loginContainer}>
@@ -220,18 +194,22 @@ const FirstStep = ({ onNext }: { onNext: () => void }) => {
{t("Ro'yxatdan o'tish")} {t("Ro'yxatdan o'tish")}
</AppText> </AppText>
{/* Ism */}
<Controller <Controller
control={control} control={control}
name="firstName" name="firstName"
render={({ field: { onChange, value } }) => ( render={({ field: { onChange, value } }) => (
<View> <View>
<AppText style={RegisterStyle.label}>{t('Ism')} </AppText> <AppText style={RegisterStyle.label}>{t('Ism')}</AppText>
<TextInput <TextInput
ref={firstNameRef}
style={RegisterStyle.input} style={RegisterStyle.input}
placeholder={t('Ismingiz')} placeholder={t('Ismingiz')}
onChangeText={onChange} onChangeText={onChange}
value={value} value={value}
placeholderTextColor={'#D8DADC'} placeholderTextColor={'#D8DADC'}
returnKeyType="next"
onSubmitEditing={() => lastNameRef.current?.focus()}
/> />
{errors.firstName && ( {errors.firstName && (
<AppText style={RegisterStyle.errorText}> <AppText style={RegisterStyle.errorText}>
@@ -241,20 +219,25 @@ const FirstStep = ({ onNext }: { onNext: () => void }) => {
</View> </View>
)} )}
/> />
{/* Familiya */}
<Controller <Controller
control={control} control={control}
name="lastName" name="lastName"
render={({ field: { onChange, value } }) => ( render={({ field: { onChange, value } }) => (
<View> <View>
<AppText style={RegisterStyle.label}> <AppText style={RegisterStyle.label}>
{t('Familiya')}{' '} {t('Familiya')}
</AppText> </AppText>
<TextInput <TextInput
ref={lastNameRef}
style={RegisterStyle.input} style={RegisterStyle.input}
placeholder={t('Familiyangiz')} placeholder={t('Familiyangiz')}
placeholderTextColor={'#D8DADC'} placeholderTextColor={'#D8DADC'}
onChangeText={onChange} onChangeText={onChange}
value={value} value={value}
returnKeyType="next"
onSubmitEditing={() => phoneRef.current?.focus()}
/> />
{errors.lastName && ( {errors.lastName && (
<AppText style={RegisterStyle.errorText}> <AppText style={RegisterStyle.errorText}>
@@ -264,6 +247,8 @@ const FirstStep = ({ onNext }: { onNext: () => void }) => {
</View> </View>
)} )}
/> />
{/* Telefon raqami */}
<Controller <Controller
control={control} control={control}
name="phoneNumber" name="phoneNumber"
@@ -275,6 +260,7 @@ const FirstStep = ({ onNext }: { onNext: () => void }) => {
{t('Telefon raqami')} {t('Telefon raqami')}
</AppText> </AppText>
<TextInput <TextInput
ref={phoneRef}
keyboardType="numeric" keyboardType="numeric"
placeholder="+998 __ ___-__-__" placeholder="+998 __ ___-__-__"
value={formatted} value={formatted}
@@ -289,6 +275,10 @@ const FirstStep = ({ onNext }: { onNext: () => void }) => {
style={RegisterStyle.input} style={RegisterStyle.input}
placeholderTextColor="#D8DADC" placeholderTextColor="#D8DADC"
maxLength={17} maxLength={17}
returnKeyType="next"
onSubmitEditing={
() => setFilialDropdownVisible(true) // ❗ Branch select ochiladi
}
/> />
{errors.phoneNumber && ( {errors.phoneNumber && (
<AppText style={RegisterStyle.errorText}> <AppText style={RegisterStyle.errorText}>
@@ -299,20 +289,23 @@ const FirstStep = ({ onNext }: { onNext: () => void }) => {
); );
}} }}
/> />
{/* Filial (dropdown) */}
<Controller <Controller
control={control} control={control}
name="branchId" name="branchId"
render={({ field: { value } }) => ( render={({ field: { value } }) => (
<View style={{ position: 'relative' }}> <View style={{ position: 'relative' }}>
<AppText style={RegisterStyle.label}> <AppText style={RegisterStyle.label}>
{t('Filial')}{' '} {t('Filial')}
</AppText> </AppText>
<View style={RegisterStyle.input}> <View style={RegisterStyle.input}>
<TouchableOpacity <TouchableOpacity
style={RegisterStyle.selector} style={RegisterStyle.selector}
onPress={() => onPress={() => {
setFilialDropdownVisible(prev => !prev) setFilialDropdownVisible(prev => !prev);
} Keyboard.dismiss();
}}
> >
<AppText <AppText
style={ style={
@@ -344,6 +337,11 @@ const FirstStep = ({ onNext }: { onNext: () => void }) => {
onPress={() => { onPress={() => {
setValue('branchId', item.id); setValue('branchId', item.id);
setFilialDropdownVisible(false); setFilialDropdownVisible(false);
// keyingi inputga focus
setTimeout(
() => addressRef.current?.focus(),
200,
);
}} }}
> >
<AppText <AppText
@@ -364,6 +362,8 @@ const FirstStep = ({ onNext }: { onNext: () => void }) => {
</View> </View>
)} )}
/> />
{/* Manzil */}
<Controller <Controller
control={control} control={control}
name="address" name="address"
@@ -373,6 +373,7 @@ const FirstStep = ({ onNext }: { onNext: () => void }) => {
{t('Manzilingizni kiriting')} {t('Manzilingizni kiriting')}
</AppText> </AppText>
<TextInput <TextInput
ref={addressRef}
style={RegisterStyle.input} style={RegisterStyle.input}
placeholder={t( placeholder={t(
"Toshkent Shahri, Mirzo Ulug'bek tumani...", "Toshkent Shahri, Mirzo Ulug'bek tumani...",
@@ -380,15 +381,21 @@ const FirstStep = ({ onNext }: { onNext: () => void }) => {
placeholderTextColor={'#D8DADC'} placeholderTextColor={'#D8DADC'}
onChangeText={onChange} onChangeText={onChange}
value={value} value={value}
returnKeyType="done"
onSubmitEditing={
() => setRecommendedDropdownVisible(true) // ❗ recommend select ochiladi
}
/> />
{errors.lastName && ( {errors.address && (
<AppText style={RegisterStyle.errorText}> <AppText style={RegisterStyle.errorText}>
{t(errors.lastName.message || '')} {t(errors.address.message || '')}
</AppText> </AppText>
)} )}
</View> </View>
)} )}
/> />
{/* Recommend (dropdown) */}
<Controller <Controller
control={control} control={control}
name="recommend" name="recommend"
@@ -458,6 +465,8 @@ const FirstStep = ({ onNext }: { onNext: () => void }) => {
</View> </View>
)} )}
/> />
{/* Terms */}
<View style={RegisterStyle.termsContainer}> <View style={RegisterStyle.termsContainer}>
<TouchableOpacity <TouchableOpacity
style={RegisterStyle.checkboxContainer} style={RegisterStyle.checkboxContainer}
@@ -503,7 +512,6 @@ const FirstStep = ({ onNext }: { onNext: () => void }) => {
</View> </View>
</TouchableOpacity> </TouchableOpacity>
</View> </View>
<TouchableOpacity <TouchableOpacity
onPress={handleSubmit(onSubmit)} onPress={handleSubmit(onSubmit)}
style={[ style={[

View File

@@ -21,8 +21,8 @@ import {
Dimensions, Dimensions,
Image, Image,
ImageBackground, ImageBackground,
Keyboard,
KeyboardAvoidingView, KeyboardAvoidingView,
Platform,
ScrollView, ScrollView,
TextInput, TextInput,
TouchableOpacity, TouchableOpacity,
@@ -55,8 +55,11 @@ const SecondStep = () => {
const passportNumberRef = useRef<TextInput>(null); const passportNumberRef = useRef<TextInput>(null);
const [checkboxAnimation] = useState(new Animated.Value(1)); const [checkboxAnimation] = useState(new Animated.Value(1));
const [inputValue, setInputValue] = useState(''); const [inputValue, setInputValue] = useState('');
const [error, setError] = useState<string>('');
const { firstName, lastName } = useUserStore(state => state); const { firstName, lastName } = useUserStore(state => state);
const passportSeriyaRef = useRef<TextInput>(null);
const jshshirRef = useRef<TextInput>(null);
const birthDateRef = useRef<TextInput>(null);
const navigation = const navigation =
useNavigation<NativeStackNavigationProp<RootStackParamList, 'Login'>>(); useNavigation<NativeStackNavigationProp<RootStackParamList, 'Login'>>();
const route = useRoute<RouteProp<RootStackParamList, 'Register'>>(); const route = useRoute<RouteProp<RootStackParamList, 'Register'>>();
@@ -76,8 +79,8 @@ const SecondStep = () => {
onSuccess: res => { onSuccess: res => {
navigation.navigate('Home'); navigation.navigate('Home');
}, },
onError: err => { onError: (err: any) => {
console.dir(err); setError(err.response.data);
}, },
}); });
@@ -145,10 +148,14 @@ const SecondStep = () => {
</View> </View>
<KeyboardAvoidingView <KeyboardAvoidingView
style={RegisterStyle.container} style={{ flex: 1 }}
behavior={Platform.OS === 'ios' ? 'padding' : 'height'} behavior="padding"
keyboardVerticalOffset={50}
>
<ScrollView
contentContainerStyle={{ flexGrow: 1 }}
keyboardShouldPersistTaps="handled"
> >
<ScrollView style={RegisterStyle.content}>
<View style={RegisterStyle.scrollContainer}> <View style={RegisterStyle.scrollContainer}>
<View style={RegisterStyle.loginContainer}> <View style={RegisterStyle.loginContainer}>
<AppText style={RegisterStyle.title}> <AppText style={RegisterStyle.title}>
@@ -170,6 +177,7 @@ const SecondStep = () => {
name="passportSeriya" name="passportSeriya"
render={({ field: { onChange, value } }) => ( render={({ field: { onChange, value } }) => (
<TextInput <TextInput
ref={passportSeriyaRef}
style={[ style={[
RegisterStyle.input, RegisterStyle.input,
RegisterStyle.seriyaInput, RegisterStyle.seriyaInput,
@@ -178,12 +186,16 @@ const SecondStep = () => {
maxLength={2} maxLength={2}
autoCapitalize="characters" autoCapitalize="characters"
value={value} value={value}
returnKeyType="next"
onChangeText={text => { onChangeText={text => {
onChange(text); onChange(text);
if (text.length === 2) if (text.length === 2)
passportNumberRef.current?.focus(); passportNumberRef.current?.focus();
}} }}
placeholderTextColor="#D8DADC" placeholderTextColor="#D8DADC"
onSubmitEditing={() =>
passportNumberRef.current?.focus()
}
/> />
)} )}
/> />
@@ -201,10 +213,12 @@ const SecondStep = () => {
maxLength={7} maxLength={7}
keyboardType="numeric" keyboardType="numeric"
value={value} value={value}
returnKeyType="next"
onChangeText={text => { onChangeText={text => {
const onlyNumbers = text.replace(/[^0-9]/g, ''); const onlyNumbers = text.replace(/[^0-9]/g, '');
onChange(onlyNumbers); onChange(onlyNumbers);
}} }}
onSubmitEditing={() => jshshirRef.current?.focus()}
placeholderTextColor="#D8DADC" placeholderTextColor="#D8DADC"
/> />
)} )}
@@ -228,14 +242,17 @@ const SecondStep = () => {
</AppText> </AppText>
<TextInput <TextInput
style={RegisterStyle.input} style={RegisterStyle.input}
ref={jshshirRef}
placeholder="12345678901234" placeholder="12345678901234"
placeholderTextColor="#D8DADC" placeholderTextColor="#D8DADC"
keyboardType="numeric" keyboardType="numeric"
maxLength={14} maxLength={14}
returnKeyType="next"
value={value} value={value}
onChangeText={text => onChangeText={text =>
onChange(text.replace(/[^0-9]/g, '')) onChange(text.replace(/[^0-9]/g, ''))
} }
onSubmitEditing={() => birthDateRef.current?.focus()}
/> />
{errors.jshshir && ( {errors.jshshir && (
<AppText style={RegisterStyle.errorText}> <AppText style={RegisterStyle.errorText}>
@@ -267,10 +284,12 @@ const SecondStep = () => {
RegisterStyle.input, RegisterStyle.input,
{ flex: 1, borderWidth: 0 }, { flex: 1, borderWidth: 0 },
]} ]}
ref={birthDateRef}
placeholder="dd/mm/yyyy" placeholder="dd/mm/yyyy"
placeholderTextColor="#D8DADC" placeholderTextColor="#D8DADC"
keyboardType="numeric" keyboardType="numeric"
value={value} value={value}
returnKeyType="done"
onChangeText={text => { onChangeText={text => {
let cleaned = text let cleaned = text
.replace(/[^\d]/g, '') .replace(/[^\d]/g, '')
@@ -326,6 +345,7 @@ const SecondStep = () => {
setValue('birthDate', formatted); setValue('birthDate', formatted);
}} }}
onSubmitEditing={handleSubmit(onSubmit)}
/> />
<TouchableOpacity <TouchableOpacity
onPress={() => setDatePickerVisibility(true)} onPress={() => setDatePickerVisibility(true)}
@@ -377,7 +397,10 @@ const SecondStep = () => {
> >
<SingleFileDrop <SingleFileDrop
title={t('Old tomon')} title={t('Old tomon')}
onFileSelected={setFrontImage} onFileSelected={file => {
setFrontImage(file);
Keyboard.dismiss();
}}
/> />
</View> </View>
<View <View
@@ -388,11 +411,18 @@ const SecondStep = () => {
> >
<SingleFileDrop <SingleFileDrop
title={t('Orqa tomon')} title={t('Orqa tomon')}
onFileSelected={setBackImage} onFileSelected={file => {
setBackImage(file);
Keyboard.dismiss();
}}
/> />
</View> </View>
</View> </View>
{error && (
<AppText style={[RegisterStyle.errorText, { fontSize: 14 }]}>
{error}
</AppText>
)}
{/* BUTTON */} {/* BUTTON */}
<TouchableOpacity <TouchableOpacity
onPress={handleSubmit(onSubmit)} onPress={handleSubmit(onSubmit)}

View File

@@ -3,7 +3,14 @@ import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import AppText from 'components/AppText'; import AppText from 'components/AppText';
import React from 'react'; import React from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { ScrollView, StyleSheet, TouchableOpacity, View } from 'react-native'; import {
Linking,
ScrollView,
StyleSheet,
TouchableOpacity,
View,
} from 'react-native';
import AppLink from 'react-native-app-link';
import { SafeAreaView } from 'react-native-safe-area-context'; import { SafeAreaView } from 'react-native-safe-area-context';
import ArrowLeft from 'svg/ArrowLeft'; import ArrowLeft from 'svg/ArrowLeft';
import { RootStackParamList } from 'types/types'; import { RootStackParamList } from 'types/types';
@@ -16,11 +23,21 @@ type TermsScreenNavigationProp = NativeStackNavigationProp<
const TermsAndConditions = () => { const TermsAndConditions = () => {
const navigation = useNavigation<TermsScreenNavigationProp>(); const navigation = useNavigation<TermsScreenNavigationProp>();
const { t } = useTranslation(); const { t } = useTranslation();
const handleAgree = () => { const handleAgree = () => {
navigation.goBack(); navigation.goBack();
}; };
const openTelegram = React.useCallback(async () => {
try {
await AppLink.maybeOpenURL('tg://resolve?domain=cpost_admin', {
appName: 'Telegram',
appStoreId: 686449807,
appStoreLocale: 'us',
playStoreId: 'org.telegram.messenger',
});
} catch (err) {
Linking.openURL('https://t.me/cpost_admin');
}
}, []);
return ( return (
<SafeAreaView style={styles.container}> <SafeAreaView style={styles.container}>
<View style={styles.header}> <View style={styles.header}>
@@ -35,16 +52,24 @@ const TermsAndConditions = () => {
<ScrollView style={styles.content} showsVerticalScrollIndicator={false}> <ScrollView style={styles.content} showsVerticalScrollIndicator={false}>
<AppText style={styles.title}> <AppText style={styles.title}>
{t('foydalanish_shartlari_va_qoidalari')} {t('Foydalanish shartlari va qoidalari')}
</AppText> </AppText>
<AppText style={styles.sectionTitle}>{t('umumiy_qoidalar')}</AppText> <AppText style={styles.text}>
<AppText style={styles.text}>{t('umumiy_qoidalar_text')}</AppText> {t(
"Biz sizdan Xitoy xalq Respublikasi Davlatidan sotib olingan tovarlarni olib kelishda quyidagi tovarlarni jonatmaslikka rozilik so'raymiz.",
)}
</AppText>
<AppText style={styles.sectionTitle}>1. {t('Umumiy qoidalar')}</AppText>
<AppText style={styles.text}>{t('Taqiqlangan tovarlar matni')}</AppText>
<AppText style={styles.text}>{t('Tovarlar')}</AppText>
<AppText style={styles.sectionTitle}> <AppText style={styles.sectionTitle}>
{t('foydalanuvchi_majburiyatlari')} {t('foydalanuvchi_majburiyatlari')}
</AppText> </AppText>
<AppText style={styles.text}> <AppText style={[styles.text, { textAlign: 'left' }]}>
{t('foydalanuvchi_majburiyatlari_text')} {t('foydalanuvchi_majburiyatlari_text')}
</AppText> </AppText>
@@ -63,17 +88,30 @@ const TermsAndConditions = () => {
<AppText style={styles.sectionTitle}>{t('aloqa')}</AppText> <AppText style={styles.sectionTitle}>{t('aloqa')}</AppText>
<AppText style={styles.text}>{t('aloqa_text')}</AppText> <AppText style={styles.text}>{t('aloqa_text')}</AppText>
<TouchableOpacity
onPress={() => Linking.openURL('mailto:info@cpost.uz')}
>
<AppText style={styles.text}>{t('Email')}: info@cpost.uz</AppText>
</TouchableOpacity>
<TouchableOpacity onPress={() => Linking.openURL('tel:+998951264477')}>
<AppText style={styles.text}>
{t('Telefon')}: +998 (95) 126 44 77
</AppText>
</TouchableOpacity>
<TouchableOpacity onPress={openTelegram}>
<AppText style={styles.text}>{t('Telegram')}: @cpost_admin</AppText>
</TouchableOpacity>
<View style={styles.footer}> <View style={styles.footer}>
<AppText style={styles.footerText}> <AppText style={styles.footerText}>
{t('oxirgi_yangilanish')} {new Date().toLocaleDateString('uz-UZ')} {t('oxirgi_yangilanish')} 01/09/2025
</AppText> </AppText>
</View> </View>
</ScrollView> </ScrollView>
<View style={styles.bottomContainer}> <View style={styles.bottomContainer}>
<TouchableOpacity style={styles.agreeButton} onPress={handleAgree}> <TouchableOpacity style={styles.agreeButton} onPress={handleAgree}>
<AppText style={styles.agreeButtonText}>{t('roziman')}</AppText> <AppText style={styles.agreeButtonText}>{t('Roziman')}</AppText>
</TouchableOpacity> </TouchableOpacity>
</View> </View>
</SafeAreaView> </SafeAreaView>

View File

@@ -41,10 +41,16 @@ const SelectAuth = () => {
styles.logoImage, styles.logoImage,
{ {
width: 180, width: 180,
height: 180, height: 150,
marginLeft: 35,
}, },
]} ]}
/> />
<AppText
style={[styles.logoText, { fontSize: 52, fontWeight: '900' }]}
>
CPOST
</AppText>
{/* <AppText style={[styles.logoText, { fontSize: 32 }]}>CPOST</AppText> */} {/* <AppText style={[styles.logoText, { fontSize: 32 }]}>CPOST</AppText> */}
</View> </View>

View File

@@ -6,7 +6,14 @@ import AppText from 'components/AppText';
import LayoutTwo from 'components/LayoutTwo'; import LayoutTwo from 'components/LayoutTwo';
import * as React from 'react'; import * as React from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { ScrollView, StyleSheet, TouchableOpacity, View } from 'react-native'; import {
Linking,
ScrollView,
StyleSheet,
TouchableOpacity,
View,
} from 'react-native';
import AppLink from 'react-native-app-link';
import Tabs from '../../home/ui/Tabs'; import Tabs from '../../home/ui/Tabs';
interface CargoPricesProps {} interface CargoPricesProps {}
@@ -25,6 +32,19 @@ const CargoPrices = (props: CargoPricesProps) => {
refetch(); refetch();
}, [activeTab]); }, [activeTab]);
const openTelegram = React.useCallback(async () => {
try {
await AppLink.maybeOpenURL('tg://resolve?domain=cpost_admin', {
appName: 'Telegram',
appStoreId: 686449807,
appStoreLocale: 'us',
playStoreId: 'org.telegram.messenger',
});
} catch (err) {
Linking.openURL('https://t.me/cpost_admin');
}
}, []);
return ( return (
<LayoutTwo title={t('Kargo narxlari')}> <LayoutTwo title={t('Kargo narxlari')}>
<ScrollView style={{ flex: 1 }}> <ScrollView style={{ flex: 1 }}>
@@ -105,7 +125,10 @@ const CargoPrices = (props: CargoPricesProps) => {
</AppText> </AppText>
</View> </View>
<AppText style={[styles.desc, { color: '#000000' }]}> <AppText style={[styles.desc, { color: '#000000' }]}>
{t('Batafsil')}: @CPcargo_admin {t('Batafsil')}:{' '}
<AppText style={{ color: '#28A7E8' }} onPress={openTelegram}>
@cpost_admin
</AppText>
</AppText> </AppText>
</View> </View>
<View style={[styles.card]}> <View style={[styles.card]}>
@@ -193,7 +216,10 @@ const CargoPrices = (props: CargoPricesProps) => {
</AppText> </AppText>
</View> </View>
<AppText style={[styles.desc, { color: '#000000' }]}> <AppText style={[styles.desc, { color: '#000000' }]}>
{t('Batafsil')}: @CPcargo_admin {t('Batafsil')}:{' '}
<AppText style={{ color: '#28A7E8' }} onPress={openTelegram}>
@cpost_admin
</AppText>
</AppText> </AppText>
</View> </View>
<View style={[styles.card]}> <View style={[styles.card]}>

View File

@@ -75,7 +75,11 @@ const Home = () => {
removeClippedSubviews={true} removeClippedSubviews={true}
keyboardShouldPersistTaps="handled" keyboardShouldPersistTaps="handled"
> >
<PartyCarousel autoData={autoData} aviaData={aviaData} /> <PartyCarousel
autoData={autoData}
aviaData={aviaData}
activeTab={activeTab}
/>
<Tabs setActiveTab={setActiveTab} activeTab={activeTab} /> <Tabs setActiveTab={setActiveTab} activeTab={activeTab} />
{activeTabContent} {activeTabContent}
<Pages /> <Pages />

View File

@@ -1,6 +1,6 @@
import AnimatedIcon from 'components/AnimatedIcon'; import AnimatedIcon from 'components/AnimatedIcon';
import AppText from 'components/AppText'; import AppText from 'components/AppText';
import React, { useMemo, useRef, useState } from 'react'; import React, { useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { import {
FlatList, FlatList,
@@ -10,6 +10,11 @@ import {
useWindowDimensions, useWindowDimensions,
View, View,
} from 'react-native'; } from 'react-native';
import Animated, {
useAnimatedStyle,
useSharedValue,
withTiming,
} from 'react-native-reanimated';
import Auto from 'svg/Auto'; import Auto from 'svg/Auto';
import Avia from 'svg/Avia'; import Avia from 'svg/Avia';
import BoxCreate from 'svg/BoxCreate'; import BoxCreate from 'svg/BoxCreate';
@@ -18,16 +23,35 @@ import { HomeStyle } from './styled';
const PartyCarousel = ({ const PartyCarousel = ({
aviaData, aviaData,
activeTab,
autoData, autoData,
}: { }: {
autoData: any; autoData: any;
aviaData: any; aviaData: any;
activeTab: 'AUTO' | 'AVIA';
}) => { }) => {
const { width: screenWidth } = useWindowDimensions(); const { width: screenWidth } = useWindowDimensions();
const cardWidth = screenWidth * 0.95; const cardWidth = screenWidth * 0.95;
const styles = useMemo(() => HomeStyle(), []); const styles = useMemo(() => HomeStyle(), []);
const { t } = useTranslation(); const { t } = useTranslation();
// animatsiya
const opacity = useSharedValue(0);
const translateY = useSharedValue(20);
useEffect(() => {
opacity.value = 1;
translateY.value = 0;
opacity.value = withTiming(1, { duration: 500 });
translateY.value = withTiming(0, { duration: 500 });
}, [activeTab]);
const animatedStyle = useAnimatedStyle(() => ({
opacity: opacity.value,
transform: [{ translateY: translateY.value }],
}));
// status config
const statusConfig: any = { const statusConfig: any = {
COLLECTING: { COLLECTING: {
backgroundColor: '#28A7E8', backgroundColor: '#28A7E8',
@@ -56,7 +80,7 @@ const PartyCarousel = ({
}, },
}; };
// calendarList tayyorlash // calendarList faqat activeTab uchun
const calendarList = useMemo(() => { const calendarList = useMemo(() => {
const data: any[] = []; const data: any[] = [];
const weekdays = [ const weekdays = [
@@ -89,10 +113,14 @@ const PartyCarousel = ({
}); });
}; };
if (activeTab === 'AUTO') {
prepareList(autoData, 'auto'); prepareList(autoData, 'auto');
} else if (activeTab === 'AVIA') {
prepareList(aviaData, 'avia'); prepareList(aviaData, 'avia');
}
return data; return data;
}, [autoData, aviaData]); }, [autoData, aviaData, activeTab]);
const flatListRef = useRef<FlatList>(null); const flatListRef = useRef<FlatList>(null);
const today = useMemo(() => { const today = useMemo(() => {
@@ -102,6 +130,7 @@ const PartyCarousel = ({
}, []); }, []);
const [selectedItem, setSelectedItem] = useState<any>(null); const [selectedItem, setSelectedItem] = useState<any>(null);
const [modalVisible, setModalVisible] = useState(false); const [modalVisible, setModalVisible] = useState(false);
const renderItem = ({ item, index }: { item: any; index: number }) => { const renderItem = ({ item, index }: { item: any; index: number }) => {
const isLast = index === calendarList.length - 1; const isLast = index === calendarList.length - 1;
return ( return (
@@ -171,7 +200,7 @@ const PartyCarousel = ({
{item.cargo.toUpperCase()} {item.cargo.toUpperCase()}
</AppText> </AppText>
<View style={styles.animatedIconWrapper}> <View style={styles.animatedIconWrapper}>
<AnimatedIcon type={item.cargo} /> <AnimatedIcon type={activeTab} />
</View> </View>
</View> </View>
</> </>
@@ -181,9 +210,8 @@ const PartyCarousel = ({
}; };
return ( return (
<> <Animated.View style={animatedStyle}>
<FlatList <FlatList
ref={flatListRef}
data={calendarList} data={calendarList}
keyExtractor={(_, index) => index.toString()} keyExtractor={(_, index) => index.toString()}
renderItem={renderItem} renderItem={renderItem}
@@ -233,7 +261,7 @@ const PartyCarousel = ({
</View> </View>
</View> </View>
</Modal> </Modal>
</> </Animated.View>
); );
}; };

View File

@@ -12,7 +12,6 @@ import {
ActivityIndicator, ActivityIndicator,
Dimensions, Dimensions,
KeyboardAvoidingView, KeyboardAvoidingView,
Platform,
ScrollView, ScrollView,
TextInput, TextInput,
TouchableOpacity, TouchableOpacity,
@@ -42,6 +41,17 @@ const CreatePassword = () => {
const [error, setError] = useState(false); const [error, setError] = useState(false);
const [frontImage, setFrontImage] = useState<FileData | null>(null); const [frontImage, setFrontImage] = useState<FileData | null>(null);
const [backImage, setBackImage] = useState<FileData | null>(null); const [backImage, setBackImage] = useState<FileData | null>(null);
// firstName: '',
// lastName: '',
// birthDate: '',
// passportSeriya: '',
// passportNumber: '',
// jshshir: '',
const firstNameRef = useRef<TextInput>(null);
const lastNameRef = useRef<TextInput>(null);
const birthDateRef = useRef<TextInput>(null);
const passportSeriyaRef = useRef<TextInput>(null);
const jshshirRef = useRef<TextInput>(null);
const { mutate, isPending } = useMutation({ const { mutate, isPending } = useMutation({
mutationFn: (payload: AddPassportPayload) => { mutationFn: (payload: AddPassportPayload) => {
@@ -105,12 +115,14 @@ const CreatePassword = () => {
}); });
}; };
return ( return (
<LayoutTwo title="Yangi pasport qo'shish"> <LayoutTwo title={t("Yangi pasport qo'shish")}>
<KeyboardAvoidingView <KeyboardAvoidingView
style={PassportStyle.container} style={PassportStyle.container}
behavior={Platform.OS === 'ios' ? 'padding' : 'height'} behavior={'padding'}
keyboardVerticalOffset={30}
> >
<ScrollView <ScrollView
keyboardShouldPersistTaps="handled"
showsVerticalScrollIndicator={false} showsVerticalScrollIndicator={false}
style={PassportStyle.content} style={PassportStyle.content}
> >
@@ -123,6 +135,9 @@ const CreatePassword = () => {
<View> <View>
<AppText style={PassportStyle.label}>{t('Ism')}</AppText> <AppText style={PassportStyle.label}>{t('Ism')}</AppText>
<TextInput <TextInput
ref={firstNameRef}
returnKeyType="next"
onSubmitEditing={() => lastNameRef.current?.focus()}
style={PassportStyle.input} style={PassportStyle.input}
placeholder={t('Ismingiz')} placeholder={t('Ismingiz')}
onChangeText={onChange} onChangeText={onChange}
@@ -146,6 +161,9 @@ const CreatePassword = () => {
{t('Familiya')} {t('Familiya')}
</AppText> </AppText>
<TextInput <TextInput
ref={lastNameRef}
returnKeyType="next"
onSubmitEditing={() => passportSeriyaRef.current?.focus()}
style={PassportStyle.input} style={PassportStyle.input}
placeholder={t('Familiyangiz')} placeholder={t('Familiyangiz')}
placeholderTextColor={'#D8DADC'} placeholderTextColor={'#D8DADC'}
@@ -170,6 +188,11 @@ const CreatePassword = () => {
name="passportSeriya" name="passportSeriya"
render={({ field: { onChange, value } }) => ( render={({ field: { onChange, value } }) => (
<TextInput <TextInput
ref={passportSeriyaRef}
returnKeyType="next"
onSubmitEditing={() =>
passportNumberRef.current?.focus()
}
style={[PassportStyle.input, PassportStyle.seriyaInput]} style={[PassportStyle.input, PassportStyle.seriyaInput]}
placeholder="AA" placeholder="AA"
maxLength={2} maxLength={2}
@@ -191,6 +214,8 @@ const CreatePassword = () => {
render={({ field: { onChange, value } }) => ( render={({ field: { onChange, value } }) => (
<TextInput <TextInput
ref={passportNumberRef} ref={passportNumberRef}
returnKeyType="next"
onSubmitEditing={() => jshshirRef.current?.focus()}
style={[PassportStyle.input, PassportStyle.raqamInput]} style={[PassportStyle.input, PassportStyle.raqamInput]}
placeholder="1234567" placeholder="1234567"
maxLength={7} maxLength={7}
@@ -220,6 +245,9 @@ const CreatePassword = () => {
render={({ field: { onChange, value } }) => ( render={({ field: { onChange, value } }) => (
<TextInput <TextInput
style={PassportStyle.input} style={PassportStyle.input}
ref={jshshirRef}
returnKeyType="next"
onSubmitEditing={() => birthDateRef.current?.focus()}
placeholder="12345678901234" placeholder="12345678901234"
placeholderTextColor={'#D8DADC'} placeholderTextColor={'#D8DADC'}
keyboardType="numeric" keyboardType="numeric"
@@ -250,6 +278,8 @@ const CreatePassword = () => {
<View style={[PassportStyle.inputContainer]}> <View style={[PassportStyle.inputContainer]}>
<TextInput <TextInput
ref={birthDateRef}
returnKeyType="done"
style={[ style={[
PassportStyle.input, PassportStyle.input,
{ flex: 1, borderWidth: 0, padding: 0 }, { flex: 1, borderWidth: 0, padding: 0 },

View File

@@ -51,15 +51,14 @@ const ProfilePages = (props: componentNameProps) => {
const openTelegram = React.useCallback(async () => { const openTelegram = React.useCallback(async () => {
try { try {
await AppLink.maybeOpenURL('tg://resolve?domain=cpostuz', { await AppLink.maybeOpenURL('tg://resolve?domain=cpost_admin', {
appName: 'Telegram', appName: 'Telegram',
appStoreId: 686449807, appStoreId: 686449807,
appStoreLocale: 'us', appStoreLocale: 'us',
playStoreId: 'org.telegram.messenger', playStoreId: 'org.telegram.messenger',
}); });
} catch (err) { } catch (err) {
// Agar ilovani ham, storeni ham ochib bolmasa, fallback URL Linking.openURL('https://t.me/cpost_admin');
Linking.openURL('https://t.me/cpostuz');
} }
}, []); }, []);

View File

@@ -75,7 +75,7 @@ const TabsAutoWarehouses = () => {
}; };
const { data } = useQuery({ const { data } = useQuery({
queryKey: ['warhouses'], queryKey: ['warhouses_auto'],
queryFn: () => warhouses_api.getWarhouses({ cargoType: 'AUTO' }), queryFn: () => warhouses_api.getWarhouses({ cargoType: 'AUTO' }),
}); });

View File

@@ -75,7 +75,7 @@ const TabsAviaWarehouses = () => {
}; };
const { data } = useQuery({ const { data } = useQuery({
queryKey: ['warhouses'], queryKey: ['warhouses_avia'],
queryFn: () => warhouses_api.getWarhouses({ cargoType: 'AVIA' }), queryFn: () => warhouses_api.getWarhouses({ cargoType: 'AVIA' }),
}); });
@@ -108,7 +108,7 @@ const TabsAviaWarehouses = () => {
<View style={[styles.card, { marginRight: isLast ? 0 : 10 }]}> <View style={[styles.card, { marginRight: isLast ? 0 : 10 }]}>
<View style={styles.titleCard}> <View style={styles.titleCard}>
<Kitay width={24 * scale} height={24 * scale} /> <Kitay width={24 * scale} height={24 * scale} />
<AppText style={styles.title}>China (Auto)</AppText> <AppText style={styles.title}>China (AVIA)</AppText>
</View> </View>
<View style={styles.infoId}> <View style={styles.infoId}>
<View style={{ gap: 4 * scale, width: '90%' }}> <View style={{ gap: 4 * scale, width: '90%' }}>

View File

@@ -100,15 +100,14 @@ Cargo Idsi: ${getMe?.aviaCargoId}
); );
const openTelegram = React.useCallback(async () => { const openTelegram = React.useCallback(async () => {
try { try {
await AppLink.maybeOpenURL('tg://resolve?domain=cpostuz', { await AppLink.maybeOpenURL('tg://resolve?domain=cpost_admin', {
appName: 'Telegram', appName: 'Telegram',
appStoreId: 686449807, appStoreId: 686449807,
appStoreLocale: 'us', appStoreLocale: 'us',
playStoreId: 'org.telegram.messenger', playStoreId: 'org.telegram.messenger',
}); });
} catch (err) { } catch (err) {
// Agar ilovani ham, storeni ham ochib bolmasa, fallback URL Linking.openURL('https://t.me/cpost_admin');
Linking.openURL('https://t.me/cpostuz');
} }
}, []); }, []);
return ( return (

View File

@@ -40,11 +40,14 @@ const SelectLangPage = ({
styles.logoImage, styles.logoImage,
{ {
width: 180, width: 180,
height: 180, height: 150,
marginLeft: 35,
}, },
]} ]}
/> />
<AppText style={[styles.logoText, { fontSize: 24 }]}> <AppText
style={[styles.logoText, { fontSize: 42, fontWeight: '700' }]}
>
CPOST CPOST
</AppText> </AppText>
</View> </View>
@@ -59,10 +62,19 @@ const SelectLangPage = ({
<View style={styles.btnContainer}> <View style={styles.btnContainer}>
<TouchableOpacity <TouchableOpacity
onPress={() => onSelectLang('uz')} onPress={() => onSelectLang('uz')}
style={styles.button} style={[
styles.button,
{
backgroundColor: 'none',
borderWidth: 1,
borderColor: '#28A7E8',
},
]}
> >
<Image source={UZ} style={styles.flag} /> <Image source={UZ} style={styles.flag} />
<AppText style={styles.btnText}>O'zbek tili</AppText> <AppText style={[styles.btnText, { color: '#28A7E8' }]}>
O'zbek tili
</AppText>
</TouchableOpacity> </TouchableOpacity>
<TouchableOpacity <TouchableOpacity
@@ -134,7 +146,7 @@ const styles = StyleSheet.create({
}, },
flag: { flag: {
width: 30, width: 30,
height: 30, height: 20,
resizeMode: 'cover', resizeMode: 'cover',
}, },
}); });

View File

@@ -6,7 +6,7 @@
"*": ["./src/*"], "*": ["./src/*"],
"@screens": ["./src/screens/*"], "@screens": ["./src/screens/*"],
"screens": ["./src/screens"], "screens": ["./src/screens"],
"components": ["./src/components"], "components": ["./src/components/*"],
"assets": ["./src/assets"], "assets": ["./src/assets"],
"api": ["./src/api"], "api": ["./src/api"],
"helpers": ["./src/helpers"], "helpers": ["./src/helpers"],