summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src-migrate/modules/product-detail/components/Information.tsx114
-rw-r--r--src-migrate/modules/product-detail/components/ProductDetail.tsx127
2 files changed, 185 insertions, 56 deletions
diff --git a/src-migrate/modules/product-detail/components/Information.tsx b/src-migrate/modules/product-detail/components/Information.tsx
index a7a58cbc..b7d3401e 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, SimpleGrid, Flex, Text, Box } 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,7 +29,7 @@ type Props = {
};
const Information = ({ product }: Props) => {
- const { selectedVariant, setSelectedVariant, setSla, setActive, sla } =
+ const { selectedVariant, setSelectedVariant, setSla, sla } =
useProductDetail();
const [inputValue, setInputValue] = useState<string | null>(
@@ -45,15 +44,6 @@ const Information = ({ product }: Props) => {
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;
-
useEffect(() => {
if (selectedVariant) {
setInputValue(
@@ -66,14 +56,13 @@ const Information = ({ product }: Props) => {
}, [selectedVariant]);
useEffect(() => {
- if (isLoading){
+ if (isLoading) {
setSla(null);
}
if (slaVariant) {
setSla(slaVariant);
}
- }, [slaVariant, isLoading]);
-
+ }, [slaVariant, isLoading, setSla]);
const handleOnChange = (vals: any) => {
setDisableFilter(true);
@@ -98,6 +87,15 @@ const Information = ({ product }: Props) => {
setInputValue(e.target.value);
};
+ // STYLE CUSTOM UNTUK BARIS (Item Code, dll)
+ const rowStyle = {
+ backgroundColor: '#ffffff',
+ fontSize: '13px',
+ borderBottom: '1px dashed #e2e8f0',
+ padding: '8px 0',
+ marginBottom: '0px'
+ };
+
return (
<div className={style['wrapper']}>
<div className='realtive mb-5'>
@@ -183,12 +181,15 @@ const Information = ({ product }: Props) => {
</AutoComplete>
</div>
- <div className={style['row']}>
- <div className={style['label']}>Item Code</div>
+ {/* ITEM CODE */}
+ <div className={style['row']} style={rowStyle}>
+ <div className={style['label']} style={{ color: '#6b7280' }}>Item Code</div>
<div className={style['value']}>{selectedVariant?.code}</div>
</div>
- <div className={style['row']}>
- <div className={style['label']}>Manufacture</div>
+
+ {/* MANUFACTURE */}
+ <div className={style['row']} style={rowStyle}>
+ <div className={style['label']} style={{ color: '#6b7280' }}>Manufacture</div>
<div className={style['value']}>
{!!product.manufacture.name ? (
<Link
@@ -217,29 +218,78 @@ const Information = ({ product }: Props) => {
)}
</div>
</div>
- <div className={style['row']}>
- <div className={style['label']}>Berat Barang</div>
+
+ {/* BERAT BARANG */}
+ <div className={style['row']} style={rowStyle}>
+ <div className={style['label']} style={{ color: '#6b7280' }}>Berat Barang</div>
<div className={style['value']}>
{selectedVariant?.weight > 0 ? `${selectedVariant?.weight} Kg` : '-'}
</div>
</div>
- <div className={style['row']}>
- <div className={style['label']}>Terjual</div>
+
+ {/* TERJUAL */}
+ <div className={style['row']} style={{ ...rowStyle, borderBottom: 'none' }}>
+ <div className={style['label']} style={{ color: '#6b7280' }}>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 && (
- <div className={style['value']}>
- <Skeleton height={5} width={100} />
- </div>
- )}
- {!isLoading && <div className={style['value']}>{sla?.sla_date}</div>}
+
+ {/* === DETAIL INFORMASI PRODUK (Updated Layout) === */}
+ <div className="mt-6 border-t pt-4">
+ <h2 className="font-bold text-gray-800 text-sm mb-4">Detail Informasi Produk</h2>
+
+ {/* Perubahan: Spacing diperbesar menjadi 10 agar estimasi bergeser ke kanan */}
+ <SimpleGrid columns={{ base: 1, md: 3 }} spacing={10}>
+ {/* 1. Distributor Resmi */}
+ <Flex align="center" className="gap-3">
+ <img
+ src="/images/produk_asli.svg"
+ alt="Distributor Resmi"
+ className="w-10 h-10 shrink-0"
+ />
+ <Box>
+ <Text fontSize="11px" color="gray.500" lineHeight="short" mb="1px">Distributor Resmi</Text>
+ <Text fontSize="12px" fontWeight="bold" color="gray.800" lineHeight="short">Jaminan Produk Asli</Text>
+ </Box>
+ </Flex>
+
+ {/* 2. Estimasi Penyiapan */}
+ <Flex align="center" className="gap-3">
+ <img
+ src="/images/estimasi.svg"
+ alt="Estimasi Penyiapan"
+ className="w-9 h-9 shrink-0"
+ />
+ <Box>
+ <Text fontSize="11px" color="gray.500" lineHeight="short" mb="1px">Estimasi Penyiapan</Text>
+ {isLoading ? (
+ <Skeleton height="12px" width="60px" mt="2px" />
+ ) : (
+ <Text fontSize="12px" fontWeight="bold" color="gray.800" lineHeight="short">
+ {sla?.sla_date || '3 - 7 Hari'}
+ </Text>
+ )}
+ </Box>
+ </Flex>
+
+ {/* 3. Garansi Produk */}
+ <Flex align="center" className="gap-3">
+ <img
+ src="/images/garansi.svg"
+ alt="Garansi Produk"
+ className="w-10 h-10 shrink-0"
+ />
+ <Box>
+ <Text fontSize="11px" color="gray.500" lineHeight="short" mb="1px">Garansi Produk</Text>
+ <Text fontSize="12px" fontWeight="bold" color="gray.800" lineHeight="short">24 Bulan</Text>
+ </Box>
+ </Flex>
+ </SimpleGrid>
</div>
+
</div>
);
};
-export default Information;
+export default Information; \ No newline at end of file
diff --git a/src-migrate/modules/product-detail/components/ProductDetail.tsx b/src-migrate/modules/product-detail/components/ProductDetail.tsx
index e4ba2b2f..1bacd2e2 100644
--- a/src-migrate/modules/product-detail/components/ProductDetail.tsx
+++ b/src-migrate/modules/product-detail/components/ProductDetail.tsx
@@ -4,9 +4,22 @@ import Link from 'next/link';
import { useRouter } from 'next/router';
import { useEffect, useRef, useState, UIEvent } from 'react';
-import { Button } from '@chakra-ui/react';
+// Import komponen Chakra UI yang dibutuhkan
+import {
+ Button,
+ Tabs,
+ TabList,
+ TabPanels,
+ Tab,
+ TabPanel,
+ Table,
+ Tbody,
+ Tr,
+ Td,
+ Box
+} from '@chakra-ui/react';
+
import {
- AlertCircle,
AlertTriangle,
MessageCircleIcon,
Share2Icon,
@@ -62,7 +75,6 @@ const ProductDetail = ({ product }: Props) => {
setIsApproval,
isApproval,
setSelectedVariant,
- setSla,
} = useProductDetail();
useEffect(() => {
@@ -136,11 +148,15 @@ const ProductDetail = ({ product }: Props) => {
const scrollToIndex = (i: number) => {
const el = sliderRef.current;
if (!el) return;
- el.scrollTo({ left: i * el.clientWidth, behavior: 'smooth' });
+ const elRef = sliderRef.current;
+ elRef.scrollTo({ left: i * elRef.clientWidth, behavior: 'smooth' });
setCurrentIdx(i);
setMainImage(allImages[i] || '');
};
+ console.log('detail product render');
+ console.log('product: ', product);
+
return (
<>
<div className='relative'>
@@ -195,7 +211,6 @@ const ProductDetail = ({ product }: Props) => {
key={i}
className='w-full flex-shrink-0 snap-center flex justify-center items-center'
>
- {/* gambar diperkecil */}
<img
src={img}
alt={`Gambar ${i + 1}`}
@@ -218,7 +233,6 @@ const ProductDetail = ({ product }: Props) => {
)}
</div>
- {/* Dots indicator */}
{allImages.length > 1 && (
<div className='absolute bottom-2 left-0 right-0 flex justify-center gap-2'>
{allImages.map((_, i) => (
@@ -238,8 +252,6 @@ const ProductDetail = ({ product }: Props) => {
<>
{/* === DESKTOP: Tetap seperti sebelumnya === */}
<ProductImage product={{ ...product, image: mainImage }} />
-
- {/* Carousel horizontal (thumbnail) – hanya desktop */}
{allImages.length > 0 && (
<div className='mt-4 overflow-x-auto'>
<div className='flex space-x-3 pb-3'>
@@ -271,7 +283,6 @@ const ProductDetail = ({ product }: Props) => {
</>
)}
</div>
- {/* <<=== TUTUP kolom kiri */}
{/* ===== Kolom kanan: info ===== */}
{isDesktop && (
@@ -332,21 +343,89 @@ const ProductDetail = ({ product }: Props) => {
<div className='h-0 md:h-6' />
+ {/* === SECTION TABS: DESKRIPSI & SPESIFIKASI === */}
<div className={style['section-card']}>
- <h2 className={style['heading']}>Informasi Produk</h2>
- <div className='h-4' />
- <div className='overflow-x-auto'>
- <div
- className={style['description']}
- dangerouslySetInnerHTML={{
- __html:
- !product.description ||
- product.description == '<p><br></p>'
- ? 'Belum ada deskripsi'
- : product.description,
- }}
- />
- </div>
+ <Tabs variant="unstyled">
+ {/* Header Tabs */}
+ <TabList borderBottom="1px solid" borderColor="gray.200">
+ <Tab
+ _selected={{
+ color: 'red.600',
+ borderColor: 'red.600',
+ borderBottomWidth: '3px',
+ fontWeight: 'bold',
+ marginBottom: '-1.5px'
+ }}
+ color="gray.500"
+ fontWeight="medium"
+ fontSize="sm"
+ px={4}
+ py={3}
+ >
+ Deskripsi
+ </Tab>
+ <Tab
+ _selected={{
+ color: 'red.600',
+ borderColor: 'red.600',
+ borderBottomWidth: '3px',
+ fontWeight: 'bold',
+ marginBottom: '-1.5px'
+ }}
+ color="gray.500"
+ fontWeight="medium"
+ fontSize="sm"
+ px={4}
+ py={3}
+ >
+ Spesifikasi
+ </Tab>
+ <Tab
+ _selected={{
+ color: 'red.600',
+ borderColor: 'red.600',
+ borderBottomWidth: '3px',
+ fontWeight: 'bold',
+ marginBottom: '-1.5px'
+ }}
+ color="gray.500"
+ fontWeight="medium"
+ fontSize="sm"
+ px={4}
+ py={3}
+ >
+ Detail Lainnya
+ </Tab>
+ </TabList>
+
+ <TabPanels>
+ {/* PANEL 1: DESKRIPSI */}
+ <TabPanel px={0} py={6}>
+ <div className='overflow-x-auto text-sm text-gray-700'>
+ <div
+ className={style['description']}
+ dangerouslySetInnerHTML={{
+ __html:
+ !product.description || product.description === '<p><br></p>'
+ ? '<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>'
+ : product.description,
+ }}
+ />
+ </div>
+ </TabPanel>
+
+ {/* PANEL 2: SPESIFIKASI (Sesuai Gambar) */}
+ <TabPanel px={0} py={6}>
+ <p className="text-gray-500 text-sm">Informasi tambahan belum tersedia.</p>
+ </TabPanel>
+
+ {/* PANEL 3: DETAIL LAINNYA */}
+ <TabPanel px={0} py={6}>
+ <p className="text-gray-500 text-sm">Informasi tambahan belum tersedia.</p>
+ </TabPanel>
+
+ </TabPanels>
+ </Tabs>
</div>
</div>
</div>
@@ -422,4 +501,4 @@ const ProductDetail = ({ product }: Props) => {
);
};
-export default ProductDetail;
+export default ProductDetail; \ No newline at end of file