diff options
| author | Mqdd <ahmadmiqdad27@gmail.com> | 2025-12-15 13:10:42 +0700 |
|---|---|---|
| committer | Mqdd <ahmadmiqdad27@gmail.com> | 2025-12-15 13:10:42 +0700 |
| commit | 517dce1136351f57e68e08f632635ac0a1ab6bff (patch) | |
| tree | 1514478948c9c9d6a71661842a57122efece5062 | |
| parent | 4f133e1de46fa50982e9cd3b6063eea7c1d10528 (diff) | |
<Miqdad> fix bug select variant
| -rw-r--r-- | src-migrate/modules/product-detail/components/Information.tsx | 145 | ||||
| -rw-r--r-- | src-migrate/modules/product-detail/components/ProductDetail.tsx | 12 |
2 files changed, 78 insertions, 79 deletions
diff --git a/src-migrate/modules/product-detail/components/Information.tsx b/src-migrate/modules/product-detail/components/Information.tsx index a7a58cbc..813b6bf5 100644 --- a/src-migrate/modules/product-detail/components/Information.tsx +++ b/src-migrate/modules/product-detail/components/Information.tsx @@ -11,12 +11,11 @@ import Link from 'next/link'; import { useEffect, useRef, useState } from 'react'; import currencyFormat from '@/core/utils/currencyFormat'; -import { InputGroup, InputRightElement, Spinner } from '@chakra-ui/react'; +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 { IProductDetail } from '~/types/product'; import { useProductDetail } from '../stores/useProductDetail'; import useVariant from '../hook/useVariant'; @@ -30,67 +29,57 @@ type Props = { }; const Information = ({ product }: Props) => { - const { selectedVariant, setSelectedVariant, setSla, setActive, sla } = + const { selectedVariant, setSelectedVariant, setSla, sla } = useProductDetail(); - const [inputValue, setInputValue] = useState<string | null>( - selectedVariant?.code + ' - ' + selectedVariant?.attributes[0] - ); + const [inputValue, setInputValue] = useState<string>(''); const [disableFilter, setDisableFilter] = useState<boolean>(false); const inputRef = useRef<HTMLInputElement>(null); - const [variantOptions, setVariantOptions] = useState<any[]>( - product?.variants - ); + // source of truth + const variantOptions = product.variants; + const variantId = selectedVariant?.id; const { slaVariant, isLoading } = useVariant({ variantId }); - // let variantOptions = product?.variants; - - // const querySLA = useQuery<IProductVariantSLA>({ - // queryKey: ['variant-sla', selectedVariant?.id], - // queryFn: () => getVariantSLA(selectedVariant?.id), - // enabled: !!selectedVariant?.id, - // }); - // const sla = querySLA?.data; - + /* ====================== + * Sync input text + * ====================== */ useEffect(() => { - if (selectedVariant) { - setInputValue( - selectedVariant?.code + - (selectedVariant?.attributes[0] - ? ' - ' + selectedVariant?.attributes[0] - : '') - ); - } + if (!selectedVariant) return; + + setInputValue( + selectedVariant.code + + (selectedVariant.attributes?.[0] + ? ` - ${selectedVariant.attributes[0]}` + : '') + ); }, [selectedVariant]); + /* ====================== + * Sync SLA + * ====================== */ useEffect(() => { - if (isLoading){ + if (isLoading) { setSla(null); + return; } if (slaVariant) { setSla(slaVariant); } - }, [slaVariant, isLoading]); - + }, [slaVariant, isLoading, setSla]); - const handleOnChange = (vals: any) => { + /* ====================== + * Handlers + * ====================== */ + const handleOnChange = (value: string) => { setDisableFilter(true); - let code = vals.replace(/\s-\s.*$/, '').trim(); - let variant = variantOptions.find((item) => item.code === code); + + const variant = variantOptions.find((item) => String(item.id) === value); + + if (!variant) return; + setSelectedVariant(variant); - 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) => { @@ -100,80 +89,72 @@ const Information = ({ product }: Props) => { return ( <div className={style['wrapper']}> - <div className='realtive mb-5'> + {/* ===== Variant Selector ===== */} + <div className='relative mb-5'> <label className='form-label mb-2 text-lg text-red-600'> Pilih Variant * :{' '} <span className='text-gray_r-9 text-sm'> - {product?.variants?.length} Variants - </span>{' '} + {product.variants.length} Variants + </span> </label> + <AutoComplete disableFilter={disableFilter} openOnFocus className='form-input' - onChange={(vals) => handleOnChange(vals)} + onChange={handleOnChange} > <InputGroup> <AutoCompleteInput ref={inputRef} - value={inputValue as string} - onChange={(e) => handleOnKeyUp(e)} + value={inputValue} + onChange={handleOnKeyUp} onFocus={() => setDisableFilter(true)} /> <InputRightElement className='mr-4'> <ChevronDownIcon - className='h-6 w-6 text-gray-500' - onClick={() => inputRef?.current?.focus()} + className='h-6 w-6 text-gray-500 cursor-pointer' + onClick={() => inputRef.current?.focus()} /> </InputRightElement> </InputGroup> <AutoCompleteList> - {variantOptions.map((option, cid) => ( + {variantOptions.map((option) => ( <AutoCompleteItem - key={`option-${cid}`} - value={ - option.code + - (option?.attributes[0] ? ' - ' + option?.attributes[0] : '') - } + key={option.id} + value={String(option.id)} _selected={ option.id === selectedVariant?.id - ? { - bg: 'gray.300', - } + ? { bg: 'gray.300' } : undefined } - textTransform='capitalize' > - <div - key={cid} - className='flex gap-x-2 w-full justify-between px-3 items-center p-2' - > + <div 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?.attributes[0] - : '')} + {option.code} + {option.attributes?.[0] ? ` - ${option.attributes[0]}` : ''} </div> + <div className={ - option?.price?.discount_percentage - ? 'flex gap-x-4 items-center justify-between' + option.price?.discount_percentage + ? 'flex gap-x-4 items-center' : '' } > - {option?.price?.discount_percentage > 0 && ( + {option.price?.discount_percentage > 0 && ( <> <div className='badge-solid-red text-xs'> - {Math.floor(option?.price?.discount_percentage)}% + {Math.floor(option.price.discount_percentage)}% </div> <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)} + {currencyFormat(option.price.price)} </div> </> )} <div className='min-w-20 sm:min-w-28 text-danger-500 font-semibold'> - {currencyFormat(option?.price?.price_discount)} + {currencyFormat(option.price.price_discount)} </div> </div> </div> @@ -183,10 +164,12 @@ const Information = ({ product }: Props) => { </AutoComplete> </div> + {/* ===== Info Rows ===== */} <div className={style['row']}> <div className={style['label']}>Item Code</div> <div className={style['value']}>{selectedVariant?.code}</div> </div> + <div className={style['row']}> <div className={style['label']}>Manufacture</div> <div className={style['value']}> @@ -198,7 +181,7 @@ const Information = ({ product }: Props) => { product.manufacture.id.toString() )} > - {product?.manufacture.logo ? ( + {product.manufacture.logo ? ( <Image height={50} width={100} @@ -217,26 +200,30 @@ const Information = ({ product }: Props) => { )} </div> </div> + <div className={style['row']}> <div className={style['label']}>Berat Barang</div> <div className={style['value']}> - {selectedVariant?.weight > 0 ? `${selectedVariant?.weight} Kg` : '-'} + {selectedVariant?.weight > 0 ? `${selectedVariant.weight} Kg` : '-'} </div> </div> + <div className={style['row']}> <div className={style['label']}>Terjual</div> <div className={style['value']}> {product.qty_sold > 0 ? formatToShortText(product.qty_sold) : '-'} </div> </div> + <div className={style['row']}> <div className={style['label']}>Persiapan Barang</div> - {isLoading && ( + {isLoading ? ( <div className={style['value']}> <Skeleton height={5} width={100} /> </div> + ) : ( + <div className={style['value']}>{sla?.sla_date}</div> )} - {!isLoading && <div className={style['value']}>{sla?.sla_date}</div>} </div> </div> ); diff --git a/src-migrate/modules/product-detail/components/ProductDetail.tsx b/src-migrate/modules/product-detail/components/ProductDetail.tsx index 085bbb1c..129ca8de 100644 --- a/src-migrate/modules/product-detail/components/ProductDetail.tsx +++ b/src-migrate/modules/product-detail/components/ProductDetail.tsx @@ -83,6 +83,18 @@ const ProductDetail = ({ product }: Props) => { setAskAdminUrl(createdAskUrl); }, [router.asPath, product.manufacture.name, product.name, setAskAdminUrl]); + // useEffect(() => { + // if (!product?.variants?.length) return; + + // setIsApproval(auth?.feature?.soApproval); + + // setSelectedVariant((prev: any) => { + // if (prev) return prev; + + // return product.variants[0]; + // }); + // }, [product?.id]); + useEffect(() => { if (typeof auth === 'object') { setIsApproval(auth?.feature?.soApproval); |
