289 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			289 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| import React, {useContext, useEffect, useState} from "react";
 | |
| import {Button, Card, Col, Form, Input, message, Modal, Row, Select, Upload} from "antd";
 | |
| import {FilterOutlined, PlusOutlined, UploadOutlined,} from "@ant-design/icons";
 | |
| import {BreadcumbComponent} from "../../component/BreadcumbComponent";
 | |
| import {useStore} from "../../utils/useStore";
 | |
| import {observer} from "mobx-react-lite";
 | |
| import {ProductComponent} from "../../component/ProductComponent";
 | |
| import {LINKS} from "../../routes/app";
 | |
| import {ModalLoaderContext} from "../../utils/modal";
 | |
| 
 | |
| const {Search} = Input;
 | |
| const {Option} = Select;
 | |
| 
 | |
| export const Product = observer(() => {
 | |
|   const store = useStore();
 | |
|   const modalLoader = useContext(ModalLoaderContext);
 | |
|   const [loading, setLoading] = useState(false);
 | |
|   const [visibleModalUpload, setVisibleModalUpload] = useState(false);
 | |
|   const [excel, setExcel] = useState("");
 | |
|   const [fileList, setFileList] = useState([]);
 | |
|   const [form] = Form.useForm();
 | |
| 
 | |
|   useEffect(() => {
 | |
|     const init = async () => {
 | |
|       try {
 | |
|         store.supplier.page = 0;
 | |
|         store.supplier.pageSize = 1000;
 | |
|         modalLoader.setLoading(true);
 | |
|         await Promise.allSettled([
 | |
|           store.supplier.getData(),
 | |
|           store.category.getData(),
 | |
|           store.product.getDataSubCategories(),
 | |
|           store.product.getProductPartner()
 | |
|         ]);
 | |
|         await store.product.getData();
 | |
|         modalLoader.setLoading(false);
 | |
|       } catch (e) {
 | |
|         modalLoader.setLoading(false);
 | |
|         if (e.response?.body?.message) {
 | |
|           message.error(e.response.body.message);
 | |
|           return;
 | |
|         }
 | |
|         message.error(e.message);
 | |
|       }
 | |
|     };
 | |
| 
 | |
|     init();
 | |
| 
 | |
|     return () => {
 | |
|       store.supplier.pageSize = 10;
 | |
|     };
 | |
|   }, []);
 | |
| 
 | |
|   const routeData = [
 | |
|     {
 | |
|       route: LINKS.HOME,
 | |
|       name: "Beranda",
 | |
|     },
 | |
|     {
 | |
|       route: LINKS.PRODUCT,
 | |
|       name: <span style={{fontWeight: "bold"}}>Produk</span>,
 | |
|     },
 | |
|   ];
 | |
| 
 | |
|   const beforeUpload = (file) => {
 | |
|     let isLt2M;
 | |
|     let allowedFile = [
 | |
|       "text/csv", "application/csv",
 | |
|       "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
 | |
|       "application/vnd.ms-excel.sheet.binary.macroEnabled.12",
 | |
|       "application/vnd.ms-excel",
 | |
|       "application/vnd.ms-excel.sheet.macroEnabled.12"
 | |
|     ];
 | |
|     let isValid = allowedFile.includes(file.type);
 | |
|     if (!isValid) {
 | |
|       message.error("You can only upload Excel file!");
 | |
|     }
 | |
|     isLt2M = file.size / 1024 / 1024 < 10;
 | |
|     if (!isLt2M) {
 | |
|       message.error("File must smaller than 10MB!");
 | |
|     }
 | |
|     return isValid && isLt2M ? true : Upload.LIST_IGNORE;
 | |
|   };
 | |
| 
 | |
|   const uploadHandler = async (args) => {
 | |
|     const file = args.file;
 | |
|     try {
 | |
|       const response = await store.product.uploadExcel(file);
 | |
| 
 | |
|       if (response.status === 201) {
 | |
|         message.success("Success upload excel!");
 | |
|       } else {
 | |
|         message.error("Failed upload excel!");
 | |
|       }
 | |
| 
 | |
|       setFileList([{
 | |
|         uid: '-1',
 | |
|         name: response.body.filename,
 | |
|         status: 'done',
 | |
|         url: '',
 | |
|       }]);
 | |
|       setExcel(response.body.filename);
 | |
|     } catch (e) {
 | |
|       setLoading(false);
 | |
|       message.error("Failed upload excel!");
 | |
|     }
 | |
|   };
 | |
| 
 | |
|   const handleChange = (info) => {
 | |
|     if (info.file.status === 'uploading') {
 | |
|       setLoading(true);
 | |
|     } else {
 | |
|       setLoading(false)
 | |
|     }
 | |
|   };
 | |
| 
 | |
|   const handleUploadProduct = async (data) => {
 | |
|     try {
 | |
|       const response = await store.product.uploadProduct(data);
 | |
| 
 | |
|       if (response.status === 201) {
 | |
|         message.success("Success Create Product by Excel!");
 | |
|       } else {
 | |
|         message.error("Failed Create Product by Excel!");
 | |
|       }
 | |
|       return response;
 | |
|     } catch (e) {
 | |
|       setLoading(false);
 | |
|       message.error("Failed Create Product by Excel!");
 | |
|     }
 | |
|   };
 | |
| 
 | |
|   const handleCancel = () => {
 | |
|     form.resetFields();
 | |
|     setFileList([]);
 | |
|     setExcel("");
 | |
|     setVisibleModalUpload(false);
 | |
|   };
 | |
| 
 | |
|   const handleSubmit = async (data) => {
 | |
|     const request = {
 | |
|       fileName: excel,
 | |
|       supplierCode: data.supplierCode
 | |
|     };
 | |
|     const responseUploadProduct = await handleUploadProduct(request);
 | |
| 
 | |
|     await store.product.getData();
 | |
|     setLoading(false);
 | |
|     setFileList([]);
 | |
|     setExcel("");
 | |
|     setVisibleModalUpload(false);
 | |
|   };
 | |
| 
 | |
|   return (
 | |
|       <div className={["ppob-container"].join(" ")}>
 | |
|         <BreadcumbComponent data={routeData}/>
 | |
|         <Card>
 | |
|               <div>
 | |
|                 <Row style={{marginBottom: 20}}>
 | |
|                   <Col span={12}>
 | |
|                     <Button
 | |
|                         onClick={() => {
 | |
|                           store.product.visibleModalFilterProduct = true;
 | |
|                         }}
 | |
|                     >
 | |
|                       <FilterOutlined/>
 | |
|                       Filter
 | |
|                     </Button>
 | |
|                   </Col>
 | |
|                   <Col span={12}>
 | |
|                     <div
 | |
|                         style={{
 | |
|                           display: store.ui.mediaQuery.isMobile ? "" : "flex",
 | |
|                           justifyContent: "flex-end",
 | |
|                           textAlign: "right",
 | |
|                         }}
 | |
|                     >
 | |
|                       {/* <Search
 | |
|                     placeholder="input search text"
 | |
|                     style={{
 | |
|                       width: store.ui.mediaQuery.isMobile ? 160 : 200,
 | |
|                       marginRight: store.ui.mediaQuery.isMobile ? 0 : 10,
 | |
|                       marginBottom: store.ui.mediaQuery.isMobile ? 10 : 0,
 | |
|                     }}
 | |
|                   /> */}
 | |
| 
 | |
|                       {store.authentication.userData.role == "Admin" && <div
 | |
|                           style={{
 | |
|                             display: store.ui.mediaQuery.isMobile ? "" : "flex",
 | |
|                             justifyContent: "flex-end",
 | |
|                             textAlign: "right",
 | |
|                           }}
 | |
|                       >
 | |
|                         <Button
 | |
|                             disabled={visibleModalUpload}
 | |
|                             style={{
 | |
|                               marginRight: store.ui.mediaQuery.isMobile ? 0 : 10,
 | |
|                               marginBottom: store.ui.mediaQuery.isMobile ? 10 : 10,
 | |
|                             }}
 | |
|                             icon={<PlusOutlined/>}
 | |
|                             onClick={() => setVisibleModalUpload(true)}
 | |
|                         >
 | |
|                           Tambah Produk
 | |
|                         </Button>
 | |
|                       </div>}
 | |
|                     </div>
 | |
|                   </Col>
 | |
|                 </Row>
 | |
|               </div>
 | |
|           <ProductComponent/>
 | |
|         </Card>
 | |
| 
 | |
|         <Modal
 | |
|             visible={visibleModalUpload}
 | |
|             title={"Upload Excel Product"}
 | |
|             okText={"Create"}
 | |
|             cancelText="Cancel"
 | |
|             onCancel={() => {
 | |
|               form.resetFields();
 | |
|               handleCancel();
 | |
|             }}
 | |
|             onOk={() => {
 | |
|               form
 | |
|                   .validateFields()
 | |
|                   .then((values) => {
 | |
|                     console.log(values, "isi form");
 | |
|                     handleSubmit(values);
 | |
|                     form.resetFields();
 | |
|                   })
 | |
|                   .catch((info) => {
 | |
|                     console.error("Validate Failed:", info);
 | |
|                   });
 | |
|             }}
 | |
|         >
 | |
|           <Form form={form} layout="vertical">
 | |
|             <Form.Item
 | |
|                 name="fileName"
 | |
|                 label="Upload Excel Product"
 | |
|                 rules={[{required: true, message: "Please Upload Excel Product!"}]}
 | |
|             >
 | |
|               <Upload
 | |
|                   fileList={fileList}
 | |
|                   onChange={handleChange}
 | |
|                   beforeUpload={(file) => beforeUpload(file)}
 | |
|                   customRequest={(args) => uploadHandler(args)}
 | |
|                   onRemove={(file) => {
 | |
|                     setLoading(false);
 | |
|                     setFileList([]);
 | |
|                     setExcel("");
 | |
|                   }}
 | |
|               >
 | |
|                 <div
 | |
|                     style={{
 | |
|                       display: "flex",
 | |
|                       flexDirection: "row",
 | |
|                       justifyContent: "center",
 | |
|                     }}
 | |
|                 >
 | |
|                   <Button
 | |
|                       disabled={loading}
 | |
|                       style={{
 | |
|                         marginRight: store.ui.mediaQuery.isMobile ? 0 : 10,
 | |
|                       }}
 | |
|                       icon={<UploadOutlined/>}
 | |
|                   >
 | |
|                     Upload Product
 | |
|                   </Button>
 | |
|                 </div>
 | |
|               </Upload>
 | |
|             </Form.Item>
 | |
|             <Form.Item
 | |
|                 name="supplierCode"
 | |
|                 label="Supplier Code"
 | |
|                 rules={[{required: true, message: "Please input Supplier Code!"}]}
 | |
|             >
 | |
|               <Select>
 | |
|                 {store.supplier.data.map(data => (
 | |
|                     <Option key={data.id} value={data.code}>
 | |
|                       {data.name}
 | |
|                     </Option>
 | |
|                 ))}
 | |
|               </Select>
 | |
|             </Form.Item>
 | |
|           </Form>
 | |
|         </Modal>
 | |
|       </div>
 | |
|   );
 | |
| });
 |