287 lines
9.6 KiB
TypeScript
287 lines
9.6 KiB
TypeScript
import {useDispatch, useSelector} from "react-redux";
|
|
import {RootState, useAppDispatch} from "../../redux/store";
|
|
import {ASSEMBLY_STATE} from "../../types/assembly";
|
|
import {StyleSheet, Text, View} from "react-native";
|
|
import BasicButton, {BasicButtonProps} from "../../components/BasicButton/BasicButton";
|
|
import {BaseButton} from "react-native-gesture-handler";
|
|
import {
|
|
confirmAssembly, endAssembly,
|
|
openAcceptModal,
|
|
selectProduct,
|
|
setAssembled,
|
|
skipCrpt
|
|
} from "../../features/assembly/assemblySlice";
|
|
import {useScanningContext} from "../../providers/ScanProvider";
|
|
import assemblyApi from "../../api/assemblyApi";
|
|
import {OkMessageResponse} from "../../types/api";
|
|
import Toast from "react-native-toast-message";
|
|
import {useEffect, useState} from "react";
|
|
import {RFPercentage} from "react-native-responsive-fontsize";
|
|
import {responsiveHeight} from "react-native-responsive-dimensions";
|
|
import {closeLoadingModal, openLoadingModal, setLoadingText} from "../../features/loadingModal/loadingModalSlice";
|
|
import printingService from "../../utils/PrintingService";
|
|
import printingApi from "../../api/printingApi";
|
|
import {setPrinterName} from "../../features/printing/printingSlice";
|
|
import {openReprintModal} from "../../features/reprintModal/reprintModalSlice";
|
|
import {showReward} from "../../features/animations/animationsSlice";
|
|
import {fetchBalance, refreshTransactions} from "../../features/balance/balanceSlice";
|
|
import {NavigationProp, useNavigation} from "@react-navigation/native";
|
|
import {TabNavigatorParamList} from "../MainScreen/MainScreen";
|
|
|
|
|
|
const AssemblyButton = (props: BasicButtonProps) => {
|
|
return (
|
|
<BasicButton
|
|
{...props}
|
|
containerStyle={{flex: 1}}
|
|
/>
|
|
)
|
|
}
|
|
const NotStartedButtons = () => {
|
|
const dispatch = useDispatch();
|
|
const onStartAssembly = () => {
|
|
dispatch(openAcceptModal());
|
|
}
|
|
return (
|
|
<AssemblyButton
|
|
label={"Начать сборку"}
|
|
onPress={onStartAssembly}
|
|
/>
|
|
)
|
|
|
|
}
|
|
|
|
const ScanningCrptButtons = () => {
|
|
const dispatch = useAppDispatch();
|
|
|
|
const state = useSelector((state: RootState) => state.assembly);
|
|
const [isInitialized, setIsInitialized] = useState(false);
|
|
const getNeedState = () => {
|
|
if (!state.order) return {};
|
|
return state.order.products.reduce((acc, product) => {
|
|
acc[product.databaseId] = false;
|
|
return acc;
|
|
}, {} as { [key: number]: boolean })
|
|
}
|
|
|
|
const [crptNeedState, setCrptNeedState] = useState<{ [key: number]: boolean }>(getNeedState());
|
|
const {scan} = useScanningContext();
|
|
const onAttached = (response: OkMessageResponse) => {
|
|
|
|
Toast.show({
|
|
type: response.ok ? "success" : "error",
|
|
text1: "Сканирование честного знака",
|
|
text2: response.message,
|
|
});
|
|
|
|
if (!response.ok) return
|
|
|
|
setCrptNeedState(prevState => {
|
|
if (!state.selectedProduct) return prevState;
|
|
return {...prevState, [state.selectedProduct.databaseId]: false}
|
|
|
|
})
|
|
}
|
|
const onScanned = (data: string) => {
|
|
if (!state.selectedProduct) return;
|
|
assemblyApi.attachCrpt(state.selectedProduct.databaseId, data).then(onAttached);
|
|
}
|
|
const onScanClick = () => {
|
|
scan({callback: onScanned});
|
|
}
|
|
const initialize = async () => {
|
|
dispatch(setLoadingText('Проверка необходимости сканирования честного знака...'))
|
|
dispatch(openLoadingModal());
|
|
if (!state.order) return;
|
|
const responses = await Promise.all(state.order.products.map(async (product) => {
|
|
const response = await assemblyApi.needCrpt(product.databaseId);
|
|
return {productId: product.databaseId, need: response.needCrpt};
|
|
}));
|
|
// update state
|
|
setCrptNeedState(responses.reduce((acc, {productId, need}) => {
|
|
acc[productId] = need;
|
|
return acc;
|
|
}, {} as { [key: number]: boolean }));
|
|
|
|
setIsInitialized(true);
|
|
dispatch(closeLoadingModal());
|
|
////
|
|
////
|
|
dispatch(selectProduct(0))
|
|
}
|
|
useEffect(() => {
|
|
if (!isInitialized) return;
|
|
if (Object.values(crptNeedState).every(value => !value))
|
|
dispatch(skipCrpt())
|
|
}, [crptNeedState]);
|
|
|
|
useEffect(() => {
|
|
initialize();
|
|
}, []);
|
|
return (
|
|
<>
|
|
<AssemblyButton
|
|
disabled={!state.selectedProduct || !crptNeedState[state.selectedProduct.databaseId]}
|
|
onPress={onScanClick}
|
|
label={"Сканировать честный знак"}
|
|
/>
|
|
<AssemblyButton
|
|
onPress={() => {
|
|
dispatch(skipCrpt())
|
|
}}
|
|
label={"Пропустить"}
|
|
/>
|
|
</>
|
|
)
|
|
}
|
|
|
|
const AssemblingButtons = () => {
|
|
const dispatch = useAppDispatch();
|
|
const state = useSelector((state: RootState) => state.assembly);
|
|
useEffect(() => {
|
|
dispatch(selectProduct(0));
|
|
}, []);
|
|
return (
|
|
<AssemblyButton
|
|
disabled={state.selectedProduct?.assembled}
|
|
onPress={() => {
|
|
if (!state.selectedProduct) return;
|
|
dispatch(setAssembled({orderProductId: state.selectedProduct.databaseId}));
|
|
}}
|
|
label={"Отметить как собранный"}
|
|
/>
|
|
)
|
|
}
|
|
|
|
const AllProductsAssembledButtons = () => {
|
|
const dispatch = useAppDispatch();
|
|
const state = useSelector((state: RootState) => state.assembly);
|
|
|
|
const [skipButtonVisible, setSkipButtonVisible] = useState(false);
|
|
|
|
const onConfirmClick = () => {
|
|
if (!state.assembly) return;
|
|
dispatch(setLoadingText('Подтверждение сборки...'))
|
|
dispatch(openLoadingModal());
|
|
assemblyApi.confirm(state.assembly.databaseId).then(({ok, message}) => {
|
|
dispatch(closeLoadingModal());
|
|
Toast.show({
|
|
type: ok ? 'success' : 'error',
|
|
text1: 'Подтверждение сборки',
|
|
text2: message
|
|
})
|
|
if (ok) {
|
|
dispatch(confirmAssembly());
|
|
} else {
|
|
setSkipButtonVisible(true);
|
|
}
|
|
})
|
|
}
|
|
const onSkipClick = () => {
|
|
dispatch(confirmAssembly());
|
|
}
|
|
return (
|
|
<>
|
|
<AssemblyButton label={"Подтвердить сборку"} onPress={onConfirmClick}/>
|
|
{skipButtonVisible && <AssemblyButton label={"Пропустить"} onPress={onSkipClick}/>}
|
|
</>
|
|
)
|
|
|
|
}
|
|
|
|
const ConfirmedButtons = () => {
|
|
const navigator = useNavigation<NavigationProp<TabNavigatorParamList, 'Barcode'>>();
|
|
|
|
const dispatch = useAppDispatch();
|
|
const order = useSelector((state: RootState) => state.assembly.order);
|
|
const assembly = useSelector((state: RootState) => state.assembly.assembly);
|
|
const onPrintLabel = () => {
|
|
|
|
return;
|
|
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());
|
|
});
|
|
})
|
|
}
|
|
const onEndAssembly = () => {
|
|
if (!assembly) return;
|
|
assemblyApi.close(assembly.databaseId).then(({ok, message, reward}) => {
|
|
Toast.show({
|
|
type: ok ? 'success' : 'error',
|
|
text1: 'Завершение сборки',
|
|
text2: message
|
|
});
|
|
if (ok) {
|
|
dispatch(showReward({reward}));
|
|
dispatch(fetchBalance())
|
|
dispatch(refreshTransactions())
|
|
|
|
}
|
|
|
|
dispatch(endAssembly());
|
|
navigator.navigate('Barcode');
|
|
})
|
|
}
|
|
useEffect(() => {
|
|
onPrintLabel();
|
|
}, []);
|
|
return (<>
|
|
<AssemblyButton
|
|
onPress={onPrintLabel}
|
|
label={"Печать этикетки"}/>
|
|
<AssemblyButton
|
|
onPress={onEndAssembly}
|
|
label={"Завершить сборку"}/>
|
|
</>)
|
|
|
|
}
|
|
|
|
const EndedButtons = () => {
|
|
return (<></>)
|
|
|
|
}
|
|
|
|
const AssemblyControls = () => {
|
|
const state = useSelector((state: RootState) => state.assembly);
|
|
const getButtons = () => {
|
|
if (state.localState === undefined) return (<BasicButton
|
|
label={"Ошибка"}
|
|
disabled={true}
|
|
/>)
|
|
|
|
switch (state.localState) {
|
|
case ASSEMBLY_STATE.NOT_STARTED:
|
|
return <NotStartedButtons/>
|
|
case ASSEMBLY_STATE.SCANNING_CRPT:
|
|
return <ScanningCrptButtons/>
|
|
case ASSEMBLY_STATE.ASSEMBLING_PRODUCTS:
|
|
return <AssemblingButtons/>
|
|
case ASSEMBLY_STATE.ALL_PRODUCTS_ASSEMBLED:
|
|
return <AllProductsAssembledButtons/>
|
|
case ASSEMBLY_STATE.CONFIRMED:
|
|
return <ConfirmedButtons/>
|
|
case ASSEMBLY_STATE.ENDED:
|
|
return <EndedButtons/>
|
|
}
|
|
}
|
|
return (<>{getButtons()}</>)
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
buttonsContainer: {
|
|
backgroundColor: "white",
|
|
padding: RFPercentage(2),
|
|
flex: 0.5,
|
|
borderRadius: RFPercentage(3),
|
|
rowGap: responsiveHeight(2)
|
|
},
|
|
})
|
|
export default AssemblyControls; |