diff options
| author | trisusilo48 <tri.susilo@altama.co.id> | 2024-09-26 15:45:03 +0700 |
|---|---|---|
| committer | trisusilo48 <tri.susilo@altama.co.id> | 2024-09-26 15:45:03 +0700 |
| commit | 9a3d52dc189f7a309951c60fd923c49e9fb9085a (patch) | |
| tree | a25ba0d8c956dc8d8bd7fe2c3295f578b98999d0 | |
| parent | 8fe167e2e03efcd3d7058c22f4efc6db961de71f (diff) | |
dertail product
4 files changed, 100 insertions, 47 deletions
diff --git a/src-migrate/modules/product-detail/components/Information.tsx b/src-migrate/modules/product-detail/components/Information.tsx index 075ff8d1..8655517d 100644 --- a/src-migrate/modules/product-detail/components/Information.tsx +++ b/src-migrate/modules/product-detail/components/Information.tsx @@ -1,32 +1,24 @@ -import style from '../styles/information.module.css'; import { AutoComplete, AutoCompleteInput, AutoCompleteItem, AutoCompleteList, } from '@choc-ui/chakra-autocomplete'; +import style from '../styles/information.module.css'; -import React, { useEffect, useState } from 'react'; import dynamic from 'next/dynamic'; import Link from 'next/link'; -import { useQuery } from 'react-query'; +import { useEffect, useRef, useState } from 'react'; -import { IProductDetail } from '~/types/product'; -import { IProductVariantSLA } from '~/types/productVariant'; +import currencyFormat from '@/core/utils/currencyFormat'; +import { InputGroup, InputRightElement } from '@chakra-ui/react'; +import { ChevronDownIcon } from '@heroicons/react/24/outline'; +import Image from 'next/image'; +import { formatToShortText } from '~/libs/formatNumber'; import { createSlug } from '~/libs/slug'; import { getVariantSLA } from '~/services/productVariant'; -import { formatToShortText } from '~/libs/formatNumber'; -import currencyFormat from '@/core/utils/currencyFormat'; -import { Icon, InputGroup, InputRightElement } from '@chakra-ui/react'; -import { - CheckIcon, - ChevronDownIcon, - FingerPrintIcon, -} from '@heroicons/react/24/outline'; +import { IProductDetail } from '~/types/product'; import { useProductDetail } from '../stores/useProductDetail'; -import Image from 'next/image'; -import useDevice from '@/core/hooks/useDevice'; -import { optimizedAppearDataAttribute } from 'framer-motion'; const Skeleton = dynamic(() => import('@chakra-ui/react').then((mod) => mod.Skeleton) @@ -43,7 +35,13 @@ const Information = ({ product }: Props) => { const [inputValue, setInputValue] = useState<string | null>( selectedVariant?.code + ' - ' + selectedVariant?.attributes[0] ); - const variantOptions = product?.variants; + + const inputRef = useRef<HTMLInputElement>(null); + + const [variantOptions, setVariantOptions] = useState<any[]>( + product?.variants + ); + // let variantOptions = product?.variants; // const querySLA = useQuery<IProductVariantSLA>({ // queryKey: ['variant-sla', selectedVariant?.id], @@ -59,13 +57,29 @@ const Information = ({ product }: Props) => { useEffect(() => { getsla(); + setInputValue( + selectedVariant?.code + + (selectedVariant?.attributes[0] + ? ' - ' + selectedVariant?.attributes[0] + : '') + ); }, [selectedVariant]); const handleOnChange = (vals: any) => { let code = vals.split(' ')[0]; let variant = variantOptions.find((item) => item.code === code); setSelectedVariant(variant); - setInputValue(variant?.code + ' - ' + variant?.attributes[0]); + setInputValue( + variant?.code + + (variant?.attributes[0] ? ' - ' + variant?.attributes[0] : '') + ); + if (variant) { + const filteredOptions = product?.variants.filter( + (item) => item !== variant + ); + const newOptions = [variant, ...filteredOptions]; + setVariantOptions(newOptions); + } }; const handleOnKeyUp = (e: any) => { @@ -88,11 +102,15 @@ const Information = ({ product }: Props) => { > <InputGroup> <AutoCompleteInput + ref={inputRef} value={inputValue as string} onChange={(e) => handleOnKeyUp(e)} /> <InputRightElement> - <ChevronDownIcon className='h-6 w-6 text-gray-500' /> + <ChevronDownIcon + className='h-6 w-6 text-gray-500' + onClick={() => inputRef?.current?.focus()} + /> </InputRightElement> </InputGroup> @@ -100,26 +118,47 @@ const Information = ({ product }: Props) => { {variantOptions.map((option, cid) => ( <AutoCompleteItem key={`option-${cid}`} - value={option.code + ' - ' + option.attributes[0]} + value={ + option.code + + (option?.attributes[0] ? ' - ' + option?.attributes[0] : '') + } + _selected={ + option.id === selectedVariant?.id + ? { + bg: 'gray.300', + } + : undefined + } textTransform='capitalize' > - <div className='flex gap-x-2 justify-between w-full'> + <div + key={cid} + className='flex gap-x-2 w-full justify-between px-3 items-center p-2' + > <div className='text-small'> - {option.code + ' - ' + option.attributes[0]} + {option.code + + (option?.attributes[0] + ? ' - ' + option?.attributes[0] + : '')} </div> - <div className='grid grid-cols-3 items-end justify-items-end'> + <div + className={ + option?.price?.discount_percentage + ? 'flex gap-x-4 items-center justify-between' + : '' + } + > {option?.price?.discount_percentage > 0 && ( <> <div className='badge-solid-red text-xs'> {Math.floor(option?.price?.discount_percentage)}% </div> - <div className='text-gray_r-11 line-through text-[11px] sm:text-caption-2'> + <div className='min-w-16 sm:min-w-24 text-gray_r-11 line-through text-[11px] sm:text-caption-2'> {currencyFormat(option?.price?.price)} </div> </> )} - - <div className='text-danger-500 font-semibold mb-2'> + <div className='min-w-20 sm:min-w-28 text-danger-500 font-semibold'> {currencyFormat(option?.price?.price_discount)} </div> </div> diff --git a/src-migrate/modules/product-detail/components/PriceAction.tsx b/src-migrate/modules/product-detail/components/PriceAction.tsx index a39877e9..3544fa26 100644 --- a/src-migrate/modules/product-detail/components/PriceAction.tsx +++ b/src-migrate/modules/product-detail/components/PriceAction.tsx @@ -1,13 +1,12 @@ import style from '../styles/price-action.module.css'; -import React, { useEffect } from 'react'; +import Image from 'next/image'; +import Link from 'next/link'; +import { useEffect } from 'react'; import formatCurrency from '~/libs/formatCurrency'; import { IProductDetail } from '~/types/product'; import { useProductDetail } from '../stores/useProductDetail'; import AddToCart from './AddToCart'; -import Link from 'next/link'; -import { getAuth } from '~/libs/auth'; -import Image from 'next/image'; type Props = { product: IProductDetail; @@ -54,7 +53,7 @@ const PriceAction = ({ product }: Props) => { return ( <div - className='block md:sticky md:top-[150px] md:py-6 fixed bottom-0 left-0 right-0 bg-white p-4 z-10' + className='block md:sticky md:top-[150px] md:py-6 fixed bottom-0 left-0 right-0 bg-white p-2 z-10' id='price-section' > {!!activePrice && activePrice.price > 0 && ( @@ -97,20 +96,33 @@ const PriceAction = ({ product }: Props) => { <div className='h-4' /> <div className='flex gap-x-5 items-center'> - <div> - <label htmlFor='quantity' className='hidden'> - Quantity - </label> - <div className='flex items-center space-x-2'> - <input - type='number' - id='quantity' - value={quantityInput} - onChange={(e) => setQuantityInput(e.target.value)} - className={style['quantity-input']} - /> - </div> + <div className='relative flex items-center'> + <button + type='button' + className='absolute left-0 px-2 py-1 h-full text-gray-500' + onClick={() => + setQuantityInput(String(Math.max(1, Number(quantityInput) - 1))) + } + > + - + </button> + <input + type='number' + id='quantity' + min={1} + value={quantityInput} + onChange={(e) => setQuantityInput(e.target.value)} + className={style['quantity-input']} + /> + <button + type='button' + className='absolute right-0 px-2 py-1 h-full text-gray-500' + onClick={() => setQuantityInput(String(Number(quantityInput) + 1))} + > + + + </button> </div> + <div> <span className={sla?.qty < 10 ? 'text-red-600 font-medium' : ''}> {' '} diff --git a/src-migrate/modules/product-detail/components/ProductDetail.tsx b/src-migrate/modules/product-detail/components/ProductDetail.tsx index 8e8df646..b036cc2d 100644 --- a/src-migrate/modules/product-detail/components/ProductDetail.tsx +++ b/src-migrate/modules/product-detail/components/ProductDetail.tsx @@ -10,6 +10,7 @@ import { LazyLoadComponent } from 'react-lazy-load-image-component'; import { RWebShare } from 'react-web-share'; import useDevice from '@/core/hooks/useDevice'; +import { getAuth } from '~/libs/auth'; import { whatsappUrl } from '~/libs/whatsappUrl'; import ProductPromoSection from '~/modules/product-promo/components/Section'; import { IProductDetail } from '~/types/product'; @@ -21,8 +22,6 @@ import Information from './Information'; import PriceAction from './PriceAction'; import SimilarBottom from './SimilarBottom'; import SimilarSide from './SimilarSide'; -import VariantList from './VariantList'; -import { getAuth } from '~/libs/auth'; import { gtagProductDetail } from '@/core/utils/googleTag'; diff --git a/src-migrate/modules/product-detail/styles/price-action.module.css b/src-migrate/modules/product-detail/styles/price-action.module.css index de69f5f1..cea50bff 100644 --- a/src-migrate/modules/product-detail/styles/price-action.module.css +++ b/src-migrate/modules/product-detail/styles/price-action.module.css @@ -8,7 +8,10 @@ @apply flex gap-x-2.5; } .quantity-input { - @apply px-2 rounded text-center border border-gray-300 w-24 h-10 focus:outline-none; + @apply w-24 h-10 text-center border border-gray-300 rounded focus:outline-none; + /* Padding di kiri dan kanan untuk memberi ruang bagi tombol */ + padding-left: 2rem; + padding-right: 2rem; } .contact-us { |
