diff --git a/README.md b/README.md index 4a5fabb9b877030f5cc01b40a53da62850e0f5fe..650849241e47db98d81da78a2d9527595b92d962 100644 --- a/README.md +++ b/README.md @@ -6,27 +6,47 @@ A local e-commerce application created for ease of buying and selling transactions. ## Table of Contents + - [Install](#install) - [Running Development Mode](#running-development-mode) - [References](#references) ## Install + The Admin Website's frontend uses Node.js and is developed using React. You need to install the required dependencies prior to building and contributing to the project. - [Node.js](https://nodejs.org/en/download/releases/) and npm package manager Verify that Node.js has been successfully installed. Make sure the interpreter can be invoked from the shell. For example: + ``` npm --version ``` Now install the packages required for Node.js: + ``` npm install ``` +## Build + +``` +npm build +``` + +## Prepare environment + +Create a .env file in the root folder. Inside the .env file, put + +``` +REACT_APP_BASE_URL= https://industripilar-staging.herokuapp.com +``` + ## Running Development Mode + To serve the frontend: + ``` npm run start ``` @@ -34,6 +54,6 @@ npm run start You can see the app running by going to localhost:1234 via your favourite web browser. ## References + - https://docs.gitlab.com/ee/user/markdown.html#wiki---direct-page-link - https://nodejs.org/en/download/package-manager/ - diff --git a/package-lock.json b/package-lock.json index b5bd8a0e3f4452fb2f0c59a689dbe31f26752cef..097b18675c848d5ac2067ff69288d3785ad2b44c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5327,6 +5327,11 @@ "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", "dev": true }, + "downloadjs": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/downloadjs/-/downloadjs-1.4.7.tgz", + "integrity": "sha1-9p+W+UDg0FU9rCkROYZaPNAQHjw=" + }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -5913,9 +5918,9 @@ "dev": true }, "eventemitter3": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.0.tgz", - "integrity": "sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz", + "integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==", "dev": true }, "events": { @@ -6884,9 +6889,9 @@ } }, "http-proxy": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.0.tgz", - "integrity": "sha512-84I2iJM/n1d4Hdgc6y2+qY5mDaz2PUVjlg9znE9byl+q0uC3DeByqBGReQu5tpLK0TAqTIXScRUV+dg7+bUPpQ==", + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", "dev": true, "requires": { "eventemitter3": "^4.0.0", @@ -10911,9 +10916,9 @@ "dev": true }, "moment": { - "version": "2.25.3", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.25.3.tgz", - "integrity": "sha512-PuYv0PHxZvzc15Sp8ybUCoQ+xpyPWvjOuK72a5ovzp2LI32rJXOiIfyoFoYvG3s6EwwrdkMyWuRiEHSZRLJNdg==" + "version": "2.26.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.26.0.tgz", + "integrity": "sha512-oIixUO+OamkUkwjhAVE18rAMfRJNsNe/Stid/gwHSOfHrOtw9EhAY2AHvdKZ/k/MggcYELFCJz/Sn2pL8b8JMw==" }, "moment-timezone": { "version": "0.5.28", diff --git a/package.json b/package.json index afc57f5f9412bc272dae836795888c77bfb7b6b4..27b3eb91e870d65a17e6198434b05bcbde9fbab2 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,9 @@ "@material-ui/icons": "^4.9.1", "@reach/router": "^1.3.3", "bootstrap": "^4.4.1", + "downloadjs": "^1.4.7", "jquery": "^3.5.0", - "moment": "2.25.3", + "moment": "^2.26.0", "moment-timezone": "^0.5.28", "popper.js": "^1.16.1", "react": "^16.13.1", diff --git a/src/__test__/context_state.test.js b/src/__test__/context_state.test.js index c2c988d630c100b2720d0dbca3316812637ed8f7..2497cc9e5235bcb757b0403b9ddb2c2eb52f0a75 100644 --- a/src/__test__/context_state.test.js +++ b/src/__test__/context_state.test.js @@ -23,7 +23,6 @@ test("Test context state", async () => { await act(async () => { await navigate("/pengguna"); }); - expect(getByTestId("page").textContent).toContain("Pengguna"); await act(async () => { await fireEvent.click(getByTestId("logout")); diff --git a/src/__test__/donasi/ListDonasi.test.js b/src/__test__/donasi/ListDonasi.test.js index ebd869e4d35984b49ca83d3f0fde01d589cf28be..833e6a44b5511a3e8b00005a988f13d750625712 100644 --- a/src/__test__/donasi/ListDonasi.test.js +++ b/src/__test__/donasi/ListDonasi.test.js @@ -94,7 +94,7 @@ test(" Test List transaksi filter", async () => { }); await act(async () => { await fireEvent.input( - getByLabelText("Status Donasi:", { target: { value: "001" } }) + getByLabelText("Status Donasi", { target: { value: "001" } }) ); await fireEvent.click(getByTestId("submit-filter")); }); diff --git a/src/__test__/transaksi/ListTransaksi.test.js b/src/__test__/transaksi/ListTransaksi.test.js index f9317b6e299407512fc5bbff8cbf7dfc33103ed1..68c741030eb97eb57f3d7ec299ead474851cdd65 100644 --- a/src/__test__/transaksi/ListTransaksi.test.js +++ b/src/__test__/transaksi/ListTransaksi.test.js @@ -178,7 +178,7 @@ test(" Test List transaksi filter", async () => { }); await act(async () => { await fireEvent.input( - getByLabelText("Status transaksi:", { target: { value: "002" } }) + getByLabelText("Status transaksi", { target: { value: "002" } }) ); await fireEvent.click(getByTestId("submit-filter")); }); diff --git a/src/component/FormDownload.jsx b/src/component/FormDownload.jsx new file mode 100644 index 0000000000000000000000000000000000000000..5a98c82fa0abfc4e23a5d51010fc3e009a851f1e --- /dev/null +++ b/src/component/FormDownload.jsx @@ -0,0 +1,64 @@ +import React from "react"; +import { useForm } from "react-hook-form"; +import useDownloadFile from "../utils/useDownloadFile"; +import { ErrorDiv } from "./html/html"; +import Button from "@material-ui/core/Button"; +import { css } from "@emotion/core"; +import GetAppIcon from "@material-ui/icons/GetApp"; + +const FormDownload = ({ url }) => { + const [download, error] = useDownloadFile( + `${process.env.REACT_APP_BASE_URL}${url}` + ); + const { register, handleSubmit } = useForm(); + const onSubmit = (data) => { + download({ ...data }); + }; + return ( + <form + onSubmit={handleSubmit(onSubmit)} + css={css` + display: flex; + `} + > + {error && <ErrorDiv>Mohon maaf ada sesuatu yang salah</ErrorDiv>} + <div> + <label + htmlFor="after" + css={css` + font-weight: bold; + `} + > + Tanggal Mulai{" "} + </label> + <input name="after" type="date" ref={register} /> + </div> + <div> + <label + htmlFor="before" + css={css` + font-weight: bold; + `} + > + Tanggal Berakhir{" "} + </label> + <input name="before" type="date" ref={register} /> + </div> + <Button + type="submit" + variant="contained" + color="primary" + startIcon={<GetAppIcon />} + css={css` + margin-top: 5%; + height: 70%; + width: 8rem; + `} + > + UNDUH + </Button> + </form> + ); +}; + +export default FormDownload; diff --git a/src/component/TableComponent.jsx b/src/component/TableComponent.jsx index 622255724069b30cff1197dac37570b4c9e655a7..30bed8d42f126a6fca2eb23bf70a60f8731f85d1 100644 --- a/src/component/TableComponent.jsx +++ b/src/component/TableComponent.jsx @@ -147,9 +147,7 @@ const TableComponent = ({ if (Array.isArray(field)) { return ( <RowInput key={field[0]}> - <LabelInput htmlFor={field[0]}> - {field[1]}: - </LabelInput> + <LabelInput htmlFor={field[0]}>{field[1]}</LabelInput> <InputForm id={field[0]} type="date" @@ -163,7 +161,7 @@ const TableComponent = ({ return ( <RowInput key={k[0]}> <LabelInput htmlFor={k[0]}> - {field[k].label}: + {field[k].label} </LabelInput> <InputSelectForm id={k[0]} @@ -199,7 +197,7 @@ const TableComponent = ({ `} data-testid="submit-filter" type="submit" - value="Filter" + value="FILTER" /> <Button variant="outlined" @@ -294,7 +292,6 @@ const TableComponent = ({ </TableContainer> </Paper> </div> - {/*<Paginator />*/} </div> ); }; diff --git a/src/layout/Layout.jsx b/src/layout/Layout.jsx index 85851d57b240cfdfd9d83f3866a907bc8583ea63..40f1e2605ba847f7c040649bf7c586d924ca17c5 100644 --- a/src/layout/Layout.jsx +++ b/src/layout/Layout.jsx @@ -33,7 +33,7 @@ const Layout = (props) => { border: 1px solid #e0e0e0; box-sizing: border-box; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); - overflow: scroll; + overflow: auto; `} > <Component {...rest} /> diff --git a/src/page/bank/FormBank.jsx b/src/page/bank/FormBank.jsx index a5cb1420069eac91d278c272c93f8ed9a2fa14f3..627ff86d04a7750fc7b98238fc6fb005a40337bf 100644 --- a/src/page/bank/FormBank.jsx +++ b/src/page/bank/FormBank.jsx @@ -36,7 +36,7 @@ const FormBank = ({ onSubmit, initialData = null }) => { name="bank_name" ref={register({ required: true })} /> - {errors.name && <ErrorDiv>Nama bank tidak boleh kosong</ErrorDiv>} + {errors.bank_name && <ErrorDiv>Nama bank tidak boleh kosong</ErrorDiv>} </RowInput> <RowInput> <LabelInput htmlFor="account_number">Nomor rekening</LabelInput> diff --git a/src/page/donasi/DetailDonasi.jsx b/src/page/donasi/DetailDonasi.jsx index c5f2c1f3d72b675d664201a5662f34fc04e3e8e0..928cfb7964e8d1d093a08d400a1263a722d900b1 100644 --- a/src/page/donasi/DetailDonasi.jsx +++ b/src/page/donasi/DetailDonasi.jsx @@ -157,7 +157,7 @@ const DetailDonasi = ({ idDonasi }) => { margin-right: 0.5rem; `} > - Tanggal diperbarui:{" "} + Tanggal Update:{" "} </div> <div>{stringToDate(donation.updated_at)}</div> </div> diff --git a/src/page/donasi/ListDonasi.jsx b/src/page/donasi/ListDonasi.jsx index 249fb26d6a3ac2033e14087dfaa0c2fb30b1b81d..7d5ac7e38d817095db918f8264e926d07210031d 100644 --- a/src/page/donasi/ListDonasi.jsx +++ b/src/page/donasi/ListDonasi.jsx @@ -2,6 +2,7 @@ import React from "react"; import TableComponent from "../../component/TableComponent"; import { css } from "@emotion/core"; import { donationToColoredStatus } from "../../component/TableUtils"; +import FormDownload from "../../component/FormDownload"; const ListDonasi = () => { const data = { @@ -47,6 +48,16 @@ const ListDonasi = () => { > KELOLA DONASI </div> + <div + css={css` + display: flex; + width: 25%; + margin-left: auto; + margin-right: 26%; + `} + > + <FormDownload url="/reports/program-donation/" /> + </div> <TableComponent {...data} /> </div> ); diff --git a/src/page/pengaturan/Pengaturan.jsx b/src/page/pengaturan/Pengaturan.jsx index 548fc950c9780562c19de6a73282f7a102d3cc6b..0ebb69e490a8a5b1fbef4449228cc52753eb31db 100644 --- a/src/page/pengaturan/Pengaturan.jsx +++ b/src/page/pengaturan/Pengaturan.jsx @@ -29,7 +29,24 @@ const Pengaturan = () => { Fetching data.. </div> ); - return <PengaturanForm {...{ email, shipping }} />; + return ( + <div + css={css` + display: flex; + flex-direction: column; + margin: 2rem 3rem 3rem 3rem; + `} + > + <div + css={css` + font-size: 35px; + `} + > + KELOLA PENGATURAN + </div> + <PengaturanForm {...{ email, shipping }} /> + </div> + ); }; export default Pengaturan; diff --git a/src/page/pengaturan/PengaturanForm.jsx b/src/page/pengaturan/PengaturanForm.jsx index 5bbcad4e2b82d7aafa315dde9fcaf8d5c335418a..05f8afec692fcc7eff09ecbbe389317581ed8ab5 100644 --- a/src/page/pengaturan/PengaturanForm.jsx +++ b/src/page/pengaturan/PengaturanForm.jsx @@ -68,7 +68,7 @@ const PengaturanForm = ({ email, shipping }) => { <h4>Kontak admin</h4> {errorEmail && <ErrorDiv>Error simpan konfigurasi kontak</ErrorDiv>} <RowInput> - <LabelInput htmlFor="name">Email admin: </LabelInput> + <LabelInput htmlFor="name">Email admin </LabelInput> <InputForm data-testid="email-admin" name="email" @@ -109,7 +109,7 @@ const PengaturanForm = ({ email, shipping }) => { <ErrorDiv>Error simpan konfigurasi pengiriman</ErrorDiv> )} <RowInput> - <LabelInput htmlFor="name">RW: </LabelInput> + <LabelInput htmlFor="name">RW </LabelInput> <InputForm data-testid="rw" name="hamlet" @@ -126,7 +126,7 @@ const PengaturanForm = ({ email, shipping }) => { </RowInput> <RowInput> - <LabelInput htmlFor="name">Kelurahan: </LabelInput> + <LabelInput htmlFor="name">Kelurahan </LabelInput> <InputForm data-testid="kelurahan" name="urban_village" @@ -137,7 +137,7 @@ const PengaturanForm = ({ email, shipping }) => { )} </RowInput> <RowInput> - <LabelInput htmlFor="name">Kecamatan: </LabelInput> + <LabelInput htmlFor="name">Kecamatan </LabelInput> <InputForm data-testid="kecamatan" name="sub_district" @@ -148,7 +148,7 @@ const PengaturanForm = ({ email, shipping }) => { )} </RowInput> <RowInput> - <LabelInput htmlFor="name">Biaya satu RW: </LabelInput> + <LabelInput htmlFor="name">Biaya satu RW </LabelInput> <InputForm data-testid="rw-cost" name="same_hamlet_costs" @@ -160,7 +160,7 @@ const PengaturanForm = ({ email, shipping }) => { )} </RowInput> <RowInput> - <LabelInput htmlFor="name">Biaya satu kelurahan: </LabelInput> + <LabelInput htmlFor="name">Biaya satu kelurahan </LabelInput> <InputForm data-testid="kelurahan-cost" name="same_urban_village_different_hamlet_costs" @@ -172,7 +172,7 @@ const PengaturanForm = ({ email, shipping }) => { )} </RowInput> <RowInput> - <LabelInput htmlFor="name">Biaya satu kecamatan: </LabelInput> + <LabelInput htmlFor="name">Biaya satu kecamatan </LabelInput> <InputForm data-testid="kecamatan-cost" name="same_sub_district_different_urban_village_costs" diff --git a/src/page/pengguna/DetailPengguna.jsx b/src/page/pengguna/DetailPengguna.jsx index 8c09272034fce5cd21641c9875585fbee8ae489a..df69ae03278c81b1ebe1173750381ecc7352c003 100644 --- a/src/page/pengguna/DetailPengguna.jsx +++ b/src/page/pengguna/DetailPengguna.jsx @@ -135,12 +135,25 @@ const DetailPengguna = ({ userId }) => { Profil </div> <div + className="row mt-2" css={css` margin-top: 1rem; margin-bottom: 1rem; `} > - <div data-testid="profile"> + <div className="col-sm-2"> + <img + alt={user.username} + className="img-fluid" + src={user.profile_picture} + css={css` + object-fit: cover; + width: 150px; + height: 150px; + `} + /> + </div> + <div data-testid="profile" className="col-sm-10"> <div css={css` margin-top: 1rem; diff --git a/src/page/pengguna/ListPengguna.jsx b/src/page/pengguna/ListPengguna.jsx index 3d57edca827a1f279e7c11f4e7ad871613c5b8a9..e6141701321651ab0ec74858ee01b81b0fdd07a0 100644 --- a/src/page/pengguna/ListPengguna.jsx +++ b/src/page/pengguna/ListPengguna.jsx @@ -7,7 +7,7 @@ const ListPengguna = () => { url: `${process.env.REACT_APP_BASE_URL}/users/`, pageDefault: 1, searchDefault: "", - title: "Pengguna", + title: "", keyValuePairs: [ ["id", "id"], ["full_name", "Nama Lengkap"], @@ -20,9 +20,18 @@ const ListPengguna = () => { return ( <div css={css` - margin-top: 2rem; + display: flex; + flex-direction: column; + margin: 2rem 3rem 3rem 3rem; `} > + <div + css={css` + font-size: 35px; + `} + > + KELOLA PENGGUNA + </div> <TableComponent {...data} /> </div> ); diff --git a/src/page/produk/DetailProduk.jsx b/src/page/produk/DetailProduk.jsx index d5df0f094b71c55bddf0b451dc12dc2ea82e4890..ef0c60090da990c9e583768b76d9f7bed1098a70 100644 --- a/src/page/produk/DetailProduk.jsx +++ b/src/page/produk/DetailProduk.jsx @@ -176,7 +176,7 @@ const DetailProduk = ({ productId }) => { <span className="text" css={css` - margin-top: 1rem; + vertical-align: middle; margin-left: 1%; `} > @@ -199,7 +199,7 @@ const DetailProduk = ({ productId }) => { <span className="text" css={css` - margin-top: 1rem; + vertical-align: middle; margin-left: 1%; `} > @@ -223,7 +223,7 @@ const DetailProduk = ({ productId }) => { <span className="text" css={css` - margin-top: 1rem; + vertical-align: middle; margin-left: 1%; `} > @@ -245,7 +245,7 @@ const DetailProduk = ({ productId }) => { <span className="text" css={css` - margin-top: 1rem; + vertical-align: middle; margin-left: 1%; `} > diff --git a/src/page/produk/FormProduk.jsx b/src/page/produk/FormProduk.jsx index 1624926fb893d7ea7d9e68c5ec402a656c06ce8b..a14dea1f2855dbfb23d8ca190f715fac5174f61f 100644 --- a/src/page/produk/FormProduk.jsx +++ b/src/page/produk/FormProduk.jsx @@ -88,7 +88,7 @@ const FormProduk = ({ onSubmit, initialData = null }) => { </RowInput> {results === undefined || Object.keys(results).length === 0 ? null : ( <RowInput> - <LabelInput htmlFor="name">Kategori: </LabelInput> + <LabelInput htmlFor="name">Kategori </LabelInput> <InputSelectForm data-testid="category-produk-input" name="category" @@ -139,7 +139,7 @@ const FormProduk = ({ onSubmit, initialData = null }) => { )} </RowInput> <RowInput> - <LabelInput htmlFor="is-preorder">Tipe Barang:</LabelInput> + <LabelInput htmlFor="is-preorder">Tipe Barang</LabelInput> <div css={css` display: flex; diff --git a/src/page/program/FormProgram.jsx b/src/page/program/FormProgram.jsx index 98b49e4073f0f0b20b407b04b026ffd470245310..1c81da6adcff93f17bae9f30aa75151af0cf5aa7 100644 --- a/src/page/program/FormProgram.jsx +++ b/src/page/program/FormProgram.jsx @@ -15,7 +15,7 @@ const FormProgram = ({ onSubmit, initialData = null }) => { defaultValues: initialData !== null ? { - name: initialData["name"], + program_name: initialData["name"], description: initialData["description"], link: initialData["link"], start_date_time: initialData["start_date_time"], @@ -34,7 +34,7 @@ const FormProgram = ({ onSubmit, initialData = null }) => { } else { formData.append("open_donation", true); } - formData.append("name", data["name"]); + formData.append("name", data["program_name"]); formData.append("description", data["description"]); formData.append("link", data["link"]); formData.append("start_date_time", data["start_date_time"]); @@ -60,10 +60,12 @@ const FormProgram = ({ onSubmit, initialData = null }) => { <LabelInput htmlFor="name">Nama program </LabelInput> <InputForm data-testid="name-program-input" - name="name" + name="program_name" ref={register({ required: true })} /> - {errors.name && <ErrorDiv>Nama program tidak boleh kosong</ErrorDiv>} + {errors.program_name && ( + <ErrorDiv>Nama program tidak boleh kosong</ErrorDiv> + )} </RowInput> <RowInput css={css` @@ -78,16 +80,20 @@ const FormProgram = ({ onSubmit, initialData = null }) => { name="description" ref={register({ required: true })} /> - {errors.description} + {errors.description && ( + <ErrorDiv>Deskripsi program tidak boleh kosong</ErrorDiv> + )} </RowInput> <RowInput> <LabelInput htmlFor="link">Link</LabelInput> <InputForm data-testid="link-program-input" name="link" - ref={register({ required: false })} + ref={register({ required: false, pattern: /^(https?|ftp):(\/)(\/)[^\s/$.?#].[^\s]*$/i })} /> - {<ErrorDiv>Link harus ada http://</ErrorDiv>} + {errors.link && ( + <ErrorDiv>Mohon periksa kembali tautan</ErrorDiv> + )} </RowInput> <RowInput> <LabelInput htmlFor="start_date_time"> @@ -99,7 +105,6 @@ const FormProgram = ({ onSubmit, initialData = null }) => { name="start_date_time" ref={register({ required: false })} /> - {errors.start_date_time} </RowInput> <RowInput> <LabelInput htmlFor="end_date_time"> @@ -111,7 +116,6 @@ const FormProgram = ({ onSubmit, initialData = null }) => { name="end_date_time" ref={register({ required: false })} /> - {errors.end_date_time} </RowInput> <RowInput> <LabelInput htmlFor="location">Lokasi </LabelInput> @@ -120,7 +124,6 @@ const FormProgram = ({ onSubmit, initialData = null }) => { name="location" ref={register({ required: false })} /> - {errors.location} </RowInput> <RowInput> <LabelInput htmlFor="speaker">Pembicara </LabelInput> @@ -129,7 +132,6 @@ const FormProgram = ({ onSubmit, initialData = null }) => { name="speaker" ref={register({ required: false })} /> - {errors.name} </RowInput> <RowInput> <LabelInput htmlFor="open_donation">Donasi</LabelInput> diff --git a/src/page/transaksi/DetailTransaksi.jsx b/src/page/transaksi/DetailTransaksi.jsx index 752bd432995c62ae9a70197884c7c26a3a45445d..8ff84372ea52cd82b8eb23973d5efed2ce8f6076 100644 --- a/src/page/transaksi/DetailTransaksi.jsx +++ b/src/page/transaksi/DetailTransaksi.jsx @@ -152,7 +152,7 @@ const DetailTransaksi = ({ idTransaksi }) => { margin-right: 0.5rem; `} > - Tanggal dibuat:{" "} + Tanggal Pembuatan:{" "} </div> <div>{stringToDate(transaction.created_at)}</div> </div> @@ -167,7 +167,7 @@ const DetailTransaksi = ({ idTransaksi }) => { margin-right: 0.5rem; `} > - Tanggal diperbarui:{" "} + Tanggal Update:{" "} </div> <div>{stringToDate(transaction.updated_at)}</div> </div> @@ -277,10 +277,11 @@ const DetailTransaksi = ({ idTransaksi }) => { {" "} <div css={css` - font-size: 1.5rem; + font-size: 1.4rem; + font-weight: bold; `} > - Pembayaran + Detail Pembayaran </div> {transaction.payment_method === "COD" && ( <div @@ -288,7 +289,7 @@ const DetailTransaksi = ({ idTransaksi }) => { font-size: 1.3rem; `} > - Cash On Delivery + Jenis Pembayaran: Cash On Delivery </div> )} {transaction.payment_method === "TRF" && ( @@ -297,7 +298,7 @@ const DetailTransaksi = ({ idTransaksi }) => { font-size: 1.3rem; `} > - Transfer + Jenis Pembayaran: Transfer <div> {transaction.proof_of_payment === null ? ( <div>User belum mengirimkan bukti pembayaran</div> @@ -352,7 +353,7 @@ const DetailTransaksi = ({ idTransaksi }) => { margin-right: 1rem; `} > - Nama Bank dan Pemilik Rekening Tujuan:{" "} + Nama Bank dan Pemilik Rekening Tujuan: </div> <div> {transaction.transfer_destination_bank_name} -{" "} diff --git a/src/page/transaksi/ListTransaksi.jsx b/src/page/transaksi/ListTransaksi.jsx index 2770515562108233fa4fee2e49219d4a05ab05f5..7e7def894ca1f16ef6148cdc498f488bdc5a62cf 100644 --- a/src/page/transaksi/ListTransaksi.jsx +++ b/src/page/transaksi/ListTransaksi.jsx @@ -6,6 +6,7 @@ import { stringToDate, transactionToColoredStatus, } from "../../component/TableUtils"; +import FormDownload from "../../component/FormDownload"; const ListTransaksi = () => { const data = { @@ -23,8 +24,8 @@ const ListTransaksi = () => { ], link: "/transaksi/", filter: [ - ["updated_at_date_range_after", "Updated from"], - ["updated_at_date_range_before", "Updated before"], + ["updated_at_date_range_after", "Tanggal Update dari"], + ["updated_at_date_range_before", "Tanggal Update hingga"], { transaction_status: { label: "Status transaksi", @@ -55,6 +56,16 @@ const ListTransaksi = () => { > KELOLA TRANSAKSI </div> + <div + css={css` + display: flex; + width: 25%; + margin-left: auto; + margin-right: 26%; + `} + > + <FormDownload url="/reports/transaction/" /> + </div> <TableComponent {...data} /> </div> ); diff --git a/src/utils/useDownloadFile.jsx b/src/utils/useDownloadFile.jsx new file mode 100644 index 0000000000000000000000000000000000000000..77d771740d3a571555cb1020186778ec25a76540 --- /dev/null +++ b/src/utils/useDownloadFile.jsx @@ -0,0 +1,52 @@ +import { useCallback, useState } from "react"; +import { useAuthContext } from "./contex"; +import download from "downloadjs"; +import { trackPromise } from "react-promise-tracker"; + +const useDownloadFile = (urlString) => { + const { profile } = useAuthContext(); + const [error, setErrorState] = useState(false); + const downloadFunction = useCallback( + ({ after, before }) => { + setErrorState(false); + let url = urlString.concat("?"); + let filename = "laporan"; + url = + after !== "" + ? url.concat(`created_at_date_range_after=${after}&`) + : url; + url = + before !== "" + ? url.concat(`created_at_date_range_before=${before}&`) + : url; + trackPromise( + fetch(url, { + method: "GET", + headers: { + Authorization: `Token ${profile.token}`, + "Access-Control-Expose-Headers": "Content-Disposition", + }, + }) + .then((response) => { + let disposition = response.headers.get("content-disposition"); + if (disposition && disposition.indexOf("inline") !== -1) { + let filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/; + let matches = filenameRegex.exec(disposition); + if (matches != null && matches[1]) { + filename = matches[1].replace(/['"]/g, ""); + } + } + return response.blob(); + }) + .then((blob) => { + download(blob, filename); + }) + .catch((e) => setErrorState(!(e instanceof DOMException))) + ); + }, + [urlString, profile.token] + ); + return [downloadFunction, error]; +}; + +export default useDownloadFile;