diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/cart/components/Cart.jsx | 6 | ||||
| -rw-r--r-- | src/lib/transaction/api/checkoutPoApi.js | 10 | ||||
| -rw-r--r-- | src/lib/transaction/components/Transaction.jsx | 191 | ||||
| -rw-r--r-- | src/lib/transaction/components/Transactions.jsx | 3 | ||||
| -rw-r--r-- | src/pages/my/menu.jsx | 24 |
5 files changed, 224 insertions, 10 deletions
diff --git a/src/lib/cart/components/Cart.jsx b/src/lib/cart/components/Cart.jsx index bb1f21f6..e7606582 100644 --- a/src/lib/cart/components/Cart.jsx +++ b/src/lib/cart/components/Cart.jsx @@ -141,7 +141,7 @@ const Cart = () => { </button> <Link href={createSlug('/shop/product/', product?.parent.name, product?.parent.id)} - className="w-3/12 flex-shrink-0" + className="w-[30%] flex-shrink-0" > <Image src={product?.parent?.image} alt={product?.name} className="object-contain object-center border border-gray_r-6 h-40 w-full rounded-md" /> </Link> @@ -182,7 +182,7 @@ const Cart = () => { - </button> <input - className="form-input w-10 border-0 border-b rounded-none py-1 px-0 text-center" + className="form-input w-6 border-0 border-b rounded-none py-1 px-0 text-center" type="number" value={product?.quantity} onChange={(e) => updateQuantity(e.target.value, product?.id)} @@ -213,7 +213,7 @@ const Cart = () => { <div className="text-gray_r-11"> Total: <span className="text-red_r-11 font-semibold"> - { selectedProduct().length > 0 ? currencyFormat(totalPriceBeforeTax - totalDiscountAmount + totalTaxAmount) : ' - ' } + { selectedProduct().length > 0 ? currencyFormat(totalPriceBeforeTax - totalDiscountAmount + totalTaxAmount) : '-' } </span> </div> </div> diff --git a/src/lib/transaction/api/checkoutPoApi.js b/src/lib/transaction/api/checkoutPoApi.js new file mode 100644 index 00000000..aed43cff --- /dev/null +++ b/src/lib/transaction/api/checkoutPoApi.js @@ -0,0 +1,10 @@ +import odooApi from "@/core/api/odooApi" +import { getAuth } from "@/core/utils/auth" + +const checkoutPoApi = async ({ id }) => { + const auth = getAuth() + const dataCheckout = await odooApi('POST', `/api/v1/partner/${auth?.partnerId}/sale_order/${id}/checkout`) + return dataCheckout +} + +export default checkoutPoApi
\ No newline at end of file diff --git a/src/lib/transaction/components/Transaction.jsx b/src/lib/transaction/components/Transaction.jsx index c9bdf715..143b24bb 100644 --- a/src/lib/transaction/components/Transaction.jsx +++ b/src/lib/transaction/components/Transaction.jsx @@ -3,13 +3,18 @@ import useTransaction from "../hooks/useTransaction" import TransactionStatusBadge from "./TransactionStatusBadge" import Divider from "@/core/components/elements/Divider/Divider" import { useRef, useState } from "react" -import { downloadPurchaseOrder } from "../utils/transactions" +import { downloadPurchaseOrder, downloadQuotation } from "../utils/transactions" import BottomPopup from "@/core/components/elements/Popup/BottomPopup" import uploadPoApi from "../api/uploadPoApi" import { toast } from "react-hot-toast" import getFileBase64 from "@/core/utils/getFileBase64" import currencyFormat from "@/core/utils/currencyFormat" import VariantGroupCard from "@/lib/variant/components/VariantGroupCard" +import { ChevronDownIcon, ChevronRightIcon, ChevronUpIcon } from "@heroicons/react/24/outline" +import Link from "@/core/components/elements/Link/Link" +import Alert from "@/core/components/elements/Alert/Alert" +import checkoutPoApi from "../api/checkoutPoApi" +import cancelTransactionApi from "../api/cancelTransactionApi" const Transaction = ({ id }) => { const { transaction } = useTransaction({ id }) @@ -41,6 +46,37 @@ const Transaction = ({ id }) => { toast.error('Terjadi kesalahan internal, coba lagi nanti atau hubungi kami') } + const [ section, setSection ] = useState({ + customer: false, + invoice: false, + shipping: false + }) + const toggleSection = (name) => { + setSection({ ...section, [name]: !section[name] }) + } + + const [ cancelTransaction, setCancelTransaction ] = useState(false) + const openCancelTransaction = () => setCancelTransaction(true) + const closeCancelTransaction = () => setCancelTransaction(false) + const submitCancelTransaction = async () => { + const isCancelled = await cancelTransactionApi({ transaction: transaction.data }) + if (isCancelled) { + toast.success('Berhasil batalkan transaksi') + transaction.refetch() + } + closeCancelTransaction() + } + + const checkout = async () => { + if (!transaction.data?.purchaseOrderFile) { + toast.error('Mohon upload dokumen PO anda sebelum melanjutkan pesanan') + return + } + await checkoutPoApi({ id }) + toast.success('Berhasil melanjutkan pesanan') + transaction.refetch() + } + return ( <> { transaction.isLoading && ( @@ -105,6 +141,122 @@ const Transaction = ({ id }) => { </div> <Divider /> + + <SectionButton + label="Detail Pelanggan" + active={section.customer} + toggle={() => toggleSection('customer')} + /> + + { section.customer && <SectionContent address={transaction.data?.address?.customer} /> } + + <Divider /> + + <SectionButton + label="Detail Pengiriman" + active={section.shipping} + toggle={() => toggleSection('shipping')} + /> + + { section.shipping && <SectionContent address={transaction.data?.address?.shipping} /> } + + <Divider /> + + <SectionButton + label="Detail Penagihan" + active={section.invoice} + toggle={() => toggleSection('invoice')} + /> + + { section.invoice && <SectionContent address={transaction.data?.address?.invoice} /> } + + <Divider /> + + <div className="p-4"> + <p className="font-medium">Invoice</p> + <div className="flex flex-col gap-y-3 mt-4"> + { transaction.data?.invoices?.map((invoice, index) => ( + <Link href={`/my/invoice/${invoice.id}`} key={index}> + <div className="shadow rounded-md p-4 text-gray_r-12 font-normal flex justify-between"> + <div> + <p className="mb-2">{ invoice?.name }</p> + <div className="flex items-center gap-x-1"> + { invoice.amountResidual > 0 ? ( + <div className="badge-red">Belum Lunas</div> + ) : ( + <div className="badge-green">Lunas</div> + ) } + <p className="text-caption-2 text-gray_r-11"> + { currencyFormat(invoice.amountTotal) } + </p> + </div> + </div> + <ChevronRightIcon className="w-5 stroke-2" /> + </div> + </Link> + )) } + { transaction.data?.invoices?.length === 0 && ( + <Alert type='info' className='text-center'> + Belum ada Invoice + </Alert> + ) } + </div> + </div> + + <Divider /> + + <div className="p-4 pt-0"> + { transaction.data?.status == 'draft' && ( + <button + className="btn-yellow w-full mt-4" + onClick={checkout} + > + Lanjutkan Transaksi + </button> + ) } + <button + className="btn-light w-full mt-4" + disabled={transaction.data?.status != 'draft'} + onClick={downloadQuotation} + > + Download Quotation + </button> + { transaction.data?.status != 'draft' && ( + <button + className="btn-light w-full mt-4" + disabled={transaction.data?.status != 'waiting'} + onClick={openCancelTransaction} + > + Batalkan Transaksi + </button> + ) } + </div> + + <BottomPopup + active={cancelTransaction} + close={closeCancelTransaction} + title="Batalkan Transaksi" + > + <div className="leading-7 text-gray_r-12/80"> + Apakah anda yakin membatalkan transaksi <span className="underline">{transaction.data?.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={closeCancelTransaction} + > + Batal + </button> + </div> + </BottomPopup> <BottomPopup title="Upload PO" @@ -139,6 +291,43 @@ const Transaction = ({ id }) => { ) } +const SectionButton = ({ label, active, toggle }) => ( + <button className="p-4 font-medium flex justify-between w-full" onClick={toggle}> + <span>{label}</span> + { active ? ( + <ChevronUpIcon className="w-5" /> + ) : ( + <ChevronDownIcon className="w-5" /> + ) } + </button> +) + +const SectionContent = ({ address }) => { + let fullAddress = [] + if (address?.street) fullAddress.push(address.street) + if (address?.sub_district?.name) fullAddress.push(address.sub_district.name) + if (address?.district?.name) fullAddress.push(address.district.name) + if (address?.city?.name) fullAddress.push(address.city.name) + fullAddress = fullAddress.join(', ') + + return ( + <div className="flex flex-col gap-y-4 p-4 border-t border-gray_r-6"> + <DescriptionRow label="Nama"> + { address.name } + </DescriptionRow> + <DescriptionRow label="Email"> + { address.email || '-' } + </DescriptionRow> + <DescriptionRow label="No Telepon"> + { address.mobile || '-' } + </DescriptionRow> + <DescriptionRow label="Alamat"> + { fullAddress } + </DescriptionRow> + </div> + ) +} + const DescriptionRow = ({ children, label }) => ( <div className="grid grid-cols-2"> <span className="text-gray_r-11">{ label }</span> diff --git a/src/lib/transaction/components/Transactions.jsx b/src/lib/transaction/components/Transactions.jsx index 246a4a2c..25a6076a 100644 --- a/src/lib/transaction/components/Transactions.jsx +++ b/src/lib/transaction/components/Transactions.jsx @@ -38,7 +38,6 @@ const Transactions = () => { const submitCancelTransaction = async () => { const isCancelled = await cancelTransactionApi({ - partnerId: auth.partnerId, transaction: toCancel }) if (isCancelled) { @@ -171,7 +170,7 @@ const Transactions = () => { <button className="btn-solid-red flex-1" type="button" - onClick={() => submitCancelTransaction()} + onClick={submitCancelTransaction} > Ya, Batalkan </button> diff --git a/src/pages/my/menu.jsx b/src/pages/my/menu.jsx index d3edaa3b..69e4b8bb 100644 --- a/src/pages/my/menu.jsx +++ b/src/pages/my/menu.jsx @@ -1,9 +1,20 @@ import Divider from "@/core/components/elements/Divider/Divider" import Link from "@/core/components/elements/Link/Link" import AppLayout from "@/core/components/layouts/AppLayout" +import useAuth from "@/core/hooks/useAuth" +import { deleteAuth } from "@/core/utils/auth" import { ChevronRightIcon, UserIcon } from "@heroicons/react/24/solid" +import { useRouter } from "next/router" export default function Menu() { + const auth = useAuth() + const router = useRouter() + + const logout = () => { + deleteAuth() + router.push('/login') + } + return ( <AppLayout title="Menu Utama"> <Link href="/my/profile" className="p-4 flex items-center"> @@ -11,8 +22,13 @@ export default function Menu() { <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 className="font-semibold text-gray_r-12">{ auth?.name }</div> + { auth?.company && ( + <div className="badge-solid-red mt-1">Akun Bisnis</div> + ) } + { !auth?.company && ( + <div className="badge-gray mt-1">Akun Individu</div> + ) } </div> <div className="ml-auto !text-gray_r-12"> <ChevronRightIcon className="w-6" /> @@ -67,9 +83,9 @@ export default function Menu() { <LinkItem href="/"> Ubah Password </LinkItem> - <LinkItem href="/"> + <div onClick={logout} className="!text-gray_r-11 font-normal p-4 flex items-center"> Keluar Akun - </LinkItem> + </div> </div> </div> </div> |
