From b34bd9a0d418f2e334fc6f2174c6213d1c6f73f8 Mon Sep 17 00:00:00 2001 From: fakz9 Date: Wed, 20 Dec 2023 01:05:46 +0300 Subject: [PATCH] feat: cancel assembly --- src/api/assemblyApi.ts | 16 +++++++- .../Modals/AcceptModal/AcceptModal.tsx | 8 +--- .../CancelAssemblyModal.tsx | 31 ++++++++++++++ .../cancelAssemblyModalSlice.ts | 32 +++++++++++++++ src/redux/store.ts | 4 +- src/screens/CommonPage/CommonPage.tsx | 3 +- src/screens/OrderScreen/OrderScreen.tsx | 41 ++++++++++++------- 7 files changed, 111 insertions(+), 24 deletions(-) create mode 100644 src/components/Modals/CancelAssemblyModal/CancelAssemblyModal.tsx create mode 100644 src/features/cancelAssemblyModal/cancelAssemblyModalSlice.ts diff --git a/src/api/assemblyApi.ts b/src/api/assemblyApi.ts index da1eae4..4ce3db3 100644 --- a/src/api/assemblyApi.ts +++ b/src/api/assemblyApi.ts @@ -1,5 +1,6 @@ import apiClient from "./apiClient"; import {Assembly} from "../types/assembly"; +import {closeCancelAssemblyModal} from "../features/cancelAssemblyModal/cancelAssemblyModalSlice"; const router = '/assembly'; @@ -8,7 +9,8 @@ const assemblyApi = { ok: boolean, message: string, assemblyId: number, - statusCode: string + statusCode: AssemblyCreationStatusCode, + userName?: string }> => { let response = await apiClient.post(`${router}/create`, {orderId}); return response.data; @@ -36,7 +38,19 @@ const assemblyApi = { confirm: async (assemblyId: number): Promise<{ ok: boolean, message: string }> => { let response = await apiClient.post(`${router}/confirm`, {assemblyId}); return response.data; + }, + cancelById: async (assemblyId: number): Promise<{ ok: boolean, message: string }> => { + let response = await apiClient.post(`${router}/cancelById`, {assemblyId}); + return response.data; } } + +export enum AssemblyCreationStatusCode { + ASSEMBLY_ALREADY_EXISTS = "ASSEMBLY_ALREADY_EXISTS", + USER_ALREADY_HAS_ACTIVE_ASSEMBLY = "USER_ALREADY_HAS_ACTIVE_ASSEMBLY", + CREATED = "CREATED", + INVALID_EXCEPTION = "INVALID_EXCEPTION" +} + export default assemblyApi; \ No newline at end of file diff --git a/src/components/Modals/AcceptModal/AcceptModal.tsx b/src/components/Modals/AcceptModal/AcceptModal.tsx index 05342eb..69c769a 100644 --- a/src/components/Modals/AcceptModal/AcceptModal.tsx +++ b/src/components/Modals/AcceptModal/AcceptModal.tsx @@ -1,14 +1,10 @@ import {FC} from "react"; import {StyleSheet, View} from "react-native"; -import {BottomSheetModalProvider} from "@gorhom/bottom-sheet"; -import {useSelector} from "react-redux"; -import {RootState} from "../../../redux/store"; + import Modal from "react-native-modal"; -import {background, blue} from "../../../css/colors"; +import {background} from "../../../css/colors"; import {responsiveHeight, responsiveWidth} from "react-native-responsive-dimensions"; -import * as Progress from 'react-native-progress'; import DTitle from "../../DTitle/DTitle"; -import {RFPercentage} from "react-native-responsive-fontsize"; import BasicButton from "../../BasicButton/BasicButton"; type Props = { diff --git a/src/components/Modals/CancelAssemblyModal/CancelAssemblyModal.tsx b/src/components/Modals/CancelAssemblyModal/CancelAssemblyModal.tsx new file mode 100644 index 0000000..df2dfdf --- /dev/null +++ b/src/components/Modals/CancelAssemblyModal/CancelAssemblyModal.tsx @@ -0,0 +1,31 @@ +import {FC} from "react"; +import AcceptModal from "../AcceptModal/AcceptModal"; +import {RootState} from "../../../redux/store"; +import {useDispatch, useSelector} from "react-redux"; +import assemblyApi from "../../../api/assemblyApi"; +import Toast from "react-native-toast-message"; +import {closeCancelAssemblyModal} from "../../../features/cancelAssemblyModal/cancelAssemblyModalSlice"; + +const CancelAssemblyModal: FC = () => { + const state = useSelector((state: RootState) => state.cancelAssemblyModal); + const dispatch = useDispatch(); + const onAccepted = () => { + if (!state.assemblyId) return; + assemblyApi.cancelById(state.assemblyId).then(({ok, message}) => { + Toast.show({ + type: ok ? 'success' : 'error', + text1: "Отмена сборки", + text2: message + }) + dispatch(closeCancelAssemblyModal()); + }) + } + const onRefused = () => { + dispatch(closeCancelAssemblyModal()); + } + return () +} + +export default CancelAssemblyModal; \ No newline at end of file diff --git a/src/features/cancelAssemblyModal/cancelAssemblyModalSlice.ts b/src/features/cancelAssemblyModal/cancelAssemblyModalSlice.ts new file mode 100644 index 0000000..4cd4cec --- /dev/null +++ b/src/features/cancelAssemblyModal/cancelAssemblyModalSlice.ts @@ -0,0 +1,32 @@ +import {createSlice, PayloadAction} from "@reduxjs/toolkit"; +import {startAssembly} from "../assembly/assemblySlice"; +import assemblyApi from "../../api/assemblyApi"; + +export interface CancelAssemblyModalState { + isVisible: boolean; + message: string; + assemblyId?: number; +} + +const initialState: CancelAssemblyModalState = { + isVisible: false, + message: "" +} + +export const cancelAssemblyModalSlice = createSlice({ + name: 'cancelAssemblyModal', + initialState, + reducers: { + openCancelAssemblyModal: (state, action: PayloadAction<{ assemblyId: number, message: string }>) => { + state.isVisible = true; + state.assemblyId = action.payload.assemblyId; + state.message = action.payload.message; + }, + closeCancelAssemblyModal: (state) => { + state.isVisible = false + }, + } +}) +export const {openCancelAssemblyModal, closeCancelAssemblyModal} = cancelAssemblyModalSlice.actions + +export default cancelAssemblyModalSlice.reducer; \ No newline at end of file diff --git a/src/redux/store.ts b/src/redux/store.ts index 5e47c56..074aacd 100644 --- a/src/redux/store.ts +++ b/src/redux/store.ts @@ -11,6 +11,7 @@ import reprintModalReducer from 'features/reprintModal/reprintModalSlice'; import ordersFilterReducer from 'features/ordersFilter/ordersFilterSlice'; import shippingWarehouseSelectReducer from 'features/shippingWarehouseSelect/shippingWarehouseSelectSlice'; import citySelectReducer from 'features/citySelect/citySelectSlice'; +import cancelAssemblyModal from 'features/cancelAssemblyModal/cancelAssemblyModalSlice'; import {useDispatch} from "react-redux"; export const store = configureStore({ @@ -25,7 +26,8 @@ export const store = configureStore({ imageZoomModal: imageZoomModalReducer, ordersFilter: ordersFilterReducer, shippingWarehouseSelect: shippingWarehouseSelectReducer, - citySelect: citySelectReducer + citySelect: citySelectReducer, + cancelAssemblyModal: cancelAssemblyModal }, }); diff --git a/src/screens/CommonPage/CommonPage.tsx b/src/screens/CommonPage/CommonPage.tsx index 087b478..be0f491 100644 --- a/src/screens/CommonPage/CommonPage.tsx +++ b/src/screens/CommonPage/CommonPage.tsx @@ -30,6 +30,7 @@ import { setLoadingText, setProgress } from "../../features/loadingModal/loadingModalSlice"; +import CancelAssemblyModal from "../../components/Modals/CancelAssemblyModal/CancelAssemblyModal"; function CommonPage() { const dim = useSelector((state: RootState) => state.interface.dim); @@ -61,7 +62,6 @@ function CommonPage() { }) } - const checkUpdates = async () => { const currentVersion = Constants.manifest2?.extra?.expoClient?.version || Constants.manifest?.version; @@ -96,6 +96,7 @@ function CommonPage() { + diff --git a/src/screens/OrderScreen/OrderScreen.tsx b/src/screens/OrderScreen/OrderScreen.tsx index 7e05238..b5c7675 100644 --- a/src/screens/OrderScreen/OrderScreen.tsx +++ b/src/screens/OrderScreen/OrderScreen.tsx @@ -1,4 +1,4 @@ -import {View, Image, StyleSheet, TouchableOpacity, ScrollView} from "react-native"; +import {Image, ScrollView, StyleSheet, TouchableOpacity, View} from "react-native"; import {responsiveHeight, responsiveWidth} from "react-native-responsive-dimensions"; import DText from "../../components/DText/DText"; import {RFPercentage} from "react-native-responsive-fontsize"; @@ -10,31 +10,27 @@ 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, + 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 assemblyApi, {AssemblyCreationStatusCode} from "../../api/assemblyApi"; import Toast from "react-native-toast-message"; -import mainScreen, {TabNavigatorParamList} from "../MainScreen/MainScreen"; -import toast from "../../components/Toast/Toast"; +import {TabNavigatorParamList} from "../MainScreen/MainScreen"; import {openImageZoomModal, setImages} from "../../features/imageZoomModal/loadingModalSlice"; import {OrderStatus, OrderStatusDictionary} from "../../features/ordersFilter/ordersFilterSlice"; +import {openCancelAssemblyModal} from "../../features/cancelAssemblyModal/cancelAssemblyModalSlice"; type AssemblyPeriod = { @@ -262,13 +258,28 @@ const OrderScreen: FC = ({order}) => { text={`Вы уверены что хотите начать сборку заказа ${order.orderNumber}`} onAccepted={() => { setAcceptModalVisible(false); - assemblyApi.create(order.databaseId).then(creationResult => { + assemblyApi.create(order.databaseId).then(({ + ok, + assemblyId, + message, + statusCode, + userName + }) => { Toast.show({ - type: creationResult.ok ? 'success' : 'error', + type: ok ? 'success' : 'error', text1: 'Создание сборки', - text2: creationResult.message + text2: message }); - if (!creationResult.ok) return; + if (!ok) { + if (statusCode !== AssemblyCreationStatusCode.ASSEMBLY_ALREADY_EXISTS) return; + const message = + `Заказ собирает ${userName}. Отменить и начать сборку на ваш аккаунт?\n\n` + + 'Удостоверьтесь, что текущая сборка ошибочна и никто другой её не выполняет.'; + + dispatch(openCancelAssemblyModal({assemblyId: assemblyId, message: message})); + + return; + } assemblyApi.getActive().then(activeAssembly => { dispatch(setAssembly(activeAssembly)); dispatch(startAssembly())