summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafi Zadanly <zadanlyr@gmail.com>2023-02-20 17:03:28 +0700
committerRafi Zadanly <zadanlyr@gmail.com>2023-02-20 17:03:28 +0700
commited950b23d50f9b3993cfd2ac2386a5b3a68d5e57 (patch)
tree0094beddcb6df11a3bc5347759caf4cf7aeada59
parente33a330786ffbfcd774de00dc697c6dff47faf27 (diff)
fix
-rw-r--r--src/core/components/elements/Sidebar/Sidebar.jsx37
-rw-r--r--src/core/components/layouts/AnimationLayout.jsx2
-rw-r--r--src/core/components/layouts/AppLayout.jsx2
-rw-r--r--src/core/hooks/useAuth.js3
-rw-r--r--src/lib/transaction/api/cancelTransactionApi.js8
-rw-r--r--src/lib/transaction/api/transactionsApi.js8
-rw-r--r--src/lib/transaction/components/TransactionStatusBadge.jsx45
-rw-r--r--src/lib/transaction/components/Transactions.jsx149
-rw-r--r--src/lib/transaction/hooks/useTransactions.js15
-rw-r--r--src/lib/transaction/utils/transactions.js14
-rw-r--r--src/pages/my/menu.jsx94
-rw-r--r--src/pages/my/transactions.jsx12
12 files changed, 373 insertions, 16 deletions
diff --git a/src/core/components/elements/Sidebar/Sidebar.jsx b/src/core/components/elements/Sidebar/Sidebar.jsx
index 74984393..412ed915 100644
--- a/src/core/components/elements/Sidebar/Sidebar.jsx
+++ b/src/core/components/elements/Sidebar/Sidebar.jsx
@@ -1,13 +1,22 @@
-import { getAuth } from "@/core/utils/auth"
import Link from "../Link/Link"
import greeting from "@/core/utils/greeting"
import { Cog6ToothIcon } from "@heroicons/react/24/solid"
+import useAuth from "@/core/hooks/useAuth"
const Sidebar = ({
active,
close
}) => {
- const auth = getAuth()
+ const auth = useAuth()
+
+ const SidebarLink = ({ children, ...props }) => (
+ <Link
+ {...props}
+ onClick={close}
+ >{ children }</Link>
+ )
+
+ const itemClassName = 'px-4 py-3 block !text-gray_r-12/80 font-normal'
return (
<>
@@ -24,29 +33,31 @@ const Sidebar = ({
{ auth && (
<>
<div className="text-caption-2 text-gray_r-11">
- {/* { greeting() }, */}
+ { greeting() },
<span className="text-body-2 text-gray_r-12 block mt-1 font-medium">
{ auth?.name }
</span>
</div>
- <Link href="/my/menu" className="!text-gray_r-11 ml-auto my-auto">
+ <Link
+ onClick={close}
+ href="/my/menu"
+ className="!text-gray_r-11 ml-auto my-auto"
+ >
<Cog6ToothIcon className="w-6" />
</Link>
</>
) }
</div>
- <Link href="/" className="px-4 py-3 block !text-gray_r-12 font-normal">
+ <SidebarLink className={itemClassName} href="/">
Semua Brand
- </Link>
- <Link href="/" className="px-4 py-3 block !text-gray_r-12 font-normal">
+ </SidebarLink>
+ <SidebarLink className={itemClassName} href="/">
Tentang Indoteknik
- </Link>
- <Link href="/" className="px-4 py-3 block !text-gray_r-12 font-normal">
+ </SidebarLink>
+ <SidebarLink className={itemClassName} href="/">
Pusat Bantuan
- </Link>
- <Link href="/" className="px-4 py-3 block !text-gray_r-12 font-normal">
- Kategori
- </Link>
+ </SidebarLink>
+ <button className={`${itemClassName} w-full text-left`}>Kategori</button>
</div>
</div>
</>
diff --git a/src/core/components/layouts/AnimationLayout.jsx b/src/core/components/layouts/AnimationLayout.jsx
index adb6b081..cf2b06d5 100644
--- a/src/core/components/layouts/AnimationLayout.jsx
+++ b/src/core/components/layouts/AnimationLayout.jsx
@@ -2,7 +2,7 @@ import { motion } from 'framer-motion'
const AnimationLayout = ({ children, ...props }) => {
const transition = {
- ease: 'easeOut',
+ ease: 'easeIn',
duration: 0.3
}
diff --git a/src/core/components/layouts/AppLayout.jsx b/src/core/components/layouts/AppLayout.jsx
index 7aaa52ca..3e986477 100644
--- a/src/core/components/layouts/AppLayout.jsx
+++ b/src/core/components/layouts/AppLayout.jsx
@@ -4,8 +4,8 @@ import AnimationLayout from "./AnimationLayout"
const AppLayout = ({ children, title }) => {
return (
<>
- <AppBar title={title}/>
<AnimationLayout>
+ <AppBar title={title}/>
{ children }
</AnimationLayout>
</>
diff --git a/src/core/hooks/useAuth.js b/src/core/hooks/useAuth.js
index 488562f6..13f04454 100644
--- a/src/core/hooks/useAuth.js
+++ b/src/core/hooks/useAuth.js
@@ -1,3 +1,4 @@
+import { useEffect, useState } from "react"
import { getAuth } from "../utils/auth"
const useAuth = () => {
@@ -8,7 +9,7 @@ const useAuth = () => {
handleIsAuthenticated()
}, [])
- return [auth, setAuth]
+ return auth
}
export default useAuth \ No newline at end of file
diff --git a/src/lib/transaction/api/cancelTransactionApi.js b/src/lib/transaction/api/cancelTransactionApi.js
new file mode 100644
index 00000000..19891b5a
--- /dev/null
+++ b/src/lib/transaction/api/cancelTransactionApi.js
@@ -0,0 +1,8 @@
+import odooApi from "@/core/api/odooApi"
+
+const cancelTransactionApi = async ({ partnerId, transaction }) => {
+ const dataCancelTransaction = await odooApi('POST', `/api/v1/partner/${partnerId}/sale_order/${transaction.id}/cancel`)
+ return dataCancelTransaction
+}
+
+export default cancelTransactionApi \ No newline at end of file
diff --git a/src/lib/transaction/api/transactionsApi.js b/src/lib/transaction/api/transactionsApi.js
new file mode 100644
index 00000000..d36c3664
--- /dev/null
+++ b/src/lib/transaction/api/transactionsApi.js
@@ -0,0 +1,8 @@
+import odooApi from "@/core/api/odooApi"
+
+const transactionsApi = async ({partnerId, query}) => {
+ const dataTransactions = await odooApi('GET', `/api/v1/partner/${partnerId}/sale_order?${query}`)
+ return dataTransactions
+}
+
+export default transactionsApi \ No newline at end of file
diff --git a/src/lib/transaction/components/TransactionStatusBadge.jsx b/src/lib/transaction/components/TransactionStatusBadge.jsx
new file mode 100644
index 00000000..28fe714a
--- /dev/null
+++ b/src/lib/transaction/components/TransactionStatusBadge.jsx
@@ -0,0 +1,45 @@
+const TransactionStatusBadge = ({ status }) => {
+ let badgeProps = {
+ className: ['h-fit'],
+ text: ''
+ }
+ switch (status) {
+ case 'cancel':
+ badgeProps.className.push('badge-solid-red')
+ badgeProps.text = 'Pesanan batal'
+ break
+ case 'draft':
+ badgeProps.className.push('badge-red')
+ badgeProps.text = 'Pending quotation'
+ break
+ case 'waiting':
+ badgeProps.className.push('badge-yellow')
+ badgeProps.text = 'Pesanan diterima'
+ break
+ case 'sale':
+ badgeProps.className.push('badge-yellow')
+ badgeProps.text = 'Pesanan diproses'
+ break
+ case 'shipping':
+ badgeProps.className.push('badge-green')
+ badgeProps.text = 'Pesanan dikirim'
+ break
+ case 'partial_shipping':
+ badgeProps.className.push('badge-green')
+ badgeProps.text = 'Dikirim sebagian'
+ break
+ case 'done':
+ badgeProps.className.push('badge-solid-green')
+ badgeProps.text = 'Pesanan selesai'
+ break
+ }
+ badgeProps.className = badgeProps.className.join(' ')
+
+ return (
+ <div className={badgeProps.className}>
+ { badgeProps.text }
+ </div>
+ )
+}
+
+export default TransactionStatusBadge \ No newline at end of file
diff --git a/src/lib/transaction/components/Transactions.jsx b/src/lib/transaction/components/Transactions.jsx
new file mode 100644
index 00000000..97eb5f91
--- /dev/null
+++ b/src/lib/transaction/components/Transactions.jsx
@@ -0,0 +1,149 @@
+import { useRouter } from "next/router"
+import { getAuth } from "@/core/utils/auth"
+import { useState } from "react"
+import { toast } from "react-hot-toast"
+import { EllipsisVerticalIcon } from "@heroicons/react/24/outline"
+
+import { downloadPurchaseOrder, downloadQuotation } from "../utils/transactions"
+import useTransactions from "../hooks/useTransactions"
+import currencyFormat from "@/core/utils/currencyFormat"
+import cancelTransactionApi from "../api/cancelTransactionApi"
+import TransactionStatusBadge from "./TransactionStatusBadge"
+import Spinner from "@/core/components/elements/Spinner/Spinner"
+import Link from "@/core/components/elements/Link/Link"
+import BottomPopup from "@/core/components/elements/Popup/BottomPopup"
+
+const Transactions = () => {
+ const auth = getAuth()
+ const router = useRouter()
+ const {
+ q = '',
+ page = 1
+ } = router.query
+
+ const { transactions } = useTransactions({
+ partnerId: auth?.partnerId,
+ query: {
+ name: q,
+ limit: 30,
+ offset: (page - 1) * 30
+ }
+ })
+
+ const [ toOthers, setToOthers ] = useState(null)
+ const [ toDelete, setToDelete ] = useState(null)
+
+ const submitCancelTransaction = async () => {
+ const isCancelled = await cancelTransactionApi({
+ partnerId: auth.partnerId,
+ transaction: toDelete
+ })
+ if (isCancelled) {
+ toast.success('Berhasil batalkan transaksi')
+ transactions.refetch()
+ }
+ setToDelete(null)
+ }
+
+ return (
+ <div className="p-4">
+ <div className="flex flex-col gap-y-4">
+ { transactions.isLoading && (
+ <div className="flex justify-center my-4">
+ <Spinner className="w-6 text-gray_r-12/50 fill-gray_r-12" />
+ </div>
+ ) }
+ { transactions.data?.saleOrders?.map((saleOrder, index) => (
+ <div className="p-4 shadow border border-gray_r-3 rounded-md" key={index}>
+ <div className="grid grid-cols-2">
+ <Link href={`/my/transaction/${saleOrder.id}`}>
+ <span className="text-caption-2 text-gray_r-11">No. Transaksi</span>
+ <h2 className="text-red_r-11 mt-1">{ saleOrder.name }</h2>
+ </Link>
+ <div className="flex gap-x-1 justify-end">
+ <TransactionStatusBadge status={saleOrder.status} />
+ <EllipsisVerticalIcon className="w-5 h-5" onClick={() => setToOthers(saleOrder)} />
+ </div>
+ </div>
+ <Link href={`/my/transaction/${saleOrder.id}`}>
+ <div className="grid grid-cols-2 mt-3">
+ <div>
+ <span className="text-caption-2 text-gray_r-11">No. Purchase Order</span>
+ <p className="mt-1 font-medium text-gray_r-12">{ saleOrder.purchaseOrderName || '-' }</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">{ saleOrder.invoiceCount } Invoice</p>
+ </div>
+ </div>
+ <div className="grid grid-cols-2 mt-3">
+ <div>
+ <span className="text-caption-2 text-gray_r-11">Sales</span>
+ <p className="mt-1 font-medium text-gray_r-12">{ saleOrder.sales }</p>
+ </div>
+ <div className="text-right">
+ <span className="text-caption-2 text-gray_r-11">Total Harga</span>
+ <p className="mt-1 font-medium text-gray_r-12">{ currencyFormat(saleOrder.amountTotal) }</p>
+ </div>
+ </div>
+ </Link>
+ </div>
+ )) }
+ </div>
+
+ <BottomPopup title="Lainnya" active={toOthers} close={() => setToOthers(null)}>
+ <div className="flex flex-col gap-y-4 mt-2">
+ <button
+ className="text-left disabled:opacity-60"
+ disabled={!toOthers?.purchaseOrderFile}
+ onClick={() => { downloadPurchaseOrder(auth.partnerId, toOthers); setToOthers(null) }}
+ >
+ Download PO
+ </button>
+ <button
+ className="text-left disabled:opacity-60"
+ disabled={toOthers?.status != 'draft'}
+ onClick={() => { downloadQuotation(auth.partnerId, toOthers); setToOthers(null) }}
+ >
+ Download Quotation
+ </button>
+ <button
+ className="text-left disabled:opacity-60"
+ disabled={ toOthers?.status != 'waiting' }
+ onClick={() => { setToDelete(toOthers); setToOthers(null) }}
+ >
+ Batalkan Transaksi
+ </button>
+ </div>
+ </BottomPopup>
+
+ <BottomPopup
+ active={toDelete}
+ close={() => setToDelete(null)}
+ title="Batalkan Transaksi"
+ >
+ <div className="leading-7 text-gray_r-12/80">
+ Apakah anda yakin membatalkan transaksi <span className="underline">{toDelete?.name}</span>?
+ </div>
+ <div className="flex mt-6 gap-x-4">
+ <button
+ className="btn-solid-red flex-1"
+ type="button"
+ onClick={() => submitCancelTransaction()}
+ >
+ Ya, Batalkan
+ </button>
+ <button
+ className="btn-light flex-1"
+ type="button"
+ onClick={() => setToDelete(null)}
+ >
+ Batal
+ </button>
+ </div>
+ </BottomPopup>
+ </div>
+ )
+}
+
+export default Transactions \ No newline at end of file
diff --git a/src/lib/transaction/hooks/useTransactions.js b/src/lib/transaction/hooks/useTransactions.js
new file mode 100644
index 00000000..b5742cae
--- /dev/null
+++ b/src/lib/transaction/hooks/useTransactions.js
@@ -0,0 +1,15 @@
+import { useQuery } from "react-query"
+import transactionsApi from "../api/transactionsApi"
+import _ from "lodash-contrib"
+
+const useTransactions = ({ partnerId, query }) => {
+ const queryString = _.toQuery(query)
+ const fetchTransactions = async () => await transactionsApi({ partnerId, query: queryString })
+ const { data, isLoading, refetch } = useQuery(`transactions-${queryString}`, fetchTransactions)
+
+ return {
+ transactions: { data, isLoading, refetch }
+ }
+}
+
+export default useTransactions \ No newline at end of file
diff --git a/src/lib/transaction/utils/transactions.js b/src/lib/transaction/utils/transactions.js
new file mode 100644
index 00000000..166e8a7e
--- /dev/null
+++ b/src/lib/transaction/utils/transactions.js
@@ -0,0 +1,14 @@
+const downloadPurchaseOrder = (partnerId, transaction) => {
+ const url = `${process.env.ODOO_HOST}/api/v1/partner/${partnerId}/sale_order/${transaction.id}/download_po/${transaction.token}`
+ window.open(url, 'download')
+}
+
+const downloadQuotation = (partnerId, transaction) => {
+ const url = `${process.env.ODOO_HOST}/api/v1/partner/${partnerId}/sale_order/${transaction.id}/download/${transaction.token}`
+ window.open(url, 'download')
+}
+
+export {
+ downloadPurchaseOrder,
+ downloadQuotation
+} \ No newline at end of file
diff --git a/src/pages/my/menu.jsx b/src/pages/my/menu.jsx
new file mode 100644
index 00000000..d3edaa3b
--- /dev/null
+++ b/src/pages/my/menu.jsx
@@ -0,0 +1,94 @@
+import Divider from "@/core/components/elements/Divider/Divider"
+import Link from "@/core/components/elements/Link/Link"
+import AppLayout from "@/core/components/layouts/AppLayout"
+import { ChevronRightIcon, UserIcon } from "@heroicons/react/24/solid"
+
+export default function Menu() {
+ return (
+ <AppLayout title="Menu Utama">
+ <Link href="/my/profile" className="p-4 flex items-center">
+ <div className="rounded-full p-3 bg-gray_r-6 text-gray_r-12/90">
+ <UserIcon className="w-5" />
+ </div>
+ <div className="ml-4">
+ <div className="font-semibold text-gray_r-12">Rafi Zadanly</div>
+ <div className="badge-solid-red mt-1">Akun Bisnis</div>
+ </div>
+ <div className="ml-auto !text-gray_r-12">
+ <ChevronRightIcon className="w-6" />
+ </div>
+ </Link>
+
+ <Divider />
+
+ <div className="flex flex-col gap-y-6 py-6">
+ <div>
+ <MenuHeader>
+ Aktivitas Pembelian
+ </MenuHeader>
+
+ <div className="divide-y divide-gray_r-6 border-y border-gray_r-6 mt-4">
+ <LinkItem href="/my/transactions">
+ Daftar Transaksi
+ </LinkItem>
+ <LinkItem href="/">
+ Invoice & Faktur Pajak
+ </LinkItem>
+ <LinkItem href="/">
+ Wishlist
+ </LinkItem>
+ </div>
+ </div>
+
+ <div>
+ <MenuHeader>
+ Pusat Bantuan
+ </MenuHeader>
+
+ <div className="divide-y divide-gray_r-6 border-y border-gray_r-6 mt-4">
+ <LinkItem href="/">
+ Customer Support
+ </LinkItem>
+ <LinkItem href="/">
+ F.A.Q
+ </LinkItem>
+ </div>
+ </div>
+
+ <div>
+ <MenuHeader>
+ Pengaturan Akun
+ </MenuHeader>
+
+ <div className="divide-y divide-gray_r-6 border-y border-gray_r-6 mt-4">
+ <LinkItem href="/">
+ Daftar Alamat
+ </LinkItem>
+ <LinkItem href="/">
+ Ubah Password
+ </LinkItem>
+ <LinkItem href="/">
+ Keluar Akun
+ </LinkItem>
+ </div>
+ </div>
+ </div>
+ </AppLayout>
+ )
+}
+
+const MenuHeader = ({ children, ...props }) => (
+ <div {...props} className="font-medium px-4 flex">
+ { children }
+
+ </div>
+)
+
+const LinkItem = ({ children, ...props }) => (
+ <Link {...props} className="!text-gray_r-11 font-normal p-4 flex items-center">
+ { children }
+ <div className="ml-auto !text-gray_r-11">
+ <ChevronRightIcon className="w-5" />
+ </div>
+ </Link>
+) \ No newline at end of file
diff --git a/src/pages/my/transactions.jsx b/src/pages/my/transactions.jsx
new file mode 100644
index 00000000..a530afcc
--- /dev/null
+++ b/src/pages/my/transactions.jsx
@@ -0,0 +1,12 @@
+import AppLayout from "@/core/components/layouts/AppLayout"
+import dynamic from "next/dynamic"
+
+const TransactionsComponent = dynamic(() => import("@/lib/transaction/components/Transactions"))
+
+export default function Transactions() {
+ return (
+ <AppLayout title="Transaksi">
+ <TransactionsComponent />
+ </AppLayout>
+ )
+} \ No newline at end of file