summaryrefslogtreecommitdiff
path: root/src-migrate
diff options
context:
space:
mode:
authorFIN-IT_AndriFP <andrifebriyadiputra@gmail.com>2026-01-12 13:33:39 +0700
committerFIN-IT_AndriFP <andrifebriyadiputra@gmail.com>2026-01-12 13:33:39 +0700
commitab4819716063f4d7eb4578cbcb0d66077145bdab (patch)
tree179b9583580b21602126dddd3a52cffe2c737e26 /src-migrate
parent6c2de1aa1cc655b1da525015ac0280fd4c72731f (diff)
(andri) fix index table spek & fix view detail information di mobile
Diffstat (limited to 'src-migrate')
-rw-r--r--src-migrate/modules/product-detail/components/Information.tsx88
-rw-r--r--src-migrate/modules/product-detail/components/ProductDetail.tsx106
2 files changed, 114 insertions, 80 deletions
diff --git a/src-migrate/modules/product-detail/components/Information.tsx b/src-migrate/modules/product-detail/components/Information.tsx
index c565682f..e07537fb 100644
--- a/src-migrate/modules/product-detail/components/Information.tsx
+++ b/src-migrate/modules/product-detail/components/Information.tsx
@@ -9,10 +9,10 @@ import style from '../styles/information.module.css';
import dynamic from 'next/dynamic';
import Link from 'next/link';
import { useEffect, useRef, useState } from 'react';
-import axios from 'axios'; // <--- 1. TAMBAHAN IMPORT AXIOS
+import axios from 'axios';
import currencyFormat from '@/core/utils/currencyFormat';
-import { InputGroup, InputRightElement, SimpleGrid, Flex, Text, Box } from '@chakra-ui/react';
+import { InputGroup, InputRightElement, SimpleGrid, Flex, Text, Box, Center } from '@chakra-ui/react';
import { ChevronDownIcon } from '@heroicons/react/24/outline';
import Image from 'next/image';
import { formatToShortText } from '~/libs/formatNumber';
@@ -54,23 +54,16 @@ const Information = ({ product }: Props) => {
setLoadingWarranty(true);
try {
- // Ambil semua SKU untuk dikirim ke API
const skus = product.variants.map((v) => v.id).join(',');
const mainSku = product.variants[0].id;
- console.log("Fetching warranties for SKUs:", skus);
- console.log("Main SKU:", mainSku);
- // Panggil API magento-product
const res = await axios.get('/api/magento-product', {
params: { skus, main_sku: mainSku }
});
- // Simpan hasil ke state lokal
if (res.data && res.data.warranties) {
setWarranties(res.data.warranties);
}
- console.log("Warranties API Response:", res);
- console.log("Warranties fetched:", res.data.warranties);
} catch (error) {
console.error("Gagal ambil garansi:", error);
} finally {
@@ -80,8 +73,6 @@ const Information = ({ product }: Props) => {
fetchWarrantyDirectly();
}, [product]);
- // ======================================================
-
useEffect(() => {
if (selectedVariant) {
@@ -103,27 +94,26 @@ const Information = ({ product }: Props) => {
}
}, [slaVariant, isLoading, setSla]);
-const handleOnChange = (vals: any) => {
-    setDisableFilter(true);
-    let code = vals.replace(/\s-\s.*$/, '').trim();
-    let variant = product?.variants.find((item) => item.code === code);
-   
+ const handleOnChange = (vals: any) => {
+ setDisableFilter(true);
+ let code = vals.replace(/\s-\s.*$/, '').trim();
+ let variant = product?.variants.find((item) => item.code === code);
+
if (variant) {
-    setSelectedVariant(variant);
-    setInputValue(
-      variant?.code +
-        (variant?.attributes[0] ? ' - ' + variant?.attributes[0] : '')
-    );
+ setSelectedVariant(variant);
+ setInputValue(
+ variant?.code +
+ (variant?.attributes[0] ? ' - ' + variant?.attributes[0] : '')
+ );
setVariantOptions(product?.variants);
-    }
-  };
+ }
+ };
const handleOnKeyUp = (e: any) => {
setDisableFilter(false);
setInputValue(e.target.value);
};
- // STYLE CUSTOM UNTUK BARIS (Item Code, dll)
const rowStyle = {
backgroundColor: '#ffffff',
fontSize: '13px',
@@ -275,37 +265,49 @@ const handleOnChange = (vals: any) => {
</div>
</div>
- {/* === DETAIL INFORMASI PRODUK (Updated Layout) === */}
+ {/* === DETAIL INFORMASI PRODUK (Horizontal Minimalis) === */}
<div className="mt-6 border-t pt-4">
<h2 className="font-bold text-gray-800 text-sm mb-4">Detail Informasi Produk</h2>
- <SimpleGrid columns={{ base: 1, md: 3 }} spacing={10}>
+ {/* Mobile: 3 Kolom, Spacing Kecil. Desktop: 3 Kolom, Spacing Besar */}
+ <SimpleGrid columns={{ base: 3, md: 3 }} spacing={{ base: 2, md: 10 }}>
+
{/* 1. Distributor Resmi */}
- <Flex align="center" className="gap-3">
+ <Flex
+ direction={{ base: 'column', md: 'row' }}
+ align="center"
+ textAlign={{ base: 'center', md: 'left' }}
+ gap={{ base: 2, md: 3 }}
+ >
<img
src="/images/produk_asli.svg"
alt="Distributor Resmi"
- className="w-10 h-10 shrink-0"
+ className="w-8 h-8 md:w-10 md: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>
+ <Text fontSize={{ base: "10px", md: "11px" }} color="gray.500" lineHeight="short" mb="1px">Distributor Resmi</Text>
+ <Text fontSize={{ base: "10px", md: "12px" }} fontWeight="bold" color="gray.800" lineHeight="1.2">Jaminan Produk Asli</Text>
</Box>
</Flex>
{/* 2. Estimasi Penyiapan */}
- <Flex align="center" className="gap-3">
+ <Flex
+ direction={{ base: 'column', md: 'row' }}
+ align="center"
+ textAlign={{ base: 'center', md: 'left' }}
+ gap={{ base: 2, md: 3 }}
+ >
<img
src="/images/estimasi.svg"
alt="Estimasi Penyiapan"
- className="w-9 h-9 shrink-0"
+ className="w-8 h-8 md:w-9 md:h-9 shrink-0"
/>
<Box>
- <Text fontSize="11px" color="gray.500" lineHeight="short" mb="1px">Estimasi Penyiapan</Text>
+ <Text fontSize={{ base: "10px", md: "11px" }} color="gray.500" lineHeight="short" mb="1px">Estimasi Penyiapan</Text>
{isLoading ? (
- <Skeleton height="12px" width="60px" mt="2px" />
+ <Center><Skeleton height="10px" width="50px" mt="2px" /></Center>
) : (
- <Text fontSize="12px" fontWeight="bold" color="gray.800" lineHeight="short">
+ <Text fontSize={{ base: "10px", md: "12px" }} fontWeight="bold" color="gray.800" lineHeight="1.2">
{sla?.sla_date || '3 - 7 Hari'}
</Text>
)}
@@ -313,20 +315,24 @@ const handleOnChange = (vals: any) => {
</Flex>
{/* 3. Garansi Produk */}
- <Flex align="center" className="gap-3">
+ <Flex
+ direction={{ base: 'column', md: 'row' }}
+ align="center"
+ textAlign={{ base: 'center', md: 'left' }}
+ gap={{ base: 2, md: 3 }}
+ >
<img
src="/images/garansi.svg"
alt="Garansi Produk"
- className="w-10 h-10 shrink-0"
+ className="w-8 h-8 md:w-10 md:h-10 shrink-0"
/>
<Box>
- <Text fontSize="11px" color="gray.500" lineHeight="short" mb="1px">Garansi Produk</Text>
+ <Text fontSize={{ base: "10px", md: "11px" }} color="gray.500" lineHeight="short" mb="1px">Garansi Produk</Text>
- {/* Menggunakan Loading State & Data dari 'warranties' */}
{loadingWarranty ? (
- <Skeleton height="12px" width="80px" mt="2px" />
+ <Center><Skeleton height="10px" width="50px" mt="2px" /></Center>
) : (
- <Text fontSize="12px" fontWeight="bold" color="gray.800" lineHeight="short">
+ <Text fontSize={{ base: "10px", md: "12px" }} fontWeight="bold" color="gray.800" lineHeight="1.2">
{selectedVariant && warranties[selectedVariant.id]
? warranties[selectedVariant.id]
: '-'}
diff --git a/src-migrate/modules/product-detail/components/ProductDetail.tsx b/src-migrate/modules/product-detail/components/ProductDetail.tsx
index 7ca2f9a7..04bf5533 100644
--- a/src-migrate/modules/product-detail/components/ProductDetail.tsx
+++ b/src-migrate/modules/product-detail/components/ProductDetail.tsx
@@ -60,6 +60,45 @@ const RWebShare = dynamic(
() => import('react-web-share').then((m) => m.RWebShare),
{ ssr: false }
);
+// 1. STYLE DESKTOP (Tebal, Jelas, dengan Border/Padding)
+const cssScrollbarDesktop = {
+ '&::-webkit-scrollbar': {
+ width: '10px',
+ height: '10px',
+ },
+ '&::-webkit-scrollbar-track': {
+ background: '#f1f1f1',
+ borderRadius: '4px',
+ },
+ '&::-webkit-scrollbar-thumb': {
+ backgroundColor: '#9ca3af', // Gray-400
+ borderRadius: '6px',
+ border: '2px solid #f1f1f1', // Efek padding
+ },
+ '&::-webkit-scrollbar-thumb:hover': {
+ backgroundColor: '#6b7280',
+ },
+};
+
+// 2. STYLE MOBILE (Tipis, Minimalis, Tanpa Border)
+const cssScrollbarMobile = {
+ '&::-webkit-scrollbar': {
+ width: '8px', // Sangat tipis vertikal
+ height: '8px', // Sangat tipis horizontal
+ },
+ '&::-webkit-scrollbar-track': {
+ background: '#f1f1f1',
+ borderRadius: '4px',
+ },
+ '&::-webkit-scrollbar-thumb': {
+ backgroundColor: '#9ca3af', // Gray-400
+ borderRadius: '6px',
+ border: '2px solid #f1f1f1', // Efek padding
+ },
+ '&::-webkit-scrollbar-thumb:hover': {
+ backgroundColor: '#6b7280',
+ },
+};
const SELF_HOST = process.env.NEXT_PUBLIC_SELF_HOST;
@@ -494,7 +533,7 @@ const ProductDetail = ({ product }: Props) => {
<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>
+ {/* <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>
@@ -514,29 +553,13 @@ const ProductDetail = ({ product }: Props) => {
overflowX="auto"
overflowY="auto"
maxHeight="500px"
- css={{
- '&::-webkit-scrollbar': {
- width: '12px',
- height: '12px',
- },
- '&::-webkit-scrollbar-track': {
- background: '#f1f1f1',
- },
- '&::-webkit-scrollbar-thumb': {
- backgroundColor: '#a0aec0',
- borderRadius: '8px',
- border: '4px solid transparent',
- backgroundClip: 'content-box',
- },
- '&::-webkit-scrollbar-thumb:hover': {
- backgroundColor: '#718096',
- },
- }}
+ css={isMobile ? cssScrollbarMobile : cssScrollbarDesktop}
>
{loadingSpecs ? (
<Center py={6}><Spinner color='red.500' /></Center>
) : specsMatrix.length > 0 ? (
(() => {
+ // --- 1. PROSES DATA ---
const topHeaders: any[] = [];
const subHeaders: any[] = [];
const flatSpecs: any[] = [];
@@ -564,17 +587,19 @@ const ProductDetail = ({ product }: Props) => {
}
});
+ // --- 2. RENDER TABLE (Z-INDEX DITURUNKAN) ---
return (
- <Table variant="simple" size="md">
- <Thead bg="red.600" position="sticky" top={0} zIndex={20}>
- {/* Baris 1: Header Utama */}
+ <Table variant="simple" size={isMobile ? "sm" : "md"}>
+ <Thead bg="red.600" position="sticky" top={0} zIndex={3}> {/* Turun dari 20 ke 3 */}
+ {/* Row 1: Header Utama */}
<Tr>
{topHeaders.map((th, idx) => (
<Th
key={`top-${idx}`}
+ // LOGIC STICKY: Index 0 Selalu Sticky
position={idx === 0 ? "sticky" : "static"}
left={idx === 0 ? 0 : undefined}
- zIndex={idx === 0 ? 22 : 20}
+ zIndex={idx === 0 ? 4 : 3} // Turun dari 22 -> 4, dan 20 -> 3
boxShadow={idx === 0 ? "2px 0 5px -2px rgba(0,0,0,0.2)" : "none"}
bg="red.600"
@@ -582,29 +607,31 @@ const ProductDetail = ({ product }: Props) => {
rowSpan={th.rowSpan}
color="white"
textAlign="center"
- fontSize="sm"
+ fontSize={isMobile ? "xs" : "sm"}
textTransform="none"
fontWeight="800"
letterSpacing="wide"
verticalAlign="middle"
borderBottom="none"
+ px={isMobile ? 2 : 4}
>
{th.label}
</Th>
))}
</Tr>
-
- {/* Baris 2: Sub Header */}
+
+ {/* Row 2: Sub Header */}
<Tr>
- {subHeaders.map((sub, idx) => {
+ {subHeaders.map((sub, idx) => {
const isFirstHeaderGroup = topHeaders[0]?.type === 'group';
const shouldSticky = idx === 0 && isFirstHeaderGroup;
return (
<Th
key={`sub-${idx}`}
+ // LOGIC STICKY: Aktif jika Header Utama Group & Index 0
position={shouldSticky ? "sticky" : "static"}
left={shouldSticky ? 0 : undefined}
- zIndex={shouldSticky ? 21 : 1}
+ zIndex={shouldSticky ? 4 : 1} // Turun dari 21 -> 4
boxShadow={shouldSticky ? "2px 0 5px -2px rgba(0,0,0,0.2)" : "none"}
color="white"
@@ -614,7 +641,9 @@ const ProductDetail = ({ product }: Props) => {
verticalAlign="middle"
whiteSpace="nowrap"
bg="red.600"
+ borderBottom="none"
pt={1} pb={1}
+ px={isMobile ? 2 : 4}
>
{sub.label}
</Th>
@@ -622,35 +651,34 @@ const ProductDetail = ({ product }: Props) => {
})}
</Tr>
</Thead>
-
+
<Tbody>
{sortedVariants.map((v, vIdx) => (
<Tr key={v.id} bg={vIdx % 2 === 0 ? 'white' : 'gray.50'}>
{flatSpecs.map((spec, sIdx) => {
const rawValue = spec.values[v.id] || '-';
- const isFirstCol = sIdx === 0;
+ const isFirstCol = sIdx === 0;
return (
<Td
key={sIdx}
- // === LOGIC STICKY DATA PERTAMA ===
+ // LOGIC STICKY: Data Kolom Pertama Selalu Sticky
position={isFirstCol ? "sticky" : "static"}
left={isFirstCol ? 0 : undefined}
- zIndex={isFirstCol ? 10 : 1}
+ zIndex={isFirstCol ? 2 : 1} // Turun dari 10 -> 2
bg={vIdx % 2 === 0 ? 'white' : 'gray.50'}
boxShadow={isFirstCol ? "2px 0 5px -2px rgba(0,0,0,0.1)" : "none"}
- // =================================
borderColor="gray.200"
textAlign="center"
- fontSize="sm"
+ fontSize={isMobile ? "xs" : "sm"}
verticalAlign="middle"
- px={2}
+ px={isMobile ? 1 : 2}
py={3}
- minW="100px"
- maxW="150px"
+ minW={isMobile ? "100px" : "120px"}
+ maxW="200px"
whiteSpace="normal"
overflowWrap="break-word"
- fontWeight={isFirstCol ? "bold" : "normal"}
+ fontWeight={isFirstCol ? "bold" : "normal"}
>
{renderSpecValue(rawValue)}
</Td>
@@ -669,7 +697,7 @@ const ProductDetail = ({ product }: Props) => {
</TabPanel>
{/* DETAIL LAINNYA */}
- <TabPanel px={0} py={6}><p className="text-gray-500 text-sm">Informasi tambahan belum tersedia.</p></TabPanel>
+ {/* <TabPanel px={0} py={6}><p className="text-gray-500 text-sm">Informasi tambahan belum tersedia.</p></TabPanel> */}
</TabPanels>
</Tabs>
</div>