diff options
| author | IT Fixcomart <it@fixcomart.co.id> | 2022-10-31 16:31:56 +0700 |
|---|---|---|
| committer | IT Fixcomart <it@fixcomart.co.id> | 2022-10-31 16:31:56 +0700 |
| commit | d6d2d9ceef2e95b604ac4ebdc054cad44a8440b1 (patch) | |
| tree | 376278eb3f7baa6b9405177b8fb57805d4a066b9 /src/pages | |
| parent | 97c98e0a6fa0757e58ca9dacf8e720a52e10dcf5 (diff) | |
Product detail and header
Diffstat (limited to 'src/pages')
| -rw-r--r-- | src/pages/_app.js | 7 | ||||
| -rw-r--r-- | src/pages/index.js | 12 | ||||
| -rw-r--r-- | src/pages/shop/product/[slug].js | 172 |
3 files changed, 191 insertions, 0 deletions
diff --git a/src/pages/_app.js b/src/pages/_app.js new file mode 100644 index 00000000..1e1cec92 --- /dev/null +++ b/src/pages/_app.js @@ -0,0 +1,7 @@ +import '../styles/globals.css' + +function MyApp({ Component, pageProps }) { + return <Component {...pageProps} /> +} + +export default MyApp diff --git a/src/pages/index.js b/src/pages/index.js new file mode 100644 index 00000000..57f96ec9 --- /dev/null +++ b/src/pages/index.js @@ -0,0 +1,12 @@ +import { useEffect, useState } from "react"; +import Header from "../components/header"; + +export default function Home() { + const [product, setProduct] = useState({}); + + return ( + <> + <Header /> + </> + ) +} diff --git a/src/pages/shop/product/[slug].js b/src/pages/shop/product/[slug].js new file mode 100644 index 00000000..519f8160 --- /dev/null +++ b/src/pages/shop/product/[slug].js @@ -0,0 +1,172 @@ +import Link from "next/link"; +import { useRouter } from "next/router"; +import { useEffect, useState } from "react"; +import Header from "../../../components/header"; +import ProductCard from "../../../components/productCard"; +import { getOdoo } from "../../../helpers/apiOdoo"; +import { createSlug, getId } from "../../../helpers/slug"; +import currencyFormat from "../../../helpers/currencyFormat"; +import Head from "next/head"; +import { Swiper, SwiperSlide } from "swiper/react"; + +import 'swiper/css'; + + +export async function getServerSideProps(context) { + const { slug } = context.query; + let product = await getOdoo('/api/v1/product/' + getId(slug)); + product = product[0]; + + const similarProducts = await getOdoo(`/api/v1/product/${getId(slug)}/similar?limit=20`); + + return {props: {product, similarProducts}}; +} + +export default function ProductDetail({product, similarProducts}) { + 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: '', + }); + + useEffect(() => { + if (product.variants.length == 1) { + setSelectedVariant(product.variants[0].id); + } + }, [product.variants]); + + 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]) + + let onchangeVariant = (e) => { + setSelectedVariant(e.target.value); + setQuantity("1"); + } + + let addToCart = () => { + return true; + } + + return ( + <> + <Head> + <title>{product.name + '- Indoteknik'}</title> + </Head> + <Header /> + <div className="px-4 pt-5 pb-10"> + <img src={product.image} alt={product.name} className="border border-gray-300 rounded-md mb-4 w-full h-[300px] object-contain object-center" /> + <Link href={'/shop/brands/' + createSlug(product.manufacture.name, product.manufacture.id)}> + {product.manufacture.name || '-'} + </Link> + <h1 className="mb-3">{product.name}{activeVariant.attributes != '' ? ' - ' + activeVariant.attributes : ''}</h1> + + {product.variant_total > 1 && selectedVariant == "" ? ( + <p className="text-xs text-gray-800 mb-1">Harga mulai dari:</p> + ) : ''} + + {product.lowest_price.discount_percentage > 0 ? ( + <div className="flex gap-x-1 items-center"> + <span className="badge-yellow">{activeVariant.price.discount_percentage}%</span> + <p className="text-xs text-gray-800 line-through">{currencyFormat(activeVariant.price.price)}</p> + </div> + ) : ''} + + {product.lowest_price.price > 0 ? ( + <p className="text-lg text-gray-900 font-semibold">{currencyFormat(activeVariant.price.price_discount)}</p> + ) : ( + <p className="text-gray-800">Dapatkan harga terbaik, <a href="">hubungi kami.</a></p> + )} + + <div className="flex gap-x-2 mt-5"> + <div className="w-9/12"> + <label className="form-label">Pilih: <span className="text-gray-800">{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> + <div className="w-3/12"> + <label htmlFor="quantity" className="form-label">Jumlah</label> + <input type="number" name="quantity" id="quantity" className="form-input text-center is-invalid" value={quantity} onChange={(e) => setQuantity(e.target.value)} /> + </div> + </div> + + <div className="flex gap-x-2 mt-2"> + <button className="btn-light w-full" >+ Quotation</button> + <button className="btn-primary w-full" onClick={addToCart} disabled={(product.lowest_price.price == 0 ? true : false)}>+ Keranjang</button> + </div> + + <div className="mt-10"> + <h2 className="h1 mb-2">Detail Produk</h2> + <div className="flex py-2 justify-between items-center gap-x-1 border-b border-gray-300"> + <h3 className="text-gray-900">Jumlah Varian</h3> + <p className="text-gray-800">{product.variant_total} Varian</p> + </div> + <div className="flex py-2 justify-between items-center gap-x-1 border-b border-gray-300"> + <h3 className="text-gray-900">Nomor SKU</h3> + <p className="text-gray-800" id="sku_number">SKU-{activeVariant.id}</p> + </div> + <div className="flex py-2 justify-between items-center gap-x-1 border-b border-gray-300"> + <h3 className="text-gray-900">Part Number</h3> + <p className="text-gray-800" id="part_number">{activeVariant.code}</p> + </div> + <div className="flex py-2 justify-between items-center gap-x-1 border-b border-gray-300"> + <h3 className="text-gray-900">Stok</h3> + <p className="text-gray-800" id="stock"> + {activeVariant.stock > 0 ? (activeVariant.stock > 5 ? 'Lebih dari 5' : 'Kurang dari 5') : '0'} + </p> + </div> + <div className="flex py-2 justify-between items-center gap-x-1 border-b border-gray-300"> + <h3 className="text-gray-900">Berat Barang</h3> + <p className="text-gray-800" id="weight">{activeVariant.weight > 0 ? activeVariant.weight : '1'} KG</p> + </div> + </div> + + <div className="mt-10"> + <h2 className="h1 mb-4">Deskripsi Produk</h2> + <div className="text-gray-800 leading-7" dangerouslySetInnerHTML={{__html: (product.description.trim() != '' ? product.description.replaceAll(/<*b>/g, '') : 'Belum ada deskripsi produk.')}}></div> + </div> + + <div className="mt-10"> + <h2 className="h1 mb-4">Produk Lainnya</h2> + <Swiper freeMode={true} slidesPerView={2.15} spaceBetween={8} loop={true}> + {similarProducts.products.map((product, index) => (<SwiperSlide key={index}><ProductCard data={product} /></SwiperSlide>))} + </Swiper> + </div> + + </div> + </> + ); +}
\ No newline at end of file |
