ebanutsya

This commit is contained in:
2023-11-06 07:23:11 +03:00
parent 2a4479faac
commit f015090143
18 changed files with 400 additions and 108 deletions

View File

@@ -14,6 +14,8 @@
"dependencies": {
"@expo/webpack-config": "^19.0.0",
"@gorhom/bottom-sheet": "^4",
"@react-native-community/datetimepicker": "7.2.0",
"@react-native-picker/picker": "^2.5.1",
"@react-navigation/bottom-tabs": "^6.5.8",
"@react-navigation/native": "^6.1.7",
"@reduxjs/toolkit": "^1.9.5",

View File

@@ -16,7 +16,6 @@ export default function App() {
})
if (!fontsLoading)
return <View><Text>Loading...</Text></View>
return (
<Provider store={store}>
<GestureHandlerRootView style={{flex: 1}}>

View File

@@ -4,8 +4,16 @@ import {Order} from "../types/order";
const router = '/orders';
const ordersApi = {
getOrders: async (lastId: number) => {
getOrders: async (page: number, orderBy: string, desc: boolean, shipmentDate: string, status: number): Promise<Order[]> => {
const params = {
page: page,
orderBy: orderBy,
desc: Number(desc), // Преобразование boolean в Number (0 или 1)
status: status,
shipmentDate: shipmentDate
};
let response = await apiClient.get(`${router}/getOrders`, {params})
return response.data;
},
getOrdersBySupplierProduct: async (supplierProductId: number): Promise<Order[]> => {
let response = await apiClient.get(`${router}/getBySupplierProductId?supplierProductId=${supplierProductId}`);

View File

@@ -21,6 +21,7 @@ const ReprintModal: FC = () => {
dispatch(closeReprintModal());
dispatch(openLoadingModal());
PrintingApi.getLabel(order.databaseId).then(pdfBytes => {
PrintingService.getInstance().printPdf(printerName, pdfBytes).then(r => {
dispatch(closeLoadingModal());
if (r) dispatch(closeReprintModal());

View File

@@ -3,11 +3,22 @@ import {BottomSheetModal} from "@gorhom/bottom-sheet";
import {disableDim, enableDim} from "../../../features/interface/interfaceSlice";
import {StyleSheet, View} from "react-native";
import BasicButton from "../../BasicButton/BasicButton";
import {useDispatch} from "react-redux";
import {useDispatch, useSelector} from "react-redux";
import {RFPercentage} from "react-native-responsive-fontsize";
import RadioGroup from 'react-native-radio-buttons-group';
import {responsiveHeight, responsiveWidth} from "react-native-responsive-dimensions";
import {blue} from "../../../css/colors";
import {Picker} from "@react-native-picker/picker";
import DateTimePicker from '@react-native-community/datetimepicker';
import {RootState} from "../../../redux/store";
import {
closeOrdersFilterModal,
OrderStatus,
orderStatuses,
setDesc,
setOrderBy, setShipmentDate, setStatus
} from "../../../features/ordersFilter/ordersFilterSlice";
import {retry} from "@reduxjs/toolkit/query";
export type SortingModalHandles = {
present: () => void;
@@ -19,12 +30,7 @@ export type SortingModalElement = {
label: string;
value: string;
}
type Props = {
onChange: (sortingValue: string) => void;
onClose: () => void;
elements: SortingModalElement[];
defaultElementId?: string;
};
const createRadioButton = (element: SortingModalElement) => {
return {
@@ -41,55 +47,101 @@ const createRadioButton = (element: SortingModalElement) => {
};
}
const SortingModal = forwardRef<SortingModalHandles, Props>((props: Props, ref) => {
const {elements, onChange, onClose, defaultElementId = ""} = props;
const snapPoints = useMemo(() => ['40%', '40%'], []);
const SortingModal = () => {
const state = useSelector((state: RootState) => state.ordersFilter);
const elements = [
{id: 'createdOnAsc', value: 'createdOnAsc', label: 'Дата создания по возрастанию'},
{id: 'createdOnDesc', value: 'createdOnDesc', label: 'Дата создания по убыванию'},
{id: 'shipmentDateAsc', value: 'shipmentDateAsc', label: 'Дата отгрузки по возрастанию'},
{id: 'shipmentDateDesc', value: 'shipmentDateDesc', label: 'Дата отгрузки по убыванию'},
];
const [showShipmentPicker, setShowShipmentPicker] = useState(false);
const snapPoints = useMemo(() => ['60%', '60%'], []);
const dispatch = useDispatch();
const modalRef = useRef<BottomSheetModal>(null);
const dismiss = () => {
if (!modalRef.current) return;
dispatch(disableDim());
modalRef.current.dismiss();
onClose();
}
const present = () => {
if (!modalRef.current) return;
modalRef.current.present();
dispatch(enableDim());
}
useImperativeHandle(ref, () => ({
present: present,
dismiss: dismiss
}));
const [selectedId, setSelectedId] = useState<string>(defaultElementId);
useEffect(() => {
onChange(selectedId);
}, [selectedId]);
if (state.isVisible) present();
else dismiss();
}, [state.isVisible]);
return (
<BottomSheetModal
ref={modalRef}
snapPoints={snapPoints}
onDismiss={() => {
dispatch(disableDim());
dispatch(closeOrdersFilterModal())
}}>
<View style={styles.container}>
<View style={styles.content}>
<RadioGroup selectedId={selectedId}
onPress={setSelectedId}
<RadioGroup selectedId={state.orderBy + (state.desc ? "Desc" : "Asc")}
onPress={(event) => {
const orderRegex = /(Asc|Desc)$/;
const orderMatch = event.match(orderRegex);
if (!orderMatch) return;
const isDesc = orderMatch[0] === 'Desc';
const orderByField = event.replace(orderRegex, '');
if (!["createdOn", "shipmentDate"].includes(orderByField)) return
dispatch(setDesc(isDesc));
dispatch(setOrderBy(orderByField as "createdOn" | "shipmentDate"));
}}
containerStyle={styles.radioButtons}
radioButtons={elements.map(createRadioButton)}/>
<View style={{
borderWidth: responsiveWidth(0.1),
borderRadius: responsiveWidth(1)
}}>
<Picker selectedValue={state.status}
onValueChange={(value, event) => dispatch(setStatus(value))}>
{orderStatuses.map((status) => {
return (
<Picker.Item
key={status.key}
label={status.label}
value={status.key}
style={{fontSize: responsiveWidth(3)}}
/>
)
})}
</Picker>
</View>
<BasicButton onPress={() => setShowShipmentPicker(oldValue => !oldValue)}
label={"Выбрать дату отгрузки"}/>
{showShipmentPicker &&
<DateTimePicker value={new Date(state.shipmentDate)}
onChange={(event) => {
if (!event.nativeEvent.timestamp) return;
setShowShipmentPicker(false);
if (event.type === 'set') {
const selectedDate = new Date(event.nativeEvent.timestamp);
dispatch(setShipmentDate(selectedDate.toISOString()));
}
}}/>}
</View>
<BasicButton label={"Закрыть"} style={styles.button} onPress={() => {
dismiss();
dispatch(closeOrdersFilterModal());
}}/>
</View>
</BottomSheetModal>
);
});
)
};
const styles = StyleSheet.create({
container: {
width: "100%",
@@ -97,13 +149,17 @@ const styles = StyleSheet.create({
flex: 1,
padding: RFPercentage(3),
flexDirection: "column",
justifyContent: "space-between"
justifyContent: "space-between",
rowGap: responsiveHeight(1)
},
radioButtons: {
alignItems: "flex-start"
},
content: {},
content: {
rowGap: responsiveHeight(1)
},
button: {
marginTop: "auto"
},

View File

@@ -4,10 +4,11 @@ import {RFPercentage} from "react-native-responsive-fontsize";
import DText from "../DText/DText";
import {responsiveHeight, responsiveWidth} from "react-native-responsive-dimensions";
import DTitle from "../DTitle/DTitle";
import {Order} from "../../types/order";
import {BaseMarketplace, Order} from "../../types/order";
import OrderProductsList from "./OrderProductsList";
import {useDispatch} from "react-redux";
import {setOrder} from "../../features/assembly/assemblySlice";
import {OrderStatus, OrderStatusDictionary} from "../../features/ordersFilter/ordersFilterSlice";
type Props = {
onPress?: (event: GestureResponderEvent) => void
@@ -15,7 +16,15 @@ type Props = {
onSelect: (order: Order) => void
}
const BaseMarketplaceIconDict = {
[BaseMarketplace.Wildberries]: require('assets/icons/marketplaces/wildberries.png'),
[BaseMarketplace.Ozon]: require('assets/icons/marketplaces/ozon.png'),
[BaseMarketplace.YandexMarket]: require('assets/icons/marketplaces/yandex_market.png'),
};
const OrderCard: FC<Props> = ({onPress, onSelect, order}) => {
return (
<TouchableOpacity onPress={() => {
if (onSelect) onSelect(order);
@@ -26,7 +35,7 @@ const OrderCard: FC<Props> = ({onPress, onSelect, order}) => {
<View style={styles.title}>
<DTitle>{order.orderNumber}</DTitle>
<Image source={require('assets/icons/marketplaces/ozon.png')} style={styles.titleImage}/>
<Image source={BaseMarketplaceIconDict[order.baseMarketplace]} style={styles.titleImage}/>
</View>
<DText>Селлер: {order.sellerName}</DText>
<DText>Маркетплейс: {order.marketplaceName}</DText>
@@ -34,7 +43,7 @@ const OrderCard: FC<Props> = ({onPress, onSelect, order}) => {
</View>
<View style={styles.descriptionStatus}>
<DText>
Ожидает сборки
{OrderStatusDictionary[order.status as OrderStatus]}
</DText>
</View>
</View>

View File

@@ -9,16 +9,16 @@ import {background} from "../../css/colors";
type ListProps = {
products: OrderProduct[];
onSelected: (product: OrderProduct) => void;
onSelected: (product: number) => void;
}
type CardProps = {
product: OrderProduct;
onPress: (product: OrderProduct) => void;
onPress: (product: number) => void;
id: number;
}
const OrderProductCard: FC<CardProps> = ({product, onPress, id}) => {
return (
<TouchableOpacity onPress={() => onPress(product)}>
<TouchableOpacity onPress={() => onPress(id)}>
<View style={cardStyles.container}>
<View style={cardStyles.content}>
<DText>{id + 1}) {product.productName}</DText>

View File

@@ -7,16 +7,15 @@ import SelectProductModal from "../Modals/SelectProductModal/SelectProductModal"
import {SupplierProduct} from "../../types/supplierProduct";
import barcodeApi from "../../api/barcodeApi";
import {useDispatch, useSelector} from "react-redux";
import {openScanModal} from "../../features/scanModal/scanModalSlice";
import {openScanModal, setScannedData} from "../../features/scanModal/scanModalSlice";
import {RootState} from "../../redux/store";
type Props = {
onSearch: (text: string) => void;
onSearch?: (text: string) => void;
onSupplierProductSelected?: (supplierProduct: SupplierProduct) => void
}
const SearchBar: FC<Props> = ({onSearch, onSupplierProductSelected}) => {
// const [isScanModalVisible, setIsScanModalVisible] = useState<boolean>(false);
// const [, setSelectProductModalVisible] = useState(false);
const dispatch = useDispatch();
const [searchInput, setSearchInput] = useState<string>("");
const textInputRef = useRef<TextInput>(null);
@@ -26,19 +25,19 @@ const SearchBar: FC<Props> = ({onSearch, onSupplierProductSelected}) => {
useEffect(() => {
if (!scannedData) return;
barcodeApi.searchProducts(scannedData).then((response) => {
console.log("Response: " + response);
setProducts(response)
});
}, [scannedData]);
const selectProductModalVisible = products.length > 0;
return (
<View style={styles.container}>
<SelectProductModal visible={selectProductModalVisible} products={products} onSelected={(product) => {
if (onSupplierProductSelected) onSupplierProductSelected(product);
setProducts([]);
dispatch(setScannedData(undefined));
}}/>
<BasicButton onPress={() => {
if (!onSearch) return;
onSearch(searchInput);
if (textInputRef.current) {
textInputRef.current.clear();

View File

@@ -1,12 +1,16 @@
import {createSlice, PayloadAction} from "@reduxjs/toolkit";
import {Order} from "../../types/order";
import {Order, OrderProduct} from "../../types/order";
import {Assembly, ASSEMBLY_STATE} from "../../types/assembly";
import selectProductElement from "../../components/Modals/SelectProductModal/SelectProductElement";
export interface AssemblyState {
order?: Order;
initialOrder?: Order;
assembly?: Assembly;
localState?: ASSEMBLY_STATE
selectedProductId?: number;
localState?: ASSEMBLY_STATE;
selectedProduct?: OrderProduct
}
const initialState: AssemblyState = {
@@ -18,7 +22,9 @@ export const assembly = createSlice({
initialState,
reducers: {
setOrder: (state, action) => {
state.initialOrder = action.payload;
state.order = action.payload;
state.selectedProductId = 0;
},
setAssembly: (state, action: PayloadAction<Assembly>) => {
state.assembly = action.payload;
@@ -56,6 +62,7 @@ export const assembly = createSlice({
product.assembled = true;
}
});
state.selectedProduct = state.order.products.find(product => product.databaseId == action.payload.orderProductId);
// If all products is assembled
if (!state.order.products.find(product => !product.assembled)) {
state.assembly.state = ASSEMBLY_STATE.ALL_PRODUCTS_ASSEMBLED;
@@ -72,9 +79,23 @@ export const assembly = createSlice({
product.shipped = true;
}
});
state.selectedProduct = state.order.products.find(product => product.databaseId == action.payload.orderProductId);
},
selectProduct: (state, action: PayloadAction<number>) => {
if (!state.order) return;
state.selectedProduct = state.order.products[action.payload];
}
}
})
export const {setOrder, setAssembled, setAssembly, startAssembly, endAssembly, confirmAssembly} = assembly.actions;
export const {
setOrder,
setAssembled,
selectProduct,
setAssembly,
startAssembly,
endAssembly,
confirmAssembly
} = assembly.actions;
export default assembly.reducer;

View File

@@ -0,0 +1,100 @@
import {createSlice, PayloadAction} from "@reduxjs/toolkit";
export enum OrderStatus {
ALL = -1,
AWAITING_PACKAGING,
AWAITING_DELIVER,
DELIVERING,
DELIVERED,
CANCELLED,
PARTIALLY_RETURNED,
FULLY_RETURNED,
DISPUTED
}
export const orderStatuses = [
{key: OrderStatus.ALL, label: 'Все'},
{key: OrderStatus.AWAITING_PACKAGING, label: 'Ожидает сборки'},
{key: OrderStatus.AWAITING_DELIVER, label: 'Ожидает отгрузки'},
{key: OrderStatus.DELIVERING, label: 'Доставляется'},
{key: OrderStatus.DELIVERED, label: 'Доставлен'},
{key: OrderStatus.CANCELLED, label: 'Отменен'},
{key: OrderStatus.PARTIALLY_RETURNED, label: 'Частичный возврат'},
{key: OrderStatus.FULLY_RETURNED, label: 'Полный возврат'},
{key: OrderStatus.DISPUTED, label: 'Спорный'},
];
export const OrderStatusDictionary: { [key in OrderStatus]: string } = {
[OrderStatus.ALL]: 'Все',
[OrderStatus.AWAITING_PACKAGING]: 'Ожидает сборки',
[OrderStatus.AWAITING_DELIVER]: 'Ожидает отгрузки',
[OrderStatus.DELIVERING]: 'Доставляется',
[OrderStatus.DELIVERED]: 'Доставлен',
[OrderStatus.CANCELLED]: 'Отменен',
[OrderStatus.PARTIALLY_RETURNED]: 'Частичный возврат',
[OrderStatus.FULLY_RETURNED]: 'Полный возврат',
[OrderStatus.DISPUTED]: 'Спорный',
};
export interface OrdersFilterState {
isVisible: boolean;
orderBy: "createdOn" | "shipmentDate";
desc: boolean;
status: OrderStatus;
shipmentDate: string;
page: number;
}
const initialState: OrdersFilterState = {
isVisible: false,
orderBy: "createdOn",
desc: true,
shipmentDate: (new Date()).toISOString(),
status: OrderStatus.AWAITING_PACKAGING,
page: 0
}
export const ordersFilterSlice = createSlice({
name: 'ordersFilter',
initialState,
reducers: {
openOrdersFilterModal: (state) => {
state.isVisible = true
},
closeOrdersFilterModal: (state) => {
state.isVisible = false
},
setOrderBy: (state, action: PayloadAction<"createdOn" | "shipmentDate">) => {
state.orderBy = action.payload;
},
setDesc: (state, action: PayloadAction<boolean>) => {
state.desc = action.payload;
},
setStatus: (state, action: PayloadAction<OrderStatus>) => {
state.status = action.payload;
},
setShipmentDate: (state, action: PayloadAction<string>) => {
state.shipmentDate = action.payload;
},
setPage: (state, action: PayloadAction<number>) => {
state.page = action.payload;
},
nextPage: (state) => {
state.page = state.page + 1
},
refreshPagination: (state) => {
state.page = 0
}
}
})
export const {
openOrdersFilterModal,
closeOrdersFilterModal,
refreshPagination,
nextPage,
setOrderBy,
setDesc,
setStatus,
setShipmentDate
} = ordersFilterSlice.actions;
export default ordersFilterSlice.reducer;

View File

@@ -8,6 +8,7 @@ import imageZoomModalReducer from 'features/imageZoomModal/loadingModalSlice';
import assemblyReducer from 'features/assembly/assemblySlice';
import printingReducer from 'features/printing/printingSlice';
import reprintModalReducer from 'features/reprintModal/reprintModalSlice';
import ordersFilterReducer from 'features/ordersFilter/ordersFilterSlice';
import {useDispatch} from "react-redux";
export const store = configureStore({
@@ -19,7 +20,8 @@ export const store = configureStore({
assembly: assemblyReducer,
printing: printingReducer,
reprintModal: reprintModalReducer,
imageZoomModal: imageZoomModalReducer
imageZoomModal: imageZoomModalReducer,
ordersFilter: ordersFilterReducer
},
});

View File

@@ -1,15 +1,68 @@
import {Button, Text, View} from "react-native";
import {Button, StyleSheet, Text, View} from "react-native";
import {useAppDispatch} from "../../redux/store";
import * as process from "process";
import {responsiveHeight, responsiveWidth} from "react-native-responsive-dimensions";
import SearchBar from "../../components/SearchBar/SearchBar";
import {useDispatch} from "react-redux";
import {NavigationProp, useNavigation} from "@react-navigation/native";
import {TabNavigatorParamList} from "../MainScreen/MainScreen";
import {FlashList} from "@shopify/flash-list";
import {Order} from "../../types/order";
import OrderCard from "../../components/OrderCard/OrderCard";
import {setOrder} from "../../features/assembly/assemblySlice";
import flashListSeparator from "../../components/FlashListSeparator/FlashListSeparator";
import {useEffect, useState} from "react";
import {openScanModal} from "../../features/scanModal/scanModalSlice";
import ordersApi from "../../api/ordersApi";
function BarcodeScreen() {
const dispatch = useDispatch();
const navigator = useNavigation<NavigationProp<TabNavigatorParamList, 'Home'>>();
const [orders, setOrders] = useState<Order[]>([]);
useEffect(() => {
dispatch(openScanModal());
}, []);
return (
<View>
<Text style={{fontSize: 36}}>Barcode</Text>
<View style={styles.container}>
<SearchBar onSupplierProductSelected={product => {
ordersApi.getOrdersBySupplierProduct(product.supplierProductId).then(setOrders)
}}/>
<View style={styles.content}>
<FlashList
keyboardShouldPersistTaps={"never"}
data={orders}
keyExtractor={(item: Order) => item.orderNumber.toString()}
renderItem={({item}) =>
<OrderCard onSelect={(order) => {
dispatch(setOrder(order));
navigator.navigate("Home");
}} order={item}/>}
showsHorizontalScrollIndicator={false}
showsVerticalScrollIndicator={true}
onEndReachedThreshold={0.1}
estimatedItemSize={720}
ItemSeparatorComponent={flashListSeparator}
/>
</View>
</View>
)
}
const styles = StyleSheet.create({
container: {
width: "100%",
height: "100%",
display: "flex",
paddingHorizontal: responsiveWidth(5),
rowGap: responsiveHeight(2),
fontWeight: '500'
},
content: {
flex: 1,
},
});
export default BarcodeScreen;

View File

@@ -18,6 +18,7 @@ import assemblyApi from "../../api/assemblyApi";
import {assembly, setAssembly, setOrder} from "../../features/assembly/assemblySlice";
import ordersApi from "../../api/ordersApi";
import ImageZoomModal from "../../components/Modals/ImageZoomModal/ImageZoomModal";
import SortingModal from "../../components/Modals/SortingModal/SortingModal";
function CommonPage() {
const dim = useSelector((state: RootState) => state.interface.dim);
@@ -62,6 +63,7 @@ function CommonPage() {
<ScanModal/>
<ReprintModal/>
<ImageZoomModal/>
<SortingModal/>
<Toast config={toastConfig}/>
</View>

View File

@@ -17,7 +17,7 @@ import printingApi from "../../api/printingApi";
import PrintingService from "../../utils/PrintingService";
import OrderProductsList from "../../components/OrderCard/OrderProductsList";
import {
confirmAssembly, endAssembly,
confirmAssembly, endAssembly, selectProduct,
setAssembled,
setAssembly,
setOrder,
@@ -82,9 +82,9 @@ const OrderScreen: FC<OrderScreenProps> = ({order}) => {
const dispatch = useDispatch();
const assembly = useSelector((state: RootState) => state.assembly.assembly);
const assemblyState = useSelector((state: RootState) => state.assembly.localState);
const initialOrder = useSelector((state: RootState) => state.assembly.initialOrder);
const [selectedProduct, setSelectedProduct] = useState(order.products[0]);
const selectedProduct = useSelector((state: RootState) => state.assembly.selectedProduct);
const [acceptModalVisible, setAcceptModalVisible] = useState(false);
const [skipConfirmButtonVisible, setSkipConfirmButtonVisible] = useState(false);
const _confirmAssembly = async () => {
@@ -113,11 +113,13 @@ const OrderScreen: FC<OrderScreenProps> = ({order}) => {
onPress={() => setAcceptModalVisible(true)}
label={"Начать сборку"}/>)
case ASSEMBLY_STATE.ASSEMBLING_PRODUCTS:
return (<BasicButton
containerStyle={styles.buttonContainer}
label={"Отметить как собранный"}
disabled={selectedProduct.assembled}
disabled={selectedProduct?.assembled}
onPress={() => {
if (!selectedProduct) return;
dispatch(setAssembled({orderProductId: selectedProduct.databaseId}))
}}
/>)
@@ -183,10 +185,10 @@ const OrderScreen: FC<OrderScreenProps> = ({order}) => {
dispatch(setLoadingText('Идет печать этикетки...'))
dispatch(openLoadingModal())
printingApi.getLabel(order.databaseId).then(pdfData => {
printingService.getInstance().printPdf('ozon', pdfData).then((response) => {
printingService.getInstance().printPdf('wildberries', pdfData).then((response) => {
dispatch(closeLoadingModal());
if (response) return;
dispatch(setPrinterName({printerName: 'ozon'}));
dispatch(setPrinterName({printerName: 'wildberries'}));
dispatch(openReprintModal());
});
})
@@ -204,23 +206,27 @@ const OrderScreen: FC<OrderScreenProps> = ({order}) => {
});
}, [assemblyState]);
useEffect(() => {
if (!order) return;
dispatch(selectProduct(0));
}, [initialOrder]);
return (
<View style={styles.container}>
<View style={styles.productsContainer}>
<View style={styles.orderProductsListWrapper}>
<OrderProductsList products={order.products} onSelected={(product) => {
<OrderProductsList products={order.products} onSelected={(productId) => {
if (!order) return;
setSelectedProduct(product)
dispatch(selectProduct(productId))
}}/>
</View>
<TouchableOpacity style={styles.imageWrapper} onPress={() => {
if (!selectedProduct) return;
dispatch(setImages([selectedProduct.imageUrl]));
dispatch(openImageZoomModal());
}}>
<View style={{flex: 1}}>
<Image style={styles.image} source={{uri: selectedProduct.imageUrl}}/>
<Image style={styles.image} source={{uri: selectedProduct?.imageUrl}}/>
</View>
</TouchableOpacity>
@@ -233,11 +239,11 @@ const OrderScreen: FC<OrderScreenProps> = ({order}) => {
<DText>Селлер: {order.sellerName}</DText>
<DText>{}</DText>
<DTitle style={styles.contentTitle}>Товар</DTitle>
<DText>Артикул DENCO: {selectedProduct.dencoArticle}</DText>
<DText>Поставщик: {selectedProduct.supplierName}</DText>
<DText>Артикул DENCO: {selectedProduct?.dencoArticle}</DText>
<DText>Поставщик: {selectedProduct?.supplierName}</DText>
<DText>Номер товара: {0}</DText>
<DText>{}</DText>
<DTitle style={styles.contentTitle}>Сборка</DTitle>
{/*<DText>{}</DText>*/}
{/*<DTitle style={styles.contentTitle}>Сборка</DTitle>*/}
</View>
<View style={styles.buttonsContainer}>
@@ -249,7 +255,6 @@ const OrderScreen: FC<OrderScreenProps> = ({order}) => {
onAccepted={() => {
setAcceptModalVisible(false);
assemblyApi.create(order.databaseId).then(creationResult => {
console.log(creationResult.message)
Toast.show({
type: creationResult.ok ? 'success' : 'error',
text1: 'Создание сборки',
@@ -273,7 +278,6 @@ const OrderScreen: FC<OrderScreenProps> = ({order}) => {
export const OrderScreenController: FC = () => {
const order: Order | undefined = useSelector((state: RootState) => state.assembly.order);
if (!order) return <NoOrderScreen/>
console.log(order)
return <OrderScreen order={order}/>
}

View File

@@ -0,0 +1,41 @@
import {useEffect, useState} from "react";
import {Order} from "../../types/order";
import ordersApi from "../../api/ordersApi";
import {setOrder} from "../../features/assembly/assemblySlice";
import {RootState} from "../../redux/store";
import {useDispatch, useSelector} from "react-redux";
import {refreshPagination} from "../../features/ordersFilter/ordersFilterSlice";
const useOrders = () => {
const dispatch = useDispatch();
const [orders, setOrders] = useState<Order[]>([]);
const [isRefreshing, setIsRefreshing] = useState(false);
const filterState = useSelector((state: RootState) => state.ordersFilter);
const refresh = () => {
if (filterState.page == 0) return;
setIsRefreshing(true);
setOrders([]);
dispatch(refreshPagination());
}
useEffect(() => {
if (filterState.isVisible) return;
ordersApi.getOrders(filterState.page, filterState.orderBy, filterState.desc, filterState.shipmentDate, filterState.status).then(response => {
setOrders(oldOrders => [...oldOrders, ...response]);
setIsRefreshing(false);
});
}, [filterState.page]);
useEffect(() => {
if (filterState.isVisible) return;
setOrders([]);
setIsRefreshing(true);
dispatch(refreshPagination());
}, [filterState.orderBy, filterState.desc, filterState.status, filterState.shipmentDate, filterState.isVisible]);
return {refresh, isRefreshing, orders};
}
export default useOrders;

View File

@@ -1,5 +1,4 @@
import {StyleSheet, View} from "react-native";
import SearchBar from "../../components/SearchBar/SearchBar";
import OrderCard from "../../components/OrderCard/OrderCard";
import {RFPercentage} from "react-native-responsive-fontsize";
import {responsiveHeight, responsiveWidth} from "react-native-responsive-dimensions";
@@ -9,66 +8,50 @@ import {useEffect, useRef, useState} from "react";
import {Order} from "../../types/order";
import {FlashList} from "@shopify/flash-list";
import SortingModal, {
SortingModalElement,
SortingModalHandles
} from "../../components/Modals/SortingModal/SortingModal";
import flashListSeparator from "../../components/FlashListSeparator/FlashListSeparator";
import ordersApi from "../../api/ordersApi";
import {setOrder} from "../../features/assembly/assemblySlice";
import {NavigationProp, useNavigation} from "@react-navigation/native";
import {TabNavigatorParamList} from "../MainScreen/MainScreen";
import useOrders from "../OrderScreen/useOrders";
import {nextPage, openOrdersFilterModal} from "../../features/ordersFilter/ordersFilterSlice";
function OrdersScreen() {
const dispatch = useDispatch();
const navigator = useNavigation<NavigationProp<TabNavigatorParamList, 'Home'>>();
const {refresh, isRefreshing, orders} = useOrders();
const [orders, setOrders] = useState<Order[]>([]);
const sortingModalRef = useRef<SortingModalHandles | null>(null);
const defaultSortingValue = 'createdOnAsc';
const sortingModalElements: SortingModalElement[] = [
{id: 'createdOnAsc', value: 'createdOnAsc', label: 'Дата создания по убыванию'},
{id: 'createdOnDesc', value: 'createdOnDesc', label: 'Дата создания по возрастанию'},
{id: 'shipmentDateAsc', value: 'shipmentDateAsc', label: 'Дата отгрузки по убыванию'},
{id: 'shipmentDateDesc', value: 'shipmentDateDesc', label: 'Дата отгрузки по возрастанию'},
];
const [sortingValue, setSortingValue] = useState(defaultSortingValue);
return (
<View style={styles.container}>
<SearchBar onSearch={() => {
}} onSupplierProductSelected={product => {
ordersApi.getOrdersBySupplierProduct(product.supplierProductId).then(setOrders)
}}/>
<View style={styles.sortingButtonWrapper}>
<SortingButton onPress={() => {
if (!sortingModalRef.current) return;
sortingModalRef.current.present();
dispatch(openOrdersFilterModal());
}}/>
</View>
<View style={styles.content}>
<FlashList
<FlashList onRefresh={refresh}
refreshing={isRefreshing}
keyboardShouldPersistTaps={"never"}
data={orders}
keyExtractor={(item: Order) => item.orderNumber.toString()}
keyExtractor={(item: Order) => item.databaseId.toString()}
renderItem={({item}) =>
<OrderCard onSelect={(order) => dispatch(setOrder(order))} order={item}/>}
<OrderCard onSelect={(order) => {
dispatch(setOrder(order));
navigator.navigate("Home");
}} order={item}/>}
showsHorizontalScrollIndicator={false}
showsVerticalScrollIndicator={true}
onEndReachedThreshold={0.1}
onEndReachedThreshold={0.5}
estimatedItemSize={720}
onEndReached={() => {
if (!orders.length) return;
dispatch(nextPage());
}}
ItemSeparatorComponent={flashListSeparator}
/>
<SortingModal onChange={setSortingValue}
onClose={() => {
}}
ref={sortingModalRef}
elements={sortingModalElements}
defaultElementId={defaultSortingValue}
/>
</View>
</View>

View File

@@ -0,0 +1,3 @@
const useOrdersFilter = () => {
}

View File

@@ -10,10 +10,19 @@ export type OrderProduct = {
};
export enum BaseMarketplace {
Wildberries,
Ozon,
YandexMarket
}
export type Order = {
databaseId: number;
orderNumber: string;
marketplaceName: string;
baseMarketplace: BaseMarketplace;
sellerName: string;
products: OrderProduct[];
status: number;
};