ebanutsya
This commit is contained in:
@@ -3,6 +3,7 @@ import {StyleSheet, TouchableOpacity, Text, View, StyleProp, ViewStyle, GestureR
|
|||||||
import {responsiveHeight, responsiveWidth} from "react-native-responsive-dimensions";
|
import {responsiveHeight, responsiveWidth} from "react-native-responsive-dimensions";
|
||||||
import {RFPercentage} from "react-native-responsive-fontsize";
|
import {RFPercentage} from "react-native-responsive-fontsize";
|
||||||
import DText from "../DText/DText";
|
import DText from "../DText/DText";
|
||||||
|
import DTitle from "../DTitle/DTitle";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
label: string;
|
label: string;
|
||||||
@@ -15,10 +16,11 @@ type Props = {
|
|||||||
|
|
||||||
const BasicButton: FC<Props> = ({label, onPress, containerStyle, style, isUnset = false, disabled = false}) => {
|
const BasicButton: FC<Props> = ({label, onPress, containerStyle, style, isUnset = false, disabled = false}) => {
|
||||||
return (
|
return (
|
||||||
<TouchableOpacity style={{flex: 1}} disabled={disabled} onPress={onPress}>
|
<TouchableOpacity style={containerStyle} disabled={disabled} onPress={onPress}>
|
||||||
|
<View style={[styles.container, style, disabled ? {backgroundColor: "#A0A0A0"} : {}, containerStyle]}>
|
||||||
<View style={[styles.container, style, disabled ? {backgroundColor: "#A0A0A0"} : {}]}>
|
<View style={styles.textWrapper}>
|
||||||
<DText style={styles.text}>{label}</DText>
|
<DText style={styles.text}>{label}</DText>
|
||||||
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
@@ -33,15 +35,15 @@ const styles = StyleSheet.create({
|
|||||||
alignContent: "center",
|
alignContent: "center",
|
||||||
backgroundColor: '#2478F8',
|
backgroundColor: '#2478F8',
|
||||||
borderRadius: responsiveWidth(1),
|
borderRadius: responsiveWidth(1),
|
||||||
padding: responsiveWidth(2),
|
padding: responsiveWidth(3),
|
||||||
flex: 1
|
|
||||||
},
|
},
|
||||||
text: {
|
text: {
|
||||||
color: "white",
|
color: "white",
|
||||||
fontSize: RFPercentage(2),
|
fontSize: RFPercentage(2),
|
||||||
textAlignVertical: "center",
|
textAlignVertical: "center",
|
||||||
textAlign: "center"
|
textAlign: "center",
|
||||||
}
|
},
|
||||||
|
textWrapper: {}
|
||||||
});
|
});
|
||||||
|
|
||||||
export default BasicButton;
|
export default BasicButton;
|
||||||
65
src/components/Modals/AcceptModal/AcceptModal.tsx
Normal file
65
src/components/Modals/AcceptModal/AcceptModal.tsx
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
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 {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 = {
|
||||||
|
visible: boolean;
|
||||||
|
text: string;
|
||||||
|
onAccepted: () => void;
|
||||||
|
onRefused: () => void;
|
||||||
|
}
|
||||||
|
const AcceptModal: FC<Props> = ({visible, text, onAccepted, onRefused}) => {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal isVisible={visible}>
|
||||||
|
<View style={styles.container}>
|
||||||
|
<DTitle style={{textAlign: "center"}}>{text}</DTitle>
|
||||||
|
<View style={styles.buttonsWrapper}>
|
||||||
|
<BasicButton style={[styles.button, styles.acceptButton]} label={"Да"}
|
||||||
|
onPress={() => onAccepted()}/>
|
||||||
|
<BasicButton style={[styles.button, styles.refuseButton]} label={"Нет"}
|
||||||
|
onPress={() => onRefused()}/>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
</View>
|
||||||
|
</Modal>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
alignSelf: "center",
|
||||||
|
backgroundColor: background,
|
||||||
|
width: responsiveWidth(80),
|
||||||
|
height: responsiveHeight(50),
|
||||||
|
borderRadius: responsiveWidth(2),
|
||||||
|
paddingHorizontal: responsiveWidth(15),
|
||||||
|
paddingVertical: responsiveHeight(10),
|
||||||
|
justifyContent: "center",
|
||||||
|
rowGap: responsiveHeight(5)
|
||||||
|
},
|
||||||
|
buttonsWrapper: {
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
},
|
||||||
|
progressBar: {
|
||||||
|
justifyContent: "center"
|
||||||
|
},
|
||||||
|
button: {
|
||||||
|
paddingHorizontal: responsiveWidth(8)
|
||||||
|
},
|
||||||
|
acceptButton: {},
|
||||||
|
refuseButton: {
|
||||||
|
backgroundColor: "red"
|
||||||
|
},
|
||||||
|
})
|
||||||
|
export default AcceptModal;
|
||||||
37
src/components/Modals/ReprintModal/ReprintModal.tsx
Normal file
37
src/components/Modals/ReprintModal/ReprintModal.tsx
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import {FC, useState} from "react";
|
||||||
|
import AcceptModal from "../AcceptModal/AcceptModal";
|
||||||
|
import PrintingService from "../../../utils/PrintingService";
|
||||||
|
import {useDispatch, useSelector} from "react-redux";
|
||||||
|
import {RootState} from "../../../redux/store";
|
||||||
|
import {closeReprintModal, openReprintModal} from "../../../features/reprintModal/reprintModalSlice";
|
||||||
|
import PrintingApi from "../../../api/printingApi";
|
||||||
|
import {closeLoadingModal, openLoadingModal} from "../../../features/loadingModal/loadingModalSlice";
|
||||||
|
|
||||||
|
|
||||||
|
const ReprintModal: FC = () => {
|
||||||
|
const printerName = useSelector((state: RootState) => state.printing.printerName);
|
||||||
|
const order = useSelector((state: RootState) => state.assembly.order);
|
||||||
|
const isVisible = useSelector((state: RootState) => state.reprintModal.isVisible);
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
return (<AcceptModal
|
||||||
|
visible={isVisible}
|
||||||
|
text={"Неудалось распечатать этикетку, повторить попытку?"}
|
||||||
|
onAccepted={() => {
|
||||||
|
if (!printerName || !order) return;
|
||||||
|
dispatch(closeReprintModal());
|
||||||
|
dispatch(openLoadingModal());
|
||||||
|
PrintingApi.getLabel(order.databaseId).then(pdfBytes => {
|
||||||
|
PrintingService.getInstance().printPdf(printerName, pdfBytes).then(r => {
|
||||||
|
dispatch(closeLoadingModal());
|
||||||
|
if (r) dispatch(closeReprintModal());
|
||||||
|
else dispatch(openReprintModal());
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
onRefused={() => {
|
||||||
|
dispatch(closeReprintModal())
|
||||||
|
dispatch(closeLoadingModal());
|
||||||
|
}}/>)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ReprintModal;
|
||||||
@@ -6,18 +6,20 @@ import {responsiveHeight, responsiveWidth} from "react-native-responsive-dimensi
|
|||||||
import DTitle from "../DTitle/DTitle";
|
import DTitle from "../DTitle/DTitle";
|
||||||
import {Order} from "../../types/order";
|
import {Order} from "../../types/order";
|
||||||
import OrderProductsList from "./OrderProductsList";
|
import OrderProductsList from "./OrderProductsList";
|
||||||
|
import {useDispatch} from "react-redux";
|
||||||
|
import {setOrder} from "../../features/assembly/assemblySlice";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onPress?: (event: GestureResponderEvent) => void
|
onPress?: (event: GestureResponderEvent) => void
|
||||||
onSelect: (order: Order) => void
|
|
||||||
order: Order
|
order: Order
|
||||||
|
onSelect: (order: Order) => void
|
||||||
|
|
||||||
}
|
}
|
||||||
const OrderCard: FC<Props> = React.memo(({onPress, onSelect, order}) => {
|
const OrderCard: FC<Props> = ({onPress, onSelect, order}) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TouchableOpacity onPress={() => {
|
<TouchableOpacity onPress={()=>{
|
||||||
onSelect(order);
|
if (onSelect) onSelect(order);
|
||||||
|
|
||||||
}}>
|
}}>
|
||||||
<View style={styles.container}><View style={styles.description}>
|
<View style={styles.container}><View style={styles.description}>
|
||||||
<View style={styles.descriptionContent}>
|
<View style={styles.descriptionContent}>
|
||||||
@@ -28,6 +30,7 @@ const OrderCard: FC<Props> = React.memo(({onPress, onSelect, order}) => {
|
|||||||
</View>
|
</View>
|
||||||
<DText>Селлер: {order.sellerName}</DText>
|
<DText>Селлер: {order.sellerName}</DText>
|
||||||
<DText>Маркетплейс: {order.marketplaceName}</DText>
|
<DText>Маркетплейс: {order.marketplaceName}</DText>
|
||||||
|
<DText>Товаров в заказе: {order.products.length}</DText>
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.descriptionStatus}>
|
<View style={styles.descriptionStatus}>
|
||||||
<DText>
|
<DText>
|
||||||
@@ -40,13 +43,12 @@ const OrderCard: FC<Props> = React.memo(({onPress, onSelect, order}) => {
|
|||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
||||||
)
|
)
|
||||||
})
|
}
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
backgroundColor: "white",
|
backgroundColor: "white",
|
||||||
display: "flex",
|
display: "flex",
|
||||||
borderRadius: RFPercentage(3),
|
borderRadius: RFPercentage(3),
|
||||||
height: responsiveHeight(15),
|
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
padding: RFPercentage(2),
|
padding: RFPercentage(2),
|
||||||
flex: 1
|
flex: 1
|
||||||
@@ -80,7 +82,6 @@ const styles = StyleSheet.create({
|
|||||||
marginLeft: responsiveHeight(1)
|
marginLeft: responsiveHeight(1)
|
||||||
},
|
},
|
||||||
descriptionContent: {
|
descriptionContent: {
|
||||||
// backgroundColor: "green",
|
|
||||||
flex: 1
|
flex: 1
|
||||||
},
|
},
|
||||||
descriptionStatus: {
|
descriptionStatus: {
|
||||||
|
|||||||
@@ -14,9 +14,12 @@ const ScanModal: FC = () => {
|
|||||||
const visible = useSelector((state: RootState) => state.scanModal.isVisible);
|
const visible = useSelector((state: RootState) => state.scanModal.isVisible);
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (visible) inputRef.current?.focus();
|
// if (visible) inputRef.current?.focus();
|
||||||
|
if (visible){
|
||||||
|
dispatch(setScannedData('4750735280715'));
|
||||||
|
dispatch(closeScanModal())
|
||||||
|
}
|
||||||
}, [visible]);
|
}, [visible]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal isVisible={visible}>
|
<Modal isVisible={visible}>
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
|
|||||||
@@ -25,10 +25,12 @@ const SearchBar: FC<Props> = ({onSearch, onSupplierProductSelected}) => {
|
|||||||
const scannedData = useSelector((state: RootState) => state.scanModal.scannedData);
|
const scannedData = useSelector((state: RootState) => state.scanModal.scannedData);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!scannedData) return;
|
if (!scannedData) return;
|
||||||
barcodeApi.searchProducts(scannedData).then(setProducts);
|
barcodeApi.searchProducts(scannedData).then((response) => {
|
||||||
|
console.log("Response: " + response);
|
||||||
|
setProducts(response)
|
||||||
|
});
|
||||||
}, [scannedData]);
|
}, [scannedData]);
|
||||||
|
const selectProductModalVisible = products.length > 0;
|
||||||
const selectProductModalVisible = products.length > 0 && false;
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
|
|
||||||
@@ -74,6 +76,7 @@ const styles = StyleSheet.create({
|
|||||||
borderRadius: 0,
|
borderRadius: 0,
|
||||||
borderTopRightRadius: responsiveWidth(1),
|
borderTopRightRadius: responsiveWidth(1),
|
||||||
borderBottomRightRadius: responsiveWidth(1),
|
borderBottomRightRadius: responsiveWidth(1),
|
||||||
|
paddingHorizontal: responsiveWidth(5)
|
||||||
},
|
},
|
||||||
scanImageWrapper: {
|
scanImageWrapper: {
|
||||||
paddingHorizontal: responsiveWidth(1),
|
paddingHorizontal: responsiveWidth(1),
|
||||||
@@ -85,14 +88,13 @@ const styles = StyleSheet.create({
|
|||||||
},
|
},
|
||||||
textInput: {
|
textInput: {
|
||||||
height: responsiveHeight(height),
|
height: responsiveHeight(height),
|
||||||
flex: 2,
|
flex: 1,
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
borderColor: "#A5A5A5",
|
borderColor: "#A5A5A5",
|
||||||
borderTopLeftRadius: responsiveWidth(1),
|
borderTopLeftRadius: responsiveWidth(1),
|
||||||
borderBottomLeftRadius: responsiveWidth(1),
|
borderBottomLeftRadius: responsiveWidth(1),
|
||||||
paddingLeft: responsiveHeight(2),
|
paddingLeft: responsiveHeight(2),
|
||||||
fontSize: RFPercentage(2),
|
fontSize: RFPercentage(2),
|
||||||
// fontFamily: 'SF Pro Text'
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import {createSlice} from "@reduxjs/toolkit";
|
import {createSlice, PayloadAction} from "@reduxjs/toolkit";
|
||||||
import {Order} from "../../types/order";
|
import {Order} from "../../types/order";
|
||||||
|
|
||||||
export interface AssemblyState {
|
export interface AssemblyState {
|
||||||
@@ -16,13 +16,30 @@ export const assembly = createSlice({
|
|||||||
setOrder: (state, action) => {
|
setOrder: (state, action) => {
|
||||||
state.order = action.payload;
|
state.order = action.payload;
|
||||||
},
|
},
|
||||||
setAssembled: (state, payload) => {
|
setAssembled: (state, action: PayloadAction<{ orderProductId: number }>) => {
|
||||||
state.order = ({...state.order, orderNumber:"2282"})
|
if (!state.order || !state.order.products) return;
|
||||||
|
|
||||||
|
const orderProductId = action.payload.orderProductId;
|
||||||
|
|
||||||
|
state.order.products.forEach(product => {
|
||||||
|
if (product.databaseId === orderProductId) {
|
||||||
|
product.assembled = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
setShipped: (state) => {
|
setShipped: (state, action: PayloadAction<{ orderProductId: number }>) => {
|
||||||
|
if (!state.order || !state.order.products) return;
|
||||||
|
|
||||||
|
const orderProductId = action.payload.orderProductId;
|
||||||
|
|
||||||
|
state.order.products.forEach(product => {
|
||||||
|
if (product.databaseId === orderProductId) {
|
||||||
|
product.shipped = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export const {setOrder} = assembly.actions;
|
export const {setOrder, setAssembled, setShipped} = assembly.actions;
|
||||||
export default assembly.reducer;
|
export default assembly.reducer;
|
||||||
22
src/features/printing/printingSlice.ts
Normal file
22
src/features/printing/printingSlice.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import {createSlice, PayloadAction} from "@reduxjs/toolkit";
|
||||||
|
|
||||||
|
export interface PrintingState {
|
||||||
|
printerName?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialState: PrintingState = {
|
||||||
|
printerName: undefined,
|
||||||
|
}
|
||||||
|
export const printingSlice = createSlice({
|
||||||
|
name: 'printing',
|
||||||
|
initialState,
|
||||||
|
reducers: {
|
||||||
|
setPrinterName: (state, action: PayloadAction<{ printerName: string }>) => {
|
||||||
|
state.printerName = action.payload.printerName;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export const {setPrinterName} = printingSlice.actions;
|
||||||
|
export default printingSlice.reducer;
|
||||||
25
src/features/reprintModal/reprintModalSlice.ts
Normal file
25
src/features/reprintModal/reprintModalSlice.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import {createSlice} from "@reduxjs/toolkit";
|
||||||
|
|
||||||
|
export interface ReprintModalState {
|
||||||
|
isVisible: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialState: ReprintModalState = {
|
||||||
|
isVisible: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
export const reprintModalSlice = createSlice({
|
||||||
|
name: 'reprintModal',
|
||||||
|
initialState,
|
||||||
|
reducers: {
|
||||||
|
openReprintModal: (state) => {
|
||||||
|
state.isVisible = true
|
||||||
|
},
|
||||||
|
closeReprintModal: (state) => {
|
||||||
|
state.isVisible = false
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
export const {openReprintModal, closeReprintModal} = reprintModalSlice.actions;
|
||||||
|
export default reprintModalSlice.reducer;
|
||||||
@@ -5,6 +5,8 @@ import interfaceReducer from 'features/interface/interfaceSlice';
|
|||||||
import scanModalReducer from 'features/scanModal/scanModalSlice';
|
import scanModalReducer from 'features/scanModal/scanModalSlice';
|
||||||
import loadingModalReducer from 'features/loadingModal/loadingModalSlice';
|
import loadingModalReducer from 'features/loadingModal/loadingModalSlice';
|
||||||
import assemblyReducer from 'features/assembly/assemblySlice';
|
import assemblyReducer from 'features/assembly/assemblySlice';
|
||||||
|
import printingReducer from 'features/printing/printingSlice';
|
||||||
|
import reprintModalReducer from 'features/reprintModal/reprintModalSlice';
|
||||||
import {useDispatch} from "react-redux";
|
import {useDispatch} from "react-redux";
|
||||||
|
|
||||||
export const store = configureStore({
|
export const store = configureStore({
|
||||||
@@ -13,7 +15,9 @@ export const store = configureStore({
|
|||||||
interface: interfaceReducer,
|
interface: interfaceReducer,
|
||||||
scanModal: scanModalReducer,
|
scanModal: scanModalReducer,
|
||||||
loadingModal: loadingModalReducer,
|
loadingModal: loadingModalReducer,
|
||||||
assembly: assemblyReducer
|
assembly: assemblyReducer,
|
||||||
|
printing: printingReducer,
|
||||||
|
reprintModal: reprintModalReducer
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import toastConfig from "../../components/Toast/Toast";
|
|||||||
import ScanModal from "../../components/SearchBar/ScanModal";
|
import ScanModal from "../../components/SearchBar/ScanModal";
|
||||||
import {closeScanModal, setScannedData} from "../../features/scanModal/scanModalSlice";
|
import {closeScanModal, setScannedData} from "../../features/scanModal/scanModalSlice";
|
||||||
import LoadingModal from "../../components/Modals/LoadingModal/LoadingModal";
|
import LoadingModal from "../../components/Modals/LoadingModal/LoadingModal";
|
||||||
|
import ReprintModal from "../../components/Modals/ReprintModal/ReprintModal";
|
||||||
|
|
||||||
function CommonPage() {
|
function CommonPage() {
|
||||||
const dim = useSelector((state: RootState) => state.interface.dim);
|
const dim = useSelector((state: RootState) => state.interface.dim);
|
||||||
@@ -37,6 +38,7 @@ function CommonPage() {
|
|||||||
<View style={[styles.overlay, {display: dim ? 'flex' : 'none'}]}/>
|
<View style={[styles.overlay, {display: dim ? 'flex' : 'none'}]}/>
|
||||||
<LoadingModal/>
|
<LoadingModal/>
|
||||||
<ScanModal/>
|
<ScanModal/>
|
||||||
|
<ReprintModal/>
|
||||||
<Toast config={toastConfig}/>
|
<Toast config={toastConfig}/>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import moneyScreen from "../MoneyScreen/MoneyScreen";
|
|||||||
import profileScreen from "../ProfileScreen/ProfileScreen";
|
import profileScreen from "../ProfileScreen/ProfileScreen";
|
||||||
import {responsiveHeight, responsiveWidth} from "react-native-responsive-dimensions";
|
import {responsiveHeight, responsiveWidth} from "react-native-responsive-dimensions";
|
||||||
import {RFPercentage} from "react-native-responsive-fontsize";
|
import {RFPercentage} from "react-native-responsive-fontsize";
|
||||||
import OrderScreen from "../OrderScreen/OrderScreen";
|
import OrderScreen, {OrderScreenController} from "../OrderScreen/OrderScreen";
|
||||||
import OrdersScreen from "../OrdersScreen/OrdersScreen";
|
import OrdersScreen from "../OrdersScreen/OrdersScreen";
|
||||||
import {background} from "../../css/colors";
|
import {background} from "../../css/colors";
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
@@ -50,7 +50,7 @@ function MainScreen() {
|
|||||||
const tabScreens: CustomTabProps[] = [
|
const tabScreens: CustomTabProps[] = [
|
||||||
{
|
{
|
||||||
name: "Home",
|
name: "Home",
|
||||||
component: OrderScreen,
|
component: OrderScreenController,
|
||||||
icon: require('assets/icons/home.png'),
|
icon: require('assets/icons/home.png'),
|
||||||
hidden: false
|
hidden: false
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {RFPercentage} from "react-native-responsive-fontsize";
|
|||||||
import DTitle from "../../components/DTitle/DTitle";
|
import DTitle from "../../components/DTitle/DTitle";
|
||||||
import BasicButton from "../../components/BasicButton/BasicButton";
|
import BasicButton from "../../components/BasicButton/BasicButton";
|
||||||
import Hyperlink from "../../components/Hyperlink/Hyperlink";
|
import Hyperlink from "../../components/Hyperlink/Hyperlink";
|
||||||
import React, {useEffect, useState} from "react";
|
import React, {FC, useEffect, useState} from "react";
|
||||||
import userApi from "../../api/userApi";
|
import userApi from "../../api/userApi";
|
||||||
import {StatusBar} from "expo-status-bar";
|
import {StatusBar} from "expo-status-bar";
|
||||||
import * as Progress from 'react-native-progress';
|
import * as Progress from 'react-native-progress';
|
||||||
@@ -16,17 +16,25 @@ import {useNavigation} from "@react-navigation/native";
|
|||||||
import printingApi from "../../api/printingApi";
|
import printingApi from "../../api/printingApi";
|
||||||
import PrintingService from "../../utils/PrintingService";
|
import PrintingService from "../../utils/PrintingService";
|
||||||
import OrderProductsList from "../../components/OrderCard/OrderProductsList";
|
import OrderProductsList from "../../components/OrderCard/OrderProductsList";
|
||||||
import {setOrder} from "../../features/assembly/assemblySlice";
|
import {setAssembled, setOrder} 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 {setData, setPrinterName} from "../../features/printing/printingSlice";
|
||||||
|
import {openReprintModal} from "../../features/reprintModal/reprintModalSlice";
|
||||||
|
|
||||||
|
type AssemblyPeriod = {
|
||||||
|
started: Date;
|
||||||
|
ended: Date;
|
||||||
|
}
|
||||||
|
|
||||||
function OrderScreen() {
|
const NoOrderScreen: FC = () => {
|
||||||
|
return (
|
||||||
const order = useSelector((state: RootState) => state.assembly.order);
|
|
||||||
if (!order) return (
|
|
||||||
<View style={noOrderStyles.container}>
|
<View style={noOrderStyles.container}>
|
||||||
<DText style={noOrderStyles.title}>Заказ не выбран!</DText>
|
<DText style={noOrderStyles.title}>Заказ не выбран!</DText>
|
||||||
<View style={noOrderStyles.buttonWrapper}>
|
<View style={noOrderStyles.buttonWrapper}>
|
||||||
|
|
||||||
<BasicButton onPress={() => {
|
<BasicButton onPress={() => {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
navigator.navigate("Box");
|
navigator.navigate("Box");
|
||||||
@@ -35,16 +43,68 @@ function OrderScreen() {
|
|||||||
|
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
const dispatch = useDispatch();
|
}
|
||||||
const assembled = useSelector((state: RootState) => state.assembly.assembled);
|
const noOrderStyles = StyleSheet.create({
|
||||||
const shipped = useSelector((state: RootState) => state.assembly.shipped);
|
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 navigator = useNavigation();
|
||||||
|
const dispatch = useDispatch();
|
||||||
const [selectedProduct, setSelectedProduct] = useState(order.products[0]);
|
const [selectedProduct, setSelectedProduct] = useState(order.products[0]);
|
||||||
|
const [assemblyPeriod, setAssemblyPeriod] = useState<AssemblyPeriod>({started: new Date(), ended: new Date()})
|
||||||
|
const [acceptModalVisible, setAcceptModalVisible] = useState(false);
|
||||||
|
const [reprintModalVisible, setReprintModalVisible] = useState(false);
|
||||||
|
|
||||||
|
const [assemblyStarted, setAssemblyStarted] = useState(false);
|
||||||
|
const [assemblyIntervalId, setAssemblyIntervalId] = useState(0);
|
||||||
|
const prettyPrintMilliseconds = (milliseconds: number) => {
|
||||||
|
const totalSeconds = Math.floor(milliseconds / 1000);
|
||||||
|
const minutes = Math.floor(totalSeconds / 60);
|
||||||
|
const seconds = totalSeconds % 60;
|
||||||
|
|
||||||
|
// Форматируем минуты и секунды, чтобы они всегда были двузначными
|
||||||
|
const formattedMinutes = String(minutes).padStart(2, '0');
|
||||||
|
const formattedSeconds = String(seconds).padStart(2, '0');
|
||||||
|
|
||||||
|
return `${formattedMinutes}:${formattedSeconds}`;
|
||||||
|
}
|
||||||
|
const startAssembly = async () => {
|
||||||
|
setAssemblyStarted(true);
|
||||||
|
let intervalId = setInterval(() => {
|
||||||
|
setAssemblyPeriod(oldValue => ({...oldValue, ended: new Date()}))
|
||||||
|
}, 1000);
|
||||||
|
setAssemblyIntervalId(Number(intervalId))
|
||||||
|
};
|
||||||
|
useEffect(() => {
|
||||||
|
let newSelectedProduct = order.products.find(o => o.databaseId == selectedProduct.databaseId);
|
||||||
|
if (!newSelectedProduct) return;
|
||||||
|
setSelectedProduct(newSelectedProduct);
|
||||||
|
}, [order]);
|
||||||
|
useEffect(() => {
|
||||||
|
dispatch(closeLoadingModal())
|
||||||
|
}, []);
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<View style={styles.productsContainer}>
|
<View style={styles.productsContainer}>
|
||||||
<View style={styles.orderProductsListWrapper}>
|
<View style={styles.orderProductsListWrapper}>
|
||||||
<OrderProductsList products={order.products} onSelected={() => {
|
<OrderProductsList products={order.products} onSelected={(product) => {
|
||||||
|
if (!order) return;
|
||||||
|
setSelectedProduct(product)
|
||||||
}}/>
|
}}/>
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.imageWrapper}>
|
<View style={styles.imageWrapper}>
|
||||||
@@ -62,37 +122,68 @@ function OrderScreen() {
|
|||||||
<DText>Артикул DENCO: {selectedProduct.dencoArticle}</DText>
|
<DText>Артикул DENCO: {selectedProduct.dencoArticle}</DText>
|
||||||
<DText>Поставщик: {selectedProduct.supplierName}</DText>
|
<DText>Поставщик: {selectedProduct.supplierName}</DText>
|
||||||
<DText>Номер товара: {0}</DText>
|
<DText>Номер товара: {0}</DText>
|
||||||
|
<DText>{}</DText>
|
||||||
|
<DTitle style={styles.contentTitle}>Сборка</DTitle>
|
||||||
|
<DText>Затрачено
|
||||||
|
времени: {prettyPrintMilliseconds(assemblyPeriod.ended.getTime() - assemblyPeriod.started.getTime())}</DText>
|
||||||
|
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.buttonsContainer}>
|
<View style={styles.buttonsContainer}>
|
||||||
<BasicButton label={"Отметить как собранный"}
|
{assemblyStarted ? <>
|
||||||
disabled={!selectedProduct.assembled}
|
<BasicButton
|
||||||
onPress={()=>{
|
containerStyle={styles.buttonContainer}
|
||||||
setOrder(oldValue => ({ ...oldValue }));
|
label={"Отметить как собранный"}
|
||||||
}}
|
disabled={selectedProduct.assembled}
|
||||||
/>
|
onPress={() => {
|
||||||
<BasicButton label={"Печать этикетки"}
|
dispatch(setAssembled({orderProductId: selectedProduct.databaseId}))
|
||||||
disabled={Boolean(order.products.find(product => product.assembled))}/>
|
}}
|
||||||
|
/>
|
||||||
|
<BasicButton
|
||||||
|
onPress={() => {
|
||||||
|
if (!order) return;
|
||||||
|
dispatch(setLoadingText('Идет печать этикетки...'))
|
||||||
|
dispatch(openLoadingModal())
|
||||||
|
printingApi.getLabel(order.databaseId).then(pdfData => {
|
||||||
|
printingService.getInstance().printPdf('ozon', pdfData).then((response) => {
|
||||||
|
dispatch(closeLoadingModal());
|
||||||
|
if (response) return;
|
||||||
|
dispatch(setPrinterName({printerName: 'ozon'}));
|
||||||
|
dispatch(openReprintModal());
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
containerStyle={styles.buttonContainer}
|
||||||
|
label={"Печать этикетки"}
|
||||||
|
disabled={Boolean(order.products.find(product => !product.assembled))}/>
|
||||||
|
</>
|
||||||
|
: <BasicButton containerStyle={styles.buttonContainer}
|
||||||
|
onPress={() => setAcceptModalVisible(true)}
|
||||||
|
label={"Начать сборку"}/>}
|
||||||
|
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
<AcceptModal visible={acceptModalVisible}
|
||||||
|
text={`Вы уверены что хотите начать сборку заказа ${order.orderNumber}`}
|
||||||
|
onAccepted={() => {
|
||||||
|
setAcceptModalVisible(false);
|
||||||
|
startAssembly();
|
||||||
|
}}
|
||||||
|
onRefused={() => {
|
||||||
|
setAcceptModalVisible(false);
|
||||||
|
}}/>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const noOrderStyles = StyleSheet.create({
|
export const OrderScreenController: FC = () => {
|
||||||
container: {
|
const order: Order | undefined = useSelector((state: RootState) => state.assembly.order);
|
||||||
justifyContent: "center",
|
if (!order) return <NoOrderScreen/>
|
||||||
flex: 1,
|
console.log(order)
|
||||||
rowGap: responsiveHeight(5)
|
return <OrderScreen order={order}/>
|
||||||
},
|
}
|
||||||
title: {
|
|
||||||
textAlign: "center",
|
|
||||||
fontSize: responsiveWidth(5)
|
|
||||||
},
|
|
||||||
buttonWrapper: {
|
|
||||||
paddingHorizontal: responsiveWidth(20)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
orderProductsListWrapper: {
|
orderProductsListWrapper: {
|
||||||
flex: 0.5,
|
flex: 0.5,
|
||||||
@@ -100,9 +191,8 @@ const styles = StyleSheet.create({
|
|||||||
borderRadius: RFPercentage(3),
|
borderRadius: RFPercentage(3),
|
||||||
padding: RFPercentage(2),
|
padding: RFPercentage(2),
|
||||||
},
|
},
|
||||||
buttonWrapper: {
|
buttonContainer: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
backgroundColor: "red"
|
|
||||||
},
|
},
|
||||||
dataContainer: {
|
dataContainer: {
|
||||||
backgroundColor: "white",
|
backgroundColor: "white",
|
||||||
|
|||||||
@@ -1,27 +1,18 @@
|
|||||||
import {ActivityIndicator, FlatList, ScrollView, StyleSheet, View} from "react-native";
|
import {StyleSheet, View} from "react-native";
|
||||||
import SearchBar from "../../components/SearchBar/SearchBar";
|
import SearchBar from "../../components/SearchBar/SearchBar";
|
||||||
import OrderCard from "../../components/OrderCard/OrderCard";
|
import OrderCard from "../../components/OrderCard/OrderCard";
|
||||||
import {RFPercentage} from "react-native-responsive-fontsize";
|
import {RFPercentage} from "react-native-responsive-fontsize";
|
||||||
import {responsiveHeight, responsiveWidth} from "react-native-responsive-dimensions";
|
import {responsiveHeight, responsiveWidth} from "react-native-responsive-dimensions";
|
||||||
import SortingButton from "../../components/SortingButton/SortingButton";
|
import SortingButton from "../../components/SortingButton/SortingButton";
|
||||||
import {useDispatch, useSelector} from "react-redux";
|
import {useDispatch} from "react-redux";
|
||||||
import {enableDim, disableDim} from "../../features/interface/interfaceSlice";
|
import {useEffect, useRef, useState} from "react";
|
||||||
import {BottomSheetModal} from "@gorhom/bottom-sheet";
|
import {Order} from "../../types/order";
|
||||||
import {useEffect, useMemo, useRef, useState} from "react";
|
|
||||||
import {RadioButton, Button} from "react-native-paper";
|
|
||||||
import DText from "../../components/DText/DText";
|
|
||||||
import {background, blue} from "../../css/colors";
|
|
||||||
import DTitle from "../../components/DTitle/DTitle";
|
|
||||||
import BasicButton from "../../components/BasicButton/BasicButton";
|
|
||||||
import {generateRandomOrders, Order} from "../../types/order";
|
|
||||||
import {FlashList} from "@shopify/flash-list";
|
import {FlashList} from "@shopify/flash-list";
|
||||||
import SortingModal, {
|
import SortingModal, {
|
||||||
SortingModalElement,
|
SortingModalElement,
|
||||||
SortingModalHandles
|
SortingModalHandles
|
||||||
} from "../../components/Modals/SortingModal/SortingModal";
|
} from "../../components/Modals/SortingModal/SortingModal";
|
||||||
import sortingModal from "../../components/Modals/SortingModal/SortingModal";
|
|
||||||
import flashListSeparator from "../../components/FlashListSeparator/FlashListSeparator";
|
import flashListSeparator from "../../components/FlashListSeparator/FlashListSeparator";
|
||||||
import {RootState} from "../../redux/store";
|
|
||||||
import ordersApi from "../../api/ordersApi";
|
import ordersApi from "../../api/ordersApi";
|
||||||
import {setOrder} from "../../features/assembly/assemblySlice";
|
import {setOrder} from "../../features/assembly/assemblySlice";
|
||||||
import {NavigationProp, useNavigation} from "@react-navigation/native";
|
import {NavigationProp, useNavigation} from "@react-navigation/native";
|
||||||
@@ -61,10 +52,7 @@ function OrdersScreen() {
|
|||||||
data={orders}
|
data={orders}
|
||||||
keyExtractor={(item: Order) => item.orderNumber.toString()}
|
keyExtractor={(item: Order) => item.orderNumber.toString()}
|
||||||
renderItem={({item}) =>
|
renderItem={({item}) =>
|
||||||
<OrderCard order={item} onSelect={(order) => {
|
<OrderCard onSelect={(order) => dispatch(setOrder(order))} order={item}/>}
|
||||||
dispatch(setOrder(order));
|
|
||||||
navigator.navigate("Home");
|
|
||||||
}}/>}
|
|
||||||
showsHorizontalScrollIndicator={false}
|
showsHorizontalScrollIndicator={false}
|
||||||
showsVerticalScrollIndicator={true}
|
showsVerticalScrollIndicator={true}
|
||||||
onEndReachedThreshold={0.1}
|
onEndReachedThreshold={0.1}
|
||||||
|
|||||||
@@ -17,16 +17,16 @@ class PrintingService {
|
|||||||
this.port = port;
|
this.port = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async print(printer: string, type: string, bytes: Uint8Array): Promise<string> {
|
private async print(printer: string, type: string, bytes: Uint8Array): Promise<boolean> {
|
||||||
let response = await axios.post(`http://${this.apiUrl}:${this.port}/print/${printer}/${type}`, bytes.buffer);
|
let response = await axios.post(`http://${this.apiUrl}:${this.port}/print/${printer}/${type}`, bytes.buffer);
|
||||||
return response.data;
|
return response.data.ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async printPdf(printer: string, pdfBytes: Uint8Array): Promise<string> {
|
public async printPdf(printer: string, pdfBytes: Uint8Array): Promise<boolean> {
|
||||||
return this.print(printer, "pdf", pdfBytes);
|
return this.print(printer, "pdf", pdfBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async printImage(printer: string, imageBytes: Uint8Array): Promise<string> {
|
public async printImage(printer: string, imageBytes: Uint8Array): Promise<boolean> {
|
||||||
return this.print(printer, "image", imageBytes);
|
return this.print(printer, "image", imageBytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user