From 26ef51057f90c8f297dfaa90bf54fb46f83d74b0 Mon Sep 17 00:00:00 2001
From: FIN-IT_AndriFP <andrifebriyadiputra@gmail.com>
Date: Wed, 14 Jan 2026 16:15:34 +0700
Subject: (andri) fix comparable search

---
 .../components/ProductComparisonModal.tsx          | 145 ++++++++++++++++++---
 1 file changed, 126 insertions(+), 19 deletions(-)

(limited to 'src-migrate/modules/product-detail/components/ProductComparisonModal.tsx')

diff --git a/src-migrate/modules/product-detail/components/ProductComparisonModal.tsx b/src-migrate/modules/product-detail/components/ProductComparisonModal.tsx
index bc4c5415..4f1fcd82 100644
--- a/src-migrate/modules/product-detail/components/ProductComparisonModal.tsx
+++ b/src-migrate/modules/product-detail/components/ProductComparisonModal.tsx
@@ -100,7 +100,7 @@ const ProductComparisonModal = ({ isOpen, onClose, mainProduct, selectedVariant
       const variantOptions = mainProduct.variants?.map((v: any) => ({
           id: v.id,
           code: v.default_code || v.code || v.sku, 
-          name: v.name,
+          name: v.name || v.displayName || v.display_name, 
           price: v.price?.price || v.price || 0,
           image: v.image
       })) || [];
@@ -115,11 +115,13 @@ const ProductComparisonModal = ({ isOpen, onClose, mainProduct, selectedVariant
           });
       }
 
+      const displayName = activeItem.name || activeItem.displayName || mainProduct.name;
+
       const productSlot1 = {
          id: targetId,
          sku: targetId, 
          realCode: displayCode, 
-         name: mainProduct.name, 
+         name: displayName, 
          price: activeItem.price?.price || activeItem.price || mainProduct.lowest_price?.price || 0,
          image: activeItem.image || mainProduct.image,
          variants: variantOptions
@@ -230,6 +232,7 @@ const ProductComparisonModal = ({ isOpen, onClose, mainProduct, selectedVariant
               ...currentProduct,
               id: selectedVar.id,
               sku: selectedVar.id, 
+              name: selectedVar.name,
               realCode: selectedVar.code,
               price: selectedVar.price,
               image: selectedVar.image
@@ -238,21 +241,55 @@ const ProductComparisonModal = ({ isOpen, onClose, mainProduct, selectedVariant
       }
   };
 
-  const handleAddProduct = (searchItem: any, slotIndex: number) => {
-      const newProducts = [...products];
-      
-      const idToAdd = searchItem.id;
-      const codeToAdd = searchItem.code; 
-      const nameToAdd = searchItem.displayName || searchItem.name;
-      const imageToAdd = searchItem.image;
-      const priceToAdd = searchItem.lowestPrice?.price || 0; 
 
-      if (newProducts.find(p => p && String(p.id) === String(idToAdd))) {
+
+  const handleAddProduct = async (searchItem: any, slotIndex: number) => {
+
+      if (products.find(p => p && String(p.id) === String(searchItem.id))) {
           toast({ title: "Produk sudah ada", status: "warning", position: "top" });
           return;
       }
 
-      newProducts[slotIndex] = {
+      const idToAdd = searchItem.id;
+      const codeToAdd = searchItem.defaultCode || searchItem.default_code || searchItem.code; 
+      const nameToAdd = searchItem.displayName || searchItem.name;
+      const imageToAdd = searchItem.image || searchItem.imageS || searchItem.image_s; 
+      const priceToAdd = searchItem.lowestPrice?.price || searchItem.priceTier1V2F || searchItem.price || 0; 
+      
+      let parentId = searchItem.templateId || 
+                     searchItem.templateIdI || 
+                     searchItem.template_id_i || 
+                     searchItem.template_id;
+
+      if (!parentId) {
+          try {
+              const checkParams = new URLSearchParams({
+                  source: 'upsell',
+                  q: '*:*',
+                  fq: `id:${idToAdd}` 
+              });
+
+              const checkRes = await fetch(`/api/shop/search?${checkParams.toString()}`);
+              if (checkRes.ok) {
+                  const checkData = await checkRes.json();
+                  const freshItem = checkData.response?.products?.[0];
+                  
+                  if (freshItem) {
+                      const serverReturnedId = freshItem.id; 
+                      if (String(serverReturnedId) !== String(idToAdd)) {
+                          parentId = serverReturnedId;
+                      } else {
+                          parentId = freshItem.templateId || freshItem.templateIdI || idToAdd;
+                      }
+                  }
+              }
+          } catch (e) {
+              console.error("Gagal validasi parent:", e);
+              parentId = idToAdd;
+          }
+      }
+      
+      const newProductEntry = {
           id: idToAdd,
           sku: idToAdd, 
           realCode: codeToAdd, 
@@ -268,10 +305,59 @@ const ProductComparisonModal = ({ isOpen, onClose, mainProduct, selectedVariant
           }]
       };
 
-      setProducts(newProducts);
+      setProducts((prev) => {
+          const newSlots = [...prev];
+          newSlots[slotIndex] = newProductEntry;
+          return newSlots;
+      });
+
       setActiveSearchSlot(null);
       setSearchQuery('');
       setSearchResults([]);
+
+      if (parentId) {
+          try {
+              const params = new URLSearchParams({
+                  source: 'upsell', 
+                  limit: '100', 
+                  fq: `template_id_i:${parentId}` 
+              });
+
+              const res = await fetch(`/api/shop/search?${params.toString()}`);
+              
+              if (res.ok) {
+                  const data = await res.json();
+                  const siblings = data.response?.products || [];
+
+                  if (siblings.length > 0) {
+                      const allVariants = siblings.map((s: any) => ({
+                          id: s.variantId || s.productIdI || s.id, 
+                          code: s.defaultCode || s.default_code || s.code, 
+                          name: s.displayName || s.name || s.nameS,
+                          price: s.lowestPrice?.price || s.priceTier1V2F || 0,
+                          image: s.image || s.imageS
+                      }));
+
+                      allVariants.sort((a: any, b: any) => 
+                        String(a.code).localeCompare(String(b.code))
+                      );
+
+                      setProducts((prev) => {
+                          const updated = [...prev];
+                          if (updated[slotIndex] && String(updated[slotIndex].id) === String(idToAdd)) {
+                              updated[slotIndex] = {
+                                  ...updated[slotIndex],
+                                  variants: allVariants 
+                              };
+                          }
+                          return updated;
+                      });
+                  }
+              }
+          } catch (error) {
+              console.error("Gagal fetch variant lain:", error);
+          }
+      }
   };
 
   const handleRemoveProduct = (index: number) => {
@@ -387,15 +473,36 @@ const ProductComparisonModal = ({ isOpen, onClose, mainProduct, selectedVariant
                                                 {searchResults.map((res) => (
                                                     <ListItem 
                                                         key={res.id} 
-                                                        p={2} borderBottom="1px solid #f0f0f0" 
+                                                        p={3}
+                                                        borderBottom="1px solid #f0f0f0" 
                                                         _hover={{ bg: 'red.50', cursor: 'pointer' }}
                                                         onClick={() => handleAddProduct(res, index)}
                                                     >
-                                                        <Flex align="center" gap={2}>
-                                                            <Image src={res.image || '/images/no-image-compare.svg'} boxSize="30px" objectFit="contain" onError={(e) => { (e.target as HTMLImageElement).src = '/images/no-image-compare.svg'; }} />
-                                                            <Box>
-                                                                <Text fontSize="xs" fontWeight="bold" noOfLines={1}>{res.displayName || res.name}</Text>
-                                                                <Text fontSize="xs" color="red.500">
+                                                        <Flex align="flex-start" gap={3}> {/* Align top biar rapi kalau teks panjang */}
+                                                            {/* GAMBAR */}
+                                                            <Image 
+                                                                src={res.image || '/images/no-image-compare.svg'} 
+                                                                boxSize="40px" // Gambar sedikit dibesarkan
+                                                                objectFit="contain" 
+                                                                onError={(e) => { (e.target as HTMLImageElement).src = '/images/no-image-compare.svg'; }} 
+                                                                flexShrink={0} // Mencegah gambar gepeng
+                                                                mt={1}
+                                                            />
+                                                            
+                                                            {/* TEXT CONTAINER */}
+                                                            <Box flex={1} w="0"> {/* w="0" adalah trik CSS agar text-overflow bekerja di dalam Flex */}
+                                                                <Text 
+                                                                    fontSize="xs" 
+                                                                    fontWeight="bold" 
+                                                                    noOfLines={2} // [SOLUSI UTAMA] Ijinkan maksimal 2 baris
+                                                                    lineHeight="shorter" // Spasi antar baris dirapatkan
+                                                                    whiteSpace="normal" // Pastikan text wrapping aktif
+                                                                    mb={1}
+                                                                    title={res.displayName || res.name} // Menampilkan tooltip native saat hover
+                                                                >
+                                                                    {res.displayName || res.name}
+                                                                </Text>
+                                                                <Text fontSize="xs" color="red.500" fontWeight="bold">
                                                                     {formatPrice(res.lowestPrice?.price || 0)}
                                                                 </Text>
                                                             </Box>
-- 
cgit v1.2.3

