summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/pages/api/shop/search.js36
-rw-r--r--src/pages/api/shop/searchkey.js38
-rw-r--r--src/pages/searchkey/[slug].jsx75
-rw-r--r--src/pages/sitemap/searchkey.xml.js37
-rw-r--r--src/pages/sitemap/searchkey/[page].js42
5 files changed, 228 insertions, 0 deletions
diff --git a/src/pages/api/shop/search.js b/src/pages/api/shop/search.js
index 42d16100..d60b9a46 100644
--- a/src/pages/api/shop/search.js
+++ b/src/pages/api/shop/search.js
@@ -210,6 +210,42 @@ export default async function handler(req, res) {
fq.map((val) => `fq=${encodeURIComponent(val)}`)
);
+ // Searchkey
+ if (req.query.from === 'searchkey') {
+ const ids = req.query.ids ? req.query.ids.split(',').filter(Boolean) : [];
+
+ const q = ids.map((id) => `product_id_i:${id}`).join(' OR ');
+
+ const strictQuery = [
+ `q=${encodeURIComponent(q)}`,
+ `fq=-publish_b:false AND price_tier1_v2_f:[1 TO *] AND product_rating_f:[8 TO *]`,
+ // `qf=variants_code_t variants_name_t`,
+ `rows=${limit}`,
+ `start=${offset}`,
+ ];
+
+ const solrUrl =
+ process.env.SOLR_HOST + '/solr/product/select?' + strictQuery.join('&');
+
+ console.log('[SEARCHKEY FINAL QUERY]', solrUrl);
+
+ const result = await axios(solrUrl);
+
+ try {
+ result.data.response.products = productMappingSolr(
+ result.data.response.docs,
+ auth?.pricelist || false
+ );
+
+ delete result.data.response.docs;
+ result.data = camelcaseObjectDeep(result.data);
+
+ return res.status(200).json(result.data);
+ } catch (e) {
+ return res.status(400).json({ error: e.message });
+ }
+ }
+
const solrUrl =
process.env.SOLR_HOST + '/solr/product/select?' + parameter.join('&');
diff --git a/src/pages/api/shop/searchkey.js b/src/pages/api/shop/searchkey.js
new file mode 100644
index 00000000..2735e72c
--- /dev/null
+++ b/src/pages/api/shop/searchkey.js
@@ -0,0 +1,38 @@
+import axios from 'axios';
+
+export default async function handler(req, res) {
+ const { url = '', page = 1, limit = 30 } = req.query;
+
+ let q = '*:*';
+
+ if (!req.query.all) {
+ const url = (req.query.q || '').trim();
+ q = `keywords_s:"${url}"`;
+ }
+ let offset = (page - 1) * limit;
+
+ const params = [
+ `q.op=AND`,
+ // `q=keywords_s:"${url}"`,
+ `q=${q}`,
+ `indent=true`,
+ `rows=${limit}`,
+ `start=${offset}`,
+ ];
+
+ try {
+ // let result = await axios(
+ // process.env.SOLR_HOST + `/solr/searchkey/select?` + params.join('&')
+ // );
+ let result = await axios.post(
+ process.env.SOLR_HOST + `/solr/searchkey/select`,
+ params.join('&'),
+ { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }
+ );
+
+ console.log(result.data);
+ res.status(200).json(result.data);
+ } catch (error) {
+ res.status(500).json({ error: 'Internal Server Error' });
+ }
+}
diff --git a/src/pages/searchkey/[slug].jsx b/src/pages/searchkey/[slug].jsx
new file mode 100644
index 00000000..3ebf6469
--- /dev/null
+++ b/src/pages/searchkey/[slug].jsx
@@ -0,0 +1,75 @@
+import axios from 'axios';
+import { useRouter } from 'next/router';
+import { useEffect, useState } from 'react';
+import Seo from '@/core/components/Seo';
+import dynamic from 'next/dynamic';
+import { getNameFromSlug } from '@/core/utils/slug';
+import { capitalizeEachWord } from '../../utils/capializeFIrstWord';
+
+const BasicLayout = dynamic(() =>
+ import('@/core/components/layouts/BasicLayout')
+);
+const ProductSearch = dynamic(() =>
+ import('@/lib/product/components/ProductSearch')
+);
+
+export default function FindPage() {
+ const route = useRouter();
+ const [result, setResult] = useState(null);
+ const [query, setQuery] = useState(null);
+
+ const slugRaw = route.query.slug || null;
+ console.log(slugRaw);
+
+ // const cleanKey = slugRaw ? getNameFromSlug(slugRaw) : '';
+ // console.log(cleanKey);
+ const readableSlug = capitalizeEachWord(slugRaw);
+
+ const getSearchKeyData = async (clean) => {
+ try {
+ const res = await axios(
+ `${process.env.NEXT_PUBLIC_SELF_HOST}/api/shop/searchkey?url=${clean}&from=searchkey`
+ );
+
+ setResult(res?.data?.response?.docs?.[0] || null);
+ } catch (e) {
+ console.error('Fetching searchkey failed:', e);
+ }
+ };
+
+ useEffect(() => {
+ if (!route.isReady) return;
+ if (!slugRaw) return;
+
+ getSearchKeyData(slugRaw);
+ }, [route.isReady, slugRaw]);
+
+ useEffect(() => {
+ if (result) {
+ const ids = result.product_ids_is || [];
+
+ setQuery({
+ ids: ids.join(','),
+ from: 'searchkey',
+ });
+ }
+ }, [result]);
+
+ return (
+ <BasicLayout>
+ <Seo
+ title={`Beli ${readableSlug} Original & Harga Terjangkau - indoteknik.com`}
+ description={`Beli ${readableSlug} Kirim Jakarta Surabaya Semarang Makassar Manado Denpasar.`}
+ additionalMetaTags={[
+ {
+ property: 'keywords',
+ content: `Beli ${readableSlug}, harga ${readableSlug}, ${readableSlug} murah`,
+ },
+ ]}
+ canonical={`${process.env.NEXT_PUBLIC_SELF_HOST}${route.asPath}`}
+ />
+
+ {query && <ProductSearch query={query} prefixUrl={route.asPath} />}
+ </BasicLayout>
+ );
+}
diff --git a/src/pages/sitemap/searchkey.xml.js b/src/pages/sitemap/searchkey.xml.js
new file mode 100644
index 00000000..488337d3
--- /dev/null
+++ b/src/pages/sitemap/searchkey.xml.js
@@ -0,0 +1,37 @@
+import productSearchApi from '@/lib/product/api/productSearchApi';
+import { create } from 'xmlbuilder';
+import _ from 'lodash-contrib';
+import axios from 'axios';
+
+export async function getServerSideProps({ res }) {
+ const baseUrl = process.env.SELF_HOST + '/sitemap/searchkey';
+ const limit = 500;
+ const keywords = await axios(
+ `${process.env.NEXT_PUBLIC_SELF_HOST}/api/shop/searchkey?limit=${limit}&all=1`
+ );
+ // console.log(keywords);
+ const pageCount = Math.ceil(keywords.data.response.numFound / limit);
+ const pages = Array.from({ length: pageCount }, (_, i) => i + 1);
+ const sitemapIndex = create('sitemapindex', { encoding: 'UTF-8' }).att(
+ 'xmlns',
+ 'http://www.sitemaps.org/schemas/sitemap/0.9'
+ );
+
+ const date = new Date();
+ // const date = '2025-10-30';
+ pages.forEach((page) => {
+ const sitemap = sitemapIndex.ele('sitemap');
+ sitemap.ele('loc', `${baseUrl}/${page}.xml`);
+ sitemap.ele('lastmod', date.toISOString().slice(0, 10));
+ });
+
+ res.setHeader('Content-Type', 'text/xml');
+ res.write(sitemapIndex.end());
+ res.end();
+
+ return { props: {} };
+}
+
+export default function SitemapProducts() {
+ return null;
+}
diff --git a/src/pages/sitemap/searchkey/[page].js b/src/pages/sitemap/searchkey/[page].js
new file mode 100644
index 00000000..cee53f5e
--- /dev/null
+++ b/src/pages/sitemap/searchkey/[page].js
@@ -0,0 +1,42 @@
+import productSearchApi from '@/lib/product/api/productSearchApi';
+import { create } from 'xmlbuilder';
+import _ from 'lodash-contrib';
+import { createSlug } from '@/core/utils/slug';
+import axios from 'axios';
+
+export async function getServerSideProps({ query, res }) {
+ // const baseUrl = process.env.SELF_HOST + '/shop/product/';
+ const { page } = query;
+ const limit = 500;
+ const keywords = await axios(
+ `${
+ process.env.NEXT_PUBLIC_SELF_HOST
+ }/api/shop/searchkey?limit=${limit}&page=${page.replace('.xml', '')}&all=1`
+ );
+
+ const sitemap = create('urlset', { encoding: 'utf-8' }).att(
+ 'xmlns',
+ 'http://www.sitemaps.org/schemas/sitemap/0.9'
+ );
+
+ const date = new Date();
+ // const date = '2025-10-30';
+ keywords.data.response.docs.forEach((product) => {
+ const url = sitemap.ele('url');
+ const loc = product.url_s;
+ url.ele('loc', loc);
+ url.ele('lastmod', date.toISOString().slice(0, 10));
+ url.ele('changefreq', 'daily');
+ url.ele('priority', '0.8');
+ });
+
+ res.setHeader('Content-Type', 'text/xml');
+ res.write(sitemap.end());
+ res.end();
+
+ return { props: {} };
+}
+
+export default function SitemapProducts() {
+ return null;
+}