diff options
| author | FIN-IT_AndriFP <andrifebriyadiputra@gmail.com> | 2025-12-11 16:30:48 +0700 |
|---|---|---|
| committer | FIN-IT_AndriFP <andrifebriyadiputra@gmail.com> | 2025-12-11 16:30:48 +0700 |
| commit | 13b30c5da917264cb63f41d058f2dc66f28affcc (patch) | |
| tree | f1b221afd098a72b2ebf222765849e3fb07cc8a9 | |
| parent | f77a4beee4e668b26f69a50e318a74ca8dcbbf33 (diff) | |
(andri) fix template modal
| -rw-r--r-- | src-migrate/modules/product-detail/components/ProductComparisonModal.tsx | 269 |
1 files changed, 250 insertions, 19 deletions
diff --git a/src-migrate/modules/product-detail/components/ProductComparisonModal.tsx b/src-migrate/modules/product-detail/components/ProductComparisonModal.tsx index aa4388a6..14b177ad 100644 --- a/src-migrate/modules/product-detail/components/ProductComparisonModal.tsx +++ b/src-migrate/modules/product-detail/components/ProductComparisonModal.tsx @@ -1,3 +1,4 @@ +import React from 'react'; import { Modal, ModalOverlay, @@ -6,38 +7,268 @@ import { ModalBody, ModalCloseButton, Button, - ModalFooter, - Center, Text, - Box + Box, + Badge, + Grid, + GridItem, + Image, + Input, + InputGroup, + InputLeftElement, + VStack, + HStack, + Select, + IconButton, + Flex, + Icon, // Dibutuhkan untuk membungkus icon dari Lucide } from '@chakra-ui/react'; +// Import hanya icon standar UI dari lucide-react (pengganti @chakra-ui/icons) +import { Search } from 'lucide-react'; + +// --- Dummy Data Types --- +type Product = { + id: string; + name: string; + price: string; + originalPrice: string; + image: string; + variants: string[]; + specs: Record<string, string>; +}; + type Props = { isOpen: boolean; onClose: () => void; }; +// --- Dummy Data Configuration --- +const SPEC_LABELS = [ + 'Tipe Baterai', + 'Kecepatan Tanpa Beban', + 'Torsi Maksimum', + 'Ukuran Drive', + 'Berat Bersih', + 'Garansi', +]; + +const DUMMY_PRODUCTS: (Product | null)[] = [ + { + id: '1', + name: 'TEKIRO Cordless Impact Wrench 1/2 Inch XV Brushless', + price: 'Rp 999.999', + originalPrice: 'Rp 1.500.000', + image: '/images/no-image-compare.svg', + variants: ['Unit Only', '1 Baterai Kit', '2 Baterai Kit'], + specs: { + 'Tipe Baterai': '20V Lithium-Ion', + 'Kecepatan Tanpa Beban': '0-2400 RPM', + 'Torsi Maksimum': '300 N.m', + 'Ukuran Drive': '1/2 Inch', + 'Berat Bersih': '1.5 Kg', + 'Garansi': '1 Tahun', + }, + }, + { + id: '2', + name: 'Makita Cordless Impact Wrench TW001GZ (40V)', + price: 'Rp 2.450.000', + originalPrice: 'Rp 3.000.000', + image: '/images/no-image-compare.svg', + variants: ['Unit Only', 'Full Set'], + specs: { + 'Tipe Baterai': '40V Max XGT', + 'Kecepatan Tanpa Beban': '0-2500 RPM', + 'Torsi Maksimum': '1350 N.m', + 'Ukuran Drive': '3/4 Inch', + 'Berat Bersih': '2.8 Kg', + 'Garansi': '2 Tahun', + }, + }, + { + id: '3', + name: 'DEWALT Max Brushless 1/2 High Torque Impact', + price: 'Rp 3.100.000', + originalPrice: 'Rp 3.500.000', + image: '/images/no-image-compare.svg', + variants: ['Unit Only'], + specs: { + 'Tipe Baterai': '20V XR Li-Ion', + 'Kecepatan Tanpa Beban': '0-1900 RPM', + 'Torsi Maksimum': '950 N.m', + 'Ukuran Drive': '1/2 Inch', + 'Berat Bersih': '2.6 Kg', + 'Garansi': '3 Tahun', + }, + }, + null, // Slot kosong +]; + const ProductComparisonModal = ({ isOpen, onClose }: Props) => { return ( - <Modal isOpen={isOpen} onClose={onClose} size="xl" isCentered> + <Modal isOpen={isOpen} onClose={onClose} size="6xl" scrollBehavior="inside"> <ModalOverlay /> - <ModalContent> - <ModalHeader borderBottom="1px solid #eee">Perbandingan Produk</ModalHeader> + <ModalContent height="90vh"> + <ModalHeader borderBottom="1px solid #eee" pb={2}> + <HStack spacing={3}> + <Text fontSize="xl" fontWeight="bold">Bandingkan Produk</Text> + <Badge colorScheme="red" variant="solid" borderRadius="full" px={2}> + Baru + </Badge> + </HStack> + <Text fontSize="sm" color="gray.500" fontWeight="normal" mt={1}> + Detail Spesifikasi Produk yang kamu pilih + </Text> + </ModalHeader> <ModalCloseButton /> - - <ModalBody py={10}> - <Center flexDirection="column"> - <Box fontSize="4xl" mb={4}>Test</Box> - <Text fontWeight="bold" fontSize="lg">Modal Berhasil Terbuka!</Text> - <Text fontSize="sm" color="gray.500" mt={2}> - Fitur komparasi produk akan muncul di sini nanti. - </Text> - </Center> - </ModalBody> - <ModalFooter borderTop="1px solid #eee"> - <Button colorScheme="red" onClick={onClose}>Tutup</Button> - </ModalFooter> + <ModalBody p={6}> + {/* Main Grid Layout: 5 Columns */} + <Grid templateColumns="200px repeat(4, 1fr)" gap={4}> + + {/* Cell 1: Top Left Empty Space */} + <GridItem /> + + {/* Cell 2-5: Render Products */} + {DUMMY_PRODUCTS.map((product, index) => ( + <GridItem key={index}> + {product ? ( + // --- KARTU PRODUK TERISI --- + <VStack align="stretch" spacing={3}> + {/* Search Bar (Pakai Icon Lucide) */} + <InputGroup size="sm"> + <InputLeftElement pointerEvents="none"> + <Icon as={Search} color="gray.300" /> + </InputLeftElement> + <Input placeholder="Cari Produk lain" borderRadius="md" /> + </InputGroup> + + {/* Gambar Produk */} + <Box h="180px" display="flex" alignItems="center" justifyContent="center"> + <Image + src={product.image} + alt={product.name} + maxH="100%" + objectFit="contain" + /> + </Box> + + {/* Harga */} + <Box> + <Text color="red.500" fontWeight="bold" fontSize="lg"> + {product.price} + </Text> + <Text as="s" color="gray.400" fontSize="xs"> + {product.originalPrice} + </Text> + </Box> + + {/* Nama Produk */} + <Text fontSize="sm" fontWeight="bold" noOfLines={2} h="40px"> + {product.name} + </Text> + + {/* Dropdown Varian */} + <Select size="sm" placeholder="Pilih Varian" borderRadius="md"> + {product.variants.map((v) => ( + <option key={v} value={v}>{v}</option> + ))} + </Select> + + {/* Tombol Aksi (Pakai SVG Custom untuk Keranjang) */} + <HStack spacing={2}> + <IconButton + aria-label="Add to cart" + icon={<Image src="/images/keranjang-compare.svg" w="20px" />} + variant="outline" + colorScheme="red" + size="sm" + w="40px" + /> + <Button colorScheme="red" size="sm" flex={1} fontSize="xs"> + Beli Sekarang + </Button> + </HStack> + </VStack> + ) : ( + // --- SLOT KOSONG --- + <VStack align="stretch" spacing={3} h="100%"> + <InputGroup size="sm"> + <InputLeftElement pointerEvents="none"> + <Icon as={Search} color="gray.300" /> + </InputLeftElement> + <Input placeholder="Cari Produk lain" borderRadius="md" /> + </InputGroup> + + <Flex + direction="column" + align="center" + justify="center" + h="300px" + border="2px dashed" + borderColor="gray.200" + borderRadius="md" + bg="gray.50" + > + {/* Placeholder Image (SVG Custom) */} + <Image + src="/images/no-image-compare.svg" + w="60px" + mb={4} + opacity={0.5} + /> + <Text fontSize="sm" color="gray.400" textAlign="center"> + Produk belum ditambahkan + </Text> + </Flex> + </VStack> + )} + </GridItem> + ))} + + {/* --- SEPARATOR HEADER SPEC --- */} + <GridItem colSpan={5} py={6}> + <Box> + <Text fontSize="lg" fontWeight="bold">Spesifikasi Teknis</Text> + <Text fontSize="sm" color="gray.500">Detail Spesifikasi Produk yang kamu pilih</Text> + </Box> + </GridItem> + + {/* --- TABLE SPEC --- */} + {SPEC_LABELS.map((label, rowIndex) => ( + <React.Fragment key={label}> + {/* Kolom Label */} + <GridItem + py={3} + borderBottom="1px solid" + borderColor="gray.100" + bg={rowIndex % 2 !== 0 ? "white" : "gray.50"} + > + <Text fontWeight="bold" fontSize="sm" color="gray.700"> + {label} + </Text> + </GridItem> + + {/* Kolom Value */} + {DUMMY_PRODUCTS.map((product, colIndex) => ( + <GridItem + key={`${label}-${colIndex}`} + py={3} + borderBottom="1px solid" + borderColor="gray.100" + bg={rowIndex % 2 !== 0 ? "white" : "gray.50"} + > + <Text fontSize="sm" color="gray.600"> + {product ? (product.specs[label] || '-') : '-'} + </Text> + </GridItem> + ))} + </React.Fragment> + ))} + + </Grid> + </ModalBody> </ModalContent> </Modal> ); |
