ebanutsya
This commit is contained in:
@@ -14,6 +14,8 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@expo/webpack-config": "^19.0.0",
|
"@expo/webpack-config": "^19.0.0",
|
||||||
"@gorhom/bottom-sheet": "^4",
|
"@gorhom/bottom-sheet": "^4",
|
||||||
|
"@react-native-community/datetimepicker": "7.2.0",
|
||||||
|
"@react-native-picker/picker": "^2.5.1",
|
||||||
"@react-navigation/bottom-tabs": "^6.5.8",
|
"@react-navigation/bottom-tabs": "^6.5.8",
|
||||||
"@react-navigation/native": "^6.1.7",
|
"@react-navigation/native": "^6.1.7",
|
||||||
"@reduxjs/toolkit": "^1.9.5",
|
"@reduxjs/toolkit": "^1.9.5",
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ export default function App() {
|
|||||||
})
|
})
|
||||||
if (!fontsLoading)
|
if (!fontsLoading)
|
||||||
return <View><Text>Loading...</Text></View>
|
return <View><Text>Loading...</Text></View>
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<GestureHandlerRootView style={{flex: 1}}>
|
<GestureHandlerRootView style={{flex: 1}}>
|
||||||
|
|||||||
@@ -4,8 +4,16 @@ import {Order} from "../types/order";
|
|||||||
const router = '/orders';
|
const router = '/orders';
|
||||||
|
|
||||||
const ordersApi = {
|
const ordersApi = {
|
||||||
getOrders: async (lastId: number) => {
|
getOrders: async (page: number, orderBy: string, desc: boolean, shipmentDate: string, status: number): Promise<Order[]> => {
|
||||||
|
const params = {
|
||||||
|
page: page,
|
||||||
|
orderBy: orderBy,
|
||||||
|
desc: Number(desc), // Преобразование boolean в Number (0 или 1)
|
||||||
|
status: status,
|
||||||
|
shipmentDate: shipmentDate
|
||||||
|
};
|
||||||
|
let response = await apiClient.get(`${router}/getOrders`, {params})
|
||||||
|
return response.data;
|
||||||
},
|
},
|
||||||
getOrdersBySupplierProduct: async (supplierProductId: number): Promise<Order[]> => {
|
getOrdersBySupplierProduct: async (supplierProductId: number): Promise<Order[]> => {
|
||||||
let response = await apiClient.get(`${router}/getBySupplierProductId?supplierProductId=${supplierProductId}`);
|
let response = await apiClient.get(`${router}/getBySupplierProductId?supplierProductId=${supplierProductId}`);
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ const ReprintModal: FC = () => {
|
|||||||
dispatch(closeReprintModal());
|
dispatch(closeReprintModal());
|
||||||
dispatch(openLoadingModal());
|
dispatch(openLoadingModal());
|
||||||
PrintingApi.getLabel(order.databaseId).then(pdfBytes => {
|
PrintingApi.getLabel(order.databaseId).then(pdfBytes => {
|
||||||
|
|
||||||
PrintingService.getInstance().printPdf(printerName, pdfBytes).then(r => {
|
PrintingService.getInstance().printPdf(printerName, pdfBytes).then(r => {
|
||||||
dispatch(closeLoadingModal());
|
dispatch(closeLoadingModal());
|
||||||
if (r) dispatch(closeReprintModal());
|
if (r) dispatch(closeReprintModal());
|
||||||
|
|||||||
@@ -3,11 +3,22 @@ import {BottomSheetModal} from "@gorhom/bottom-sheet";
|
|||||||
import {disableDim, enableDim} from "../../../features/interface/interfaceSlice";
|
import {disableDim, enableDim} from "../../../features/interface/interfaceSlice";
|
||||||
import {StyleSheet, View} from "react-native";
|
import {StyleSheet, View} from "react-native";
|
||||||
import BasicButton from "../../BasicButton/BasicButton";
|
import BasicButton from "../../BasicButton/BasicButton";
|
||||||
import {useDispatch} from "react-redux";
|
import {useDispatch, useSelector} from "react-redux";
|
||||||
import {RFPercentage} from "react-native-responsive-fontsize";
|
import {RFPercentage} from "react-native-responsive-fontsize";
|
||||||
import RadioGroup from 'react-native-radio-buttons-group';
|
import RadioGroup from 'react-native-radio-buttons-group';
|
||||||
import {responsiveHeight, responsiveWidth} from "react-native-responsive-dimensions";
|
import {responsiveHeight, responsiveWidth} from "react-native-responsive-dimensions";
|
||||||
import {blue} from "../../../css/colors";
|
import {blue} from "../../../css/colors";
|
||||||
|
import {Picker} from "@react-native-picker/picker";
|
||||||
|
import DateTimePicker from '@react-native-community/datetimepicker';
|
||||||
|
import {RootState} from "../../../redux/store";
|
||||||
|
import {
|
||||||
|
closeOrdersFilterModal,
|
||||||
|
OrderStatus,
|
||||||
|
orderStatuses,
|
||||||
|
setDesc,
|
||||||
|
setOrderBy, setShipmentDate, setStatus
|
||||||
|
} from "../../../features/ordersFilter/ordersFilterSlice";
|
||||||
|
import {retry} from "@reduxjs/toolkit/query";
|
||||||
|
|
||||||
export type SortingModalHandles = {
|
export type SortingModalHandles = {
|
||||||
present: () => void;
|
present: () => void;
|
||||||
@@ -19,12 +30,7 @@ export type SortingModalElement = {
|
|||||||
label: string;
|
label: string;
|
||||||
value: string;
|
value: string;
|
||||||
}
|
}
|
||||||
type Props = {
|
|
||||||
onChange: (sortingValue: string) => void;
|
|
||||||
onClose: () => void;
|
|
||||||
elements: SortingModalElement[];
|
|
||||||
defaultElementId?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
const createRadioButton = (element: SortingModalElement) => {
|
const createRadioButton = (element: SortingModalElement) => {
|
||||||
return {
|
return {
|
||||||
@@ -41,55 +47,101 @@ const createRadioButton = (element: SortingModalElement) => {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const SortingModal = forwardRef<SortingModalHandles, Props>((props: Props, ref) => {
|
const SortingModal = () => {
|
||||||
const {elements, onChange, onClose, defaultElementId = ""} = props;
|
const state = useSelector((state: RootState) => state.ordersFilter);
|
||||||
const snapPoints = useMemo(() => ['40%', '40%'], []);
|
const elements = [
|
||||||
|
{id: 'createdOnAsc', value: 'createdOnAsc', label: 'Дата создания по возрастанию'},
|
||||||
|
{id: 'createdOnDesc', value: 'createdOnDesc', label: 'Дата создания по убыванию'},
|
||||||
|
{id: 'shipmentDateAsc', value: 'shipmentDateAsc', label: 'Дата отгрузки по возрастанию'},
|
||||||
|
{id: 'shipmentDateDesc', value: 'shipmentDateDesc', label: 'Дата отгрузки по убыванию'},
|
||||||
|
];
|
||||||
|
const [showShipmentPicker, setShowShipmentPicker] = useState(false);
|
||||||
|
const snapPoints = useMemo(() => ['60%', '60%'], []);
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const modalRef = useRef<BottomSheetModal>(null);
|
const modalRef = useRef<BottomSheetModal>(null);
|
||||||
const dismiss = () => {
|
const dismiss = () => {
|
||||||
if (!modalRef.current) return;
|
if (!modalRef.current) return;
|
||||||
dispatch(disableDim());
|
dispatch(disableDim());
|
||||||
modalRef.current.dismiss();
|
modalRef.current.dismiss();
|
||||||
onClose();
|
|
||||||
}
|
}
|
||||||
const present = () => {
|
const present = () => {
|
||||||
if (!modalRef.current) return;
|
if (!modalRef.current) return;
|
||||||
modalRef.current.present();
|
modalRef.current.present();
|
||||||
dispatch(enableDim());
|
dispatch(enableDim());
|
||||||
}
|
}
|
||||||
useImperativeHandle(ref, () => ({
|
|
||||||
present: present,
|
|
||||||
dismiss: dismiss
|
|
||||||
}));
|
|
||||||
const [selectedId, setSelectedId] = useState<string>(defaultElementId);
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
onChange(selectedId);
|
if (state.isVisible) present();
|
||||||
}, [selectedId]);
|
else dismiss();
|
||||||
|
}, [state.isVisible]);
|
||||||
return (
|
return (
|
||||||
<BottomSheetModal
|
<BottomSheetModal
|
||||||
ref={modalRef}
|
ref={modalRef}
|
||||||
snapPoints={snapPoints}
|
snapPoints={snapPoints}
|
||||||
onDismiss={() => {
|
onDismiss={() => {
|
||||||
dispatch(disableDim());
|
dispatch(disableDim());
|
||||||
|
dispatch(closeOrdersFilterModal())
|
||||||
}}>
|
}}>
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<View style={styles.content}>
|
<View style={styles.content}>
|
||||||
<RadioGroup selectedId={selectedId}
|
<RadioGroup selectedId={state.orderBy + (state.desc ? "Desc" : "Asc")}
|
||||||
onPress={setSelectedId}
|
onPress={(event) => {
|
||||||
|
const orderRegex = /(Asc|Desc)$/;
|
||||||
|
const orderMatch = event.match(orderRegex);
|
||||||
|
if (!orderMatch) return;
|
||||||
|
const isDesc = orderMatch[0] === 'Desc';
|
||||||
|
const orderByField = event.replace(orderRegex, '');
|
||||||
|
if (!["createdOn", "shipmentDate"].includes(orderByField)) return
|
||||||
|
dispatch(setDesc(isDesc));
|
||||||
|
dispatch(setOrderBy(orderByField as "createdOn" | "shipmentDate"));
|
||||||
|
|
||||||
|
}}
|
||||||
containerStyle={styles.radioButtons}
|
containerStyle={styles.radioButtons}
|
||||||
radioButtons={elements.map(createRadioButton)}/>
|
radioButtons={elements.map(createRadioButton)}/>
|
||||||
|
|
||||||
|
|
||||||
|
<View style={{
|
||||||
|
borderWidth: responsiveWidth(0.1),
|
||||||
|
borderRadius: responsiveWidth(1)
|
||||||
|
}}>
|
||||||
|
|
||||||
|
<Picker selectedValue={state.status}
|
||||||
|
onValueChange={(value, event) => dispatch(setStatus(value))}>
|
||||||
|
{orderStatuses.map((status) => {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Picker.Item
|
||||||
|
key={status.key}
|
||||||
|
label={status.label}
|
||||||
|
value={status.key}
|
||||||
|
style={{fontSize: responsiveWidth(3)}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</Picker>
|
||||||
|
</View>
|
||||||
|
<BasicButton onPress={() => setShowShipmentPicker(oldValue => !oldValue)}
|
||||||
|
label={"Выбрать дату отгрузки"}/>
|
||||||
|
{showShipmentPicker &&
|
||||||
|
<DateTimePicker value={new Date(state.shipmentDate)}
|
||||||
|
onChange={(event) => {
|
||||||
|
if (!event.nativeEvent.timestamp) return;
|
||||||
|
setShowShipmentPicker(false);
|
||||||
|
if (event.type === 'set') {
|
||||||
|
const selectedDate = new Date(event.nativeEvent.timestamp);
|
||||||
|
dispatch(setShipmentDate(selectedDate.toISOString()));
|
||||||
|
}
|
||||||
|
}}/>}
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
|
|
||||||
<BasicButton label={"Закрыть"} style={styles.button} onPress={() => {
|
<BasicButton label={"Закрыть"} style={styles.button} onPress={() => {
|
||||||
dismiss();
|
dispatch(closeOrdersFilterModal());
|
||||||
}}/>
|
}}/>
|
||||||
|
|
||||||
</View>
|
</View>
|
||||||
</BottomSheetModal>
|
</BottomSheetModal>
|
||||||
);
|
)
|
||||||
});
|
};
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
width: "100%",
|
width: "100%",
|
||||||
@@ -97,13 +149,17 @@ const styles = StyleSheet.create({
|
|||||||
flex: 1,
|
flex: 1,
|
||||||
padding: RFPercentage(3),
|
padding: RFPercentage(3),
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
justifyContent: "space-between"
|
justifyContent: "space-between",
|
||||||
|
rowGap: responsiveHeight(1)
|
||||||
},
|
},
|
||||||
radioButtons: {
|
radioButtons: {
|
||||||
alignItems: "flex-start"
|
alignItems: "flex-start"
|
||||||
},
|
},
|
||||||
content: {},
|
content: {
|
||||||
|
rowGap: responsiveHeight(1)
|
||||||
|
},
|
||||||
button: {
|
button: {
|
||||||
|
|
||||||
marginTop: "auto"
|
marginTop: "auto"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -4,10 +4,11 @@ import {RFPercentage} from "react-native-responsive-fontsize";
|
|||||||
import DText from "../DText/DText";
|
import DText from "../DText/DText";
|
||||||
import {responsiveHeight, responsiveWidth} from "react-native-responsive-dimensions";
|
import {responsiveHeight, responsiveWidth} from "react-native-responsive-dimensions";
|
||||||
import DTitle from "../DTitle/DTitle";
|
import DTitle from "../DTitle/DTitle";
|
||||||
import {Order} from "../../types/order";
|
import {BaseMarketplace, Order} from "../../types/order";
|
||||||
import OrderProductsList from "./OrderProductsList";
|
import OrderProductsList from "./OrderProductsList";
|
||||||
import {useDispatch} from "react-redux";
|
import {useDispatch} from "react-redux";
|
||||||
import {setOrder} from "../../features/assembly/assemblySlice";
|
import {setOrder} from "../../features/assembly/assemblySlice";
|
||||||
|
import {OrderStatus, OrderStatusDictionary} from "../../features/ordersFilter/ordersFilterSlice";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onPress?: (event: GestureResponderEvent) => void
|
onPress?: (event: GestureResponderEvent) => void
|
||||||
@@ -15,9 +16,17 @@ type Props = {
|
|||||||
onSelect: (order: Order) => void
|
onSelect: (order: Order) => void
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const BaseMarketplaceIconDict = {
|
||||||
|
[BaseMarketplace.Wildberries]: require('assets/icons/marketplaces/wildberries.png'),
|
||||||
|
[BaseMarketplace.Ozon]: require('assets/icons/marketplaces/ozon.png'),
|
||||||
|
[BaseMarketplace.YandexMarket]: require('assets/icons/marketplaces/yandex_market.png'),
|
||||||
|
};
|
||||||
const OrderCard: FC<Props> = ({onPress, onSelect, order}) => {
|
const OrderCard: FC<Props> = ({onPress, onSelect, order}) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TouchableOpacity onPress={()=>{
|
<TouchableOpacity onPress={() => {
|
||||||
if (onSelect) onSelect(order);
|
if (onSelect) onSelect(order);
|
||||||
|
|
||||||
}}>
|
}}>
|
||||||
@@ -26,7 +35,7 @@ const OrderCard: FC<Props> = ({onPress, onSelect, order}) => {
|
|||||||
<View style={styles.title}>
|
<View style={styles.title}>
|
||||||
|
|
||||||
<DTitle>{order.orderNumber}</DTitle>
|
<DTitle>{order.orderNumber}</DTitle>
|
||||||
<Image source={require('assets/icons/marketplaces/ozon.png')} style={styles.titleImage}/>
|
<Image source={BaseMarketplaceIconDict[order.baseMarketplace]} style={styles.titleImage}/>
|
||||||
</View>
|
</View>
|
||||||
<DText>Селлер: {order.sellerName}</DText>
|
<DText>Селлер: {order.sellerName}</DText>
|
||||||
<DText>Маркетплейс: {order.marketplaceName}</DText>
|
<DText>Маркетплейс: {order.marketplaceName}</DText>
|
||||||
@@ -34,7 +43,7 @@ const OrderCard: FC<Props> = ({onPress, onSelect, order}) => {
|
|||||||
</View>
|
</View>
|
||||||
<View style={styles.descriptionStatus}>
|
<View style={styles.descriptionStatus}>
|
||||||
<DText>
|
<DText>
|
||||||
Ожидает сборки
|
{OrderStatusDictionary[order.status as OrderStatus]}
|
||||||
</DText>
|
</DText>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
@@ -9,16 +9,16 @@ import {background} from "../../css/colors";
|
|||||||
|
|
||||||
type ListProps = {
|
type ListProps = {
|
||||||
products: OrderProduct[];
|
products: OrderProduct[];
|
||||||
onSelected: (product: OrderProduct) => void;
|
onSelected: (product: number) => void;
|
||||||
}
|
}
|
||||||
type CardProps = {
|
type CardProps = {
|
||||||
product: OrderProduct;
|
product: OrderProduct;
|
||||||
onPress: (product: OrderProduct) => void;
|
onPress: (product: number) => void;
|
||||||
id: number;
|
id: number;
|
||||||
}
|
}
|
||||||
const OrderProductCard: FC<CardProps> = ({product, onPress, id}) => {
|
const OrderProductCard: FC<CardProps> = ({product, onPress, id}) => {
|
||||||
return (
|
return (
|
||||||
<TouchableOpacity onPress={() => onPress(product)}>
|
<TouchableOpacity onPress={() => onPress(id)}>
|
||||||
<View style={cardStyles.container}>
|
<View style={cardStyles.container}>
|
||||||
<View style={cardStyles.content}>
|
<View style={cardStyles.content}>
|
||||||
<DText>{id + 1}) {product.productName}</DText>
|
<DText>{id + 1}) {product.productName}</DText>
|
||||||
|
|||||||
@@ -7,16 +7,15 @@ import SelectProductModal from "../Modals/SelectProductModal/SelectProductModal"
|
|||||||
import {SupplierProduct} from "../../types/supplierProduct";
|
import {SupplierProduct} from "../../types/supplierProduct";
|
||||||
import barcodeApi from "../../api/barcodeApi";
|
import barcodeApi from "../../api/barcodeApi";
|
||||||
import {useDispatch, useSelector} from "react-redux";
|
import {useDispatch, useSelector} from "react-redux";
|
||||||
import {openScanModal} from "../../features/scanModal/scanModalSlice";
|
import {openScanModal, setScannedData} from "../../features/scanModal/scanModalSlice";
|
||||||
import {RootState} from "../../redux/store";
|
import {RootState} from "../../redux/store";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onSearch: (text: string) => void;
|
onSearch?: (text: string) => void;
|
||||||
onSupplierProductSelected?: (supplierProduct: SupplierProduct) => void
|
onSupplierProductSelected?: (supplierProduct: SupplierProduct) => void
|
||||||
}
|
}
|
||||||
const SearchBar: FC<Props> = ({onSearch, onSupplierProductSelected}) => {
|
const SearchBar: FC<Props> = ({onSearch, onSupplierProductSelected}) => {
|
||||||
// const [isScanModalVisible, setIsScanModalVisible] = useState<boolean>(false);
|
|
||||||
// const [, setSelectProductModalVisible] = useState(false);
|
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const [searchInput, setSearchInput] = useState<string>("");
|
const [searchInput, setSearchInput] = useState<string>("");
|
||||||
const textInputRef = useRef<TextInput>(null);
|
const textInputRef = useRef<TextInput>(null);
|
||||||
@@ -26,19 +25,19 @@ const SearchBar: FC<Props> = ({onSearch, onSupplierProductSelected}) => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!scannedData) return;
|
if (!scannedData) return;
|
||||||
barcodeApi.searchProducts(scannedData).then((response) => {
|
barcodeApi.searchProducts(scannedData).then((response) => {
|
||||||
console.log("Response: " + response);
|
|
||||||
setProducts(response)
|
setProducts(response)
|
||||||
});
|
});
|
||||||
}, [scannedData]);
|
}, [scannedData]);
|
||||||
const selectProductModalVisible = products.length > 0;
|
const selectProductModalVisible = products.length > 0;
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
|
|
||||||
<SelectProductModal visible={selectProductModalVisible} products={products} onSelected={(product) => {
|
<SelectProductModal visible={selectProductModalVisible} products={products} onSelected={(product) => {
|
||||||
if (onSupplierProductSelected) onSupplierProductSelected(product);
|
if (onSupplierProductSelected) onSupplierProductSelected(product);
|
||||||
setProducts([]);
|
setProducts([]);
|
||||||
|
dispatch(setScannedData(undefined));
|
||||||
}}/>
|
}}/>
|
||||||
<BasicButton onPress={() => {
|
<BasicButton onPress={() => {
|
||||||
|
if (!onSearch) return;
|
||||||
onSearch(searchInput);
|
onSearch(searchInput);
|
||||||
if (textInputRef.current) {
|
if (textInputRef.current) {
|
||||||
textInputRef.current.clear();
|
textInputRef.current.clear();
|
||||||
@@ -77,7 +76,7 @@ const styles = StyleSheet.create({
|
|||||||
borderTopRightRadius: responsiveWidth(1),
|
borderTopRightRadius: responsiveWidth(1),
|
||||||
borderBottomRightRadius: responsiveWidth(1),
|
borderBottomRightRadius: responsiveWidth(1),
|
||||||
paddingHorizontal: responsiveWidth(5),
|
paddingHorizontal: responsiveWidth(5),
|
||||||
height:'100%'
|
height: '100%'
|
||||||
},
|
},
|
||||||
scanImageWrapper: {
|
scanImageWrapper: {
|
||||||
paddingHorizontal: responsiveWidth(1),
|
paddingHorizontal: responsiveWidth(1),
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
import {createSlice, PayloadAction} from "@reduxjs/toolkit";
|
import {createSlice, PayloadAction} from "@reduxjs/toolkit";
|
||||||
import {Order} from "../../types/order";
|
import {Order, OrderProduct} from "../../types/order";
|
||||||
import {Assembly, ASSEMBLY_STATE} from "../../types/assembly";
|
import {Assembly, ASSEMBLY_STATE} from "../../types/assembly";
|
||||||
|
import selectProductElement from "../../components/Modals/SelectProductModal/SelectProductElement";
|
||||||
|
|
||||||
|
|
||||||
export interface AssemblyState {
|
export interface AssemblyState {
|
||||||
order?: Order;
|
order?: Order;
|
||||||
|
initialOrder?: Order;
|
||||||
assembly?: Assembly;
|
assembly?: Assembly;
|
||||||
localState?: ASSEMBLY_STATE
|
selectedProductId?: number;
|
||||||
|
localState?: ASSEMBLY_STATE;
|
||||||
|
selectedProduct?: OrderProduct
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialState: AssemblyState = {
|
const initialState: AssemblyState = {
|
||||||
@@ -18,7 +22,9 @@ export const assembly = createSlice({
|
|||||||
initialState,
|
initialState,
|
||||||
reducers: {
|
reducers: {
|
||||||
setOrder: (state, action) => {
|
setOrder: (state, action) => {
|
||||||
|
state.initialOrder = action.payload;
|
||||||
state.order = action.payload;
|
state.order = action.payload;
|
||||||
|
state.selectedProductId = 0;
|
||||||
},
|
},
|
||||||
setAssembly: (state, action: PayloadAction<Assembly>) => {
|
setAssembly: (state, action: PayloadAction<Assembly>) => {
|
||||||
state.assembly = action.payload;
|
state.assembly = action.payload;
|
||||||
@@ -56,6 +62,7 @@ export const assembly = createSlice({
|
|||||||
product.assembled = true;
|
product.assembled = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
state.selectedProduct = state.order.products.find(product => product.databaseId == action.payload.orderProductId);
|
||||||
// If all products is assembled
|
// If all products is assembled
|
||||||
if (!state.order.products.find(product => !product.assembled)) {
|
if (!state.order.products.find(product => !product.assembled)) {
|
||||||
state.assembly.state = ASSEMBLY_STATE.ALL_PRODUCTS_ASSEMBLED;
|
state.assembly.state = ASSEMBLY_STATE.ALL_PRODUCTS_ASSEMBLED;
|
||||||
@@ -72,9 +79,23 @@ export const assembly = createSlice({
|
|||||||
product.shipped = true;
|
product.shipped = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
state.selectedProduct = state.order.products.find(product => product.databaseId == action.payload.orderProductId);
|
||||||
|
|
||||||
|
},
|
||||||
|
selectProduct: (state, action: PayloadAction<number>) => {
|
||||||
|
if (!state.order) return;
|
||||||
|
state.selectedProduct = state.order.products[action.payload];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export const {setOrder, setAssembled, setAssembly, startAssembly, endAssembly, confirmAssembly} = assembly.actions;
|
export const {
|
||||||
|
setOrder,
|
||||||
|
setAssembled,
|
||||||
|
selectProduct,
|
||||||
|
setAssembly,
|
||||||
|
startAssembly,
|
||||||
|
endAssembly,
|
||||||
|
confirmAssembly
|
||||||
|
} = assembly.actions;
|
||||||
export default assembly.reducer;
|
export default assembly.reducer;
|
||||||
100
src/features/ordersFilter/ordersFilterSlice.ts
Normal file
100
src/features/ordersFilter/ordersFilterSlice.ts
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
import {createSlice, PayloadAction} from "@reduxjs/toolkit";
|
||||||
|
|
||||||
|
export enum OrderStatus {
|
||||||
|
ALL = -1,
|
||||||
|
AWAITING_PACKAGING,
|
||||||
|
AWAITING_DELIVER,
|
||||||
|
DELIVERING,
|
||||||
|
DELIVERED,
|
||||||
|
CANCELLED,
|
||||||
|
PARTIALLY_RETURNED,
|
||||||
|
FULLY_RETURNED,
|
||||||
|
DISPUTED
|
||||||
|
}
|
||||||
|
|
||||||
|
export const orderStatuses = [
|
||||||
|
{key: OrderStatus.ALL, label: 'Все'},
|
||||||
|
{key: OrderStatus.AWAITING_PACKAGING, label: 'Ожидает сборки'},
|
||||||
|
{key: OrderStatus.AWAITING_DELIVER, label: 'Ожидает отгрузки'},
|
||||||
|
{key: OrderStatus.DELIVERING, label: 'Доставляется'},
|
||||||
|
{key: OrderStatus.DELIVERED, label: 'Доставлен'},
|
||||||
|
{key: OrderStatus.CANCELLED, label: 'Отменен'},
|
||||||
|
{key: OrderStatus.PARTIALLY_RETURNED, label: 'Частичный возврат'},
|
||||||
|
{key: OrderStatus.FULLY_RETURNED, label: 'Полный возврат'},
|
||||||
|
{key: OrderStatus.DISPUTED, label: 'Спорный'},
|
||||||
|
];
|
||||||
|
export const OrderStatusDictionary: { [key in OrderStatus]: string } = {
|
||||||
|
[OrderStatus.ALL]: 'Все',
|
||||||
|
[OrderStatus.AWAITING_PACKAGING]: 'Ожидает сборки',
|
||||||
|
[OrderStatus.AWAITING_DELIVER]: 'Ожидает отгрузки',
|
||||||
|
[OrderStatus.DELIVERING]: 'Доставляется',
|
||||||
|
[OrderStatus.DELIVERED]: 'Доставлен',
|
||||||
|
[OrderStatus.CANCELLED]: 'Отменен',
|
||||||
|
[OrderStatus.PARTIALLY_RETURNED]: 'Частичный возврат',
|
||||||
|
[OrderStatus.FULLY_RETURNED]: 'Полный возврат',
|
||||||
|
[OrderStatus.DISPUTED]: 'Спорный',
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface OrdersFilterState {
|
||||||
|
isVisible: boolean;
|
||||||
|
orderBy: "createdOn" | "shipmentDate";
|
||||||
|
desc: boolean;
|
||||||
|
status: OrderStatus;
|
||||||
|
shipmentDate: string;
|
||||||
|
page: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialState: OrdersFilterState = {
|
||||||
|
isVisible: false,
|
||||||
|
orderBy: "createdOn",
|
||||||
|
desc: true,
|
||||||
|
shipmentDate: (new Date()).toISOString(),
|
||||||
|
status: OrderStatus.AWAITING_PACKAGING,
|
||||||
|
page: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ordersFilterSlice = createSlice({
|
||||||
|
name: 'ordersFilter',
|
||||||
|
initialState,
|
||||||
|
reducers: {
|
||||||
|
openOrdersFilterModal: (state) => {
|
||||||
|
state.isVisible = true
|
||||||
|
},
|
||||||
|
closeOrdersFilterModal: (state) => {
|
||||||
|
state.isVisible = false
|
||||||
|
},
|
||||||
|
setOrderBy: (state, action: PayloadAction<"createdOn" | "shipmentDate">) => {
|
||||||
|
state.orderBy = action.payload;
|
||||||
|
},
|
||||||
|
setDesc: (state, action: PayloadAction<boolean>) => {
|
||||||
|
state.desc = action.payload;
|
||||||
|
},
|
||||||
|
setStatus: (state, action: PayloadAction<OrderStatus>) => {
|
||||||
|
state.status = action.payload;
|
||||||
|
},
|
||||||
|
setShipmentDate: (state, action: PayloadAction<string>) => {
|
||||||
|
state.shipmentDate = action.payload;
|
||||||
|
},
|
||||||
|
setPage: (state, action: PayloadAction<number>) => {
|
||||||
|
state.page = action.payload;
|
||||||
|
},
|
||||||
|
nextPage: (state) => {
|
||||||
|
state.page = state.page + 1
|
||||||
|
},
|
||||||
|
refreshPagination: (state) => {
|
||||||
|
state.page = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
export const {
|
||||||
|
openOrdersFilterModal,
|
||||||
|
closeOrdersFilterModal,
|
||||||
|
refreshPagination,
|
||||||
|
nextPage,
|
||||||
|
setOrderBy,
|
||||||
|
setDesc,
|
||||||
|
setStatus,
|
||||||
|
setShipmentDate
|
||||||
|
} = ordersFilterSlice.actions;
|
||||||
|
export default ordersFilterSlice.reducer;
|
||||||
@@ -8,6 +8,7 @@ import imageZoomModalReducer from 'features/imageZoomModal/loadingModalSlice';
|
|||||||
import assemblyReducer from 'features/assembly/assemblySlice';
|
import assemblyReducer from 'features/assembly/assemblySlice';
|
||||||
import printingReducer from 'features/printing/printingSlice';
|
import printingReducer from 'features/printing/printingSlice';
|
||||||
import reprintModalReducer from 'features/reprintModal/reprintModalSlice';
|
import reprintModalReducer from 'features/reprintModal/reprintModalSlice';
|
||||||
|
import ordersFilterReducer from 'features/ordersFilter/ordersFilterSlice';
|
||||||
import {useDispatch} from "react-redux";
|
import {useDispatch} from "react-redux";
|
||||||
|
|
||||||
export const store = configureStore({
|
export const store = configureStore({
|
||||||
@@ -19,7 +20,8 @@ export const store = configureStore({
|
|||||||
assembly: assemblyReducer,
|
assembly: assemblyReducer,
|
||||||
printing: printingReducer,
|
printing: printingReducer,
|
||||||
reprintModal: reprintModalReducer,
|
reprintModal: reprintModalReducer,
|
||||||
imageZoomModal: imageZoomModalReducer
|
imageZoomModal: imageZoomModalReducer,
|
||||||
|
ordersFilter: ordersFilterReducer
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,68 @@
|
|||||||
import {Button, Text, View} from "react-native";
|
import {Button, StyleSheet, Text, View} from "react-native";
|
||||||
import {useAppDispatch} from "../../redux/store";
|
import {useAppDispatch} from "../../redux/store";
|
||||||
import * as process from "process";
|
import * as process from "process";
|
||||||
|
import {responsiveHeight, responsiveWidth} from "react-native-responsive-dimensions";
|
||||||
|
import SearchBar from "../../components/SearchBar/SearchBar";
|
||||||
|
import {useDispatch} from "react-redux";
|
||||||
|
import {NavigationProp, useNavigation} from "@react-navigation/native";
|
||||||
|
import {TabNavigatorParamList} from "../MainScreen/MainScreen";
|
||||||
|
import {FlashList} from "@shopify/flash-list";
|
||||||
|
import {Order} from "../../types/order";
|
||||||
|
import OrderCard from "../../components/OrderCard/OrderCard";
|
||||||
|
import {setOrder} from "../../features/assembly/assemblySlice";
|
||||||
|
import flashListSeparator from "../../components/FlashListSeparator/FlashListSeparator";
|
||||||
|
import {useEffect, useState} from "react";
|
||||||
|
import {openScanModal} from "../../features/scanModal/scanModalSlice";
|
||||||
|
import ordersApi from "../../api/ordersApi";
|
||||||
|
|
||||||
function BarcodeScreen() {
|
function BarcodeScreen() {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const navigator = useNavigation<NavigationProp<TabNavigatorParamList, 'Home'>>();
|
||||||
|
const [orders, setOrders] = useState<Order[]>([]);
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
dispatch(openScanModal());
|
||||||
|
}, []);
|
||||||
return (
|
return (
|
||||||
<View>
|
<View style={styles.container}>
|
||||||
<Text style={{fontSize: 36}}>Barcode</Text>
|
<SearchBar onSupplierProductSelected={product => {
|
||||||
|
ordersApi.getOrdersBySupplierProduct(product.supplierProductId).then(setOrders)
|
||||||
|
}}/>
|
||||||
|
<View style={styles.content}>
|
||||||
|
<FlashList
|
||||||
|
|
||||||
|
keyboardShouldPersistTaps={"never"}
|
||||||
|
data={orders}
|
||||||
|
keyExtractor={(item: Order) => item.orderNumber.toString()}
|
||||||
|
renderItem={({item}) =>
|
||||||
|
<OrderCard onSelect={(order) => {
|
||||||
|
dispatch(setOrder(order));
|
||||||
|
navigator.navigate("Home");
|
||||||
|
}} order={item}/>}
|
||||||
|
showsHorizontalScrollIndicator={false}
|
||||||
|
showsVerticalScrollIndicator={true}
|
||||||
|
onEndReachedThreshold={0.1}
|
||||||
|
estimatedItemSize={720}
|
||||||
|
ItemSeparatorComponent={flashListSeparator}
|
||||||
|
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
width: "100%",
|
||||||
|
height: "100%",
|
||||||
|
display: "flex",
|
||||||
|
paddingHorizontal: responsiveWidth(5),
|
||||||
|
rowGap: responsiveHeight(2),
|
||||||
|
fontWeight: '500'
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
});
|
||||||
export default BarcodeScreen;
|
export default BarcodeScreen;
|
||||||
@@ -18,6 +18,7 @@ import assemblyApi from "../../api/assemblyApi";
|
|||||||
import {assembly, setAssembly, setOrder} from "../../features/assembly/assemblySlice";
|
import {assembly, setAssembly, setOrder} from "../../features/assembly/assemblySlice";
|
||||||
import ordersApi from "../../api/ordersApi";
|
import ordersApi from "../../api/ordersApi";
|
||||||
import ImageZoomModal from "../../components/Modals/ImageZoomModal/ImageZoomModal";
|
import ImageZoomModal from "../../components/Modals/ImageZoomModal/ImageZoomModal";
|
||||||
|
import SortingModal from "../../components/Modals/SortingModal/SortingModal";
|
||||||
|
|
||||||
function CommonPage() {
|
function CommonPage() {
|
||||||
const dim = useSelector((state: RootState) => state.interface.dim);
|
const dim = useSelector((state: RootState) => state.interface.dim);
|
||||||
@@ -62,6 +63,7 @@ function CommonPage() {
|
|||||||
<ScanModal/>
|
<ScanModal/>
|
||||||
<ReprintModal/>
|
<ReprintModal/>
|
||||||
<ImageZoomModal/>
|
<ImageZoomModal/>
|
||||||
|
<SortingModal/>
|
||||||
<Toast config={toastConfig}/>
|
<Toast config={toastConfig}/>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ 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 {
|
import {
|
||||||
confirmAssembly, endAssembly,
|
confirmAssembly, endAssembly, selectProduct,
|
||||||
setAssembled,
|
setAssembled,
|
||||||
setAssembly,
|
setAssembly,
|
||||||
setOrder,
|
setOrder,
|
||||||
@@ -82,9 +82,9 @@ const OrderScreen: FC<OrderScreenProps> = ({order}) => {
|
|||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const assembly = useSelector((state: RootState) => state.assembly.assembly);
|
const assembly = useSelector((state: RootState) => state.assembly.assembly);
|
||||||
const assemblyState = useSelector((state: RootState) => state.assembly.localState);
|
const assemblyState = useSelector((state: RootState) => state.assembly.localState);
|
||||||
|
const initialOrder = useSelector((state: RootState) => state.assembly.initialOrder);
|
||||||
|
|
||||||
const [selectedProduct, setSelectedProduct] = useState(order.products[0]);
|
const selectedProduct = useSelector((state: RootState) => state.assembly.selectedProduct);
|
||||||
|
|
||||||
const [acceptModalVisible, setAcceptModalVisible] = useState(false);
|
const [acceptModalVisible, setAcceptModalVisible] = useState(false);
|
||||||
const [skipConfirmButtonVisible, setSkipConfirmButtonVisible] = useState(false);
|
const [skipConfirmButtonVisible, setSkipConfirmButtonVisible] = useState(false);
|
||||||
const _confirmAssembly = async () => {
|
const _confirmAssembly = async () => {
|
||||||
@@ -113,11 +113,13 @@ const OrderScreen: FC<OrderScreenProps> = ({order}) => {
|
|||||||
onPress={() => setAcceptModalVisible(true)}
|
onPress={() => setAcceptModalVisible(true)}
|
||||||
label={"Начать сборку"}/>)
|
label={"Начать сборку"}/>)
|
||||||
case ASSEMBLY_STATE.ASSEMBLING_PRODUCTS:
|
case ASSEMBLY_STATE.ASSEMBLING_PRODUCTS:
|
||||||
|
|
||||||
return (<BasicButton
|
return (<BasicButton
|
||||||
containerStyle={styles.buttonContainer}
|
containerStyle={styles.buttonContainer}
|
||||||
label={"Отметить как собранный"}
|
label={"Отметить как собранный"}
|
||||||
disabled={selectedProduct.assembled}
|
disabled={selectedProduct?.assembled}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
|
if (!selectedProduct) return;
|
||||||
dispatch(setAssembled({orderProductId: selectedProduct.databaseId}))
|
dispatch(setAssembled({orderProductId: selectedProduct.databaseId}))
|
||||||
}}
|
}}
|
||||||
/>)
|
/>)
|
||||||
@@ -183,10 +185,10 @@ const OrderScreen: FC<OrderScreenProps> = ({order}) => {
|
|||||||
dispatch(setLoadingText('Идет печать этикетки...'))
|
dispatch(setLoadingText('Идет печать этикетки...'))
|
||||||
dispatch(openLoadingModal())
|
dispatch(openLoadingModal())
|
||||||
printingApi.getLabel(order.databaseId).then(pdfData => {
|
printingApi.getLabel(order.databaseId).then(pdfData => {
|
||||||
printingService.getInstance().printPdf('ozon', pdfData).then((response) => {
|
printingService.getInstance().printPdf('wildberries', pdfData).then((response) => {
|
||||||
dispatch(closeLoadingModal());
|
dispatch(closeLoadingModal());
|
||||||
if (response) return;
|
if (response) return;
|
||||||
dispatch(setPrinterName({printerName: 'ozon'}));
|
dispatch(setPrinterName({printerName: 'wildberries'}));
|
||||||
dispatch(openReprintModal());
|
dispatch(openReprintModal());
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
@@ -204,23 +206,27 @@ const OrderScreen: FC<OrderScreenProps> = ({order}) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
}, [assemblyState]);
|
}, [assemblyState]);
|
||||||
|
useEffect(() => {
|
||||||
|
if (!order) return;
|
||||||
|
dispatch(selectProduct(0));
|
||||||
|
}, [initialOrder]);
|
||||||
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={(product) => {
|
<OrderProductsList products={order.products} onSelected={(productId) => {
|
||||||
if (!order) return;
|
if (!order) return;
|
||||||
setSelectedProduct(product)
|
dispatch(selectProduct(productId))
|
||||||
}}/>
|
}}/>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<TouchableOpacity style={styles.imageWrapper} onPress={()=>{
|
<TouchableOpacity style={styles.imageWrapper} onPress={() => {
|
||||||
|
if (!selectedProduct) return;
|
||||||
dispatch(setImages([selectedProduct.imageUrl]));
|
dispatch(setImages([selectedProduct.imageUrl]));
|
||||||
dispatch(openImageZoomModal());
|
dispatch(openImageZoomModal());
|
||||||
}}>
|
}}>
|
||||||
<View style={{flex: 1}}>
|
<View style={{flex: 1}}>
|
||||||
<Image style={styles.image} source={{uri: selectedProduct.imageUrl}}/>
|
<Image style={styles.image} source={{uri: selectedProduct?.imageUrl}}/>
|
||||||
</View>
|
</View>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
||||||
@@ -233,11 +239,11 @@ const OrderScreen: FC<OrderScreenProps> = ({order}) => {
|
|||||||
<DText>Селлер: {order.sellerName}</DText>
|
<DText>Селлер: {order.sellerName}</DText>
|
||||||
<DText>{}</DText>
|
<DText>{}</DText>
|
||||||
<DTitle style={styles.contentTitle}>Товар</DTitle>
|
<DTitle style={styles.contentTitle}>Товар</DTitle>
|
||||||
<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>
|
{/*<DText>{}</DText>*/}
|
||||||
<DTitle style={styles.contentTitle}>Сборка</DTitle>
|
{/*<DTitle style={styles.contentTitle}>Сборка</DTitle>*/}
|
||||||
|
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.buttonsContainer}>
|
<View style={styles.buttonsContainer}>
|
||||||
@@ -249,7 +255,6 @@ const OrderScreen: FC<OrderScreenProps> = ({order}) => {
|
|||||||
onAccepted={() => {
|
onAccepted={() => {
|
||||||
setAcceptModalVisible(false);
|
setAcceptModalVisible(false);
|
||||||
assemblyApi.create(order.databaseId).then(creationResult => {
|
assemblyApi.create(order.databaseId).then(creationResult => {
|
||||||
console.log(creationResult.message)
|
|
||||||
Toast.show({
|
Toast.show({
|
||||||
type: creationResult.ok ? 'success' : 'error',
|
type: creationResult.ok ? 'success' : 'error',
|
||||||
text1: 'Создание сборки',
|
text1: 'Создание сборки',
|
||||||
@@ -273,7 +278,6 @@ const OrderScreen: FC<OrderScreenProps> = ({order}) => {
|
|||||||
export const OrderScreenController: FC = () => {
|
export const OrderScreenController: FC = () => {
|
||||||
const order: Order | undefined = useSelector((state: RootState) => state.assembly.order);
|
const order: Order | undefined = useSelector((state: RootState) => state.assembly.order);
|
||||||
if (!order) return <NoOrderScreen/>
|
if (!order) return <NoOrderScreen/>
|
||||||
console.log(order)
|
|
||||||
return <OrderScreen order={order}/>
|
return <OrderScreen order={order}/>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
41
src/screens/OrderScreen/useOrders.tsx
Normal file
41
src/screens/OrderScreen/useOrders.tsx
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import {useEffect, useState} from "react";
|
||||||
|
import {Order} from "../../types/order";
|
||||||
|
import ordersApi from "../../api/ordersApi";
|
||||||
|
import {setOrder} from "../../features/assembly/assemblySlice";
|
||||||
|
import {RootState} from "../../redux/store";
|
||||||
|
import {useDispatch, useSelector} from "react-redux";
|
||||||
|
import {refreshPagination} from "../../features/ordersFilter/ordersFilterSlice";
|
||||||
|
|
||||||
|
|
||||||
|
const useOrders = () => {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const [orders, setOrders] = useState<Order[]>([]);
|
||||||
|
const [isRefreshing, setIsRefreshing] = useState(false);
|
||||||
|
const filterState = useSelector((state: RootState) => state.ordersFilter);
|
||||||
|
const refresh = () => {
|
||||||
|
if (filterState.page == 0) return;
|
||||||
|
setIsRefreshing(true);
|
||||||
|
setOrders([]);
|
||||||
|
dispatch(refreshPagination());
|
||||||
|
}
|
||||||
|
useEffect(() => {
|
||||||
|
if (filterState.isVisible) return;
|
||||||
|
|
||||||
|
ordersApi.getOrders(filterState.page, filterState.orderBy, filterState.desc, filterState.shipmentDate, filterState.status).then(response => {
|
||||||
|
setOrders(oldOrders => [...oldOrders, ...response]);
|
||||||
|
setIsRefreshing(false);
|
||||||
|
});
|
||||||
|
}, [filterState.page]);
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (filterState.isVisible) return;
|
||||||
|
setOrders([]);
|
||||||
|
setIsRefreshing(true);
|
||||||
|
dispatch(refreshPagination());
|
||||||
|
}, [filterState.orderBy, filterState.desc, filterState.status, filterState.shipmentDate, filterState.isVisible]);
|
||||||
|
|
||||||
|
return {refresh, isRefreshing, orders};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useOrders;
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
import {StyleSheet, View} from "react-native";
|
import {StyleSheet, View} from "react-native";
|
||||||
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";
|
||||||
@@ -9,66 +8,50 @@ import {useEffect, useRef, useState} from "react";
|
|||||||
import {Order} from "../../types/order";
|
import {Order} from "../../types/order";
|
||||||
import {FlashList} from "@shopify/flash-list";
|
import {FlashList} from "@shopify/flash-list";
|
||||||
import SortingModal, {
|
import SortingModal, {
|
||||||
SortingModalElement,
|
|
||||||
SortingModalHandles
|
SortingModalHandles
|
||||||
} from "../../components/Modals/SortingModal/SortingModal";
|
} from "../../components/Modals/SortingModal/SortingModal";
|
||||||
import flashListSeparator from "../../components/FlashListSeparator/FlashListSeparator";
|
import flashListSeparator from "../../components/FlashListSeparator/FlashListSeparator";
|
||||||
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";
|
||||||
import {TabNavigatorParamList} from "../MainScreen/MainScreen";
|
import {TabNavigatorParamList} from "../MainScreen/MainScreen";
|
||||||
|
import useOrders from "../OrderScreen/useOrders";
|
||||||
|
import {nextPage, openOrdersFilterModal} from "../../features/ordersFilter/ordersFilterSlice";
|
||||||
|
|
||||||
function OrdersScreen() {
|
function OrdersScreen() {
|
||||||
|
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const navigator = useNavigation<NavigationProp<TabNavigatorParamList, 'Home'>>();
|
const navigator = useNavigation<NavigationProp<TabNavigatorParamList, 'Home'>>();
|
||||||
|
const {refresh, isRefreshing, orders} = useOrders();
|
||||||
|
|
||||||
const [orders, setOrders] = useState<Order[]>([]);
|
|
||||||
const sortingModalRef = useRef<SortingModalHandles | null>(null);
|
|
||||||
const defaultSortingValue = 'createdOnAsc';
|
|
||||||
const sortingModalElements: SortingModalElement[] = [
|
|
||||||
{id: 'createdOnAsc', value: 'createdOnAsc', label: 'Дата создания по убыванию'},
|
|
||||||
{id: 'createdOnDesc', value: 'createdOnDesc', label: 'Дата создания по возрастанию'},
|
|
||||||
{id: 'shipmentDateAsc', value: 'shipmentDateAsc', label: 'Дата отгрузки по убыванию'},
|
|
||||||
{id: 'shipmentDateDesc', value: 'shipmentDateDesc', label: 'Дата отгрузки по возрастанию'},
|
|
||||||
];
|
|
||||||
|
|
||||||
const [sortingValue, setSortingValue] = useState(defaultSortingValue);
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<SearchBar onSearch={() => {
|
|
||||||
}} onSupplierProductSelected={product => {
|
|
||||||
ordersApi.getOrdersBySupplierProduct(product.supplierProductId).then(setOrders)
|
|
||||||
}}/>
|
|
||||||
<View style={styles.sortingButtonWrapper}>
|
<View style={styles.sortingButtonWrapper}>
|
||||||
<SortingButton onPress={() => {
|
<SortingButton onPress={() => {
|
||||||
if (!sortingModalRef.current) return;
|
dispatch(openOrdersFilterModal());
|
||||||
sortingModalRef.current.present();
|
|
||||||
}}/>
|
}}/>
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.content}>
|
<View style={styles.content}>
|
||||||
<FlashList
|
<FlashList onRefresh={refresh}
|
||||||
keyboardShouldPersistTaps={"never"}
|
refreshing={isRefreshing}
|
||||||
data={orders}
|
keyboardShouldPersistTaps={"never"}
|
||||||
keyExtractor={(item: Order) => item.orderNumber.toString()}
|
data={orders}
|
||||||
renderItem={({item}) =>
|
keyExtractor={(item: Order) => item.databaseId.toString()}
|
||||||
<OrderCard onSelect={(order) => dispatch(setOrder(order))} order={item}/>}
|
renderItem={({item}) =>
|
||||||
showsHorizontalScrollIndicator={false}
|
<OrderCard onSelect={(order) => {
|
||||||
showsVerticalScrollIndicator={true}
|
dispatch(setOrder(order));
|
||||||
onEndReachedThreshold={0.1}
|
navigator.navigate("Home");
|
||||||
estimatedItemSize={720}
|
}} order={item}/>}
|
||||||
onEndReached={() => {
|
showsHorizontalScrollIndicator={false}
|
||||||
}}
|
showsVerticalScrollIndicator={true}
|
||||||
ItemSeparatorComponent={flashListSeparator}
|
onEndReachedThreshold={0.5}
|
||||||
|
estimatedItemSize={720}
|
||||||
|
onEndReached={() => {
|
||||||
|
if (!orders.length) return;
|
||||||
|
dispatch(nextPage());
|
||||||
|
}}
|
||||||
|
ItemSeparatorComponent={flashListSeparator}
|
||||||
|
|
||||||
/>
|
/>
|
||||||
<SortingModal onChange={setSortingValue}
|
|
||||||
onClose={() => {
|
|
||||||
}}
|
|
||||||
ref={sortingModalRef}
|
|
||||||
elements={sortingModalElements}
|
|
||||||
defaultElementId={defaultSortingValue}
|
|
||||||
/>
|
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
3
src/screens/OrdersScreen/useOrdersFilter.tsx
Normal file
3
src/screens/OrdersScreen/useOrdersFilter.tsx
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
const useOrdersFilter = () => {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -10,10 +10,19 @@ export type OrderProduct = {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export enum BaseMarketplace {
|
||||||
|
Wildberries,
|
||||||
|
Ozon,
|
||||||
|
YandexMarket
|
||||||
|
}
|
||||||
|
|
||||||
export type Order = {
|
export type Order = {
|
||||||
databaseId: number;
|
databaseId: number;
|
||||||
orderNumber: string;
|
orderNumber: string;
|
||||||
marketplaceName: string;
|
marketplaceName: string;
|
||||||
|
baseMarketplace: BaseMarketplace;
|
||||||
sellerName: string;
|
sellerName: string;
|
||||||
products: OrderProduct[];
|
products: OrderProduct[];
|
||||||
|
status: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user