diff options
| author | Rafi Zadanly <zadanlyr@gmail.com> | 2023-01-26 17:02:02 +0700 |
|---|---|---|
| committer | Rafi Zadanly <zadanlyr@gmail.com> | 2023-01-26 17:02:02 +0700 |
| commit | 902e5dabbb1ab0612764983c094af398e5f636ee (patch) | |
| tree | b1b33fed082204be057c50053aee15eede6cce25 /src | |
| parent | e340f5c4f4c47cde90e7676fcf71b55ef50e7c23 (diff) | |
Invoice and invoice detail
Diffstat (limited to 'src')
| -rw-r--r-- | src/components/elements/Disclosure.js | 4 | ||||
| -rw-r--r-- | src/components/layouts/AppBar.js | 5 | ||||
| -rw-r--r-- | src/components/transactions/TransactionDetail.js | 2 | ||||
| -rw-r--r-- | src/pages/my/address/index.js | 1 | ||||
| -rw-r--r-- | src/pages/my/invoice/[id].js | 121 | ||||
| -rw-r--r-- | src/pages/my/invoices.js | 124 | ||||
| -rw-r--r-- | src/pages/my/menu.js | 2 | ||||
| -rw-r--r-- | src/pages/my/transaction/[id].js (renamed from src/pages/my/transactions/[id].js) | 6 | ||||
| -rw-r--r-- | src/pages/my/transactions.js (renamed from src/pages/my/transactions/index.js) | 10 |
9 files changed, 262 insertions, 13 deletions
diff --git a/src/components/elements/Disclosure.js b/src/components/elements/Disclosure.js index 584fa144..1f334be3 100644 --- a/src/components/elements/Disclosure.js +++ b/src/components/elements/Disclosure.js @@ -4,9 +4,9 @@ const Disclosure = ({ label, active, onClick }) => ( <div className={`flex justify-between p-4 ` + (active && 'bg-yellow_r-2')} onClick={onClick}> <p className="font-medium leading-normal">{ label }</p> { onClick && ( active ? ( - <ChevronUpIcon className="w-5 h-5" /> + <ChevronUpIcon className="w-5 h-5 stroke-2" /> ) : ( - <ChevronDownIcon className="w-5 h-5" /> + <ChevronDownIcon className="w-5 h-5 stroke-2" /> ) ) } </div> ); diff --git a/src/components/layouts/AppBar.js b/src/components/layouts/AppBar.js index f9dddf9d..b4c7703c 100644 --- a/src/components/layouts/AppBar.js +++ b/src/components/layouts/AppBar.js @@ -1,4 +1,4 @@ -import { ChevronLeftIcon, HeartIcon, HomeIcon } from "@heroicons/react/24/outline"; +import { Bars3Icon, ChevronLeftIcon, HeartIcon, HomeIcon } from "@heroicons/react/24/outline"; import Head from "next/head"; import { useRouter } from "next/router"; import { useEffect, useState } from "react"; @@ -49,6 +49,9 @@ const AppBar = ({ title }) => { <Link href="/"> <HomeIcon className="w-6 stroke-2 text-gray_r-12"/> </Link> + <Link href="/my/menu"> + <Bars3Icon className="w-6 stroke-2 text-gray_r-12"/> + </Link> </div> {/* --- End Icons */} </div> diff --git a/src/components/transactions/TransactionDetail.js b/src/components/transactions/TransactionDetail.js index 7659a321..295a4f9f 100644 --- a/src/components/transactions/TransactionDetail.js +++ b/src/components/transactions/TransactionDetail.js @@ -33,7 +33,7 @@ const TransactionDetailAddress = ({ transaction }) => { }; return ( - <div className="m-4 rounded border border-gray_r-6 divide-y divide-gray_r-6"> + <div className="m-4 rounded-md border border-gray_r-6 divide-y divide-gray_r-6"> <Disclosure label="Detail Pelanggan" active={activeSection.purchase} diff --git a/src/pages/my/address/index.js b/src/pages/my/address/index.js index dbe082ff..54e721b6 100644 --- a/src/pages/my/address/index.js +++ b/src/pages/my/address/index.js @@ -9,6 +9,7 @@ import WithAuth from "@/components/auth/WithAuth"; import apiOdoo from "@/core/utils/apiOdoo"; import { useAuth } from "@/core/utils/auth"; import { createOrUpdateItemAddress, getItemAddress } from "@/core/utils/address"; +import { toast } from "react-hot-toast"; export default function Address() { const router = useRouter(); diff --git a/src/pages/my/invoice/[id].js b/src/pages/my/invoice/[id].js new file mode 100644 index 00000000..93eae2be --- /dev/null +++ b/src/pages/my/invoice/[id].js @@ -0,0 +1,121 @@ +import AppBar from "@/components/layouts/AppBar"; +import Layout from "@/components/layouts/Layout"; +import LineDivider from "@/components/elements/LineDivider"; +import WithAuth from "@/components/auth/WithAuth"; +import { useEffect, useState } from "react"; +import apiOdoo from "@/core/utils/apiOdoo"; +import { useRouter } from "next/router"; +import { useAuth } from "@/core/utils/auth"; +import VariantCard from "@/components/variants/VariantCard"; +import currencyFormat from "@/core/utils/currencyFormat"; +import Disclosure from "@/components/elements/Disclosure"; +import DescriptionRow from "@/components/elements/DescriptionRow"; +import { SkeletonList } from "@/components/elements/Skeleton"; + +export default function DetailInvoice() { + const router = useRouter(); + const { id } = router.query; + const [ auth ] = useAuth(); + const [ invoice, setInvoice ] = useState(null); + + useEffect(() => { + if (auth && id) { + const loadInvoice = async () => { + const dataInvoice = await apiOdoo('GET', `/api/v1/partner/${auth?.partner_id}/invoice/${id}`); + setInvoice(dataInvoice); + } + loadInvoice(); + } + }, [ auth, id ]); + + const Customer = () => { + const customer = invoice?.customer; + const fullAddress = []; + if (customer?.street) fullAddress.push(customer.street); + if (customer?.sub_district?.name) fullAddress.push(customer.sub_district.name); + if (customer?.district?.name) fullAddress.push(customer.district.name); + if (customer?.city?.name) fullAddress.push(customer.city.name); + + return ( + <div className="p-4 pt-0 flex flex-col gap-y-4"> + <DescriptionRow label="Nama">{ invoice?.customer?.name }</DescriptionRow> + <DescriptionRow label="Email">{ invoice?.customer?.email || '-' }</DescriptionRow> + <DescriptionRow label="No Telepon">{ invoice?.customer?.mobile || '-' }</DescriptionRow> + <DescriptionRow label="Alamat">{ fullAddress.join(', ') }</DescriptionRow> + </div> + ); + }; + + return ( + <WithAuth> + <Layout className="pb-4"> + <AppBar title="Detail Invoice" /> + + { invoice ? ( + <> + <div className="p-4 flex flex-col gap-y-4"> + <DescriptionRow label="No Invoice"> + { invoice?.name } + </DescriptionRow> + <DescriptionRow label="Status Transaksi"> + { invoice?.amount_residual > 0 ? ( + <span className="badge-red">Belum Lunas</span> + ) : ( + <span className="badge-green">Lunas</span> + ) } + </DescriptionRow> + <DescriptionRow label="Purchase Order"> + { invoice?.purchase_order_name || '-' } + </DescriptionRow> + <DescriptionRow label="Ketentuan Pembayaran"> + { invoice?.payment_term } + </DescriptionRow> + { invoice?.amount_residual > 0 && invoice.invoice_date != invoice.invoice_date_due && ( + <DescriptionRow label="Tanggal Jatuh Tempo"> + { invoice?.invoice_date_due } + </DescriptionRow> + ) } + <DescriptionRow label="Nama Sales"> + { invoice?.sales } + </DescriptionRow> + <DescriptionRow label="Tanggal Invoice"> + { invoice?.invoice_date } + </DescriptionRow> + </div> + + <LineDivider /> + + <Disclosure + label="Detail Penagihan" + /> + + <Customer /> + + <LineDivider /> + + <Disclosure + label="Detail Produk" + /> + + <div className="mt-2 p-4 pt-0 flex flex-col gap-y-3"> + { invoice?.products?.map((product, index) => ( + <VariantCard + key={index} + data={product} + /> + )) } + <div className="flex justify-between mt-3 font-medium"> + <p>Total Belanja</p> + <p>{ currencyFormat(invoice?.amount_total || 0) }</p> + </div> + </div> + </> + ) : ( + <div className="p-4 py-6"> + <SkeletonList number={12} /> + </div> + ) } + </Layout> + </WithAuth> + ); +}
\ No newline at end of file diff --git a/src/pages/my/invoices.js b/src/pages/my/invoices.js new file mode 100644 index 00000000..e136f4fd --- /dev/null +++ b/src/pages/my/invoices.js @@ -0,0 +1,124 @@ +import WithAuth from "@/components/auth/WithAuth"; +import Alert from "@/components/elements/Alert"; +import Link from "@/components/elements/Link"; +import AppBar from "@/components/layouts/AppBar"; +import Layout from "@/components/layouts/Layout"; +import apiOdoo from "@/core/utils/apiOdoo"; +import { useAuth } from "@/core/utils/auth"; +import currencyFormat from "@/core/utils/currencyFormat"; +import { EllipsisVerticalIcon, MagnifyingGlassIcon } from "@heroicons/react/24/outline"; +import { useRouter } from "next/router"; +import { useEffect, useRef, useState } from "react"; + +export default function Invoices() { + const [ auth ] = useAuth(); + const router = useRouter(); + const { + q, + page = 1 + } = router.query; + + const [ invoices, setInvoices ] = useState([]); + const [ activePopupId, setActivePopupId ] = useState(null); + + const [ pageCount, setPageCount ] = useState(0); + const [ isLoading, setIsLoading ] = useState(true); + + const searchQueryRef = useRef(); + + useEffect(() => { + const loadInvoices = async () => { + if (auth) { + const limit = 10; + let offset = (page - 1) * 10; + let queryParams = [`limit=${limit}`, `offset=${offset}`]; + if (q) queryParams.push(`name=${q}`); + queryParams = queryParams.join('&'); + queryParams = queryParams ? '?' + queryParams : ''; + + const dataInvoices = await apiOdoo('GET', `/api/v1/partner/${auth.partner_id}/invoice${queryParams}`); + setInvoices(dataInvoices); + setPageCount(Math.ceil(dataInvoices.sale_order_total / limit)); + setIsLoading(false); + }; + }; + loadInvoices(); + }, [ auth, q, page ]); + + const actionSearch = (e) => { + e.preventDefault(); + let queryParams = []; + if (searchQueryRef.current.value) queryParams.push(`q=${searchQueryRef.current.value}`); + queryParams = queryParams.join('&'); + queryParams = queryParams ? `?${queryParams}` : ''; + router.push(`/my/invoices${queryParams}`); + }; + + return ( + <WithAuth> + <Layout> + <AppBar title="Invoice" /> + + <form onSubmit={actionSearch} className="p-4 pb-0 flex gap-x-4"> + <input + type="text" + className="form-input" + placeholder="Cari Transaksi" + ref={searchQueryRef} + defaultValue={q} + /> + <button type="submit" className="border border-gray_r-7 rounded px-3"> + <MagnifyingGlassIcon className="w-5"/> + </button> + </form> + + <div className="p-4 flex flex-col gap-y-5"> + { invoices?.invoice_total === 0 && !isLoading && ( + <Alert type="info" className="text-center"> + Invoice tidak ditemukan + </Alert> + ) } + { invoices?.invoices?.map((invoice, index) => ( + <div className="p-4 shadow rounded-md" key={index}> + <div className="grid grid-cols-2"> + <Link href={`/my/invoice/${invoice.id}`}> + <span className="text-caption-2 text-gray_r-11">No. Transaksi</span> + <h2 className="text-red_r-11 mt-1">{ invoice.name }</h2> + </Link> + <div className="flex gap-x-1 justify-end"> + { invoice.amount_residual > 0 ? ( + <div className="badge-red h-fit ml-auto">Belum Lunas</div> + ) : ( + <div className="badge-green h-fit ml-auto">Lunas</div> + ) } + <EllipsisVerticalIcon className="w-5 h-5" onClick={() => {}} /> + </div> + </div> + <Link href={`/my/invoice/${invoice.id}`}> + <div className="grid grid-cols-2 text-caption-2 text-gray_r-11 mt-2 font-normal"> + <p> + { invoice.invoice_date } + </p> + <p className="text-right"> + { invoice.payment_term } + </p> + </div> + <hr className="my-3"/> + <div className="grid grid-cols-2"> + <div> + <span className="text-caption-2 text-gray_r-11">Nomor PO</span> + <p className="mt-1 font-medium text-gray_r-12">{ invoice.purchase_order_name || '-' }</p> + </div> + <div className="text-right"> + <span className="text-caption-2 text-gray_r-11">Total Invoice</span> + <p className="mt-1 font-medium text-gray_r-12">{ currencyFormat(invoice.amount_total) }</p> + </div> + </div> + </Link> + </div> + )) } + </div> + </Layout> + </WithAuth> + ); +}
\ No newline at end of file diff --git a/src/pages/my/menu.js b/src/pages/my/menu.js index e7ece135..3de6f8a6 100644 --- a/src/pages/my/menu.js +++ b/src/pages/my/menu.js @@ -59,7 +59,7 @@ export default function MyMenu() { <p className="font-medium mb-2">Aktivitas Pembelian</p> <div className="flex flex-col mb-6"> <Menu icon={<ReceiptPercentIcon className="w-5" />} name="Daftar Transaksi" url="/my/transactions" /> - <Menu icon={<PaperClipIcon className="w-5" />} name="Invoice & Faktur Pajak" url="/my/transactions" /> + <Menu icon={<PaperClipIcon className="w-5" />} name="Invoice & Faktur Pajak" url="/my/invoices" /> <Menu icon={<HeartIcon className="w-5" />} name="Wishlist" url="/my/wishlist" /> </div> diff --git a/src/pages/my/transactions/[id].js b/src/pages/my/transaction/[id].js index 110915cf..09bf1ec7 100644 --- a/src/pages/my/transactions/[id].js +++ b/src/pages/my/transaction/[id].js @@ -13,14 +13,14 @@ import DescriptionRow from "@/components/elements/DescriptionRow"; import { TransactionDetailAddress } from "@/components/transactions/TransactionDetail"; import { SkeletonList } from "@/components/elements/Skeleton"; -export default function DetailTransactions() { +export default function DetailTransaction() { const router = useRouter(); const { id } = router.query; const [ auth ] = useAuth(); const [ transaction, setTransaction ] = useState(null); useEffect(() => { - if (auth) { + if (auth && id) { const loadTransaction = async () => { const dataTransaction = await apiOdoo('GET', `/api/v1/partner/${auth?.partner_id}/sale_order/${id}`); setTransaction(dataTransaction); @@ -44,7 +44,7 @@ export default function DetailTransactions() { { transaction?.name } </DescriptionRow> <DescriptionRow label="Purchase Order"> - { transaction?.po_name || '-' } + { transaction?.purchase_order_name || '-' } </DescriptionRow> <DescriptionRow label="Ketentuan Pembayaran"> { transaction?.payment_term } diff --git a/src/pages/my/transactions/index.js b/src/pages/my/transactions.js index c31336f2..aca5f081 100644 --- a/src/pages/my/transactions/index.js +++ b/src/pages/my/transactions.js @@ -81,9 +81,9 @@ export default function Transactions() { </Alert> ) } { transactions?.sale_orders?.map((transaction, index) => ( - <div className="p-4 border border-gray_r-7 rounded-md" key={index}> + <div className="p-4 shadow rounded-md" key={index}> <div className="grid grid-cols-2"> - <Link href={`/my/transactions/${transaction.id}`}> + <Link href={`/my/transaction/${transaction.id}`}> <span className="text-caption-2 text-gray_r-11">No. Transaksi</span> <h2 className="text-red_r-11 mt-1">{ transaction.name }</h2> </Link> @@ -92,9 +92,9 @@ export default function Transactions() { <EllipsisVerticalIcon className="w-5 h-5" onClick={() => setActivePopupId(transaction.id)} /> </div> </div> - <Link href={`/my/transactions/${transaction.id}`} className="grid grid-cols-2 mt-3"> + <Link href={`/my/transaction/${transaction.id}`} className="grid grid-cols-2 mt-3"> <div> - <span className="text-caption-2 text-gray_r-11">Dilayani Oleh</span> + <span className="text-caption-2 text-gray_r-11">Sales</span> <p className="mt-1 font-medium text-gray_r-12">{ transaction.sales }</p> </div> <div className="text-right"> @@ -106,7 +106,7 @@ export default function Transactions() { )) } </div> - <div className="pb-6"> + <div className="pb-6 pt-2"> <Pagination currentPage={page} pageCount={pageCount} url={`/my/transactions${q ? `?q=${q}` : ''}`} /> </div> |
