diff options
| -rw-r--r-- | src-migrate/modules/product-detail/components/ProductComparisonModal.tsx | 2 | ||||
| -rw-r--r-- | src-migrate/types/productVariant.ts | 1 | ||||
| -rw-r--r-- | src/pages/api/shop/search.js | 106 | ||||
| -rw-r--r-- | src/utils/solrMapping.js | 1 |
4 files changed, 64 insertions, 46 deletions
diff --git a/src-migrate/modules/product-detail/components/ProductComparisonModal.tsx b/src-migrate/modules/product-detail/components/ProductComparisonModal.tsx index 3ee61c9d..e0685d35 100644 --- a/src-migrate/modules/product-detail/components/ProductComparisonModal.tsx +++ b/src-migrate/modules/product-detail/components/ProductComparisonModal.tsx @@ -168,7 +168,7 @@ const ProductComparisonModal = ({ isOpen, onClose, mainProduct, selectedVariant const params = new URLSearchParams({ source: 'compare', - q: '*', + q: searchQuery, limit: '5', // Filter kategori aktif agar Apple-to-Apple fq: attrSetId ? `attribute_set_id_i:${attrSetId}` : '' diff --git a/src-migrate/types/productVariant.ts b/src-migrate/types/productVariant.ts index 08fdd270..31cedf8c 100644 --- a/src-migrate/types/productVariant.ts +++ b/src-migrate/types/productVariant.ts @@ -6,6 +6,7 @@ export interface IProductVariantDetail { weight: number; attribute_set_id: number; attribute_set_name: string; + search_keywords: string; is_in_bu: boolean; is_flashsale: { remaining_time: number; diff --git a/src/pages/api/shop/search.js b/src/pages/api/shop/search.js index 90841e09..5ea6a70a 100644 --- a/src/pages/api/shop/search.js +++ b/src/pages/api/shop/search.js @@ -28,54 +28,67 @@ export default async function handler(req, res) { let { stock = '' } = req.query; // ============================================================ - // [BARU] 1. LOGIC KHUSUS COMPARE (Wajib ditaruh paling atas) + // [PERBAIKAN] 1. LOGIC KHUSUS COMPARE (PAKAI URLSearchParams) // ============================================================ if (source === 'compare') { try { let qCompare = q === '*' ? '*:*' : q; - + // Sanitasi Query if (qCompare !== '*:*') { - const escaped = escapeSolrQuery(qCompare); - qCompare = `*${escaped}*`; + // Kita escape, tapi biarkan stringnya bersih (jangan ditambah wildcard * manual) + // karena kita serahkan ke 'edismax' parser + qCompare = escapeSolrQuery(qCompare); } - // Susun Parameter Solr - const parameter = [ - `q=${encodeURIComponent(qCompare)}`, - `rows=${limit}`, - 'wt=json', - 'indent=true', - 'defType=edismax', - - // Grouping agar varian tidak banjir (per template) - 'group=true', - 'group.field=template_id_i', - 'group.limit=1', - 'group.main=true', - - // Field Wajib (Perhatikan: kita butuh product_id_i/default_code_s) - 'fl=id,display_name_s,default_code_s,image_s,price_tier1_v2_f,attribute_set_id_i,attribute_set_name_s,template_id_i,product_id_i', - - // Filter Dasar - 'fq=-publish_b:false', - 'fq=price_tier1_v2_f:[1 TO *]' - ]; + // [SOLUSI] Gunakan URLSearchParams untuk menyusun URL dengan aman + const params = new URLSearchParams(); + + params.append('q', qCompare); + params.append('rows', limit); + params.append('wt', 'json'); + params.append('indent', 'true'); + + // Gunakan eDisMax parser (Otak Cerdas) + params.append('defType', 'edismax'); + + // Set Prioritas Pencarian (Boost ^) + // 1. default_code_s^20 : SKU persis (Prioritas Tertinggi) + // 2. search_keywords_t^10 : Field baru (Case insensitive) + // 3. display_name_s^1 : Cadangan + params.append('qf', 'default_code_s^20 search_keywords_t^10 display_name_s^1'); + + // Minimum Match 100% (Semua kata harus ada), ubah jika ingin lebih longgar + params.append('mm', '100%'); + + // Grouping + params.append('group', 'true'); + params.append('group.field', 'template_id_i'); + params.append('group.limit', '1'); + params.append('group.main', 'true'); + + // Field List (fl) + params.append('fl', 'id,display_name_s,default_code_s,image_s,price_tier1_v2_f,attribute_set_id_i,attribute_set_name_s,template_id_i,product_id_i'); + + // Filter Query (fq) Dasar + params.append('fq', '-publish_b:false'); + params.append('fq', 'price_tier1_v2_f:[1 TO *]'); // Logic Locking (Filter Attribute Set ID dari Frontend) - // Frontend akan mengirim fq="attribute_set_id_i:9" if (fq) { - if (Array.isArray(fq)) { - fq.forEach(f => parameter.push(`fq=${encodeURIComponent(f)}`)); - } else { - parameter.push(`fq=${encodeURIComponent(fq)}`); - } + if (Array.isArray(fq)) { + fq.forEach(f => params.append('fq', f)); + } else { + params.append('fq', fq); + } } - // Target Core: VARIANTS (Karena compare butuh data spesifik) - const solrUrl = process.env.SOLR_HOST + '/solr/variants/select?' + parameter.join('&'); - - const result = await axios(solrUrl); + // Target Core: VARIANTS + // HAPUS parameter manual dari string URL, gunakan params object + const solrUrl = process.env.SOLR_HOST + '/solr/variants/select'; + + // Axios akan otomatis handle encoding % dan & dengan benar + const result = await axios.get(solrUrl, { params: params }); // Mapping Result const mappedProducts = productMappingSolr( @@ -84,13 +97,13 @@ export default async function handler(req, res) { ); const finalResponse = { - ...result.data, - response: { - ...result.data.response, - products: mappedProducts - } + ...result.data, + response: { + ...result.data.response, + products: mappedProducts + } }; - + delete finalResponse.response.docs; const camelCasedData = camelcaseObjectDeep(finalResponse); @@ -98,13 +111,16 @@ export default async function handler(req, res) { } catch (e) { console.error('[COMPARE SEARCH ERROR]', e.message); - // Return JSON valid meski kosong, agar frontend tidak error syntax + if (e.response && e.response.data) { + // Log detail error dari Solr + console.error('[SOLR DETAILS]:', JSON.stringify(e.response.data, null, 2)); + } return res.status(200).json({ response: { products: [], numFound: 0 } }); } } // ============================================================ - // LOGIC KHUSUS UPSELL (Simple & Direct) + // LOGIC KHUSUS UPSELL (KODE LAMA ANDA) // ============================================================ if (source === 'upsell') { try { @@ -172,7 +188,7 @@ export default async function handler(req, res) { } // ============================================================ - // SITEMAP (Biarkan tetap sama) + // SITEMAP (KODE LAMA ANDA) // ============================================================ if (source === 'sitemap') { try { @@ -197,7 +213,7 @@ export default async function handler(req, res) { } // ============================================================ - // SEARCH NORMAL (LOGIKA LAMA) + // SEARCH NORMAL (KODE LAMA ANDA) // ============================================================ let paramOrderBy = ''; diff --git a/src/utils/solrMapping.js b/src/utils/solrMapping.js index 419e0c61..8c0abcf1 100644 --- a/src/utils/solrMapping.js +++ b/src/utils/solrMapping.js @@ -129,6 +129,7 @@ export const variantsMappingSolr = (parent, products, pricelist) => { weight: product.weight_f || 0, attribute_set_id: product.attribute_set_id_i || 0, attribute_set_name: product.attribute_set_name_s || '', + search_keywords: product.search_keywords_t || '', manufacture: {}, parent: {}, qtySold: product?.qty_sold_f || 0, |
