Files
Assemblr/src/screens/OrderScreen/OrderScreen.tsx
2023-11-16 03:28:07 +03:00

359 lines
14 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import {View, Image, StyleSheet, TouchableOpacity, ScrollView} 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 {NavigationProp, 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, {TabNavigatorParamList} 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>
)
}
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<NavigationProp<TabNavigatorParamList, 'Barcode'>>();
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());
navigator.navigate('Barcode');
})
}}/>
</>
)
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: 'Неудалось обновить состояние текущей сборки на сервере'
})
});
switch (assemblyState) {
case ASSEMBLY_STATE.CONFIRMED:
printLabel();
break;
case ASSEMBLY_STATE.ASSEMBLING_PRODUCTS:
if (!selectedProduct) return;
if (order.products.length == 1) {
dispatch(setAssembled({orderProductId: selectedProduct.databaseId}));
}
break;
}
}, [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}>
<ScrollView>
<DTitle style={styles.contentTitle}>Заказ</DTitle>
<DText>Номер заказа: {order.orderNumber}</DText>
<DText>Маркетплейс: {order.marketplaceName}</DText>
<DText>Селлер: {order.sellerName}</DText>
<DText>Создан: {order.createdOn}</DText>
<DText>Отгрузка: {order.shipmentDate}</DText>
<DText>{}</DText>
<DTitle style={styles.contentTitle}>Товар</DTitle>
<DText>Арт. DENCO: {selectedProduct?.dencoArticle}</DText>
<DText>Арт. поставщика: {selectedProduct?.supplierArticle}</DText>
<DText>Фасовка: {selectedProduct?.inBlock} шт.</DText>
<DText>Поставщик: {selectedProduct?.supplierName}</DText>
</ScrollView>
</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;