summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src-migrate/modules/product-detail/components/ProductDetail.tsx106
1 files changed, 65 insertions, 41 deletions
diff --git a/src-migrate/modules/product-detail/components/ProductDetail.tsx b/src-migrate/modules/product-detail/components/ProductDetail.tsx
index fbfe262d..7b166942 100644
--- a/src-migrate/modules/product-detail/components/ProductDetail.tsx
+++ b/src-migrate/modules/product-detail/components/ProductDetail.tsx
@@ -2,7 +2,6 @@ import style from '../styles/product-detail.module.css';
import Link from 'next/link';
import { useRouter } from 'next/router';
-// Import useMemo
import { useEffect, useRef, useState, UIEvent, useMemo } from 'react';
// Import komponen Chakra UI
@@ -60,6 +59,7 @@ 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': {
@@ -83,20 +83,15 @@ const cssScrollbarDesktop = {
// 2. STYLE MOBILE (Tipis, Minimalis, Tanpa Border)
const cssScrollbarMobile = {
'&::-webkit-scrollbar': {
- width: '8px', // Sangat tipis vertikal
- height: '8px', // Sangat tipis horizontal
+ width: '3px', // Sangat tipis vertikal
+ height: '3px', // Sangat tipis horizontal
},
- '&::-webkit-scrollbar-track': {
- background: '#f1f1f1',
- borderRadius: '4px',
+ '&::-webkit-scrollbar-track': {
+ background: 'transparent',
},
'&::-webkit-scrollbar-thumb': {
- backgroundColor: '#9ca3af', // Gray-400
- borderRadius: '6px',
- border: '2px solid #f1f1f1', // Efek padding
- },
- '&::-webkit-scrollbar-thumb:hover': {
- backgroundColor: '#6b7280',
+ backgroundColor: '#cbd5e1', // Gray-300
+ borderRadius: '3px',
},
};
@@ -244,14 +239,13 @@ const ProductDetail = ({ product }: Props) => {
}, [product.id]);
// =========================================================================
- // HELPER 1: GROUPING DATA BY LABEL (Separator ':')
+ // HELPER 1: GROUPING DATA BY LABEL
// =========================================================================
const processMatrixData = (rawMatrix: any[]) => {
const groups: any = {};
const result: any[] = [];
rawMatrix.forEach(item => {
- // Cek Label: "Group Name : Sub Label"
if (item.label && item.label.includes(' : ')) {
const parts = item.label.split(' : ');
const groupName = parts[0].trim();
@@ -268,7 +262,7 @@ const ProductDetail = ({ product }: Props) => {
groups[groupName].children.push({
...item,
- label: childLabel // Override label jadi pendek
+ label: childLabel
});
} else {
@@ -287,7 +281,6 @@ const ProductDetail = ({ product }: Props) => {
if (!val) return '-';
const strVal = String(val).trim();
- // URL Link
const isUrl = !strVal.includes(' ') && (
strVal.startsWith('http') ||
strVal.startsWith('www.')
@@ -306,7 +299,6 @@ const ProductDetail = ({ product }: Props) => {
);
}
- // HTML
if (strVal.includes('<') && strVal.includes('>')) {
return (
<div
@@ -316,7 +308,6 @@ const ProductDetail = ({ product }: Props) => {
);
}
- // Teks Biasa
return strVal;
};
@@ -533,7 +524,6 @@ 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> */}
</TabList>
<TabPanels>
@@ -559,7 +549,55 @@ const ProductDetail = ({ product }: Props) => {
<Center py={6}><Spinner color='red.500' /></Center>
) : specsMatrix.length > 0 ? (
(() => {
- // --- 1. PROSES DATA ---
+ const variantCount = sortedVariants.length;
+ const isSingleVariant = variantCount === 1;
+
+ // === LOGIC 1: SINGLE VARIANT (VERTICAL TABLE) ===
+ if (isSingleVariant) {
+ const singleVariantId = sortedVariants[0].id;
+ // Flatten data untuk list vertical
+ const rows: any[] = [];
+ specsMatrix.forEach(row => {
+ if (row.type === 'group') {
+ row.children.forEach((child: any) => rows.push(child));
+ } else {
+ rows.push(row);
+ }
+ });
+
+ return (
+ <Table variant="simple" size={isMobile ? "sm" : "md"}>
+ <Tbody>
+ {rows.map((row, idx) => (
+ <Tr key={idx} bg={idx % 2 === 0 ? 'white' : 'gray.50'}>
+ {/* Kolom Label (Kiri) */}
+ <Td
+ width="40%"
+ fontWeight="bold"
+ color="gray.600"
+ borderColor="gray.200"
+ verticalAlign="top"
+ py={3}
+ >
+ {row.label}
+ </Td>
+ {/* Kolom Value (Kanan) */}
+ <Td
+ color="gray.800"
+ borderColor="gray.200"
+ verticalAlign="top"
+ py={3}
+ >
+ {renderSpecValue(row.values[singleVariantId])}
+ </Td>
+ </Tr>
+ ))}
+ </Tbody>
+ </Table>
+ );
+ }
+
+ // === LOGIC 2: MULTIPLE VARIANTS (MATRIX TABLE HORIZONTAL) ===
const topHeaders: any[] = [];
const subHeaders: any[] = [];
const flatSpecs: any[] = [];
@@ -587,21 +625,17 @@ const ProductDetail = ({ product }: Props) => {
}
});
- // --- 2. RENDER TABLE (Z-INDEX DITURUNKAN) ---
return (
<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 */}
+ <Thead bg="red.600" position="sticky" top={0} zIndex={3}>
<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 ? 4 : 3} // Turun dari 22 -> 4, dan 20 -> 3
+ zIndex={idx === 0 ? 4 : 3}
boxShadow={idx === 0 ? "2px 0 5px -2px rgba(0,0,0,0.2)" : "none"}
-
bg="red.600"
colSpan={th.colSpan}
rowSpan={th.rowSpan}
@@ -619,21 +653,17 @@ const ProductDetail = ({ product }: Props) => {
</Th>
))}
</Tr>
-
- {/* Row 2: Sub Header */}
<Tr>
{subHeaders.map((sub, idx) => {
- const isFirstHeaderGroup = topHeaders[0]?.type === 'group';
- const shouldSticky = idx === 0 && isFirstHeaderGroup;
- return (
+ 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 ? 4 : 1} // Turun dari 21 -> 4
+ zIndex={shouldSticky ? 4 : 1}
boxShadow={shouldSticky ? "2px 0 5px -2px rgba(0,0,0,0.2)" : "none"}
-
color="white"
textAlign="center"
fontSize="xs"
@@ -641,7 +671,6 @@ const ProductDetail = ({ product }: Props) => {
verticalAlign="middle"
whiteSpace="nowrap"
bg="red.600"
- borderBottom="none"
pt={1} pb={1}
px={isMobile ? 2 : 4}
>
@@ -661,13 +690,11 @@ const ProductDetail = ({ product }: Props) => {
return (
<Td
key={sIdx}
- // LOGIC STICKY: Data Kolom Pertama Selalu Sticky
position={isFirstCol ? "sticky" : "static"}
left={isFirstCol ? 0 : undefined}
- zIndex={isFirstCol ? 2 : 1} // Turun dari 10 -> 2
+ zIndex={isFirstCol ? 2 : 1}
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={isMobile ? "xs" : "sm"}
@@ -695,9 +722,6 @@ const ProductDetail = ({ product }: Props) => {
)}
</Box>
</TabPanel>
-
- {/* DETAIL LAINNYA */}
- {/* <TabPanel px={0} py={6}><p className="text-gray-500 text-sm">Informasi tambahan belum tersedia.</p></TabPanel> */}
</TabPanels>
</Tabs>
</div>