281 lines
7.3 KiB
TypeScript
281 lines
7.3 KiB
TypeScript
import { useQuery } from '@tanstack/react-query';
|
|
import packetsApi from 'api/packets';
|
|
import Layout from 'components/Layout';
|
|
import LoadingScreen from 'components/LoadingScreen';
|
|
import NoResult from 'components/NoResult';
|
|
import Pagination from 'components/Pagination';
|
|
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|
import { useTranslation } from 'react-i18next';
|
|
import {
|
|
Animated,
|
|
RefreshControl,
|
|
ScrollView,
|
|
StyleSheet,
|
|
View,
|
|
useWindowDimensions,
|
|
} from 'react-native';
|
|
import { DataInfo } from '../lib/data';
|
|
import Filter from './Filter';
|
|
import Order from './Order';
|
|
import OrderDetailModal from './OrderDetailModal';
|
|
|
|
const Status = () => {
|
|
const { width: screenWidth } = useWindowDimensions();
|
|
const scale = screenWidth < 360 ? 0.85 : 1;
|
|
const [paymentStatus, setPaymentStatus] = useState('NEW');
|
|
|
|
const [filter, setFilter] = useState<
|
|
| 'COLLECTING'
|
|
| 'ON_THE_WAY'
|
|
| 'IN_CUSTOMS'
|
|
| 'IN_WAREHOUSE'
|
|
| 'DELIVERED'
|
|
| 'PAID'
|
|
>('COLLECTING');
|
|
|
|
const [selectedOrder, setSelectedOrder] = useState<DataInfo | null>(null);
|
|
const [transportTypes, setTransportTypes] = useState<
|
|
// 'all'|
|
|
'AUTO' | 'AVIA'
|
|
>('AVIA');
|
|
const [page, setPage] = useState(0);
|
|
const {
|
|
data: statusData,
|
|
refetch,
|
|
isLoading,
|
|
isFetching,
|
|
} = useQuery({
|
|
queryKey: ['status', transportTypes, page, paymentStatus],
|
|
queryFn: () =>
|
|
packetsApi.getPackets({
|
|
page,
|
|
size: 10,
|
|
cargoType: transportTypes,
|
|
sort: 'id',
|
|
direction: 'DESC',
|
|
}),
|
|
});
|
|
|
|
const [modalVisible, setModalVisible] = useState(false);
|
|
const scaleAnim = React.useRef(new Animated.Value(0.8)).current;
|
|
const opacityAnim = React.useRef(new Animated.Value(0)).current;
|
|
|
|
const styles = useMemo(() => makeStyles(scale), [scale]);
|
|
|
|
const [loadingMessage, setLoadingMessage] = useState(
|
|
"Ma'lumotlar yuklanmoqda...",
|
|
);
|
|
const [progress, setProgress] = useState(0);
|
|
const [isDataLoaded, setIsDataLoaded] = useState(false);
|
|
|
|
useEffect(() => {
|
|
if (!isDataLoaded) {
|
|
const start = Date.now();
|
|
const duration = 1000;
|
|
|
|
const interval = setInterval(() => {
|
|
const elapsed = Date.now() - start;
|
|
const progressValue = Math.min(elapsed / duration, 1);
|
|
setProgress(progressValue);
|
|
if (progressValue >= 1) clearInterval(interval);
|
|
}, 100);
|
|
|
|
setTimeout(() => setIsDataLoaded(true), duration);
|
|
}
|
|
}, [isDataLoaded]);
|
|
|
|
useEffect(() => {
|
|
if (modalVisible) {
|
|
scaleAnim.setValue(0.8);
|
|
opacityAnim.setValue(0);
|
|
Animated.parallel([
|
|
Animated.timing(scaleAnim, {
|
|
toValue: 1,
|
|
duration: 300,
|
|
useNativeDriver: true,
|
|
}),
|
|
Animated.timing(opacityAnim, {
|
|
toValue: 1,
|
|
duration: 300,
|
|
useNativeDriver: true,
|
|
}),
|
|
]).start();
|
|
}
|
|
}, [modalVisible, scaleAnim, opacityAnim]);
|
|
|
|
const openModal = useCallback((item: DataInfo) => {
|
|
setSelectedOrder(item);
|
|
setModalVisible(true);
|
|
}, []);
|
|
|
|
const [refreshing, setRefreshing] = useState(false);
|
|
const [reys, setReys] = useState<string>('all');
|
|
const [selectedData, setSelectedData] = useState<DataInfo | null>(null);
|
|
|
|
const { t } = useTranslation();
|
|
const onRefresh = useCallback(async () => {
|
|
setRefreshing(true);
|
|
try {
|
|
await refetch();
|
|
} finally {
|
|
setRefreshing(false);
|
|
}
|
|
}, [refetch]);
|
|
|
|
const refreshControl = useMemo(
|
|
() => (
|
|
<RefreshControl
|
|
refreshing={refreshing || isFetching}
|
|
onRefresh={onRefresh}
|
|
/>
|
|
),
|
|
[refreshing, isFetching, onRefresh],
|
|
);
|
|
|
|
if (isLoading || isFetching) {
|
|
return (
|
|
<Layout>
|
|
<LoadingScreen message={loadingMessage} progress={progress} />
|
|
</Layout>
|
|
);
|
|
}
|
|
|
|
if (statusData?.data.length === 0 || statusData === undefined) {
|
|
return (
|
|
<Layout>
|
|
{/* <Tabs filter={filter} setFilter={setFilter} /> */}
|
|
<View style={styles.controls}>
|
|
<View
|
|
style={{
|
|
position: 'relative',
|
|
flexDirection: 'row',
|
|
gap: 8,
|
|
}}
|
|
>
|
|
<Filter
|
|
transportTypes={transportTypes}
|
|
setTransportTypes={setTransportTypes}
|
|
reys={reys}
|
|
setReys={setReys}
|
|
data={statusData}
|
|
setSelectedData={setSelectedData}
|
|
/>
|
|
{/* <PaymentFilter
|
|
paymentStatus={paymentStatus}
|
|
setPaymentStatus={setPaymentStatus}
|
|
/> */}
|
|
</View>
|
|
</View>
|
|
<NoResult message={t("Hech qanday ma'lumot topilmadi")} />
|
|
</Layout>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<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"
|
|
style={styles.search}
|
|
/>
|
|
<View style={styles.searchIcon}>{searchIcon}</View>
|
|
</View> */}
|
|
<View
|
|
style={{
|
|
position: 'relative',
|
|
flexDirection: 'row',
|
|
gap: 8,
|
|
}}
|
|
>
|
|
<Filter
|
|
transportTypes={transportTypes}
|
|
setTransportTypes={setTransportTypes}
|
|
reys={reys}
|
|
setReys={setReys}
|
|
data={statusData!}
|
|
setSelectedData={setSelectedData}
|
|
/>
|
|
{/* <PaymentFilter
|
|
paymentStatus={paymentStatus}
|
|
setPaymentStatus={setPaymentStatus}
|
|
/> */}
|
|
</View>
|
|
</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>
|
|
</Layout>
|
|
);
|
|
};
|
|
|
|
const makeStyles = (scale: number) =>
|
|
StyleSheet.create({
|
|
container: {
|
|
flex: 1,
|
|
},
|
|
controls: {
|
|
marginTop: 10,
|
|
paddingHorizontal: 10 * scale,
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
justifyContent: 'flex-end',
|
|
},
|
|
searchContainer: {
|
|
flex: 1,
|
|
marginRight: 8 * scale,
|
|
position: 'relative',
|
|
},
|
|
search: {
|
|
width: '100%',
|
|
height: 40 * scale,
|
|
borderColor: '#D8DADC',
|
|
borderWidth: 1,
|
|
borderRadius: 8 * scale,
|
|
paddingLeft: 40 * scale,
|
|
paddingRight: 10 * scale,
|
|
color: '#000',
|
|
fontSize: 14 * scale,
|
|
},
|
|
searchIcon: {
|
|
position: 'absolute',
|
|
left: 15 * scale,
|
|
top: '50%',
|
|
transform: [{ translateY: -12 * scale }],
|
|
zIndex: 1,
|
|
},
|
|
});
|
|
|
|
export default Status;
|