summaryrefslogtreecommitdiff
path: root/src/pages/shop/product
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/pages/shop/product
parent90e1edab9b6a8ccc09a49fed3addbec2cbc4e4c3 (diff)
Refactor
Diffstat (limited to 'src/pages/shop/product')
-rw-r--r--src/pages/shop/product/[slug].js305
-rw-r--r--src/pages/shop/product/[slug].jsx29
2 files changed, 29 insertions, 305 deletions
diff --git a/src/pages/shop/product/[slug].js b/src/pages/shop/product/[slug].js
deleted file mode 100644
index 61692c1c..00000000
--- a/src/pages/shop/product/[slug].js
+++ /dev/null
@@ -1,305 +0,0 @@
-import Link from "@/components/elements/Link"
-import { useRouter } from "next/router"
-import { useEffect, useState } from "react"
-import Header from "@/components/layouts/Header"
-import apiOdoo from "@/core/utils/apiOdoo"
-import { createSlug, getIdFromSlug } from "@/core/utils/slug"
-import currencyFormat from "@/core/utils/currencyFormat"
-import Layout from "@/components/layouts/Layout"
-import { createOrUpdateItemCart } from "@/core/utils/cart"
-import toast from "react-hot-toast"
-import Footer from "@/components/layouts/Footer"
-import Image from "@/components/elements/Image"
-import LineDivider from "@/components/elements/LineDivider"
-import { HeartIcon as HeartIconSolid } from "@heroicons/react/24/solid"
-import { useAuth } from "@/core/utils/auth"
-import { HeartIcon } from "@heroicons/react/24/outline"
-import LazyLoad from "react-lazy-load"
-import ProductSimilar from "@/components/products/ProductSimilar"
-
-export async function getServerSideProps( context ) {
- const { slug } = context.query
- let product = await apiOdoo('GET', '/api/v1/product/' + getIdFromSlug(slug))
- if (product?.length == 1) {
- product = product[0]
- product.description = product.description.replaceAll('<p>', '||p||')
- product.description = product.description.replaceAll('</p>', '||/p||')
- product.description = product.description.replace(/(<([^>]+)>)/gi, ' ')
- product.description = product.description.replaceAll('||p||', '<p>')
- product.description = product.description.replaceAll('||/p||', '</p>')
- product.description = product.description.trim()
- }
- return { props: { product } }
-}
-
-export default function ProductDetail({ product }) {
- const [ auth ] = useAuth()
- const router = useRouter()
- const { slug } = router.query
- const [selectedVariant, setSelectedVariant] = useState("")
- const [quantity, setQuantity] = useState("1")
- const [activeVariant, setActiveVariant] = useState({
- id: product.id,
- code: product.code,
- price: product.lowest_price,
- stock: product.stock_total,
- weight: product.weight,
- attributes: '',
- })
-
- const [ isAddedToWishlist, setAddedToWishlist ] = useState(false)
- const [ activeTab, setActiveTab ] = useState('specification')
-
- const addOrDeleteWishlist = async () => {
- if (auth) {
- await apiOdoo('POST', `/api/v1/user/${auth.id}/wishlist/create-or-delete`, {
- product_id: product.id
- })
- if (isAddedToWishlist) {
- toast.success('Berhasil menghapus dari wishlist')
- } else {
- toast.success('Berhasil menambahkan ke wishlist')
- }
- setAddedToWishlist(!isAddedToWishlist)
- } else {
- toast.error('Login terlebih dahulu untuk melanjutkan')
- router.push('/login')
- }
- }
-
- useEffect(() => {
- if (auth) {
- const checkWishlist = async () => {
- const wishlist = await apiOdoo('GET', `/api/v1/user/${auth.id}/wishlist?product_id=${product.id}`)
- setAddedToWishlist(wishlist.product_total > 0 ? true : false)
- }
- checkWishlist()
- }
- }, [ auth, product ])
-
- useEffect(() => {
- if (product.variants.length == 1) {
- setSelectedVariant(product.variants[0].id)
- }
- }, [ product ])
-
- useEffect(() => {
- if (selectedVariant != '') {
- let newActiveVariant = product.variants.filter((variant) => {
- return variant.id == selectedVariant
- })
-
- if (newActiveVariant.length == 1) {
- newActiveVariant = newActiveVariant[0]
- setActiveVariant({
- id: newActiveVariant.id,
- code: newActiveVariant.code,
- price: newActiveVariant.price,
- stock: newActiveVariant.stock,
- weight: newActiveVariant.weight,
- attributes: newActiveVariant.attributes.join(', '),
- })
- }
- }
- }, [selectedVariant, product])
-
- const onchangeVariant = (e) => {
- setSelectedVariant(e.target.value)
- }
-
- const onChangeQuantity = (e) => {
- let inputValue = e.target.value
- inputValue = parseInt(inputValue)
- inputValue = Math.floor(inputValue)
- setQuantity(inputValue)
- }
-
- const addItemToCart = () => {
- if (product.variant_total > 1 && !selectedVariant) {
- toast.error('Pilih varian terlebih dahulu untuk menambahkan ke keranjang', { duration: 2000 })
- return false
- }
-
- if (quantity > 0) {
- toast.success('Berhasil menambahkan ke keranjang', { duration: 1500 })
- createOrUpdateItemCart(activeVariant.id, parseInt(quantity))
- } else {
- toast.error('Jumlah barang yang ditambahkan minimal 1 pcs', { duration: 2000 })
- }
-
- return true
- }
-
- const checkoutProduct = () => {
- if (!auth) {
- toast.error('Login terlebih dahulu untuk melanjutkan', { duration: 2000 })
- router.push('/login')
- return
- }
- if (product.variant_total > 1 && !selectedVariant) {
- toast.error('Pilih varian terlebih dahulu untuk melanjutkan pembelian', { duration: 2000 })
- return
- }
- if (quantity < 0) {
- toast.error('Jumlah barang yang ditambahkan minimal 1 pcs', { duration: 2000 })
- return
- }
- router.push(`/shop/checkout?product_id=${activeVariant.id}&qty=${quantity}`)
- }
-
- const TabButton = ({ children, name }) => (
- <button
- type="button"
- className={`font-medium pb-1 ${activeTab == name ? 'text-red_r-11 border-b border-red_r-10' : 'text-gray_r-11'}`}
- onClick={() => setActiveTab(name)}
- >
- { children }
- </button>
- )
-
- return (
- <>
- <Header title={`${product.name} - Indoteknik`}/>
- <Layout>
- <Image
- src={product.image}
- alt={product.name}
- className="border-b border-gray_r-6 w-full h-[300px] object-contain object-center bg-white"
- />
-
- <div className="p-4">
- <div className="flex justify-between gap-x-3">
- <div>
- <Link href={'/shop/brands/' + createSlug(product.manufacture.name, product.manufacture.id)}>
- {product.manufacture.name ?? '-'}
- </Link>
- <h1 className="h2 mt-2 mb-3">{product.name}{activeVariant.attributes ? ' - ' + activeVariant.attributes : ''}</h1>
- </div>
- <button className="h-fit" onClick={addOrDeleteWishlist}>
- { isAddedToWishlist && (
- <HeartIconSolid className="w-6 text-red_r-10" />
- ) }
- { !isAddedToWishlist && (
- <HeartIcon className="w-6" />
- ) }
- </button>
- </div>
-
- {product.variant_total > 1 && !selectedVariant && product.lowest_price.price > 0 ? (
- <p className="text-caption-2 text-gray-800 mb-1">Harga mulai dari:</p>
- ) : ''}
-
- {product.lowest_price.discount_percentage > 0 ? (
- <div className="flex gap-x-1 items-center mb-1">
- <p className="text-caption-2 text-gray_r-11 line-through">{currencyFormat(activeVariant.price.price)}</p>
- <span className="badge-solid-red">{activeVariant.price.discount_percentage}%</span>
- </div>
- ) : ''}
-
- {product.lowest_price.price > 0 ? (
- <p className="text-body-lg font-semibold">{currencyFormat(activeVariant.price.price_discount)}</p>
- ) : (
- <p className="text-gray_r-11">Dapatkan harga terbaik, <a href="">hubungi kami.</a></p>
- )}
- </div>
-
- <LineDivider />
-
- <div className="p-4">
- <div className="">
- <label className="form-label mb-2">Pilih: <span className="text-gray_r-11 font-normal">{product.variant_total} Varian</span></label>
- <select name="variant" className="form-input" value={selectedVariant} onChange={onchangeVariant} >
- <option value="" disabled={selectedVariant != "" ? true : false}>Pilih Varian...</option>
- {product.variants.length > 1 ? (
- product.variants.map((variant) => {
- return (
- <option key={variant.id} value={variant.id}>{variant.attributes.join(', ')}</option>
- )
- })
- ) : (
- <option key={product.variants[0].id} value={product.variants[0].id}>{product.variants[0].name}</option>
- )}
- </select>
- </div>
-
- <label htmlFor="quantity" className="form-label mb-1 mt-3">Jumlah</label>
- <div className="flex gap-x-2 mt-2">
- <input type="number" name="quantity" id="quantity" className="form-input h-full w-5/12 text-center" value={quantity} onChange={onChangeQuantity} />
-
- <button
- className="btn-yellow w-full"
- onClick={addItemToCart}
- disabled={(product.lowest_price.price == 0 ? true : false)}
- >
- Keranjang
- </button>
- <button
- onClick={checkoutProduct}
- className="btn-solid-red w-full"
- >
- Beli
- </button>
- </div>
- </div>
-
- <LineDivider />
-
- <div className="p-4">
- <h2 className="font-bold mb-4">Informasi Produk</h2>
- <div className="flex gap-x-3 mb-4">
- <TabButton name="specification">Spesifikasi</TabButton>
- <TabButton name="description">Deskripsi</TabButton>
- <TabButton name="information">Info Penting</TabButton>
- </div>
-
- <div className={`border border-gray_r-6 rounded divide-y ${activeTab == 'specification' ? 'block' : 'hidden'}`}>
- <ProductSpecification label="Jumlah Varian">
- <p className="text-gray-800">{product.variant_total} Varian</p>
- </ProductSpecification>
- <ProductSpecification label="Nomor SKU">
- <p className="text-gray-800" id="sku_number">SKU-{activeVariant.id}</p>
- </ProductSpecification>
- <ProductSpecification label="Part Number">
- <p className="text-gray-800" id="part_number">{activeVariant.code}</p>
- </ProductSpecification>
- <ProductSpecification label="Stok">
- <div className="flex gap-x-2" id="stock">
- {activeVariant.stock > 0 ? (activeVariant.stock > 5 && (
- <>
- <div className="badge-solid-red">Ready Stock</div>
- <div className="badge-gray">{activeVariant.stock > 5 ? '> 5' : '< 5'}</div>
- </>
- )) : '0'}
- </div>
- </ProductSpecification>
- <ProductSpecification label="Part Number">
- <p className="text-gray-800" id="weight">{activeVariant.weight > 0 ? activeVariant.weight : '1'} KG</p>
- </ProductSpecification>
- </div>
-
- <div
- className={`text-gray-800 leading-7 ${activeTab == 'description' ? 'block' : 'hidden'}`}
- dangerouslySetInnerHTML={{__html: (product.description != '' ? product.description : 'Belum ada deskripsi produk.')}}
- ></div>
- </div>
-
- <LineDivider />
-
- <LazyLoad>
- <ProductSimilar productId={getIdFromSlug(slug || '')} />
- </LazyLoad>
-
- <Footer />
- </Layout>
- </>
- )
-}
-
-const ProductSpecification = ({ children, ...props }) => {
- return (
- <div className="flex p-3 justify-between items-center gap-x-1">
- <h3 className="text-gray-900">{ props.label }</h3>
- { children }
- </div>
- )
-} \ No newline at end of file
diff --git a/src/pages/shop/product/[slug].jsx b/src/pages/shop/product/[slug].jsx
new file mode 100644
index 00000000..84a3c7d4
--- /dev/null
+++ b/src/pages/shop/product/[slug].jsx
@@ -0,0 +1,29 @@
+import Seo from "@/core/components/Seo"
+import BasicLayout from "@/core/components/layouts/BasicLayout"
+import { getIdFromSlug } from "@/core/utils/slug"
+import productApi from "@/lib/product/api/productApi"
+import Product from "@/lib/product/components/Product"
+
+export async function getServerSideProps(context) {
+ const { slug } = context.query
+ let product = await productApi({ id: getIdFromSlug(slug) })
+ if (product?.length == 1) {
+ product = product[0]
+ product.description = product.description.replaceAll('<p>', '||p||')
+ product.description = product.description.replaceAll('</p>', '||/p||')
+ product.description = product.description.replace(/(<([^>]+)>)/gi, ' ')
+ product.description = product.description.replaceAll('||p||', '<p>')
+ product.description = product.description.replaceAll('||/p||', '</p>')
+ product.description = product.description.trim()
+ }
+ return { props: { product } }
+}
+
+export default function ProductDetail({ product }) {
+ return (
+ <BasicLayout>
+ <Seo title={product?.name} />
+ <Product product={product} />
+ </BasicLayout>
+ )
+} \ No newline at end of file