From 26ef51057f90c8f297dfaa90bf54fb46f83d74b0 Mon Sep 17 00:00:00 2001 From: FIN-IT_AndriFP 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') 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) => ( handleAddProduct(res, index)} > - - { (e.target as HTMLImageElement).src = '/images/no-image-compare.svg'; }} /> - - {res.displayName || res.name} - + {/* Align top biar rapi kalau teks panjang */} + {/* GAMBAR */} + { (e.target as HTMLImageElement).src = '/images/no-image-compare.svg'; }} + flexShrink={0} // Mencegah gambar gepeng + mt={1} + /> + + {/* TEXT CONTAINER */} + {/* w="0" adalah trik CSS agar text-overflow bekerja di dalam Flex */} + + {res.displayName || res.name} + + {formatPrice(res.lowestPrice?.price || 0)} -- cgit v1.2.3