352 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			352 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
import {View, Image, StyleSheet, TouchableOpacity} from "react-native";
 | 
						||
import {responsiveHeight, responsiveWidth} from "react-native-responsive-dimensions";
 | 
						||
import DText from "../../components/DText/DText";
 | 
						||
import {RFPercentage} from "react-native-responsive-fontsize";
 | 
						||
import DTitle from "../../components/DTitle/DTitle";
 | 
						||
import BasicButton from "../../components/BasicButton/BasicButton";
 | 
						||
import React, {FC, useEffect, useState} from "react";
 | 
						||
import {useDispatch, useSelector} from "react-redux";
 | 
						||
import {RootState} from "../../redux/store";
 | 
						||
import {closeLoadingModal, openLoadingModal, setLoadingText} from "../../features/loadingModal/loadingModalSlice";
 | 
						||
import {useNavigation} from "@react-navigation/native";
 | 
						||
import printingApi from "../../api/printingApi";
 | 
						||
import PrintingService from "../../utils/PrintingService";
 | 
						||
import OrderProductsList from "../../components/OrderCard/OrderProductsList";
 | 
						||
import {
 | 
						||
    confirmAssembly, endAssembly, selectProduct,
 | 
						||
    setAssembled,
 | 
						||
    setAssembly,
 | 
						||
    setOrder,
 | 
						||
    startAssembly
 | 
						||
} from "../../features/assembly/assemblySlice";
 | 
						||
import AcceptModal from "../../components/Modals/AcceptModal/AcceptModal";
 | 
						||
import {Order} from "../../types/order";
 | 
						||
import acceptModal from "../../components/Modals/AcceptModal/AcceptModal";
 | 
						||
import printingService from "../../utils/PrintingService";
 | 
						||
import ReprintModal from "../../components/Modals/ReprintModal/ReprintModal";
 | 
						||
import {setPrinterName} from "../../features/printing/printingSlice";
 | 
						||
import {openReprintModal} from "../../features/reprintModal/reprintModalSlice";
 | 
						||
import {ASSEMBLY_STATE} from "../../types/assembly";
 | 
						||
import {RenderTargetOptions} from "@shopify/flash-list";
 | 
						||
import {createOnShouldStartLoadWithRequest} from "react-native-webview/lib/WebViewShared";
 | 
						||
import assemblyApi from "../../api/assemblyApi";
 | 
						||
import Toast from "react-native-toast-message";
 | 
						||
import mainScreen from "../MainScreen/MainScreen";
 | 
						||
import toast from "../../components/Toast/Toast";
 | 
						||
import {openImageZoomModal, setImages} from "../../features/imageZoomModal/loadingModalSlice";
 | 
						||
 | 
						||
 | 
						||
type AssemblyPeriod = {
 | 
						||
    started: Date;
 | 
						||
    ended: Date;
 | 
						||
}
 | 
						||
 | 
						||
const NoOrderScreen: FC = () => {
 | 
						||
    return (
 | 
						||
        <View style={noOrderStyles.container}>
 | 
						||
            <DText style={noOrderStyles.title}>Заказ не выбран!</DText>
 | 
						||
            <View style={noOrderStyles.buttonWrapper}>
 | 
						||
                <BasicButton onPress={() => {
 | 
						||
                    // @ts-ignore
 | 
						||
                    navigator.navigate("Box");
 | 
						||
                }} label={"На главную"}/>
 | 
						||
            </View>
 | 
						||
 | 
						||
        </View>
 | 
						||
    )
 | 
						||
}
 | 
						||
const noOrderStyles = StyleSheet.create({
 | 
						||
    container: {
 | 
						||
        justifyContent: "center",
 | 
						||
        flex: 1,
 | 
						||
        rowGap: responsiveHeight(5)
 | 
						||
    },
 | 
						||
    title: {
 | 
						||
        textAlign: "center",
 | 
						||
        fontSize: responsiveWidth(5)
 | 
						||
    },
 | 
						||
    buttonWrapper: {
 | 
						||
        paddingHorizontal: responsiveWidth(20),
 | 
						||
    }
 | 
						||
})
 | 
						||
 | 
						||
type OrderScreenProps = {
 | 
						||
    order: Order;
 | 
						||
}
 | 
						||
const OrderScreen: FC<OrderScreenProps> = ({order}) => {
 | 
						||
    const navigator = useNavigation();
 | 
						||
    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 = useSelector((state: RootState) => state.assembly.selectedProduct);
 | 
						||
    const [acceptModalVisible, setAcceptModalVisible] = useState(false);
 | 
						||
    const [skipConfirmButtonVisible, setSkipConfirmButtonVisible] = useState(false);
 | 
						||
    const _confirmAssembly = async () => {
 | 
						||
        if (!assembly) return;
 | 
						||
        dispatch(setLoadingText('Подтверждение сборки...'))
 | 
						||
        dispatch(openLoadingModal());
 | 
						||
        assemblyApi.confirm(assembly.databaseId).then(({ok, message}) => {
 | 
						||
            dispatch(closeLoadingModal());
 | 
						||
            Toast.show({
 | 
						||
                type: ok ? 'success' : 'error',
 | 
						||
                text1: 'Подтверждение сборки',
 | 
						||
                text2: message
 | 
						||
            })
 | 
						||
            if (ok) {
 | 
						||
                dispatch(confirmAssembly());
 | 
						||
 | 
						||
            } else {
 | 
						||
                setSkipConfirmButtonVisible(true);
 | 
						||
            }
 | 
						||
        })
 | 
						||
    }
 | 
						||
    const getButtons = () => {
 | 
						||
        switch (assemblyState) {
 | 
						||
            case ASSEMBLY_STATE.NOT_STARTED:
 | 
						||
                return (<BasicButton containerStyle={styles.buttonContainer}
 | 
						||
                                     onPress={() => setAcceptModalVisible(true)}
 | 
						||
                                     label={"Начать сборку"}/>)
 | 
						||
            case ASSEMBLY_STATE.ASSEMBLING_PRODUCTS:
 | 
						||
 | 
						||
                return (<BasicButton
 | 
						||
                    containerStyle={styles.buttonContainer}
 | 
						||
                    label={"Отметить как собранный"}
 | 
						||
                    disabled={selectedProduct?.assembled}
 | 
						||
                    onPress={() => {
 | 
						||
                        if (!selectedProduct) return;
 | 
						||
                        dispatch(setAssembled({orderProductId: selectedProduct.databaseId}))
 | 
						||
                    }}
 | 
						||
                />)
 | 
						||
            case ASSEMBLY_STATE.ALL_PRODUCTS_ASSEMBLED:
 | 
						||
                return (
 | 
						||
                    <>
 | 
						||
                        <BasicButton
 | 
						||
                            onPress={() => {
 | 
						||
                                _confirmAssembly();
 | 
						||
                            }}
 | 
						||
                            containerStyle={styles.buttonContainer}
 | 
						||
                            label={"Подтвердить сборку"}
 | 
						||
                        />
 | 
						||
                        {skipConfirmButtonVisible && <BasicButton
 | 
						||
                            onPress={() => {
 | 
						||
                                dispatch(confirmAssembly());
 | 
						||
                            }}
 | 
						||
                            style={{backgroundColor: 'orange'}}
 | 
						||
                            containerStyle={styles.buttonContainer}
 | 
						||
                            label={"Пропустить подтверждение сборки"}
 | 
						||
                        />}
 | 
						||
                    </>
 | 
						||
                )
 | 
						||
            case ASSEMBLY_STATE.CONFIRMED:
 | 
						||
                return (
 | 
						||
                    <>
 | 
						||
 | 
						||
                        <BasicButton
 | 
						||
                            onPress={() => printLabel()}
 | 
						||
                            containerStyle={styles.buttonContainer}
 | 
						||
                            label={"Печать этикетки"}
 | 
						||
                        />
 | 
						||
                        <BasicButton
 | 
						||
                            containerStyle={styles.buttonContainer}
 | 
						||
                            style={{backgroundColor: 'green'}}
 | 
						||
                            label={"Завершить сборку"}
 | 
						||
                            onPress={() => {
 | 
						||
                                if (!assembly) return;
 | 
						||
                                assemblyApi.close(assembly.databaseId).then(({ok, message}) => {
 | 
						||
                                    Toast.show({
 | 
						||
                                        type: ok ? 'success' : 'error',
 | 
						||
                                        text1: 'Завершение сборки',
 | 
						||
                                        text2: message
 | 
						||
                                    });
 | 
						||
                                    dispatch(endAssembly());
 | 
						||
                                })
 | 
						||
                            }}/>
 | 
						||
                    </>
 | 
						||
                )
 | 
						||
            case ASSEMBLY_STATE.ENDED:
 | 
						||
                return (
 | 
						||
                    <BasicButton
 | 
						||
                        containerStyle={styles.buttonContainer}
 | 
						||
                        label={"Этот заказ уже собран"}
 | 
						||
                        disabled
 | 
						||
                        onPress={() => {
 | 
						||
                        }}/>
 | 
						||
                )
 | 
						||
        }
 | 
						||
    }
 | 
						||
    const printLabel = () => {
 | 
						||
        if (!order) return;
 | 
						||
        let printer = printingService.getInstance().getPrinter(order.baseMarketplace);
 | 
						||
        dispatch(setLoadingText('Идет печать этикетки...'))
 | 
						||
        dispatch(openLoadingModal())
 | 
						||
        printingApi.getLabel(order.databaseId).then(pdfData => {
 | 
						||
            printingService.getInstance().printPdf(printer, pdfData).then((response) => {
 | 
						||
                dispatch(closeLoadingModal());
 | 
						||
                if (response) return;
 | 
						||
                dispatch(setPrinterName({printerName: printer}));
 | 
						||
                dispatch(openReprintModal());
 | 
						||
            });
 | 
						||
        })
 | 
						||
    }
 | 
						||
 | 
						||
    useEffect(() => {
 | 
						||
        if (!assembly) return;
 | 
						||
        assemblyApi.updateState(assembly.databaseId, Number(assemblyState)).then(ok => {
 | 
						||
            if (ok) return;
 | 
						||
            Toast.show({
 | 
						||
                type: 'error',
 | 
						||
                text1: 'Обновление состояния',
 | 
						||
                text2: 'Неудалось обновить состояние текущей сборки на сервере'
 | 
						||
            })
 | 
						||
        });
 | 
						||
 | 
						||
    }, [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={(productId) => {
 | 
						||
                        if (!order) return;
 | 
						||
                        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}}/>
 | 
						||
                    </View>
 | 
						||
                </TouchableOpacity>
 | 
						||
 | 
						||
            </View>
 | 
						||
            <View style={styles.contentContainer}>
 | 
						||
                <View style={styles.dataContainer}>
 | 
						||
                    <DTitle style={styles.contentTitle}>Заказ</DTitle>
 | 
						||
                    <DText>Номер заказа: {order.orderNumber}</DText>
 | 
						||
                    <DText>Маркетплейс: {order.marketplaceName}</DText>
 | 
						||
                    <DText>Селлер: {order.sellerName}</DText>
 | 
						||
                    <DText>{}</DText>
 | 
						||
                    <DTitle style={styles.contentTitle}>Товар</DTitle>
 | 
						||
                    <DText>Артикул DENCO: {selectedProduct?.dencoArticle}</DText>
 | 
						||
                    <DText>Поставщик: {selectedProduct?.supplierName}</DText>
 | 
						||
                    <DText>Номер товара: {0}</DText>
 | 
						||
                    {/*<DText>{}</DText>*/}
 | 
						||
                    {/*<DTitle style={styles.contentTitle}>Сборка</DTitle>*/}
 | 
						||
 | 
						||
                </View>
 | 
						||
                <View style={styles.buttonsContainer}>
 | 
						||
                    {getButtons()}
 | 
						||
                </View>
 | 
						||
            </View>
 | 
						||
            <AcceptModal visible={acceptModalVisible}
 | 
						||
                         text={`Вы уверены что хотите начать сборку заказа ${order.orderNumber}`}
 | 
						||
                         onAccepted={() => {
 | 
						||
                             setAcceptModalVisible(false);
 | 
						||
                             assemblyApi.create(order.databaseId).then(creationResult => {
 | 
						||
                                 Toast.show({
 | 
						||
                                     type: creationResult.ok ? 'success' : 'error',
 | 
						||
                                     text1: 'Создание сборки',
 | 
						||
                                     text2: creationResult.message
 | 
						||
                                 });
 | 
						||
                                 if (!creationResult.ok) return;
 | 
						||
                                 assemblyApi.getActive().then(activeAssembly => {
 | 
						||
                                     dispatch(setAssembly(activeAssembly));
 | 
						||
                                     dispatch(startAssembly())
 | 
						||
                                 })
 | 
						||
                             })
 | 
						||
                         }}
 | 
						||
                         onRefused={() => {
 | 
						||
                             setAcceptModalVisible(false);
 | 
						||
                         }}/>
 | 
						||
        </View>
 | 
						||
 | 
						||
    )
 | 
						||
}
 | 
						||
 | 
						||
export const OrderScreenController: FC = () => {
 | 
						||
    const order: Order | undefined = useSelector((state: RootState) => state.assembly.order);
 | 
						||
    if (!order) return <NoOrderScreen/>
 | 
						||
    return <OrderScreen order={order}/>
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
const styles = StyleSheet.create({
 | 
						||
    orderProductsListWrapper: {
 | 
						||
        flex: 0.5,
 | 
						||
        backgroundColor: "white",
 | 
						||
        borderRadius: RFPercentage(3),
 | 
						||
        padding: RFPercentage(2),
 | 
						||
    },
 | 
						||
    buttonContainer: {
 | 
						||
        flex: 1,
 | 
						||
    },
 | 
						||
    dataContainer: {
 | 
						||
        backgroundColor: "white",
 | 
						||
        padding: RFPercentage(2),
 | 
						||
        flex: 0.5,
 | 
						||
        borderRadius: RFPercentage(3),
 | 
						||
    },
 | 
						||
    buttonsContainer: {
 | 
						||
        backgroundColor: "white",
 | 
						||
        padding: RFPercentage(2),
 | 
						||
        flex: 0.5,
 | 
						||
        borderRadius: RFPercentage(3),
 | 
						||
        rowGap: responsiveHeight(2)
 | 
						||
    },
 | 
						||
    contentContainer: {
 | 
						||
        flex: 1,
 | 
						||
        borderRadius: RFPercentage(3),
 | 
						||
        flexDirection: "row",
 | 
						||
        columnGap: responsiveWidth(3),
 | 
						||
    },
 | 
						||
    container: {
 | 
						||
        width: "100%",
 | 
						||
        height: "100%",
 | 
						||
        display: "flex",
 | 
						||
        paddingHorizontal: responsiveWidth(5),
 | 
						||
        paddingBottom: responsiveHeight(10),
 | 
						||
        rowGap: responsiveHeight(2)
 | 
						||
    },
 | 
						||
    productsContainer: {
 | 
						||
        display: "flex",
 | 
						||
        flexDirection: "row",
 | 
						||
        columnGap: responsiveWidth(3),
 | 
						||
        height: responsiveHeight(30)
 | 
						||
    },
 | 
						||
 | 
						||
    buttonsWrapper: {
 | 
						||
        rowGap: responsiveHeight(3)
 | 
						||
    },
 | 
						||
    imageWrapper: {
 | 
						||
        flex: 0.5,
 | 
						||
        backgroundColor: "white",
 | 
						||
        padding: RFPercentage(2),
 | 
						||
        borderRadius: RFPercentage(3)
 | 
						||
    },
 | 
						||
    image: {
 | 
						||
        flex: 1,
 | 
						||
        resizeMode: "contain"
 | 
						||
    },
 | 
						||
    contentWrapper: {
 | 
						||
        display: "flex",
 | 
						||
        flexDirection: "column",
 | 
						||
        gap: 0,
 | 
						||
    },
 | 
						||
    contentTitle: {
 | 
						||
        alignSelf: "center"
 | 
						||
    },
 | 
						||
    articleText: {
 | 
						||
        color: 'blue',
 | 
						||
        textDecorationLine: 'underline'
 | 
						||
    }
 | 
						||
})
 | 
						||
export default OrderScreen; |