This commit is contained in:
azizziy
2025-08-27 15:44:54 +05:00
20 changed files with 619 additions and 630 deletions

View File

@@ -1,4 +1,4 @@
export const BASE_URL = 'https://api.cpcargo.uz/api/v1';
export const BASE_URL = 'http://141.105.64.233:7723/api/v1';
export const REGISTER = '/mobile/auth/register';
export const LOGIN = '/mobile/auth/login';

View File

@@ -3,7 +3,7 @@ import axios, { AxiosError } from 'axios';
import { navigate } from 'components/NavigationRef';
const axiosInstance = axios.create({
baseURL: 'https://api.cpcargo.uz/api/v1',
baseURL: 'http://141.105.64.233:7723/api/v1',
timeout: 10000,
headers: {
'Content-Type': 'application/json',

49
src/components/Layout.tsx Normal file
View File

@@ -0,0 +1,49 @@
// src/components/Layout.tsx
import React from 'react';
import { StyleSheet, View } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import Navbar from './Navbar';
import Navigation from './Navigation';
interface LayoutProps {
children: React.ReactNode;
}
const Layout: React.FC<LayoutProps> = ({ children }) => {
return (
<SafeAreaView style={styles.safeArea}>
<View style={styles.container}>
<Navbar />
<View style={styles.content}>{children}</View>
<Navigation />
</View>
</SafeAreaView>
);
};
export default Layout;
const styles = StyleSheet.create({
safeArea: {
flex: 1,
backgroundColor: '#fff',
},
container: {
flex: 1,
},
header: {
height: 60,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#f5f5f5',
},
content: {
flex: 1,
},
footer: {
height: 50,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#eee',
},
});

View File

@@ -0,0 +1,50 @@
// src/components/Layout.tsx
import React from 'react';
import { StyleSheet, View } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import NavbarBack from './NavbarBack';
import Navigation from './Navigation';
interface LayoutProps {
title: string;
children: React.ReactNode;
}
const LayoutTwo: React.FC<LayoutProps> = ({ title, children }) => {
return (
<SafeAreaView style={styles.safeArea}>
<View style={styles.container}>
<NavbarBack title={title} />
<View style={styles.content}>{children}</View>
<Navigation />
</View>
</SafeAreaView>
);
};
export default LayoutTwo;
const styles = StyleSheet.create({
safeArea: {
flex: 1,
backgroundColor: '#fff',
},
container: {
flex: 1,
},
header: {
height: 60,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#f5f5f5',
},
content: {
flex: 1,
},
footer: {
height: 50,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#eee',
},
});

View File

@@ -2,6 +2,7 @@ import { useNavigation } from '@react-navigation/native';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import { useQuery } from '@tanstack/react-query';
import { branchApi } from 'api/branch';
import LayoutTwo from 'components/LayoutTwo';
import NavbarBack from 'components/NavbarBack';
import NoResult from 'components/NoResult';
import * as React from 'react';
@@ -38,8 +39,7 @@ const Branches = (props: BranchesProps) => {
}
return (
<SafeAreaView style={{ flex: 1 }}>
<NavbarBack title={t('Filiallar royxati')} />
<LayoutTwo title={t('Filiallar royxati')}>
<View style={styles.scrollWrapper}>
<ScrollView contentContainerStyle={styles.scrollContainer}>
{data &&
@@ -60,7 +60,7 @@ const Branches = (props: BranchesProps) => {
))}
</ScrollView>
</View>
</SafeAreaView>
</LayoutTwo>
);
};
@@ -76,20 +76,28 @@ const styles = StyleSheet.create({
card: {
backgroundColor: '#FFFFFF',
borderRadius: 8,
padding: 16,
padding: 4,
marginBottom: 12,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.1,
shadowRadius: 2,
elevation: 1,
},
title: {
fontSize: 18,
paddingHorizontal: 5,
fontWeight: '600',
color: '#000',
marginBottom: 6,
},
subtitle: {
fontSize: 16,
paddingHorizontal: 5,
fontWeight: '500',
color: '#000000B2',
},

View File

@@ -3,13 +3,11 @@ import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import { useQuery } from '@tanstack/react-query';
import { Branch, branchApi } from 'api/branch';
import BottomModal from 'components/BottomModal';
import LayoutTwo from 'components/LayoutTwo';
import LoadingScreen from 'components/LoadingScreen';
import NavbarBack from 'components/NavbarBack';
import Navigation from 'components/Navigation';
import React, { useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import WebView from 'react-native-webview';
import Minus from 'svg/Minus';
import Plus from 'svg/Plus';
@@ -123,8 +121,7 @@ const ListBranches = () => {
if (!data) return <LoadingScreen />;
return (
<SafeAreaView style={styles.container}>
<NavbarBack title={t('Filiallar royxati')} />
<LayoutTwo title={t('Filiallar royxati')}>
{!webViewReady && (
<View style={{ width: '100%', height: '100%', margin: 'auto' }}>
<LoadingScreen />
@@ -195,8 +192,7 @@ const ListBranches = () => {
branch={selectedBranch}
/>
</View>
<Navigation />
</SafeAreaView>
</LayoutTwo>
);
};

View File

@@ -1,7 +1,6 @@
import { useNavigation } from '@react-navigation/native';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import NavbarBack from 'components/NavbarBack';
import Navigation from 'components/Navigation';
import LayoutTwo from 'components/LayoutTwo';
import * as React from 'react';
import { useTranslation } from 'react-i18next';
import {
@@ -11,7 +10,6 @@ import {
TouchableOpacity,
View,
} from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import Tabs from '../../home/ui/Tabs';
interface CargoPricesProps {}
@@ -21,13 +19,12 @@ const CargoPrices = (props: CargoPricesProps) => {
const [activeTab, setActiveTab] = React.useState<'avia' | 'auto'>('avia');
const navigation = useNavigation<NativeStackNavigationProp<any>>();
return (
<SafeAreaView style={{ flex: 1 }}>
<NavbarBack title={t('Kargo narxlari')} />
<LayoutTwo title={t('Kargo narxlari')}>
<ScrollView style={{ flex: 1 }}>
<View style={styles.container}>
<Tabs activeTab={activeTab} setActiveTab={setActiveTab} />
{activeTab === 'avia' && (
<View style={{ marginTop: 20, gap: 10, marginBottom: 20 }}>
<View style={{ marginTop: 10, gap: 10, marginBottom: 20 }}>
<View style={styles.cardWhite}>
<View style={styles.priceCard}>
<Text style={styles.titleBlack}>
@@ -231,8 +228,7 @@ const CargoPrices = (props: CargoPricesProps) => {
)}
</View>
</ScrollView>
<Navigation />
</SafeAreaView>
</LayoutTwo>
);
};
@@ -240,7 +236,7 @@ export default CargoPrices;
const styles = StyleSheet.create({
container: {
marginTop: 20,
marginTop: 10,
},
card: {
width: '95%',
@@ -254,6 +250,14 @@ const styles = StyleSheet.create({
margin: 'auto',
padding: 10,
borderRadius: 8,
paddingVertical: 15,
paddingHorizontal: 12,
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.1,
shadowRadius: 2,
elevation: 1,
},
titleBlack: {
fontSize: 16,

View File

@@ -1,20 +1,12 @@
'use client';
import { useQuery } from '@tanstack/react-query';
import calendarAPi from 'api/calendar';
import Layout from 'components/Layout';
import LoadingScreen from 'components/LoadingScreen';
import Navbar from 'components/Navbar';
import Navigation from 'components/Navigation';
import { useCallback, useMemo, useState } from 'react';
import {
RefreshControl,
ScrollView,
useWindowDimensions,
View,
} from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { RefreshControl, ScrollView, useWindowDimensions } from 'react-native';
import Pages from './Pages';
import PartyCarousel from './PartyCarousel';
import { HomeStyle } from './styled';
import Tabs from './Tabs';
import TabsAuto from './TabsAuto';
import TabsAvia from './TabsAvia';
@@ -24,7 +16,6 @@ const Home = () => {
const [refreshing, setRefreshing] = useState(false);
const { width: screenWidth } = useWindowDimensions();
const scale = screenWidth < 360 ? 0.85 : 1;
const styles = useMemo(() => HomeStyle(scale), [scale]);
const {
data: autoData,
@@ -71,33 +62,25 @@ const Home = () => {
if (autoLoad || aviaLoad || fetchAuto || fetchAvia) {
return (
<SafeAreaView style={{ flex: 1 }}>
<View style={styles.container}>
<Navbar />
<LoadingScreen />
<Navigation />
</View>
</SafeAreaView>
<Layout>
<LoadingScreen />
</Layout>
);
}
return (
<SafeAreaView style={{ flex: 1 }}>
<View style={styles.container}>
<Navbar />
<ScrollView
refreshControl={refreshControl}
removeClippedSubviews={true}
keyboardShouldPersistTaps="handled"
>
<PartyCarousel autoData={autoData} aviaData={aviaData} />
<Tabs setActiveTab={setActiveTab} activeTab={activeTab} />
{activeTabContent}
<Pages />
</ScrollView>
<Navigation />
</View>
</SafeAreaView>
<Layout>
<ScrollView
refreshControl={refreshControl}
removeClippedSubviews={true}
keyboardShouldPersistTaps="handled"
>
<PartyCarousel autoData={autoData} aviaData={aviaData} />
<Tabs setActiveTab={setActiveTab} activeTab={activeTab} />
{activeTabContent}
<Pages />
</ScrollView>
</Layout>
);
};

View File

@@ -2,24 +2,16 @@ import { useNavigation } from '@react-navigation/native';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import React from 'react';
import { useTranslation } from 'react-i18next';
import {
StyleSheet,
Text,
TouchableOpacity,
View,
useWindowDimensions,
} from 'react-native';
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
import ArrowRightUnderline from 'svg/ArrowRightUnderline';
import Usd from 'svg/Dollar';
import InfoIcon from 'svg/Info';
import Store from 'svg/Store';
const Pages = () => {
const { width: screenWidth } = useWindowDimensions();
const navigation = useNavigation<NativeStackNavigationProp<any>>();
const scale = screenWidth < 360 ? 0.85 : 1;
const { t } = useTranslation();
const styles = makeStyles(scale);
const styles = makeStyles();
return (
<View style={styles.container}>
@@ -28,19 +20,10 @@ const Pages = () => {
style={styles.card}
>
<View style={styles.text}>
<Usd
color="#28A7E8"
width={28 * scale}
height={28 * scale}
colorCircle="#28A7E8"
/>
<Usd color="#28A7E8" width={28} height={28} colorCircle="#28A7E8" />
<Text style={styles.title}>{t('Kargo narxlari')}</Text>
</View>
<ArrowRightUnderline
color="#000000"
width={24 * scale}
height={24 * scale}
/>
<ArrowRightUnderline color="#000000" width={24} height={24} />
</TouchableOpacity>
<TouchableOpacity
@@ -48,14 +31,10 @@ const Pages = () => {
style={styles.card}
>
<View style={styles.text}>
<InfoIcon color="#28A7E8" width={28 * scale} height={28 * scale} />
<InfoIcon color="#28A7E8" width={28} height={28} />
<Text style={styles.title}>{t('Taqiqlangan buyumlar')}</Text>
</View>
<ArrowRightUnderline
color="#000000"
width={24 * scale}
height={24 * scale}
/>
<ArrowRightUnderline color="#000000" width={24} height={24} />
</TouchableOpacity>
{/* <View style={styles.card}>
@@ -80,14 +59,10 @@ const Pages = () => {
onPress={() => navigation.navigate('ListBranches')}
>
<View style={styles.text}>
<Store color="#28A7E8" width={28 * scale} height={28 * scale} />
<Store color="#28A7E8" width={28} height={28} />
<Text style={styles.title}>{t('Filiallar royxati')}</Text>
</View>
<ArrowRightUnderline
color="#000000"
width={24 * scale}
height={24 * scale}
/>
<ArrowRightUnderline color="#000000" width={24} height={24} />
</TouchableOpacity>
{/* <TouchableOpacity
@@ -108,33 +83,39 @@ const Pages = () => {
);
};
const makeStyles = (scale: number) =>
const makeStyles = () =>
StyleSheet.create({
container: {
width: '100%',
width: '95%',
marginLeft: 'auto',
marginRight: 'auto',
marginTop: 10 * scale,
borderRadius: 12 * scale,
padding: 12 * scale,
gap: 10 * scale,
borderRadius: 12,
marginBottom: 10,
gap: 10,
},
card: {
flexDirection: 'row',
justifyContent: 'space-between',
backgroundColor: '#FFFFFF',
shadowColor: '#F2FAFF',
padding: 15 * scale,
borderRadius: 8 * scale,
alignItems: 'center',
backgroundColor: '#FFFFFF',
paddingVertical: 15,
paddingHorizontal: 12,
borderRadius: 10,
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.1,
shadowRadius: 2,
elevation: 1,
},
text: {
flexDirection: 'row',
alignItems: 'center',
gap: 10 * scale,
gap: 10,
},
title: {
fontSize: 16 * scale,
fontSize: 16,
fontWeight: '600',
},
});

View File

@@ -24,9 +24,8 @@ const PartyCarousel = ({
aviaData: any;
}) => {
const { width: screenWidth } = useWindowDimensions();
const scale = screenWidth < 360 ? 0.85 : 1;
const cardWidth = screenWidth * 0.95;
const styles = useMemo(() => HomeStyle(scale), [scale]);
const styles = useMemo(() => HomeStyle(), []);
const { t } = useTranslation();
const statusConfig: any = {
@@ -57,21 +56,21 @@ const PartyCarousel = ({
},
};
// calendarList tayyorlash
const calendarList = useMemo(() => {
const data: any[] = [];
const weekdays = [
{ key: 'sunday', label: 'Ya' },
{ key: 'monday', label: 'Du' },
{ key: 'tuesday', label: 'Se' },
{ key: 'wednesday', label: 'Cho' },
{ key: 'thursday', label: 'Pa' },
{ key: 'friday', label: 'Ju' },
{ key: 'saturday', label: 'Sha' },
];
const prepareList = (calendar: any, type: 'auto' | 'avia') => {
if (!calendar) return;
const weekdays = [
{ key: 'sunday', label: 'Ya' },
{ key: 'monday', label: 'Du' },
{ key: 'tuesday', label: 'Se' },
{ key: 'wednesday', label: 'Cho' },
{ key: 'thursday', label: 'Pa' },
{ key: 'friday', label: 'Ju' },
{ key: 'saturday', label: 'Sha' },
];
data.push({
cargo: type,
party: calendar.cargoType,
@@ -79,7 +78,6 @@ const PartyCarousel = ({
start: weekdays.map((day, index) => {
const start = new Date(calendar.weekStartDate);
start.setDate(start.getDate() + index);
const status =
calendar[day.key as keyof typeof calendar] || 'DEFAULT';
return {
@@ -93,7 +91,6 @@ const PartyCarousel = ({
prepareList(autoData, 'auto');
prepareList(aviaData, 'avia');
return data;
}, [autoData, aviaData]);
@@ -103,14 +100,10 @@ const PartyCarousel = ({
d.setHours(0, 0, 0, 0);
return d;
}, []);
// --- MODAL STATE ---
const [selectedItem, setSelectedItem] = useState<any>(null);
const [modalVisible, setModalVisible] = useState(false);
const renderItem = ({ item, index }: { item: any; index: number }) => {
const isLast = index === calendarList.length - 1;
return (
<Pressable
onPress={() => {
@@ -119,67 +112,64 @@ const PartyCarousel = ({
}}
style={[
styles.autoContainer,
{ width: cardWidth, marginRight: isLast ? 0 : 10 },
{
width: cardWidth,
marginRight: isLast ? 0 : 10,
},
]}
>
{item.isAni && (
<>
<View style={styles.cardBody}>
{Array.isArray(item.start) &&
item.start.map((day: any, idx: number) => {
const dateObj = new Date(day.date);
const isToday =
dateObj.toDateString() === today.toDateString();
const config =
statusConfig[day.status] || statusConfig.DEFAULT;
<FlatList
data={item.start}
numColumns={7}
keyExtractor={(_, idx) => idx.toString()}
renderItem={({ item: day }) => {
const dateObj = new Date(day.date);
const isToday = dateObj.toDateString() === today.toDateString();
const config = statusConfig[day.status] || statusConfig.DEFAULT;
let backgroundColor = config.backgroundColor;
let textColor = config.textColor;
let backgroundColor = config.backgroundColor;
let textColor = config.textColor;
if (isToday) {
backgroundColor = '#22b1f88f';
textColor = '#fff';
}
if (isToday) {
backgroundColor = '#22b1f88f';
textColor = '#fff';
}
if (day.weekday === 'Ju') {
backgroundColor = '#4CAF50';
textColor = '#fff';
}
if (day.weekday === 'Ju') {
backgroundColor = '#4CAF50';
textColor = '#fff';
}
return (
<View
key={idx}
style={[
styles.date,
{
backgroundColor,
alignItems: 'center',
justifyContent: 'center',
height: 70,
},
]}
>
<Text style={[styles.dateLabel, { color: textColor }]}>
{day.date.slice(-2)}
</Text>
<Text style={[styles.dateLabel, { color: textColor }]}>
{t(day.weekday)}
</Text>
</View>
);
})}
</View>
<View style={styles.divider} />
<View style={styles.autoCard}>
<View style={styles.row}>
<View style={styles.rowFull}>
<Text style={styles.reysTitle}>
{item.cargo.toUpperCase()}
</Text>
<View style={styles.animatedIconWrapper}>
<AnimatedIcon type={item.cargo} />
return (
<View
style={[
styles.date,
{
backgroundColor,
marginRight: 5,
},
]}
>
<Text style={[styles.dateLabel, { color: textColor }]}>
{day.date.slice(-2)}
</Text>
<Text style={[styles.dateLabel, { color: textColor }]}>
{t(day.weekday)}
</Text>
</View>
</View>
);
}}
showsHorizontalScrollIndicator={false}
/>
<View style={styles.divider} />
<View style={styles.rowFull}>
<Text style={styles.reysTitle}>{item.cargo.toUpperCase()}</Text>
<View style={styles.animatedIconWrapper}>
<AnimatedIcon type={item.cargo} />
</View>
</View>
</>
@@ -200,9 +190,9 @@ const PartyCarousel = ({
decelerationRate="fast"
contentContainerStyle={{
paddingHorizontal: (screenWidth - cardWidth) / 2,
padding: 10,
}}
pagingEnabled
style={{ marginBottom: 20 }}
showsHorizontalScrollIndicator={false}
getItemLayout={(_, index) => ({
length: cardWidth,
@@ -210,8 +200,6 @@ const PartyCarousel = ({
index,
})}
/>
{/* MODAL */}
<Modal
transparent
visible={modalVisible}
@@ -223,15 +211,12 @@ const PartyCarousel = ({
<Text style={modalStyles.modalTitle}>
{t('Yetkazish tafsilotlari')}
</Text>
{selectedItem && (
<>
{selectedItem.start.map((day: any, idx: number) => (
<Text key={idx} style={{ textAlign: 'left', width: '100%' }}>
{day.date} - {t(day.weekday)} - {t(day.status)}
</Text>
))}
</>
)}
{selectedItem &&
selectedItem.start.map((day: any, idx: number) => (
<Text key={idx} style={{ textAlign: 'left', width: '100%' }}>
{day.date} - {t(day.weekday)} - {t(day.status)}
</Text>
))}
<Pressable
onPress={() => setModalVisible(false)}
style={modalStyles.closeButton}

View File

@@ -1,11 +1,11 @@
import { Dispatch, SetStateAction, useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import {
FlatList,
Image,
Text,
TouchableOpacity,
useWindowDimensions,
View,
} from 'react-native';
import LinearGradient from 'react-native-linear-gradient';
import AviaLogo from 'screens/../../assets/bootsplash/Avia.png';
@@ -18,22 +18,14 @@ interface Props {
}
const Tabs = ({ activeTab, setActiveTab }: Props) => {
const { width: screenWidth } = useWindowDimensions();
const { t } = useTranslation();
const scale = useMemo(() => (screenWidth < 360 ? 0.85 : 1), [screenWidth]);
const styles = useMemo(() => HomeStyle(scale), [scale]);
const handleTabPress = useCallback(
(type: 'avia' | 'auto') => {
setActiveTab(type);
},
[setActiveTab],
);
const { width: screenWidth } = useWindowDimensions();
const cardWidth = screenWidth * 0.95;
const styles = useMemo(() => HomeStyle(), []);
const gradientStyle = useMemo(
() => ({
width: '100%' as const,
flex: 1,
borderRadius: 8,
flexDirection: 'row' as const,
alignItems: 'center' as const,
@@ -44,48 +36,75 @@ const Tabs = ({ activeTab, setActiveTab }: Props) => {
[],
);
const renderTabButton = useCallback(
(type: 'avia' | 'auto', label: string, logo: any) => {
const isActive = activeTab === type;
// Tabs data
const tabsData = useMemo(
() => [
{
type: 'avia' as const,
label: t('Avia orqali yetkazish'),
logo: AviaLogo,
},
{
type: 'auto' as const,
label: t('Avto orqali yetkazish'),
logo: AutoLogo,
},
],
[t],
);
const renderItem = useCallback(
({ item }: { item: (typeof tabsData)[number] }) => {
const isActive = activeTab === item.type;
const gradientColors = isActive
? ['#28A7E8', '#28A7E8']
: ['#28a8e82d', '#28A7E8'];
const textStyle = [
styles.tabsText,
{ color: isActive ? '#fff' : '#000' },
];
return (
<TouchableOpacity
onPress={() => handleTabPress(type)}
style={styles.tabs}
key={type}
onPress={() => setActiveTab(item.type)}
style={{ flex: 1 }}
>
<LinearGradient
colors={gradientColors}
start={{ x: 0.5, y: 1 }}
end={{ x: 1.5, y: 1 }}
start={{ x: 0, y: 0 }}
end={{ x: 1, y: 0 }}
style={gradientStyle}
>
<Image source={logo} style={styles.tabsLogo} />
<Text style={textStyle}>{label}</Text>
<Image source={item.logo} style={styles.tabsLogo} />
<Text
style={[styles.tabsText, { color: isActive ? '#fff' : '#000' }]}
>
{item.label}
</Text>
</LinearGradient>
</TouchableOpacity>
);
},
[activeTab, styles, handleTabPress, gradientStyle],
[activeTab, styles, gradientStyle, setActiveTab],
);
const tabButtons = useMemo(
() => [
renderTabButton('avia', t('Avia orqali yetkazish'), AviaLogo),
renderTabButton('auto', t('Avto orqali yetkazish'), AutoLogo),
],
[renderTabButton],
return (
<FlatList
data={tabsData}
numColumns={2}
keyExtractor={(_, idx) => idx.toString()}
renderItem={renderItem}
showsHorizontalScrollIndicator={false}
scrollEnabled={false}
columnWrapperStyle={{
gap: 8,
}}
contentContainerStyle={{
paddingHorizontal: (screenWidth - cardWidth) / 2,
}}
getItemLayout={(_, index) => ({
length: cardWidth,
offset: cardWidth * index,
index,
})}
/>
);
return <View style={styles.tabsContainer}>{tabButtons}</View>;
};
export default Tabs;

View File

@@ -84,7 +84,7 @@ const TabsAuto = () => {
decelerationRate="fast"
contentContainerStyle={{
paddingHorizontal: (screenWidth - cardWidth) / 2,
marginTop: 10,
padding: 10,
}}
renderItem={({ item, index }) => {
const isLast = index === addressList.length - 1;

View File

@@ -85,7 +85,7 @@ const TabsAvia = () => {
decelerationRate="fast"
contentContainerStyle={{
paddingHorizontal: (screenWidth - cardWidth) / 2,
marginTop: 20,
padding: 10,
}}
renderItem={({ item, index }) => {
const isLast = index === addressList.length - 1;
@@ -125,7 +125,7 @@ const makeStyles = (scale: number, cardWidth: number, screenWidth: number) =>
width: '95%',
backgroundColor: '#28a8e82c',
margin: 'auto',
marginTop: 20,
// marginTop: 20,
borderRadius: 12,
padding: 12,
gap: 10,

View File

@@ -1,46 +1,42 @@
import { StyleSheet } from 'react-native';
export const HomeStyle = (scale: number) =>
export const HomeStyle = () =>
StyleSheet.create({
container: {
flex: 1,
},
header: {
backgroundColor: '#28A7E8',
height: 80 * scale,
paddingHorizontal: 10 * scale,
paddingVertical: 10 * scale,
height: 80,
paddingHorizontal: 10,
paddingVertical: 10,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
},
title: {
color: '#fff',
fontSize: 20 * scale,
fontSize: 20,
},
logo: {
flexDirection: 'row',
alignItems: 'center',
gap: 5 * scale,
gap: 5,
},
links: {
flexDirection: 'row',
alignItems: 'center',
gap: 15 * scale,
gap: 15,
},
autoContainer: {
width: '90%',
height: 140 * scale,
borderRadius: 8 * scale,
padding: 10 * scale,
borderRadius: 8,
padding: 8,
backgroundColor: '#FFFFFF',
marginTop: 10,
gap: 8 * scale,
gap: 8,
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 * scale },
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.1,
shadowRadius: 2 * scale,
margin: 'auto',
shadowRadius: 2,
elevation: 2,
},
autoCard: {
@@ -48,33 +44,34 @@ export const HomeStyle = (scale: number) =>
justifyContent: 'space-between',
},
reysTitle: {
fontSize: 20 * scale,
fontSize: 20,
color: '#28A7E8',
fontWeight: '600',
},
text: {
fontWeight: '500',
color: 'red',
fontSize: 14 * scale,
fontSize: 14,
},
box: {
backgroundColor: '#28A7E81A',
padding: 10 * scale,
padding: 10,
width: 'auto',
alignSelf: 'flex-start',
borderRadius: 8 * scale,
borderRadius: 8,
},
date: {
backgroundColor: '#28A7E8',
padding: 6 * scale,
width: '13%',
height: 50,
textAlign: 'center',
justifyContent: 'center',
alignItems: 'center',
borderRadius: 8 * scale,
borderRadius: 8,
padding: 0,
},
dateLabel: {
fontSize: 14 * scale,
fontSize: 14,
fontWeight: '500',
color: '#FFFFFF',
},
@@ -84,23 +81,23 @@ export const HomeStyle = (scale: number) =>
justifyContent: 'space-between',
},
logoIcon: {
width: 50 * scale,
height: 50 * scale,
width: 50,
height: 50,
resizeMode: 'contain',
},
bellWrapper: {
position: 'relative',
},
bellDot: {
width: 10 * scale,
height: 10 * scale,
width: 10,
height: 10,
position: 'absolute',
backgroundColor: 'red',
right: 2 * scale,
right: 2,
borderRadius: 100,
},
divider: {
height: 2 * scale,
height: 2,
width: '100%',
backgroundColor: '#28A7E81F',
},
@@ -111,23 +108,23 @@ export const HomeStyle = (scale: number) =>
infoBlock: {
alignItems: 'center',
flexDirection: 'row',
gap: 6 * scale,
gap: 6,
},
iconBox: {
backgroundColor: '#28A7E81A',
padding: 8 * scale,
borderRadius: 8 * scale,
padding: 8,
borderRadius: 8,
},
infoTextBlock: {
flexDirection: 'column',
},
infoTitle: {
fontWeight: '500',
fontSize: 18 * scale,
fontSize: 18,
},
infoSubtext: {
fontWeight: '500',
fontSize: 14 * scale,
fontSize: 14,
color: '#00000066',
},
subtextRight: {
@@ -136,38 +133,35 @@ export const HomeStyle = (scale: number) =>
highlightBox: {
backgroundColor: '#69ec6d9c',
alignSelf: 'flex-start',
padding: 4 * scale,
borderRadius: 8 * scale,
padding: 4,
borderRadius: 8,
},
highlightText: {
fontSize: 16 * scale,
fontSize: 16,
},
animatedIconWrapper: {
width: '80%',
height: 40,
},
row: {
flexDirection: 'row',
gap: 10 * scale,
width: '100%',
// flexDirection: 'row',
// gap: 10,
// width: '100%',
},
rowFull: {
flexDirection: 'row',
gap: 2 * scale,
width: '100%',
gap: 2,
},
tabs: {
width: '50%',
borderRadius: 8 * scale,
justifyContent: 'space-between',
gap: 10 * scale,
},
tabsContainer: {
marginLeft: 'auto',
paddingLeft: 8 * scale,
paddingRight: 18 * scale,
flexDirection: 'row',
gap: 8 * scale,
borderRadius: 8,
},
// tabsContainer: {
// marginLeft: 'auto',
// paddingLeft: 8,
// paddingRight: 18,
// flexDirection: 'row',
// gap: 8,
// },
tabsLogo: {
width: '40%',
height: '50%',
@@ -176,7 +170,7 @@ export const HomeStyle = (scale: number) =>
tabsText: {
width: '60%',
color: '#FFFFFF',
fontSize: 16 * scale,
fontSize: 14,
fontWeight: '600',
},
});

View File

@@ -1,9 +1,7 @@
import NavbarBack from 'components/NavbarBack';
import Navigation from 'components/Navigation';
import LayoutTwo from 'components/LayoutTwo';
import * as React from 'react';
import { useTranslation } from 'react-i18next';
import { ScrollView, StyleSheet, Text, View } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import Battery from 'svg/Battery';
import Blade from 'svg/Blade';
import Book from 'svg/Book';
@@ -22,13 +20,12 @@ const RestrictedProduct = (props: RestrictedProductProps) => {
const [activeTab, setActiveTab] = React.useState<'avia' | 'auto'>('avia');
const { t } = useTranslation();
return (
<SafeAreaView style={{ flex: 1 }}>
<NavbarBack title={t('Taqiqlangan buyumlar')} />
<LayoutTwo title={t('Taqiqlangan buyumlar')}>
<ScrollView style={{ flex: 1 }}>
<View style={styles.container}>
<Tabs activeTab={activeTab} setActiveTab={setActiveTab} />
{activeTab === 'avia' && (
<View style={{ marginTop: 20, gap: 10, marginBottom: 20 }}>
<View style={{ marginTop: 10, gap: 10, marginBottom: 20 }}>
<Text
style={{
width: '95%',
@@ -179,7 +176,7 @@ const RestrictedProduct = (props: RestrictedProductProps) => {
</View>
)}
{activeTab === 'auto' && (
<View style={{ marginTop: 20, gap: 10, marginBottom: 20 }}>
<View style={{ marginTop: 10, gap: 10, marginBottom: 20 }}>
<View style={styles.cardWhite}>
<View style={styles.priceCard}>
<Text style={styles.titleBlack}>
@@ -273,8 +270,7 @@ const RestrictedProduct = (props: RestrictedProductProps) => {
)}
</View>
</ScrollView>
<Navigation />
</SafeAreaView>
</LayoutTwo>
);
};
@@ -282,7 +278,7 @@ export default RestrictedProduct;
const styles = StyleSheet.create({
container: {
marginTop: 20,
marginTop: 10,
},
card: {
width: '95%',
@@ -294,8 +290,15 @@ const styles = StyleSheet.create({
width: '95%',
gap: 5,
margin: 'auto',
padding: 10,
borderRadius: 8,
paddingVertical: 15,
paddingHorizontal: 12,
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.1,
shadowRadius: 2,
elevation: 1,
},
titleBlack: {
fontSize: 16,

View File

@@ -16,7 +16,6 @@ import {
Text,
TouchableOpacity,
View,
useWindowDimensions,
} from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import PassportIcon from 'svg/Passport';
@@ -26,8 +25,6 @@ import MyPassport from './MyPassport';
const Passport = () => {
const { t } = useTranslation();
const navigation = useNavigation<NativeStackNavigationProp<any>>();
const { width: screenWidth } = useWindowDimensions();
const scale = screenWidth < 360 ? 0.85 : 1;
const [refreshing, setRefreshing] = useState(false);
const {
@@ -105,11 +102,7 @@ const Passport = () => {
{myPassport && myPassport.length === 0 ? (
<View style={styles.content}>
<View style={styles.emptyState}>
<PassportIcon
color="#ccc"
width={80 * scale}
height={80 * scale}
/>
<PassportIcon color="#ccc" width={80} height={80} />
<Text style={styles.emptyText}>
{t("Hali pasport qo'shilmagan")}
</Text>
@@ -127,7 +120,7 @@ const Passport = () => {
onPress={handleNavigateToCreatePassword}
activeOpacity={0.7}
>
<Plus color="#fff" width={24 * scale} height={24 * scale} />
<Plus color="#fff" width={24} height={24} />
<Text style={styles.addButtonText}>
{t("Yangi pasport qo'shish")}
</Text>

View File

@@ -2,6 +2,7 @@ import { PacketsData } from 'api/packets';
import React from 'react';
import { useTranslation } from 'react-i18next';
import {
FlatList,
StyleSheet,
Text,
TouchableOpacity,
@@ -11,11 +12,7 @@ import {
import CloseIcon from 'svg/Close';
import FilterIcon from 'svg/Filter';
const transportTypes = [
// 'all',
'AUTO',
'AVIA',
] as const;
const transportTypes = ['AUTO', 'AVIA'] as const;
type TransportType = (typeof transportTypes)[number];
interface Props {
@@ -38,9 +35,8 @@ const Filter = ({
const [open, setOpen] = React.useState(false);
const { width: screenWidth } = useWindowDimensions();
const { t } = useTranslation();
const scale = screenWidth < 360 ? 0.85 : 1;
const styles = makeStyles(scale);
const styles = makeStyles();
const newOrders = React.useMemo(
() => data.data.filter(item => item.paymentStatus === 'NEW'),
[data],
@@ -48,32 +44,35 @@ const Filter = ({
return (
<View style={styles.container}>
{/* Tugma */}
<TouchableOpacity
style={styles.card}
onPress={() => setOpen(prev => !prev)}
>
<FilterIcon color="#000000" width={18 * scale} height={18 * scale} />
<FilterIcon color="#000000" width={18} height={18} />
<Text style={styles.text}>{t('Filter')}</Text>
</TouchableOpacity>
{open && (
<View style={styles.dropdown}>
<View
style={{
flexDirection: 'row',
justifyContent: 'space-between',
marginBottom: 10,
}}
>
{/* Header */}
<View style={styles.dropdownHeader}>
<Text style={styles.sectionTitle}>{t('Transport')}</Text>
<TouchableOpacity onPress={() => setOpen(false)}>
<CloseIcon />
</TouchableOpacity>
</View>
<View style={styles.typeList}>
{transportTypes.map(type => (
{/* Transport Types -> FlatList */}
<FlatList
data={transportTypes}
keyExtractor={item => item}
numColumns={2}
scrollEnabled={false}
columnWrapperStyle={{ gap: 8 }}
contentContainerStyle={{ gap: 8, marginBottom: 12 }}
renderItem={({ item: type }) => (
<TouchableOpacity
key={type}
style={[
styles.typeButton,
selectedType === type && styles.activeType,
@@ -89,48 +88,28 @@ const Filter = ({
selectedType === type && styles.activeTypeText,
]}
>
{
// type === 'all'
// ? t('Barchasi')
// :
type === 'AUTO' ? t('Avto') : t('Avia')
}
{type === 'AUTO' ? t('Avto') : t('Avia')}
</Text>
</TouchableOpacity>
))}
</View>
)}
/>
<Text style={styles.sectionTitle}>{t('Reys raqami')}</Text>
<View style={styles.flightList}>
<TouchableOpacity
style={[
styles.flightButton,
selectedFlight === 'all' && styles.activeFlight,
]}
onPress={() => {
setReys('all');
setSelectedData(null);
setOpen(false);
}}
>
<Text
style={[
styles.flightText,
selectedFlight === 'all' && styles.activeFlightText,
]}
>
{t('Barchasi')}
</Text>
</TouchableOpacity>
{newOrders.map(item => (
<FlatList
data={[{ id: 'all', packetName: 'all' }, ...newOrders]}
keyExtractor={item => item.id?.toString() || 'all'}
numColumns={1}
scrollEnabled={false}
contentContainerStyle={{ gap: 8 }} // faqat shu kifoya
renderItem={({ item }) => (
<TouchableOpacity
key={item.id}
style={[
styles.flightButton,
selectedFlight === item.packetName && styles.activeFlight,
]}
onPress={() => {
setReys(item.packetName);
setSelectedData(item);
setSelectedData(item.id === 'all' ? null : item);
setOpen(false);
}}
>
@@ -141,75 +120,73 @@ const Filter = ({
styles.activeFlightText,
]}
>
{item.packetName}
{item.packetName === 'all' ? t('Barchasi') : item.packetName}
</Text>
</TouchableOpacity>
))}
</View>
)}
/>
</View>
)}
</View>
);
};
const makeStyles = (scale: number) =>
const makeStyles = () =>
StyleSheet.create({
container: {
height: 'auto',
borderRadius: 8 * scale,
borderRadius: 8,
alignItems: 'flex-end',
justifyContent: 'flex-start',
position: 'relative',
zIndex: 10,
},
card: {
paddingHorizontal: 12 * scale,
height: 40 * scale,
paddingHorizontal: 12,
height: 40,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#D8DADC',
borderRadius: 8 * scale,
borderRadius: 8,
flexDirection: 'row',
gap: 4 * scale,
gap: 4,
},
text: {
color: '#000000',
fontWeight: '500',
fontSize: 14 * scale,
fontSize: 14,
},
dropdown: {
position: 'absolute',
top: 50 * scale,
top: 50,
right: 0,
backgroundColor: '#fff',
borderRadius: 8 * scale,
paddingVertical: 8 * scale,
paddingHorizontal: 10 * scale,
borderRadius: 8,
paddingVertical: 8,
paddingHorizontal: 10,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.2,
shadowRadius: 4,
elevation: 5,
zIndex: 10,
minWidth: 200 * scale,
minWidth: 200,
},
dropdownHeader: {
flexDirection: 'row',
justifyContent: 'space-between',
marginBottom: 10,
},
sectionTitle: {
fontWeight: '600',
marginBottom: 6 * scale,
marginBottom: 6,
color: '#333',
fontSize: 16 * scale,
},
typeList: {
flexDirection: 'row',
flexWrap: 'wrap',
gap: 8 * scale,
marginBottom: 12 * scale,
fontSize: 16,
},
typeButton: {
flex: 1,
backgroundColor: '#F3FAFF',
paddingHorizontal: 5 * scale,
paddingVertical: 6 * scale,
borderRadius: 6 * scale,
paddingHorizontal: 5,
paddingVertical: 6,
borderRadius: 6,
},
activeType: {
backgroundColor: '#28A7E8',
@@ -217,22 +194,18 @@ const makeStyles = (scale: number) =>
typeText: {
color: '#28A7E8',
fontWeight: '500',
fontSize: 14 * scale,
fontSize: 14,
textAlign: 'center',
},
activeTypeText: {
color: '#fff',
},
flightList: {
flexDirection: 'row',
flexWrap: 'wrap',
gap: 8 * scale,
marginBottom: 12 * scale,
},
flightButton: {
flex: 1,
backgroundColor: '#F3FAFF',
paddingHorizontal: 10 * scale,
paddingVertical: 6 * scale,
borderRadius: 6 * scale,
paddingHorizontal: 10,
paddingVertical: 6,
borderRadius: 6,
},
activeFlight: {
backgroundColor: '#28A7E8',
@@ -240,7 +213,8 @@ const makeStyles = (scale: number) =>
flightText: {
color: '#28A7E8',
fontWeight: '500',
fontSize: 14 * scale,
fontSize: 14,
textAlign: 'center',
},
activeFlightText: {
color: '#fff',

View File

@@ -2,11 +2,11 @@ import { PacketsData } from 'api/packets';
import React, { useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import {
FlatList,
StyleSheet,
Text,
TouchableOpacity,
View,
useWindowDimensions,
} from 'react-native';
import Auto from 'svg/Auto';
import Avia from 'svg/Avia';
@@ -53,44 +53,39 @@ interface Props {
}
const Order = ({ data, openModal, selectedData }: Props) => {
const { width: screenWidth } = useWindowDimensions();
const scale = useMemo(() => (screenWidth < 360 ? 0.85 : 1), [screenWidth]);
const { t } = useTranslation();
const styles = useMemo(
() => makeStyles(scale, screenWidth),
[scale, screenWidth],
);
const styles = useMemo(() => makeStyles(), []);
const createIcons = useCallback(
(scale: number, cargo: string) => [
(cargo: string) => [
{
status: 'COLLECTING',
icon: <BoxIcon width={20 * scale} height={20 * scale} color="" />,
icon: <BoxIcon width={24} height={24} color="" />,
},
{
status: 'ON_THE_WAY',
icon:
cargo === 'avia' ? (
<Avia width={20 * scale} height={20 * scale} color="" />
<Avia width={24} height={24} color="" />
) : (
<Auto width={20 * scale} height={20 * scale} color="" view="-4" />
<Auto width={24} height={24} color="" view="-4" />
),
},
{
status: 'IN_CUSTOMS',
icon: <BagIcon width={20 * scale} height={20 * scale} color="" />,
icon: <BagIcon width={24} height={24} color="" />,
},
{
status: 'IN_WAREHOUSE',
icon: <Store width={20 * scale} height={20 * scale} color="" />,
icon: <Store width={24} height={24} color="" />,
},
{
status: 'DELIVERED',
icon: <TrunkIcon width={20 * scale} height={20 * scale} color="" />,
icon: <TrunkIcon width={24} height={24} color="" />,
},
{
status: 'PAID',
icon: <SuccessIcon width={20 * scale} height={20 * scale} color="" />,
icon: <SuccessIcon width={24} height={24} color="" />,
},
],
[],
@@ -104,31 +99,31 @@ const Order = ({ data, openModal, selectedData }: Props) => {
);
const renderOrderItem = useCallback(
(ItemLayout: DataInfo, index: number) => {
({ item, index }: { item: DataInfo; index: number }) => {
const currentStatusIndex = statuses.indexOf(
ItemLayout.deliveryStatus as FilterType,
item.deliveryStatus as FilterType,
);
const icons = createIcons(scale, ItemLayout.deliveryStatus);
const icons = createIcons(item.deliveryStatus);
return (
<TouchableOpacity
key={index}
onPress={() => handleItemPress(ItemLayout)}
>
<TouchableOpacity key={index} onPress={() => handleItemPress(item)}>
<View style={styles.card}>
<View style={styles.statusCard}>
{icons.map((item, i) => {
<FlatList
data={icons}
keyExtractor={(iconItem, i) => iconItem.status + i}
numColumns={6}
contentContainerStyle={styles.statusCard}
renderItem={({ item: iconItem, index: i }) => {
const iconColor = i <= currentStatusIndex ? '#28A7E8' : '#000';
const viewColor =
i <= currentStatusIndex ? '#28A7E81A' : '#0000001A';
return (
<React.Fragment key={item.status}>
<View style={styles.iconWrapper}>
<View
style={[styles.circle, { backgroundColor: viewColor }]}
>
{React.cloneElement(item.icon, { color: iconColor })}
{React.cloneElement(iconItem.icon, { color: iconColor })}
</View>
{i !== icons.length - 1 && (
<View
@@ -138,186 +133,159 @@ const Order = ({ data, openModal, selectedData }: Props) => {
]}
/>
)}
</React.Fragment>
</View>
);
})}
</View>
}}
/>
{/* Status Label */}
<View
style={[
styles.statusLabelWrapper,
{
backgroundColor: `${
statusColorMap[ItemLayout.deliveryStatus]
}1A`,
backgroundColor: `${statusColorMap[item.deliveryStatus]}1A`,
},
]}
>
<Text
style={[
styles.statusText,
{ color: statusColorMap[ItemLayout.deliveryStatus] },
{ color: statusColorMap[item.deliveryStatus] },
]}
>
{t(
tabList.find(item => item.value === ItemLayout.deliveryStatus)
tabList.find(tab => tab.value === item.deliveryStatus)
?.label || '',
)}
</Text>
</View>
{/* Info */}
<View style={styles.infoCard}>
<Text style={styles.infoTitle}>{t('Reys raqami')}</Text>
<Text
style={[styles.infoText, { width: '50%', textAlign: 'right' }]}
>
{ItemLayout.packetName}
{item.packetName}
</Text>
</View>
<View style={styles.infoCard}>
<Text style={styles.infoTitle}>{t('Mahsulotlar ogirligi')}</Text>
<Text style={styles.infoText}>{ItemLayout.weight}</Text>
<Text style={styles.infoText}>{item.weight}</Text>
</View>
<View style={styles.infoCard}>
<Text style={styles.infoTitle}>{t('Umumiy narxi')}</Text>
<Text style={styles.infoText}>{ItemLayout.totalPrice}</Text>
<Text style={styles.infoText}>{item.totalPrice}</Text>
</View>
</View>
</TouchableOpacity>
);
},
[scale, createIcons, handleItemPress],
[createIcons, handleItemPress],
);
const orderItems = useMemo(() => {
if (selectedData) {
return [renderOrderItem(selectedData, 0)];
}
return data.data.map(renderOrderItem);
}, [data, renderOrderItem, selectedData]);
const countSection = useMemo(
() => (
<View style={styles.count}>
<Text style={styles.title}>{t('Buyurtmalar soni')}</Text>
{selectedData ? (
<Text style={styles.title}>1</Text>
) : (
<Text style={styles.title}>{data.data.length}</Text>
)}
</View>
),
[styles.count, styles.title, data.data.length, selectedData],
const ordersData = useMemo(
() => (selectedData ? [selectedData] : data.data),
[data, selectedData],
);
return (
<View style={styles.container}>
{countSection}
{orderItems}
<View style={styles.count}>
<Text style={styles.title}>{t('Buyurtmalar soni')}</Text>
<Text style={styles.title}>
{selectedData ? '1' : data.data.length}
</Text>
</View>
<FlatList
data={ordersData}
scrollEnabled={false}
renderItem={renderOrderItem}
keyExtractor={(item, index) => item.id?.toString() || index.toString()}
/>
</View>
);
};
const makeStyles = (scale: number, screenWidth: number) =>
const makeStyles = () =>
StyleSheet.create({
container: {
width: screenWidth * 0.95,
marginTop: 10,
alignSelf: 'center',
borderRadius: 8 * scale,
padding: 8 * scale,
backgroundColor: '#F5F5F5',
width: '95%',
margin: 'auto',
borderRadius: 10,
},
count: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
marginTop: 10,
},
title: {
fontSize: 16 * scale,
fontSize: 16,
fontWeight: '500',
color: '#333',
},
card: {
backgroundColor: '#FFFFFF',
marginTop: 12 * scale,
padding: 15 * scale,
borderRadius: 10 * scale,
gap: 5 * scale,
flexDirection: 'column',
backgroundColor: '#fff',
margin: 1,
marginTop: 8,
padding: 15,
borderRadius: 10,
// iOS
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.2,
shadowRadius: 2,
// Android
elevation: 2,
},
statusCard: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
marginBottom: 10 * scale,
marginBottom: 10,
},
circle: {
padding: 8 * scale,
padding: 8,
borderRadius: 50,
alignItems: 'center',
justifyContent: 'center',
},
divider: {
width: 20 * scale,
borderBottomWidth: 2 * scale,
width: 20,
borderBottomWidth: 2,
borderStyle: 'dashed',
},
statusLabelWrapper: {
borderRadius: 8 * scale,
borderRadius: 8,
alignSelf: 'flex-start',
paddingVertical: 6 * scale,
paddingHorizontal: 10 * scale,
marginBottom: 12 * scale,
paddingVertical: 6,
paddingHorizontal: 10,
marginBottom: 12,
},
statusText: {
fontWeight: '600',
fontSize: 16 * scale,
fontSize: 16,
},
infoCard: {
flexDirection: 'row',
justifyContent: 'space-between',
marginBottom: 6 * scale,
marginBottom: 6,
},
iconWrapper: {
flexDirection: 'row',
alignItems: 'center',
flex: 1,
marginBottom: 10,
},
infoTitle: {
fontSize: 16 * scale,
fontSize: 16,
color: '#979797',
fontWeight: '500',
},
infoText: {
fontSize: 14 * scale,
fontSize: 14,
color: '#28A7E8',
fontWeight: '500',
},
modalOverlay: {
flex: 1,
backgroundColor: 'rgba(0,0,0,0.4)',
justifyContent: 'center',
alignItems: 'center',
zIndex: 20,
},
modalContent: {
width: '90%',
maxHeight: '80%',
backgroundColor: '#fff',
borderRadius: 10,
padding: 20,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.3,
shadowRadius: 4,
elevation: 5,
},
modalTitle: {
fontSize: 20 * scale,
fontWeight: '600',
marginBottom: 10,
},
closeButton: {
marginTop: 20,
backgroundColor: '#28A7E8',
paddingVertical: 10,
borderRadius: 8,
alignItems: 'center',
},
});
export default Order;

View File

@@ -1,8 +1,7 @@
import { useQuery } from '@tanstack/react-query';
import packetsApi from 'api/packets';
import Layout from 'components/Layout';
import LoadingScreen from 'components/LoadingScreen';
import Navbar from 'components/Navbar';
import Navigation from 'components/Navigation';
import NoResult from 'components/NoResult';
import Pagination from 'components/Pagination';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
@@ -15,7 +14,6 @@ import {
View,
useWindowDimensions,
} from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import Serach from 'svg/Serach';
import { DataInfo } from '../lib/data';
import Filter from './Filter';
@@ -140,61 +138,43 @@ const Status = () => {
if (isLoading || isFetching) {
return (
<SafeAreaView style={{ flex: 1 }}>
<View style={styles.container}>
<Navbar />
<LoadingScreen message={loadingMessage} progress={progress} />
<Navigation />
</View>
</SafeAreaView>
<Layout>
<LoadingScreen message={loadingMessage} progress={progress} />
</Layout>
);
}
if (statusData?.data.length === 0) {
return (
<SafeAreaView style={{ flex: 1 }}>
<View style={styles.container}>
<Navbar />
<Tabs filter={filter} setFilter={setFilter} />
<View style={styles.controls}>
{/* <View style={styles.searchContainer}>
<TextInput
placeholder={t('ID orqali izlash')}
placeholderTextColor="#D8DADC"
style={styles.search}
/>
<View style={styles.searchIcon}>{searchIcon}</View>
</View> */}
<View style={{ position: 'relative' }}>
<Filter
transportTypes={transportTypes}
setTransportTypes={setTransportTypes}
reys={reys}
setReys={setReys}
data={statusData!}
setSelectedData={setSelectedData}
/>
</View>
<Layout>
<Tabs filter={filter} setFilter={setFilter} />
<View style={styles.controls}>
<View style={{ position: 'relative' }}>
<Filter
transportTypes={transportTypes}
setTransportTypes={setTransportTypes}
reys={reys}
setReys={setReys}
data={statusData!}
setSelectedData={setSelectedData}
/>
</View>
<NoResult message={t("Hech qanday ma'lumot topilmadi")} />
<Navigation />
</View>
</SafeAreaView>
<NoResult message={t("Hech qanday ma'lumot topilmadi")} />
</Layout>
);
}
return (
<SafeAreaView style={{ flex: 1 }}>
<View style={styles.container}>
<Navbar />
<ScrollView
keyboardShouldPersistTaps="handled"
refreshControl={refreshControl}
removeClippedSubviews={true}
>
<Tabs filter={filter} setFilter={setFilter} />
<View style={styles.controls}>
{/* <View style={styles.searchContainer}>
<Layout>
<ScrollView
keyboardShouldPersistTaps="handled"
refreshControl={refreshControl}
removeClippedSubviews={true}
>
<Tabs filter={filter} setFilter={setFilter} />
<View style={styles.controls}>
{/* <View style={styles.searchContainer}>
<TextInput
placeholder={t('ID orqali izlash')}
placeholderTextColor="#D8DADC"
@@ -202,47 +182,45 @@ const Status = () => {
/>
<View style={styles.searchIcon}>{searchIcon}</View>
</View> */}
<View style={{ position: 'relative' }}>
<Filter
transportTypes={transportTypes}
setTransportTypes={setTransportTypes}
reys={reys}
setReys={setReys}
data={statusData!}
setSelectedData={setSelectedData}
/>
</View>
<View style={{ position: 'relative' }}>
<Filter
transportTypes={transportTypes}
setTransportTypes={setTransportTypes}
reys={reys}
setReys={setReys}
data={statusData!}
setSelectedData={setSelectedData}
/>
</View>
<Order
data={statusData!}
openModal={openModal}
selectedData={selectedData}
/>
</ScrollView>
<OrderDetailModal
visible={modalVisible}
setVisible={setModalVisible}
selectedOrder={selectedOrder}
/>
<View
style={{
flexDirection: 'row',
justifyContent: 'flex-end',
width: '95%',
alignSelf: 'center',
paddingRight: 20,
paddingVertical: 10,
}}
>
<Pagination
page={page}
totalPages={statusData?.totalPages ?? 1}
setPage={setPage}
/>
</View>
<Navigation />
<Order
data={statusData!}
openModal={openModal}
selectedData={selectedData}
/>
</ScrollView>
<OrderDetailModal
visible={modalVisible}
setVisible={setModalVisible}
selectedOrder={selectedOrder}
/>
<View
style={{
flexDirection: 'row',
justifyContent: 'flex-end',
width: '95%',
alignSelf: 'center',
paddingRight: 20,
paddingVertical: 10,
}}
>
<Pagination
page={page}
totalPages={statusData?.totalPages ?? 1}
setPage={setPage}
/>
</View>
</SafeAreaView>
</Layout>
);
};

View File

@@ -1,9 +1,9 @@
import React, { Dispatch, SetStateAction, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import {
FlatList,
NativeScrollEvent,
NativeSyntheticEvent,
ScrollView,
StyleSheet,
Text,
TouchableOpacity,
@@ -32,31 +32,29 @@ const tabList: { label: string; value: FilterType }[] = [
{ label: 'Bojxonada', value: 'IN_CUSTOMS' },
{ label: 'Toshkent omboriga yetib keldi', value: 'IN_WAREHOUSE' },
{ label: 'Topshirish punktiga yuborildi', value: 'DELIVERED' },
// { label: 'Qabul qilingan', value: 'DELIVERED' },
];
const Tabs = ({ filter, setFilter }: Props) => {
const { width: screenWidth } = useWindowDimensions();
const scale = screenWidth < 360 ? 0.85 : 1;
const styles = makeStyles(scale);
const scrollRef = useRef<ScrollView>(null);
const cardWidth = screenWidth * 0.95;
const styles = makeStyles();
const flatListRef = useRef<FlatList>(null);
const [scrollX, setScrollX] = useState(0);
const { t } = useTranslation();
const scrollStep = 120;
const handleScrollLeft = () => {
if (scrollRef.current) {
scrollRef.current.scrollTo({
x: Math.max(0, scrollX - scrollStep),
animated: true,
});
}
flatListRef.current?.scrollToOffset({
offset: Math.max(0, scrollX - scrollStep),
animated: true,
});
};
const handleScrollRight = () => {
if (scrollRef.current) {
scrollRef.current.scrollTo({ x: scrollX + scrollStep, animated: true });
}
flatListRef.current?.scrollToOffset({
offset: scrollX + scrollStep,
animated: true,
});
};
const onScroll = (event: NativeSyntheticEvent<NativeScrollEvent>) => {
@@ -69,27 +67,27 @@ const Tabs = ({ filter, setFilter }: Props) => {
<ArrowLeft color="#28A7E8" width={20} height={20} />
</TouchableOpacity>
<ScrollView
<FlatList
ref={flatListRef}
horizontal
onScroll={onScroll}
ref={scrollRef}
data={tabList}
keyExtractor={item => item.value}
showsHorizontalScrollIndicator={false}
contentContainerStyle={styles.scrollContent}
>
{tabList.map(tab => (
onScroll={onScroll}
renderItem={({ item }) => (
<TouchableOpacity
key={tab.value}
style={[styles.card, filter === tab.value && styles.activeCard]}
onPress={() => setFilter(tab.value)}
style={[styles.card, filter === item.value && styles.activeCard]}
onPress={() => setFilter(item.value)}
>
<Text
style={[styles.text, filter === tab.value && styles.activeText]}
style={[styles.text, filter === item.value && styles.activeText]}
>
{t(tab.label)}
{t(item.label)}
</Text>
</TouchableOpacity>
))}
</ScrollView>
)}
contentContainerStyle={styles.scrollContent}
/>
<TouchableOpacity style={styles.navButton} onPress={handleScrollRight}>
<ArrowRightUnderline color="#28A7E8" width={20} height={20} />
@@ -98,32 +96,38 @@ const Tabs = ({ filter, setFilter }: Props) => {
);
};
const makeStyles = (scale: number) =>
const makeStyles = () =>
StyleSheet.create({
container: {
flexDirection: 'row',
alignItems: 'center',
width: '95%',
height: 50 * scale,
height: 50,
backgroundColor: '#FFFFFF',
marginTop: 20 * scale,
marginTop: 10,
alignSelf: 'center',
borderRadius: 8 * scale,
paddingHorizontal: 4 * scale,
borderRadius: 8,
paddingHorizontal: 4,
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.1,
shadowRadius: 2,
elevation: 1,
},
scrollContent: {
flexDirection: 'row',
alignItems: 'center',
paddingHorizontal: 4 * scale,
paddingHorizontal: 4,
},
card: {
paddingHorizontal: 12 * scale,
paddingVertical: 8 * scale,
paddingHorizontal: 12,
paddingVertical: 8,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#F3FAFF',
marginRight: 8 * scale,
borderRadius: 8 * scale,
marginRight: 8,
borderRadius: 8,
},
activeCard: {
backgroundColor: '#28A7E8',
@@ -131,13 +135,13 @@ const makeStyles = (scale: number) =>
text: {
color: '#28A7E8',
fontWeight: '500',
fontSize: 14 * scale,
fontSize: 14,
},
activeText: {
color: '#fff',
},
navButton: {
padding: 6 * scale,
padding: 6,
},
});