From 5e3f8fa3a23cfa4faf079b33b1cc542955479eb1 Mon Sep 17 00:00:00 2001 From: caturbgs Date: Wed, 15 Dec 2021 13:54:41 +0700 Subject: [PATCH] feat: add payback page --- package.json | 2 +- src/pages/App/DesktopLayout.js | 114 ++++++------ src/pages/App/MenuList.js | 75 ++++---- src/pages/Membership/Membership.js | 36 +--- src/pages/Payback/Payback.js | 286 +++++++++++++++++++++++++++++ src/pages/Payback/PaybackModal.js | 164 +++++++++++++++++ src/routes/app.js | 7 +- 7 files changed, 568 insertions(+), 116 deletions(-) create mode 100644 src/pages/Payback/Payback.js create mode 100644 src/pages/Payback/PaybackModal.js diff --git a/package.json b/package.json index 644ea67..a356ebf 100644 --- a/package.json +++ b/package.json @@ -173,7 +173,7 @@ [ "@babel/plugin-proposal-class-properties", { - "loose": false + "loose": true } ] ] diff --git a/src/pages/App/DesktopLayout.js b/src/pages/App/DesktopLayout.js index 56a4e1c..a0e1d46 100644 --- a/src/pages/App/DesktopLayout.js +++ b/src/pages/App/DesktopLayout.js @@ -1,32 +1,32 @@ -import React, { useState } from "react"; -import { Button, Drawer, Layout, Menu, Popover, Typography } from "antd"; -import { MenuList } from "./MenuList"; -import { Link, useHistory } from "react-router-dom"; -import { HomeOutlined, MenuOutlined, UserOutlined } from "@ant-design/icons"; -import { AppRoute, LINKS } from "../../routes/app"; -import { useStore } from "../../utils/useStore"; -import { observer } from "mobx-react-lite"; -import { useMediaQuery } from "react-responsive"; +import React, {useState} from "react"; +import {Button, Drawer, Layout, Menu, Popover, Typography} from "antd"; +import {MenuList} from "./MenuList"; +import {Link, useHistory} from "react-router-dom"; +import {HomeOutlined, MenuOutlined, UserOutlined} from "@ant-design/icons"; +import {AppRoute, LINKS} from "../../routes/app"; +import {useStore} from "../../utils/useStore"; +import {observer} from "mobx-react-lite"; +import {useMediaQuery} from "react-responsive"; -const { Text, Paragraph } = Typography; -const { Header, Content, Sider } = Layout; -const { SubMenu } = Menu; +const {Text, Paragraph} = Typography; +const {Header, Content, Sider} = Layout; +const {SubMenu} = Menu; export const DesktopLayout = observer(() => { - let history = useHistory(); - const xl = useMediaQuery({ minWidth: 1024 }); - const store = useStore(); - const [clicked, setClicked] = useState(false); + let history = useHistory(); + const xl = useMediaQuery({minWidth: 1024}); + const store = useStore(); + const [clicked, setClicked] = useState(false); - return ( - { Commision - - - - Supplier - - + + + + Supplier + + )} - {store.authentication.userData.role !== "Retail" && ( - - - - Product - + {store.authentication.userData.role !== "Retail" && ( + + + + Product + + + )} + + + + Payback + - )} - {store.authentication.userData.role === "Retail" && ( - - - - Transaction - + {store.authentication.userData.role === "Retail" && ( + + + + Transaction + + + )} + + + + Profile + - )} - - - - Profile - - - + diff --git a/src/pages/App/MenuList.js b/src/pages/App/MenuList.js index c56da91..e6d6a9c 100644 --- a/src/pages/App/MenuList.js +++ b/src/pages/App/MenuList.js @@ -1,35 +1,36 @@ -import React, { useEffect, useState } from "react"; -import { Menu } from "antd"; -import { Link } from "react-router-dom"; +import React, {useEffect, useState} from "react"; +import {Menu} from "antd"; +import {Link} from "react-router-dom"; import { - HomeOutlined, - UserOutlined, AppstoreOutlined, - MenuUnfoldOutlined, DatabaseOutlined, + FileProtectOutlined, + HomeOutlined, + MenuUnfoldOutlined, MoneyCollectOutlined, ProjectOutlined, - FileProtectOutlined, + UserOutlined, } from "@ant-design/icons"; -import { observer } from "mobx-react-lite"; -import { useStore } from "../../utils/useStore"; -import { LINKS } from "../../routes/app"; +import {observer} from "mobx-react-lite"; +import {useStore} from "../../utils/useStore"; +import {LINKS} from "../../routes/app"; -const { SubMenu } = Menu; +const {SubMenu} = Menu; export const MenuList = observer((props) => { const store = useStore(); - useEffect(() => {}, []); + useEffect(() => { + }, []); const [setKeys, setSetKeys] = useState(["dashboard"]); return ( - { )} - {store.authentication.userData.role !== "Retail" && ( - - - - Product + {store.authentication.userData.role !== "Retail" && ( + + + + Product + + + )} + + + + Payback - )} - {store.authentication.userData.role === ("Retail" || "Admin") && ( - - - - Transaction - - - )} - - + {store.authentication.userData.role === ("Retail" || "Admin") && ( + + + + Transaction + + + )} + + Profile diff --git a/src/pages/Membership/Membership.js b/src/pages/Membership/Membership.js index 848a9fc..95b271f 100644 --- a/src/pages/Membership/Membership.js +++ b/src/pages/Membership/Membership.js @@ -1,29 +1,13 @@ -import React, { useEffect, useState } from "react"; -import { - Button, - Card, - Col, - Divider, - Input, - List, - message, - Modal, - Row, - Space, - Table, - Tag, -} from "antd"; -import { useStore } from "../../utils/useStore"; -import { observer } from "mobx-react-lite"; -import { - ExclamationCircleOutlined, - FilterOutlined, - PlusSquareOutlined, -} from "@ant-design/icons"; -import { MembershipModal } from "./MembershipModal"; -import { BreadcumbComponent } from "../../component/BreadcumbComponent"; +import React, {useEffect, useState} from "react"; +import {Button, Card, Col, Divider, Input, List, message, Modal, Row, Space, Table, Tag,} from "antd"; +import {useStore} from "../../utils/useStore"; +import {observer} from "mobx-react-lite"; +import {ExclamationCircleOutlined, FilterOutlined, PlusSquareOutlined,} from "@ant-design/icons"; +import {MembershipModal} from "./MembershipModal"; +import {BreadcumbComponent} from "../../component/BreadcumbComponent"; +import {LINKS} from "../../routes/app"; -const { Search } = Input; +const {Search} = Input; export const Membership = observer(() => { const store = useStore(); @@ -105,7 +89,7 @@ export const Membership = observer(() => { const routeData = [ { - route: "/app/home", + route: LINKS.HOME, name: "Home", }, { diff --git a/src/pages/Payback/Payback.js b/src/pages/Payback/Payback.js new file mode 100644 index 0000000..e319918 --- /dev/null +++ b/src/pages/Payback/Payback.js @@ -0,0 +1,286 @@ +import React, {useState} from "react"; +import {Button, Card, Col, Divider, Image, Input, List, message, Row, Space, Table,} from "antd"; +import {useStore} from "../../utils/useStore"; +import {observer} from "mobx-react-lite"; +import {CheckCircleOutlined, CloseOutlined, FilterOutlined, PlusSquareOutlined,} from "@ant-design/icons"; +import {PaybackModal} from "./PaybackModal"; +import {BreadcumbComponent} from "../../component/BreadcumbComponent"; +import {LINKS} from "../../routes/app"; + +const {Search} = Input; + +export const Payback = observer(() => { + const store = useStore(); + const [visibleModal, setVisibleModal] = useState(false); + const [confirmLoading, setConfirmLoading] = useState(false); + const [initialData, setInitialData] = useState({}); + + // useEffect(() => { + // // const init = async () => { + // // try { + // // setIsLoading(true); + // // await store.membership.getData(); + // // await store.role.getData(); + // // setIsLoading(false); + // // } catch (e) { + // // setIsLoading(false); + // // } + // // }; + // + // // init(); + // }, []); + + const dummyData = [ + { + id: 1, + name: "John Doe", + picture: "https://presidenproperti.com/wp-content/uploads/2018/11/blog-ph.jpg", + amount: "Rp. 1.000.000", + }, + { + id: 1, + name: "John Doe", + picture: "https://presidenproperti.com/wp-content/uploads/2018/11/blog-ph.jpg", + amount: "Rp. 1.000.000", + }, + { + id: 1, + name: "John Doe", + picture: "https://presidenproperti.com/wp-content/uploads/2018/11/blog-ph.jpg", + amount: "Rp. 1.000.000", + }, + { + id: 1, + name: "John Doe", + picture: "https://presidenproperti.com/wp-content/uploads/2018/11/blog-ph.jpg", + amount: "Rp. 1.000.000", + }, + ] + + const columns = [ + { + title: "Name", + dataIndex: "name", + key: "name", + }, + { + title: "Picture", + dataIndex: "picture", + key: "picture", + render: (text, record) => ( + avatar + ), + }, + { + title: "Amount", + dataIndex: "amount", + key: "amount", + }, + { + title: "Action", + key: "action", + width: 100, + render: (text, record) => ( + + + + + ), + }, + ]; + + const routeData = [ + { + route: LINKS.HOME, + name: "Home", + }, + { + route: LINKS.PAYBACK, + name: Payback, + }, + ]; + + const onSubmit = async (data) => { + setConfirmLoading(true); + try { + // await store.membership.create(data); + // message.success("Success Add New Member"); + // await store.membership.getData(); + } catch (e) { + console.error(e, "apa errornya"); + message.error("Failed Add Member"); + } + setConfirmLoading(false); + setVisibleModal(false); + }; + + const handleAction = async (record, type) => { + + }; + + return ( +
+ {/* +

Some contents...

+

Some contents...

+

Some contents...

+
*/} + + +
+ + + + + + + + + + {store.ui.mediaQuery.isDesktop && ( + { + // let pageNumber = page.current; + // store.membership.pageSize = page.pageSize; + // store.membership.page = pageNumber - 1; + // // store.membership.isLoading = true; + // await store.membership.getData(); + // // store.membership.isLoading = false; + // }} + /> + )} + + {store.ui.mediaQuery.isMobile && ( + { + // store.membership.pageSize = page.pageSize; + // store.membership.page = page.current; + // store.membership.getData(); + // }, + // pageSize: store.membership.pageSize, + // total: store.membership.total_data, + // current: store.membership.page, + // style: {marginBottom: "1rem", marginRight: "1rem"}, + // }} + dataSource={dummyData} + style={{padding: 0}} + renderItem={(item) => { + return ( +
+ + + +
+ } + /> +
+

+ {item.amount} +

+
+ + + + ); + }} + /> + )} + + + + { + await onSubmit(data); + }} + onCancel={() => { + setInitialData({}); + setVisibleModal(false); + }} + /> + + ); +}); diff --git a/src/pages/Payback/PaybackModal.js b/src/pages/Payback/PaybackModal.js new file mode 100644 index 0000000..f7fcda0 --- /dev/null +++ b/src/pages/Payback/PaybackModal.js @@ -0,0 +1,164 @@ +import React, {useState} from 'react'; +import {Button, Form, Image, Input, message, Modal, Upload} from 'antd'; +import {useStore} from "../../utils/useStore"; +import {appConfig} from "../../config/app"; +import {LoadingOutlined, UploadOutlined} from "@ant-design/icons"; + +export const PaybackModal = ({ + visible, + onCreate, + onCancel, + initialData, + }) => { + const [form] = Form.useForm(); + const store = useStore(); + + const [fileList, setFileList] = useState([]); + const [previewTitle, setPreviewTitle] = useState(""); + const [previewImage, setPreviewImage] = useState(""); + const [loading, setLoading] = useState(false); + const [fileUrl, setFileUrl] = useState(""); + const firstIndexFileList = fileList[0]; + + const beforeUpload = (file) => { + let isPdf, isLt2M; + let allowedFile = ['image/jpeg', 'image/png', "application/pdf"]; + let isValid = allowedFile.includes(file.type) + if (!isValid) { + message.error("You can only upload PDF or Image file!"); + } + // return file.type === 'application/pdf' ? true : Upload.LIST_IGNORE; + isLt2M = file.size / 1024 / 1024 < 2; + if (!isLt2M) { + message.error("File must smaller than 2MB!"); + } + return isValid && isLt2M ? true : Upload.LIST_IGNORE; + } + + const handlePreview = async (file) => { + const fileUrl = appConfig.apiUrl + file.response.path; + setPreviewTitle(file.url?.substring(file.url?.lastIndexOf("/") + 1)); + }; + + const handleChange = ({fileList}) => { + setFileList(fileList); + if (fileList.length && fileList[0].status === "done") { + form.setFieldsValue({ + file_url: fileList[0].response.path, + }); + console.log(fileList, "apaaaaaa"); + setFileUrl(fileList[0].response.path); + setPreviewImage(fileList[0].response.path); + setPreviewTitle(fileList[0].name); + } + }; + + const uploadButton = ( +
+ {loading ? ( + + ) : ( + + )} +
+ ); + + const previewUpload = ( + + ) + + return ( + { + form.resetFields() + onCancel() + }} + onOk={() => { + form + .validateFields() + .then(values => { + onCreate(values); + form.resetFields() + }) + .catch(info => { + console.log('Validate Failed:', info); + }); + }} + > +
+ + + + + +
+
+ + {!firstIndexFileList ? uploadButton : null} + +
+ Max size of file 2 mb +
+
+
+
Preview
+
+ preview +
+
{previewTitle}
+
{previewUpload} + {previewTitle && {`${previewTitle ?? ""}`}}
+
+
+
+ + + + +
+ ); +}; diff --git a/src/routes/app.js b/src/routes/app.js index 5e2aa7d..09e89b8 100644 --- a/src/routes/app.js +++ b/src/routes/app.js @@ -8,6 +8,7 @@ import {Profile} from "../pages/Profile/Profile"; import {Commission} from "../pages/Config/Commission"; import {Partner} from "../pages/Config/Partner"; import {Supplier} from "../pages/Config/Supplier"; +import {Payback} from "../pages/Payback/Payback"; export const LINKS = { @@ -20,7 +21,8 @@ export const LINKS = { PARTNER: "/app/partner", COMMISSION: "/app/commission", SUPPLIER: "/app/supplier", - + PAYBACK: "/app/payback", + }; export const AppRoute = () => { @@ -46,6 +48,9 @@ export const AppRoute = () => { + + +