summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFIN-IT_AndriFP <andrifebriyadiputra@gmail.com>2025-12-03 11:49:18 +0700
committerFIN-IT_AndriFP <andrifebriyadiputra@gmail.com>2025-12-03 11:49:18 +0700
commit219c61c5c14e3a8dfed3d7158d59d11c476e3586 (patch)
treef640aab4055aea6997e8fa281476d05300187656
parent825d86bb50f48f9a21d740d474c0dddee858dffb (diff)
(andri) fix search for similar product side dan bottom pada detail product
-rw-r--r--src-migrate/modules/product-detail/components/ProductDetail.tsx55
-rw-r--r--src-migrate/modules/product-detail/components/SimilarSide.tsx74
-rw-r--r--src-migrate/services/product.ts40
-rw-r--r--src/pages/api/magento-product.ts29
-rw-r--r--src/pages/api/shop/search.js230
5 files changed, 242 insertions, 186 deletions
diff --git a/src-migrate/modules/product-detail/components/ProductDetail.tsx b/src-migrate/modules/product-detail/components/ProductDetail.tsx
index 5f930117..cfe73628 100644
--- a/src-migrate/modules/product-detail/components/ProductDetail.tsx
+++ b/src-migrate/modules/product-detail/components/ProductDetail.tsx
@@ -67,6 +67,8 @@ const ProductDetail = ({ product }: Props) => {
// State Data dari Magento
const [specs, setSpecs] = useState<{ code: string; label: string; value: string }[]>([]);
const [upsellIds, setUpsellIds] = useState<number[]>([]);
+ const [relatedIds, setRelatedIds] = useState<number[]>([]);
+
const [loadingSpecs, setLoadingSpecs] = useState(false);
const [errorSpecs, setErrorSpecs] = useState(false);
@@ -109,7 +111,7 @@ const ProductDetail = ({ product }: Props) => {
}, [router.asPath, product.manufacture.name, product.name, setAskAdminUrl]);
// =========================================================================
- // LOGIC INISIALISASI VARIANT (HANDLE NAVIGASI)
+ // LOGIC INISIALISASI VARIANT (RESET SAAT NAVIGASI)
// =========================================================================
useEffect(() => {
if (typeof auth === 'object') {
@@ -121,28 +123,29 @@ const ProductDetail = ({ product }: Props) => {
setSelectedVariant(variantInit);
- // Reset data Magento saat produk berubah
+ // Reset data Magento
setSpecs([]);
setUpsellIds([]);
+ setRelatedIds([]);
}, [product, auth]);
// =========================================================================
- // LOGIC FETCH: SPECS & UPSELLS
+ // LOGIC FETCH: SPECS, UPSELLS, RELATED
// =========================================================================
useEffect(() => {
const fetchMagentoData = async () => {
- // Gunakan ID Variant (SKU Odoo)
- const idToFetch = selectedVariant?.id;
+ // Validasi kepemilikan varian
+ if (!selectedVariant?.id) return;
+ const isVariantOwner = product.variants.some(v => Number(v.id) === Number(selectedVariant.id));
+ if (!isVariantOwner) return;
- if (!idToFetch) return;
+ const idToFetch = selectedVariant.id;
setLoadingSpecs(true);
setErrorSpecs(false);
try {
- console.log("Fetching Magento data via Proxy for ID:", idToFetch);
-
const endpoint = `/api/magento-product?sku=${encodeURIComponent(String(idToFetch))}`;
const response = await fetch(endpoint, {
@@ -151,61 +154,75 @@ const ProductDetail = ({ product }: Props) => {
});
if (!response.ok) {
- console.warn(`Magento API status: ${response.status}`);
setSpecs([]);
setUpsellIds([]);
+ setRelatedIds([]);
return;
}
const data = await response.json();
- // 1. Simpan Data Spesifikasi
+ // Double Check
+ if (Number(idToFetch) !== Number(selectedVariant.id)) return;
+
+ // 1. Specs
if (data.specs && Array.isArray(data.specs)) {
setSpecs(data.specs);
} else {
setSpecs([]);
}
- // 2. Simpan Data Up-Sells (ID)
+ // 2. Upsell
if (data.upsell_ids && Array.isArray(data.upsell_ids)) {
setUpsellIds(data.upsell_ids);
} else {
setUpsellIds([]);
}
+ // 3. Related
+ if (data.related_ids && Array.isArray(data.related_ids)) {
+ setRelatedIds(data.related_ids);
+ } else {
+ setRelatedIds([]);
+ }
+
} catch (error) {
console.error("Gagal mengambil data Magento:", error);
setErrorSpecs(true);
setSpecs([]);
setUpsellIds([]);
+ setRelatedIds([]);
} finally {
setLoadingSpecs(false);
}
};
fetchMagentoData();
- }, [selectedVariant, product.id]);
+ }, [selectedVariant, product]);
// =========================================================================
- // HELPER: RENDER SPEC VALUE (SIMPLE TEXT/HTML ONLY)
+ // HELPER: RENDER SPEC VALUE (SIMPLE - NO LINK DETECT)
// =========================================================================
const renderSpecValue = (item: { code: string; label: string; value: string }) => {
const val = item.value;
if (!val) return '-';
- // Cek apakah mengandung tag HTML sederhana (<p>, <a>, <ul>, dll)
- if (val.includes('<') && val.includes('>')) {
+ const cleanVal = val.trim();
+
+ // 1. JIKA HTML (Legacy Data)
+ // Deteksi tag HTML sederhana
+ if (cleanVal.includes('<') && cleanVal.includes('>')) {
return (
<div
className="prose prose-sm text-gray-700"
- dangerouslySetInnerHTML={{ __html: val }}
+ dangerouslySetInnerHTML={{ __html: cleanVal }}
/>
);
}
- // Default: Teks Biasa
- return val;
+ // 2. TEKS BIASA
+ return cleanVal;
};
@@ -544,7 +561,7 @@ const ProductDetail = ({ product }: Props) => {
<div className='h-6' />
<div className={style['heading']}>Produk Serupa</div>
<div className='h-4' />
- <SimilarSide product={product} />
+ <SimilarSide product={product} relatedIds={relatedIds} />
</div>
)}
diff --git a/src-migrate/modules/product-detail/components/SimilarSide.tsx b/src-migrate/modules/product-detail/components/SimilarSide.tsx
index d70a314d..51d9eff7 100644
--- a/src-migrate/modules/product-detail/components/SimilarSide.tsx
+++ b/src-migrate/modules/product-detail/components/SimilarSide.tsx
@@ -1,33 +1,75 @@
import { Skeleton } from '@chakra-ui/react'
+import { useQuery } from 'react-query'
import ProductCard from '~/modules/product-card'
-import useProductSimilar from '~/modules/product-similar/hooks/useProductSimilar'
-import { IProductDetail } from '~/types/product'
+// Import service
+import { getProductSimilar, getProductsByIds } from '~/services/product'
+// TAMBAHKAN 'IProduct' DISINI
+import { IProduct, IProductDetail } from '~/types/product'
type Props = {
product: IProductDetail
+ relatedIds?: number[]
}
-const SimilarSide = ({ product }: Props) => {
- const productSimilar = useProductSimilar({
- name: product.name,
- except: { productId: product.id, manufactureId: product.manufacture.id },
- })
+const SimilarSide = ({ product, relatedIds = [] }: Props) => {
+
+ const hasRelated = relatedIds.length > 0;
- const products = productSimilar.data?.products || []
+ // 1. Fetch Related by ID
+ const relatedQuery = useQuery({
+ queryKey: ['product-related', relatedIds],
+ queryFn: () => getProductsByIds({ ids: relatedIds }),
+ enabled: hasRelated,
+ staleTime: 1000 * 60 * 5,
+ });
+
+ // 2. Fetch Similar Biasa
+ const similarQuery = useQuery({
+ queryKey: ['product-similar-side', product.name],
+ queryFn: () => getProductSimilar({
+ name: product.name,
+ except: {
+ productId: product.id,
+ manufactureId: product.manufacture?.id
+ }
+ }),
+ enabled: !hasRelated,
+ staleTime: 1000 * 60 * 5,
+ });
+
+ // ============================================================
+ // PERBAIKAN: Definisikan tipe array secara eksplisit (IProduct[])
+ // ============================================================
+ let products: IProduct[] = [];
+ let isLoading = false;
+
+ if (hasRelated) {
+ // Cast ke any dulu jika tipe return service belum sempurna terdeteksi, lalu ambil products
+ // Atau jika getProductsByIds me-return { products: IProduct[] }, ambil .products
+ // Sesuai kode service terakhir, getProductsByIds me-return GetProductSimilarRes yg punya .products
+ products = (relatedQuery.data as any)?.products || [];
+ isLoading = relatedQuery.isLoading;
+ } else {
+ products = similarQuery.data?.products || [];
+ isLoading = similarQuery.isLoading;
+ }
+
+ if (!isLoading && products.length === 0) return null;
return (
<Skeleton
- isLoaded={!productSimilar.isLoading}
- className="h-[500px] overflow-auto grid grid-cols-1 gap-y-4 divide-y divide-gray-300 border border-gray-300 rounded-lg"
+ isLoaded={!isLoading}
+ className="h-[500px] overflow-auto grid grid-cols-1 gap-y-4 divide-y divide-gray-300 border border-gray-300 rounded-lg p-2"
rounded='lg'
>
- {products.map((product) => (
- <ProductCard
- key={product.id}
- product={product}
- layout='horizontal'
- />
+ {products.map((item) => (
+ <div key={item.id} className="pt-2 first:pt-0">
+ <ProductCard
+ product={item}
+ layout='horizontal'
+ />
+ </div>
))}
</Skeleton>
)
diff --git a/src-migrate/services/product.ts b/src-migrate/services/product.ts
index f77fc3ec..fa9dae54 100644
--- a/src-migrate/services/product.ts
+++ b/src-migrate/services/product.ts
@@ -76,29 +76,43 @@ export interface GetProductsByIdsProps {
export const getProductsByIds = async ({
ids,
}: GetProductsByIdsProps): Promise<GetProductSimilarRes> => {
- // Jika array ID kosong, kembalikan object kosong agar tidak error
if (!ids || ids.length === 0) {
- return {
- products: [],
- num_found: 0,
- num_found_exact: true,
- start: 0
- };
+ return { products: [], num_found: 0, num_found_exact: true, start: 0 };
}
- // Buat query Solr format: product_id_i:(224102 OR 88019 OR ...)
const idQuery = ids.join(' OR ');
const query = [
- `q=*`, // Query wildcard (ambil semua)
- `fq=product_id_i:(${idQuery})`, // TAPI difilter hanya ID yang ada di list upsell
+ `q=*`,
+ `fq=(id:(${idQuery}) OR product_id_i:(${idQuery}))`,
'rows=20',
`source=upsell`,
];
const url = `${SELF_HOST}/api/shop/search?${query.join('&')}`;
- return await fetch(url)
- .then((res) => res.json())
- .then((res) => snakeCase(res.response));
+ // Request
+ const res = await fetch(url).then((res) => res.json());
+
+ // LOG 2: Hasil Pencarian SOLR
+ console.group("🔍 2. [Solr Search Result]");
+ console.log("Request URL:", url);
+ console.log("Requested IDs:", ids);
+
+ const foundDocs = res.response?.docs || [];
+ const foundIds = foundDocs.map((doc: any) => doc.id || doc.product_id_i);
+
+ console.log("Found Products Count:", res.response?.numFound);
+ console.log("Found IDs:", foundIds);
+
+ // Cek ID mana yang hilang
+ const missingIds = ids.filter((reqId) => !foundIds.includes(String(reqId)) && !foundIds.includes(Number(reqId)));
+ if (missingIds.length > 0) {
+ console.warn("⚠️ MISSING / NOT FOUND IDs:", missingIds);
+ } else {
+ console.log("✅ All IDs Found!");
+ }
+ console.groupEnd();
+
+ return snakeCase(res.response);
}; \ No newline at end of file
diff --git a/src/pages/api/magento-product.ts b/src/pages/api/magento-product.ts
index c494b05d..32dd0e5c 100644
--- a/src/pages/api/magento-product.ts
+++ b/src/pages/api/magento-product.ts
@@ -54,19 +54,14 @@ export default async function handler(
let specsWithLabels: any[] = [];
- // Cek apakah ada custom_attributes
if (data.custom_attributes) {
- // Filter atribut yang kodenya dimulai dengan 'z'
- // FIX: Menghapus filter 'Pakai link' agar MSDS tetap muncul
const zAttributes = data.custom_attributes.filter((attr: any) =>
attr.attribute_code.startsWith('z')
);
- // Fetch detail label untuk setiap atribut secara paralel
specsWithLabels = await Promise.all(
zAttributes.map(async (attr: any) => {
try {
- // Endpoint untuk ambil detail atribut (Label)
const attrUrl = `https://pimdev.1211.my.id/rest/V1/products/attributes/${attr.attribute_code}`;
const attrRes = await fetch(attrUrl, {
@@ -80,7 +75,7 @@ export default async function handler(
if (attrRes.ok) {
const attrData = await attrRes.json();
return {
- code: attr.attribute_code, // FIX: Kirim code agar bisa dideteksi frontend (z_doc_)
+ code: attr.attribute_code,
label: attrData.default_frontend_label || attr.attribute_code,
value: attr.value
};
@@ -89,12 +84,11 @@ export default async function handler(
console.error(`Failed to fetch label for ${attr.attribute_code}`);
}
- // Fallback: Format manual
const fallbackLabel = attr.attribute_code
.substring(1).replace(/_/g, ' ').trim();
return {
- code: attr.attribute_code, // FIX: Kirim code di fallback juga
+ code: attr.attribute_code,
label: fallbackLabel,
value: attr.value
};
@@ -103,15 +97,24 @@ export default async function handler(
}
// =====================================================================
- // TAMBAHAN 2: AMBIL UP-SELLS (product_links)
+ // TAMBAHAN 2: AMBIL UP-SELLS (product_links type = upsell)
// =====================================================================
let upsellIds: number[] = [];
if (data.product_links && Array.isArray(data.product_links)) {
upsellIds = data.product_links
- // Filter hanya link type 'upsell'
.filter((link: any) => link.link_type === 'upsell')
- // Ambil SKU (yang isinya ID Odoo) dan ubah ke number
+ .map((link: any) => Number(link.linked_product_sku));
+ }
+
+ // =====================================================================
+ // TAMBAHAN 3: AMBIL RELATED PRODUCTS (product_links type = related)
+ // =====================================================================
+ let relatedIds: number[] = [];
+
+ if (data.product_links && Array.isArray(data.product_links)) {
+ relatedIds = data.product_links
+ .filter((link: any) => link.link_type === 'related')
.map((link: any) => Number(link.linked_product_sku));
}
@@ -121,10 +124,12 @@ export default async function handler(
const responseData = {
...data,
specs: specsWithLabels, // Data Spesifikasi (z_*)
- upsell_ids: upsellIds // Data Upsell ID (product_links)
+ upsell_ids: upsellIds, // Data Upsell ID
+ related_ids: relatedIds // Data Related ID (BARU)
};
res.status(200).json(responseData);
+ console.log(responseData);
} catch (error) {
console.error('Proxy Server Error:', error);
diff --git a/src/pages/api/shop/search.js b/src/pages/api/shop/search.js
index 42d16100..7d4adfcb 100644
--- a/src/pages/api/shop/search.js
+++ b/src/pages/api/shop/search.js
@@ -12,7 +12,7 @@ export default async function handler(req, res) {
priceTo = 0,
orderBy = '',
operation = 'AND',
- fq = '',
+ fq = '', // bisa berupa string atau array
limit = 30,
source = '',
} = req.query;
@@ -20,107 +20,119 @@ export default async function handler(req, res) {
let { stock = '' } = req.query;
// ============================================================
- // SITEMAP
+ // LOGIC KHUSUS UPSELL (Simple & Direct)
// ============================================================
- if (source === 'sitemap') {
+ if (source === 'upsell') {
try {
- const offset = (page - 1) * limit;
+ // Ambil fq dari query (format: product_id_i:(...))
+ // Pastikan fq adalah string tunggal
+ let fqUpsell = Array.isArray(fq) ? fq.join(' OR ') : fq;
+ fqUpsell = decodeURIComponent(fqUpsell);
const parameter = [
'q=*:*',
`rows=${limit}`,
- `start=${offset}`,
- 'fl=product_id_i,name_s,default_code_s,image_s,category_name',
'wt=json',
- 'omitHeader=true',
+ 'indent=true',
+ 'defType=edismax',
+ // Filter Query khusus Upsell
+ `fq=${encodeURIComponent(fqUpsell)}`,
+ // Tetap filter yang publish & ada harga agar produk valid
+ `fq=${encodeURIComponent('-publish_b:false')}`,
+ `fq=${encodeURIComponent('price_tier1_v2_f:[1 TO *]')}`
];
- // const parameter = [
- // 'q=*:*',
- // `rows=${limit}`,
- // `start=${offset}`,
-
- // // ❌ EXCLUDE PROMOTION
- // 'fq=-(name_s:*promotion* OR display_name_s:*promotion* OR variants_name_t:*promotion*)',
-
- // // ❌ EXCLUDE DUMMY PRODUCT
- // 'fq=-(name_s:*dummy* OR display_name_s:*dummy* OR variants_name_t:*dummy* OR default_code_s:A.*)',
+ // PENTING: SEARCH DI CORE 'VARIANTS'
+ const solrUrl = process.env.SOLR_HOST + '/solr/variants/select?' + parameter.join('&');
- // 'fl=product_id_i,name_s,default_code_s,image_s,category_name',
- // 'wt=json',
- // 'omitHeader=true',
- // ];
+ const result = await axios(solrUrl);
- const solrUrl =
- process.env.SOLR_HOST + '/solr/product/select?' + parameter.join('&');
-
- // console.log('[SITEMAP SOLR QUERY]', solrUrl);
-
- const result = await axios(solrUrl, { timeout: 25000 });
-
- // mapping seperti biasa
- result.data.response.products = productMappingSolr(
+ // 1. Mapping dasar
+ const mappedProducts = productMappingSolr(
result.data.response.docs,
false
);
- delete result.data.response.docs;
+ // 2. FIX URL LINK: Override ID Varian dengan Template ID
+ const rawDocs = result.data.response.docs;
+
+ const fixedProducts = mappedProducts.map((p, index) => {
+ const raw = rawDocs[index];
+ if (raw && raw.template_id_i) {
+ return {
+ ...p,
+ id: raw.template_id_i, // Ganti ID Varian jadi ID Template agar link valid
+ variantId: raw.product_id_i
+ };
+ }
+ return p;
+ });
+
+ const finalResponse = {
+ ...result.data,
+ response: {
+ ...result.data.response,
+ products: fixedProducts
+ }
+ };
+
+ delete finalResponse.response.docs;
+ const camelCasedData = camelcaseObjectDeep(finalResponse);
+
+ return res.status(200).json(camelCasedData);
- result.data = camelcaseObjectDeep(result.data);
+ } catch (e) {
+ console.error('[UPSELL ERROR]', e.response?.data || e.message);
+ return res.status(200).json({ response: { products: [], numFound: 0 } });
+ }
+ }
+ // ============================================================
+ // SITEMAP (Biarkan tetap sama)
+ // ============================================================
+ if (source === 'sitemap') {
+ try {
+ const offset = (page - 1) * limit;
+ const parameter = [
+ 'q=*:*',
+ `rows=${limit}`,
+ `start=${offset}`,
+ 'fl=product_id_i,name_s,default_code_s,image_s,category_name',
+ 'wt=json',
+ 'omitHeader=true',
+ ];
+ const solrUrl = process.env.SOLR_HOST + '/solr/product/select?' + parameter.join('&');
+ const result = await axios(solrUrl, { timeout: 25000 });
+ result.data.response.products = productMappingSolr(result.data.response.docs, false);
+ delete result.data.response.docs;
+ result.data = camelcaseObjectDeep(result.data);
return res.status(200).json(result.data);
} catch (e) {
- console.error('[SITEMAP ERROR]', e);
return res.status(500).json({ error: 'Sitemap query failed' });
}
}
// ============================================================
- // SEARCH NORMAL
+ // SEARCH NORMAL (LOGIKA LAMA)
// ============================================================
let paramOrderBy = '';
switch (orderBy) {
- case 'flashsale-discount-desc':
- paramOrderBy += 'flashsale_discount_f DESC';
- break;
- case 'price-asc':
- paramOrderBy += 'price_tier1_v2_f ASC';
- break;
- case 'price-desc':
- paramOrderBy += 'price_tier1_v2_f DESC';
- break;
- case 'popular':
- paramOrderBy += 'product_rating_f DESC, search_rank_i DESC,';
- break;
- case 'popular-weekly':
- paramOrderBy += 'search_rank_weekly_i DESC';
- break;
- case 'stock':
- paramOrderBy += 'product_rating_f DESC, stock_total_f DESC';
- break;
- case 'flashsale-price-asc':
- paramOrderBy += 'flashsale_price_f ASC';
- break;
- default:
- paramOrderBy += '';
- break;
+ case 'flashsale-discount-desc': paramOrderBy += 'flashsale_discount_f DESC'; break;
+ case 'price-asc': paramOrderBy += 'price_tier1_v2_f ASC'; break;
+ case 'price-desc': paramOrderBy += 'price_tier1_v2_f DESC'; break;
+ case 'popular': paramOrderBy += 'product_rating_f DESC, search_rank_i DESC,'; break;
+ case 'popular-weekly': paramOrderBy += 'search_rank_weekly_i DESC'; break;
+ case 'stock': paramOrderBy += 'product_rating_f DESC, stock_total_f DESC'; break;
+ case 'flashsale-price-asc': paramOrderBy += 'flashsale_price_f ASC'; break;
+ default: paramOrderBy += ''; break;
}
let checkQ = q.trim().split(/[\s\+\-\!\(\)\{\}\[\]\^"~\*\?:\\\/]+/);
let newQ = escapeSolrQuery(q);
- const formattedQuery = `(${newQ
- .split(' ')
- .map((term) => (term.length < 2 ? term : `${term}*`))
- .join(' ')})`;
-
- const mm =
- checkQ.length > 2
- ? checkQ.length > 5
- ? '55%'
- : '85%'
- : `${checkQ.length}`;
+ const formattedQuery = `(${newQ.split(' ').map((term) => (term.length < 2 ? term : `${term}*`)).join(' ')})`;
+ const mm = checkQ.length > 2 ? (checkQ.length > 5 ? '55%' : '85%') : `${checkQ.length}`;
const filterQueries = [
'-publish_b:false',
@@ -128,23 +140,19 @@ export default async function handler(req, res) {
'price_tier1_v2_f:[1 TO *]',
];
- if (orderBy === 'stock') {
- filterQueries.push('stock_total_f:[1 TO *]');
- }
+ if (orderBy === 'stock') filterQueries.push('stock_total_f:[1 TO *]');
- if (fq && source != 'similar' && typeof fq != 'string') {
- fq.push(...filterQueries);
+ // Handle 'fq' parameter from request
+ let finalFq = [...filterQueries];
+ if (fq) {
+ if (Array.isArray(fq)) finalFq.push(...fq);
+ else finalFq.push(fq);
}
- const fq_ = filterQueries.join(' AND ');
-
let keywords = newQ;
if (source === 'similar' || checkQ.length < 3) {
- if (checkQ.length < 2 || checkQ[1].length < 2) {
- keywords = newQ;
- } else {
- keywords = newQ + '*';
- }
+ if (checkQ.length < 2 || checkQ[1].length < 2) keywords = newQ;
+ else keywords = newQ + '*';
} else {
keywords = formattedQuery;
}
@@ -164,16 +172,16 @@ export default async function handler(req, res) {
`start=${parseInt(offset)}`,
`rows=${limit}`,
`sort=${paramOrderBy}`,
- `fq=${encodeURIComponent(fq_)}`,
`mm=${encodeURIComponent(mm)}`,
];
+ // Masukkan semua Filter Query (fq)
+ finalFq.forEach(f => {
+ parameter.push(`fq=${encodeURIComponent(f)}`);
+ });
+
if (priceFrom > 0 || priceTo > 0) {
- parameter.push(
- `fq=price_tier1_v2_f:[${priceFrom == '' ? '*' : priceFrom} TO ${
- priceTo == '' ? '*' : priceTo
- }]`
- );
+ parameter.push(`fq=price_tier1_v2_f:[${priceFrom || '*'} TO ${priceTo || '*'}]`);
}
let { auth } = req.cookies;
@@ -183,49 +191,28 @@ export default async function handler(req, res) {
}
if (brand) {
- const brandExpr = brand
- .split(',')
- .map(
- (manufacturer) =>
- `manufacture_name:"${encodeURIComponent(manufacturer)}"`
- )
- .join(' OR ');
+ const brandExpr = brand.split(',').map(m => `manufacture_name:"${encodeURIComponent(m)}"`).join(' OR ');
parameter.push(`fq={!tag=brand}(${brandExpr})`);
}
if (category) {
- const catExpr = category
- .split(',')
- .map((cat) => `category_name:"${encodeURIComponent(cat)}"`)
- .join(' OR ');
+ const catExpr = category.split(',').map(c => `category_name:"${encodeURIComponent(c)}"`).join(' OR ');
parameter.push(`fq={!tag=cat}(${catExpr})`);
}
if (stock) parameter.push(`fq=stock_total_f:(1 TO *)`);
- if (typeof fq === 'string') parameter.push(`fq=${encodeURIComponent(fq)}`);
-
- if (Array.isArray(fq))
- parameter = parameter.concat(
- fq.map((val) => `fq=${encodeURIComponent(val)}`)
- );
-
- const solrUrl =
- process.env.SOLR_HOST + '/solr/product/select?' + parameter.join('&');
-
- const result = await axios(solrUrl);
+ // SEARCH NORMAL: DEFAULT KE CORE 'PRODUCT'
+ const solrUrl = process.env.SOLR_HOST + '/solr/product/select?' + parameter.join('&');
try {
+ const result = await axios(solrUrl);
result.data.response.products = productMappingSolr(
result.data.response.docs,
auth?.pricelist || false
);
- result.data.responseHeader.params.start = parseInt(
- result.data.responseHeader.params.start
- );
- result.data.responseHeader.params.rows = parseInt(
- result.data.responseHeader.params.rows
- );
+ result.data.responseHeader.params.start = parseInt(result.data.responseHeader.params.start);
+ result.data.responseHeader.params.rows = parseInt(result.data.responseHeader.params.rows);
delete result.data.response.docs;
result.data = camelcaseObjectDeep(result.data);
res.status(200).json(result.data);
@@ -236,17 +223,8 @@ export default async function handler(req, res) {
const escapeSolrQuery = (query) => {
if (query == '*') return query;
-
query = query.replace(/-/g, ' ');
-
const specialChars = /([\+\!\(\)\{\}\[\]\^"~\*\?:\\\/])/g;
const words = query.split(/\s+/);
- const escapedWords = words.map((word) => {
- if (specialChars.test(word)) {
- return word.replace(specialChars, '\\$1');
- }
- return word;
- });
-
- return escapedWords.join(' ');
-};
+ return words.map((word) => specialChars.test(word) ? word.replace(specialChars, '\\$1') : word).join(' ');
+}; \ No newline at end of file