summaryrefslogtreecommitdiff
path: root/src/lib/product/components/Product.jsx
diff options
context:
space:
mode:
authorRafi Zadanly <zadanlyr@gmail.com>2023-02-17 17:07:50 +0700
committerRafi Zadanly <zadanlyr@gmail.com>2023-02-17 17:07:50 +0700
commitf99e0aba70efad0deb907d8e27f09fc9f527c8a4 (patch)
treef0ac96e4e736a1d385e32553f0e641ee27e11fd3 /src/lib/product/components/Product.jsx
parent90e1edab9b6a8ccc09a49fed3addbec2cbc4e4c3 (diff)
Refactor
Diffstat (limited to 'src/lib/product/components/Product.jsx')
-rw-r--r--src/lib/product/components/Product.jsx276
1 files changed, 276 insertions, 0 deletions
diff --git a/src/lib/product/components/Product.jsx b/src/lib/product/components/Product.jsx
new file mode 100644
index 00000000..2a3624e7
--- /dev/null
+++ b/src/lib/product/components/Product.jsx
@@ -0,0 +1,276 @@
+import Badge from "@/core/components/elements/Badge/Badge"
+import Divider from "@/core/components/elements/Divider/Divider"
+import Image from "@/core/components/elements/Image/Image"
+import Link from "@/core/components/elements/Link/Link"
+import currencyFormat from "@/core/utils/currencyFormat"
+import { useEffect, useState } from "react"
+import Select from "react-select"
+import ProductSimilar from "./ProductSimilar"
+import LazyLoad from "react-lazy-load"
+import { toast } from "react-hot-toast"
+import { addItemCart } from "@/core/utils/cart"
+
+const informationTabOptions = [
+ { value: 'specification', label: 'Spesifikasi' },
+ { value: 'description', label: 'Deskripsi' },
+ { value: 'important', label: 'Info Penting' },
+]
+
+const Product = ({ product }) => {
+ const [ quantity, setQuantity ] = useState('1')
+ const [ selectedVariant, setSelectedVariant ] = useState(null)
+ const [ informationTab, setInformationTab ] = useState(null)
+
+ const [ activeVariant, setActiveVariant ] = useState({
+ id: product.id,
+ code: product.code,
+ name: product.name,
+ price: product.lowestPrice,
+ stock: product.stockTotal,
+ weight: product.weight,
+ })
+
+ const variantOptions = product.variants?.map((variant) => ({
+ value: variant.id,
+ label:
+ (variant.code ? `[${variant.code}] ` : '')
+ +
+ (variant.attributes.length > 0 ? variant.attributes.join(', ') : product.name)
+ }))
+
+ useEffect(() => {
+ if (!selectedVariant && variantOptions.length == 1) {
+ setSelectedVariant(variantOptions[0])
+ }
+ }, [selectedVariant, variantOptions])
+
+ useEffect(() => {
+ if (selectedVariant) {
+ const variant = product.variants.find(variant => variant.id == selectedVariant.value)
+ const variantAttributes = variant.attributes.length > 0 ? ' - ' + variant.attributes.join(', ') : ''
+ console.log(variant);
+ setActiveVariant({
+ id: variant.id,
+ code: variant.code,
+ name: variant.parent.name + variantAttributes,
+ price: variant.price,
+ stock: variant.stock,
+ weight: variant.weight
+ })
+ }
+ }, [selectedVariant, product])
+
+ useEffect(() => {
+ if (!informationTab) {
+ setInformationTab(informationTabOptions[0].value)
+ }
+ }, [informationTab])
+
+ const handleClickCart = () => {
+ if (!selectedVariant) {
+ toast.error('Pilih varian terlebih dahulu')
+ return
+ }
+ if (!quantity || quantity < 1 || isNaN(parseInt(quantity))) {
+ toast.error('Jumlah barang minimal 1')
+ return
+ }
+ addItemCart({
+ productId: activeVariant.id,
+ quantity
+ })
+ toast.success('Berhasil menambahkan ke keranjang')
+ }
+
+ return (
+ <>
+ <Image
+ src={product.image}
+ alt={product.name}
+ className="h-72 object-contain object-center w-full border-b border-gray_r-4 bg-white"
+ />
+
+ <div className="p-4">
+ <Link href="/" className="mb-2">{ product.manufacture?.name }</Link>
+ <h1 className="leading-6 font-medium">
+ {activeVariant?.name}
+ </h1>
+ { activeVariant?.price?.discountPercentage > 0 && (
+ <div className="flex gap-x-1 items-center mt-2">
+ <div className="text-gray_r-11 line-through text-caption-1">
+ {currencyFormat(activeVariant?.price?.priceDiscount)}
+ </div>
+ <Badge type="solid-red">
+ {activeVariant?.price?.discountPercentage}%
+ </Badge>
+ </div>
+ ) }
+ <h3 className="text-red_r-11 font-semibold mt-1">
+ { activeVariant?.price?.price > 0 ? currencyFormat(activeVariant?.price?.price) : (
+ <span className="text-gray_r-11 leading-6 font-normal">
+ Hubungi kami untuk dapatkan harga terbaik,&nbsp;
+ <a href="https://wa.me/" className="text-red_r-11 underline">klik disini</a>
+ </span>
+ ) }
+ </h3>
+ </div>
+
+ <Divider />
+
+ <div className="p-4">
+ <div>
+ <label className="flex justify-between">
+ Pilih Varian:
+ <span className="text-gray_r-11">
+ { product?.variantTotal } Varian
+ </span>
+ </label>
+ <Select
+ name="variant"
+ classNamePrefix="form-select"
+ options={variantOptions}
+ className="mt-2"
+ value={selectedVariant}
+ onChange={(option) => setSelectedVariant(option)}
+ isSearchable={product.variantTotal > 10}
+ />
+ </div>
+ <div className="mt-4 mb-2">Jumlah</div>
+ <div className="flex gap-x-3">
+ <div className="w-2/12">
+ <input
+ name="quantity"
+ type="number"
+ className="form-input"
+ value={quantity}
+ onChange={(e) => setQuantity(e.target.value)}
+ />
+ </div>
+ <button
+ type="button"
+ className="btn-yellow flex-1"
+ onClick={handleClickCart}
+ >
+ Keranjang
+ </button>
+ <button
+ type="button"
+ className="btn-solid-red flex-1"
+ >
+ Beli
+ </button>
+ </div>
+ </div>
+
+ <Divider />
+
+ <div className="p-4">
+ <h2 className="font-semibold">Informasi Produk</h2>
+ <div className="flex gap-x-4 mt-4 mb-3">
+ { informationTabOptions.map((option) => (
+ <TabButton
+ value={option.value}
+ key={option.value}
+ active={informationTab == option.value}
+ onClick={() => setInformationTab(option.value)}
+ >
+ {option.label}
+ </TabButton>
+ )) }
+ </div>
+
+ <TabContent
+ active={informationTab == 'specification'}
+ className="rounded border border-gray_r-6 divide-y divide-gray_r-6"
+ >
+ <SpecificationContent label="Jumlah Varian">
+ <span>{product?.variantTotal} Varian</span>
+ </SpecificationContent>
+ <SpecificationContent label="Nomor SKU">
+ <span>SKU-{product?.id}</span>
+ </SpecificationContent>
+ <SpecificationContent label="Part Number">
+ <span>{activeVariant?.code || '-'}</span>
+ </SpecificationContent>
+ <SpecificationContent label="Stok">
+ { activeVariant?.stock > 0 && (
+ <span className="flex gap-x-1.5">
+ <div className="badge-solid-red">Ready Stock</div>
+ <div className="badge-gray">
+ { activeVariant?.stock > 5 ? '> 5' : '< 5' }
+ </div>
+ </span>
+ ) }
+ { activeVariant?.stock == 0 && (
+ <a
+ href="https://wa.me"
+ className="text-red_r-11 font-medium"
+ >
+ Tanya Stok
+ </a>
+ ) }
+ </SpecificationContent>
+ <SpecificationContent label="Berat Barang">
+ { activeVariant?.weight > 0 && (
+ <span>{ activeVariant?.weight } KG</span>
+ ) }
+ { activeVariant?.weight == 0 && (
+ <a
+ href="https://wa.me"
+ className="text-red_r-11 font-medium"
+ >
+ Tanya Berat
+ </a>
+ ) }
+ </SpecificationContent>
+ </TabContent>
+
+ <TabContent
+ active={informationTab == 'description'}
+ className="leading-6 text-gray_r-11"
+ dangerouslySetInnerHTML={{__html: (product.description != '' ? product.description : 'Belum ada deskripsi produk.')}}
+ />
+ </div>
+
+ <Divider />
+
+ <div className="p-4">
+ <h2 className="font-semibold mb-4">Kamu Mungkin Juga Suka</h2>
+ <LazyLoad>
+ <ProductSimilar query={product?.name.split(' ').slice(1, 3).join(' ')} />
+ </LazyLoad>
+ </div>
+ </>
+ )
+}
+
+const TabButton = ({ children, active, ...props }) => {
+ const activeClassName = active ? 'text-red_r-11 border-b border-red_r-11' : 'text-gray_r-11'
+ return (
+ <button
+ {...props}
+ type="button"
+ className={`font-medium pb-1 ${activeClassName}`}
+ >
+ { children }
+ </button>
+ )
+}
+
+const TabContent = ({ children, active, className, ...props }) => (
+ <div
+ {...props}
+ className={`${active ? 'block' : 'hidden'} ${className}`}
+ >
+ { children }
+ </div>
+)
+
+const SpecificationContent = ({ children, label }) => (
+ <div className="flex justify-between p-3">
+ <span className="text-gray_r-11">{ label }</span>
+ { children }
+ </div>
+)
+
+export default Product \ No newline at end of file