Files
Assemblr/src/screens/AssemblyScreen/AssemblyControls.tsx
2024-10-12 03:55:19 +03:00

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;