summaryrefslogtreecommitdiff
path: root/src-migrate
diff options
context:
space:
mode:
authorFIN-IT_AndriFP <andrifebriyadiputra@gmail.com>2025-12-19 16:48:11 +0700
committerFIN-IT_AndriFP <andrifebriyadiputra@gmail.com>2025-12-19 16:48:11 +0700
commitcb447f728d30e31f0cc4f4cb9f7363274925ceef (patch)
tree886ab9873ae02010209cb3aafd6d4240d1aa0cb6 /src-migrate
parent1876d142f492714c37efdc1eabb72709917a0c1d (diff)
(andri) show product ketika cari product masi kosong
Diffstat (limited to 'src-migrate')
-rw-r--r--src-migrate/modules/product-detail/components/ProductComparisonModal.tsx38
1 files changed, 25 insertions, 13 deletions
diff --git a/src-migrate/modules/product-detail/components/ProductComparisonModal.tsx b/src-migrate/modules/product-detail/components/ProductComparisonModal.tsx
index e0685d35..43f43ac4 100644
--- a/src-migrate/modules/product-detail/components/ProductComparisonModal.tsx
+++ b/src-migrate/modules/product-detail/components/ProductComparisonModal.tsx
@@ -156,30 +156,38 @@ const ProductComparisonModal = ({ isOpen, onClose, mainProduct, selectedVariant
// 3. SEARCH LOGIC (MATCHED WITH API JSON)
// ===========================================================================
useEffect(() => {
+ // Gunakan timeout untuk debounce (menunggu user selesai ketik)
const delayDebounceFn = setTimeout(async () => {
- if (searchQuery.length < 3) {
+
+ // LOGIKA BARU:
+ // Jika ada text tapi kurang dari 3 huruf -> Jangan search (hemat API)
+ // Jika text KOSONG (0) -> Lanjut search (ini untuk fitur 'klik muncul barang')
+ if (searchQuery.length > 0 && searchQuery.length < 3) {
setSearchResults([]);
return;
}
+ // Jangan trigger search kalau slot belum dipilih (mencegah fetch saat modal baru buka)
+ if (activeSearchSlot === null) return;
+
setIsSearching(true);
try {
const attrSetId = selectedVariant?.attribute_set_id || mainProduct?.attribute_set_id;
+ // Tentukan Query: Kalau kosong pakai bintang (*), kalau ada isi pakai isinya
+ const queryParam = searchQuery === '' ? '*' : searchQuery;
+
const params = new URLSearchParams({
source: 'compare',
- q: searchQuery,
- limit: '5',
- // Filter kategori aktif agar Apple-to-Apple
+ q: queryParam, // <-- Pakai logika wildcard
+ limit: '20', // <-- Ubah limit jadi 20
fq: attrSetId ? `attribute_set_id_i:${attrSetId}` : ''
});
- // Gunakan endpoint yang benar: /api/shop/search
const res = await fetch(`/api/shop/search?${params.toString()}`);
if (res.ok) {
const data = await res.json();
- // Data sudah CamelCase dari Backend
setSearchResults(data.response?.products || []);
} else {
setSearchResults([]);
@@ -192,7 +200,7 @@ const ProductComparisonModal = ({ isOpen, onClose, mainProduct, selectedVariant
}, 500);
return () => clearTimeout(delayDebounceFn);
- }, [searchQuery, mainProduct, selectedVariant]);
+ }, [searchQuery, mainProduct, selectedVariant, activeSearchSlot]);
// ===========================================================================
// 4. HANDLERS
@@ -297,7 +305,7 @@ const ProductComparisonModal = ({ isOpen, onClose, mainProduct, selectedVariant
)}
<Box h="160px" display="flex" alignItems="center" justifyContent="center" bg="gray.50" borderRadius="md" p={2}>
<Image
- src={product.image || '/images/noimage.jpeg'}
+ src={product.image || '/images/no-image-compare.svg'}
alt={product.name} maxH="100%" objectFit="contain"
onError={(e) => { (e.target as HTMLImageElement).src = '/images/no-image-compare.svg'; }}
/>
@@ -342,8 +350,10 @@ const ProductComparisonModal = ({ isOpen, onClose, mainProduct, selectedVariant
</InputGroup>
{/* --- HASIL SEARCH (MAPPING FIX) --- */}
- {activeSearchSlot === index && searchQuery.length > 0 && (
+ {activeSearchSlot === index && (
<Box position="absolute" top="35px" left={0} right={0} bg="white" boxShadow="lg" zIndex={10} borderRadius="md" border="1px solid" borderColor="gray.200" maxH="250px" overflowY="auto">
+
+ {/* Tampilkan Loading jika sedang searching */}
{isSearching ? (
<Box p={4} textAlign="center"><Spinner size="sm" color="red.500"/></Box>
) : searchResults.length > 0 ? (
@@ -356,11 +366,9 @@ const ProductComparisonModal = ({ isOpen, onClose, mainProduct, selectedVariant
onClick={() => handleAddProduct(res, index)}
>
<Flex align="center" gap={2}>
- <Image src={res.image || '/images/noimage.jpeg'} boxSize="30px" objectFit="contain" onError={(e) => { (e.target as HTMLImageElement).src = '/images/noimage.jpeg'; }} />
+ <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>
- {/* [FIX] Gunakan displayName atau name */}
<Text fontSize="xs" fontWeight="bold" noOfLines={1}>{res.displayName || res.name}</Text>
- {/* [FIX] Gunakan lowestPrice.price */}
<Text fontSize="xs" color="red.500">
{formatPrice(res.lowestPrice?.price || 0)}
</Text>
@@ -370,7 +378,11 @@ const ProductComparisonModal = ({ isOpen, onClose, mainProduct, selectedVariant
))}
</List>
) : (
- <Box p={3} fontSize="xs" color="gray.500" textAlign="center">Tidak ditemukan.</Box>
+ // Logic tambahan: Jika input kosong tapi hasil 0 (biasanya belum kelar loading awal), jangan tampilkan "Tidak Ditemukan"
+ // Tapi kalau sudah ngetik dan hasil 0, baru tampilkan "Tidak Ditemukan"
+ <Box p={3} fontSize="xs" color="gray.500" textAlign="center">
+ {searchQuery === '' ? 'Menampilkan rekomendasi...' : 'Tidak ditemukan.'}
+ </Box>
)}
</Box>
)}