summaryrefslogtreecommitdiff
path: root/src/pages
diff options
context:
space:
mode:
authorit-fixcomart <it@fixcomart.co.id>2024-11-28 10:47:43 +0700
committerit-fixcomart <it@fixcomart.co.id>2024-11-28 10:47:43 +0700
commit5bc7a6807847610b190ea9d5046021d2db15afc5 (patch)
treee895b02c65bf97e3c6c970bb8d777922120f4570 /src/pages
parent7ed3fd96322d08bd91434b8ec4dcbc542a610998 (diff)
parent952421c810b53ec4d25ad5ef605bae1bd1d5d616 (diff)
Merge branch 'new-release' into Feature/switch-account
Diffstat (limited to 'src/pages')
-rw-r--r--src/pages/_app.jsx2
-rw-r--r--src/pages/_document.jsx13
-rw-r--r--src/pages/api/banner-section.js44
-rw-r--r--src/pages/api/category-management.js85
-rw-r--r--src/pages/api/flashsale-header.js40
-rw-r--r--src/pages/api/hero-banner.js45
-rw-r--r--src/pages/api/page-content.js43
-rw-r--r--src/pages/api/search-flashsale.js45
-rw-r--r--src/pages/api/shop/brands.js30
-rw-r--r--src/pages/api/shop/preferredBrand.js61
-rw-r--r--src/pages/api/shop/product-detail.js2
-rw-r--r--src/pages/api/shop/search.js49
-rw-r--r--src/pages/api/shop/url-category_brand.js20
-rw-r--r--src/pages/api/shop/variant-detail.js31
-rw-r--r--src/pages/garansi-resmi.jsx13
-rw-r--r--src/pages/index.jsx253
-rw-r--r--src/pages/my/address/[id]/edit.jsx5
-rw-r--r--src/pages/pembayaran-tempo.jsx13
-rw-r--r--src/pages/shop/checkout/[status].jsx22
-rw-r--r--src/pages/shop/find/[slug].jsx69
-rw-r--r--src/pages/shop/product/variant/[slug].jsx7
-rw-r--r--src/pages/sitemap/categories-brand.xml.js35
-rw-r--r--src/pages/sitemap/categories-brand/[page].js43
23 files changed, 783 insertions, 187 deletions
diff --git a/src/pages/_app.jsx b/src/pages/_app.jsx
index bcb41dd6..f52aa5f7 100644
--- a/src/pages/_app.jsx
+++ b/src/pages/_app.jsx
@@ -85,7 +85,7 @@ function MyApp({ Component, pageProps: { session, ...pageProps } }) {
return (
<SessionProvider session={session}>
<ScrollToTop />
-
+
<AnimatePresence>
{animateLoader && (
<motion.div
diff --git a/src/pages/_document.jsx b/src/pages/_document.jsx
index 6af6294f..4b67c3f9 100644
--- a/src/pages/_document.jsx
+++ b/src/pages/_document.jsx
@@ -115,6 +115,19 @@ export default function MyDocument() {
}}
/>
+ <Script
+ async
+ id='gtag-config'
+ strategy='afterInteractive'
+ dangerouslySetInnerHTML={{
+ __html: `
+ gtag('config', 'AW-954540379/fCU8CI3Y8OoZENvClMcD', {
+ 'phone_conversion_number': '(021) 29338828'
+ });
+ `,
+ }}
+ />
+
{/* <Script
id='tawk-script-tag'
strategy='afterInteractive'
diff --git a/src/pages/api/banner-section.js b/src/pages/api/banner-section.js
new file mode 100644
index 00000000..7d7040c0
--- /dev/null
+++ b/src/pages/api/banner-section.js
@@ -0,0 +1,44 @@
+import odooApi from '@/core/api/odooApi';
+import { createClient } from 'redis';
+
+const client = createClient();
+
+client.on('error', (err) => console.error('Redis Client Error', err));
+
+const connectRedis = async () => {
+ if (!client.isOpen) {
+ await client.connect();
+ }
+};
+
+export default async function handler(req, res) {
+ try {
+ await connectRedis();
+ const cacheKey = 'hero-banner';
+ // await client.del(cacheKey);
+ let cachedData = await client.get(cacheKey);
+
+ if (cachedData) {
+ const data = JSON.parse(cachedData);
+ return res.status(200).json({ data });
+ } else {
+ const dataBannerSections = await odooApi(
+ 'GET',
+ '/api/v1/banner?type=home-banner'
+ );
+
+ // Simpan hasil fetch ke Redis dengan masa kadaluarsa 3 hari (259200 detik)
+ await client.set(
+ cacheKey,
+ JSON.stringify(dataBannerSections),
+ 'EX',
+ 259200
+ );
+
+ return res.status(200).json({ data: dataBannerSections });
+ }
+ } catch (error) {
+ console.error('Error interacting with Redis or fetching data:', error);
+ return res.status(500).json({ error: 'Internal Server Error' });
+ }
+}
diff --git a/src/pages/api/category-management.js b/src/pages/api/category-management.js
new file mode 100644
index 00000000..f05d8644
--- /dev/null
+++ b/src/pages/api/category-management.js
@@ -0,0 +1,85 @@
+import { createClient } from 'redis';
+// import { fetchCategoryManagementSolr } from '../../lib/home/api/categoryManagementApi';
+const client = createClient();
+client.on('error', (err) => console.error('Redis Client Error', err));
+
+const connectRedis = async () => {
+ if (!client.isOpen) {
+ await client.connect();
+ }
+};
+
+export default async function handler(req, res) {
+ try {
+ await connectRedis();
+ // await client.del('homepage_categoryDynamic');
+
+ let cachedData;
+ if (req.method === 'GET') {
+ cachedData = await client.get('homepage_categoryDynamic');
+
+ if (!cachedData) {
+ const items = await fetchCategoryManagementSolr();
+ await client.set(
+ 'homepage_categoryDynamic',
+ JSON.stringify(items),
+ 'EX',
+ 259200 // Expiry 3 hari
+ );
+ cachedData = await client.get('homepage_categoryDynamic');
+ }
+ const data = cachedData ? JSON.parse(cachedData) : null;
+ res.status(200).json({ data });
+ } else {
+ res.setHeader('Allow', ['GET']);
+ res.status(405).end(`Method ${req.method} Not Allowed`);
+ }
+ } catch (error) {
+ console.error('Error interacting with Redis:', error);
+ res.status(500).json({ error: 'Error interacting with Redis' });
+ }
+}
+
+const fetchCategoryManagementSolr = async () => {
+ let sort = 'sort=sequence_i asc';
+ try {
+ const response = await fetch(
+ `http://34.101.189.218:8983/solr/category_management/query?q=*:*&q.op=OR&indent=true&${sort}&&rows=20`
+ );
+ if (!response.ok) {
+ throw new Error(`HTTP error! status: ${response.status}`);
+ }
+ const data = await response.json();
+ const promotions = await map(data.response.docs);
+ return promotions;
+ } catch (error) {
+ console.error('Error fetching promotion data:', error);
+ return [];
+ }
+};
+const map = async (promotions) => {
+ return promotions.map((promotion) => {
+ let parsedCategories = promotion.categories.map((category) => {
+ // Parse string JSON utama
+ let parsedCategory = JSON.parse(category);
+
+ // Parse setiap elemen di child_frontend_id_i jika ada
+ if (parsedCategory.child_frontend_id_i) {
+ parsedCategory.child_frontend_id_i =
+ parsedCategory.child_frontend_id_i.map((child) => JSON.parse(child));
+ }
+
+ return parsedCategory;
+ });
+ let productMapped = {
+ id: promotion.id,
+ name: promotion.name_s,
+ image: promotion.image_s,
+ sequence: promotion.sequence_i,
+ numFound: promotion.numFound_i,
+ categories: parsedCategories,
+ category_id: promotion.category_id_i,
+ };
+ return productMapped;
+ });
+};
diff --git a/src/pages/api/flashsale-header.js b/src/pages/api/flashsale-header.js
new file mode 100644
index 00000000..31f8efdd
--- /dev/null
+++ b/src/pages/api/flashsale-header.js
@@ -0,0 +1,40 @@
+import odooApi from '@/core/api/odooApi';
+import { createClient } from 'redis';
+
+const client = createClient();
+
+client.on('error', (err) => console.error('Redis Client Error', err));
+
+const connectRedis = async () => {
+ if (!client.isOpen) {
+ await client.connect();
+ }
+};
+
+export default async function handler(req, res) {
+ try {
+ await connectRedis();
+ const cacheKey = `flashsale_header`;
+ // await client.del(cacheKey);
+ let cachedData = await client.get(cacheKey);
+
+ if (cachedData) {
+ const data = JSON.parse(cachedData);
+ return res.status(200).json({ data });
+ } else {
+ const flashSale = await odooApi('GET', `/api/v1/flashsale/header`);
+
+ await client.set(
+ cacheKey,
+ JSON.stringify(flashSale),
+ 'EX',
+ flashSale.duration
+ );
+ cachedData = await client.get(cacheKey);
+ return res.status(200).json({ data: cachedData });
+ }
+ } catch (error) {
+ console.error('Error interacting with Redis or fetching data:', error);
+ return res.status(500).json({ error: 'Internal Server Error' });
+ }
+}
diff --git a/src/pages/api/hero-banner.js b/src/pages/api/hero-banner.js
new file mode 100644
index 00000000..7a348cfa
--- /dev/null
+++ b/src/pages/api/hero-banner.js
@@ -0,0 +1,45 @@
+import odooApi from '@/core/api/odooApi';
+import { createClient } from 'redis';
+
+const client = createClient();
+
+client.on('error', (err) => console.error('Redis Client Error', err));
+
+const connectRedis = async () => {
+ if (!client.isOpen) {
+ await client.connect();
+ }
+};
+
+export default async function handler(req, res) {
+ const { type } = req.query;
+ try {
+ await connectRedis();
+ const cacheKey = `homepage_bannerSection_${type}`;
+ // await client.del(cacheKey);
+ let cachedData = await client.get(cacheKey);
+
+ if (cachedData) {
+ const data = JSON.parse(cachedData);
+ return res.status(200).json({ data });
+ } else {
+ const dataBannerSections = await odooApi(
+ 'GET',
+ `/api/v1/banner?type=${type}`
+ );
+
+ // Simpan hasil fetch ke Redis dengan masa kadaluarsa 3 hari (259200 detik)
+ await client.set(
+ cacheKey,
+ JSON.stringify(dataBannerSections),
+ 'EX',
+ 259200
+ );
+ cachedData = await client.get(cacheKey);
+ return res.status(200).json({ data: cachedData });
+ }
+ } catch (error) {
+ console.error('Error interacting with Redis or fetching data:', error);
+ return res.status(500).json({ error: 'Internal Server Error' });
+ }
+}
diff --git a/src/pages/api/page-content.js b/src/pages/api/page-content.js
new file mode 100644
index 00000000..a6514505
--- /dev/null
+++ b/src/pages/api/page-content.js
@@ -0,0 +1,43 @@
+import { createClient } from 'redis';
+import { getPageContent } from '~/services/pageContent';
+// import { fetchCategoryManagementSolr } from '../../lib/home/api/categoryManagementApi';
+const client = createClient();
+client.on('error', (err) => console.error('Redis Client Error', err));
+
+const connectRedis = async () => {
+ if (!client.isOpen) {
+ await client.connect();
+ }
+};
+
+export default async function handler(req, res) {
+ const { path } = req.query;
+ try {
+ await connectRedis();
+ // await client.del('onbording-popup');
+
+ let cachedData;
+ if (req.method === 'GET') {
+ cachedData = await client.get(`page-content:${path}`);
+
+ if (!cachedData) {
+ const items = await getPageContent({ path });
+ await client.set(
+ `page-content:${path}`,
+ JSON.stringify(items),
+ 'EX',
+ 604800 // Expiry 1 minggu
+ );
+ cachedData = await client.get(`page-content:${path}`);
+ }
+ const data = cachedData ? JSON.parse(cachedData) : null;
+ res.status(200).json({ data });
+ } else {
+ res.setHeader('Allow', ['GET']);
+ res.status(405).end(`Method ${req.method} Not Allowed`);
+ }
+ } catch (error) {
+ console.error('Error interacting with Redis:', error);
+ res.status(500).json({ error: 'Error interacting with Redis' });
+ }
+}
diff --git a/src/pages/api/search-flashsale.js b/src/pages/api/search-flashsale.js
new file mode 100644
index 00000000..d9e56c83
--- /dev/null
+++ b/src/pages/api/search-flashsale.js
@@ -0,0 +1,45 @@
+import odooApi from '@/core/api/odooApi';
+import { createClient } from 'redis';
+import _ from 'lodash-contrib';
+import axios from 'axios';
+
+const client = createClient();
+
+client.on('error', (err) => console.error('Redis Client Error', err));
+
+const connectRedis = async () => {
+ if (!client.isOpen) {
+ await client.connect();
+ }
+};
+
+export default async function handler(req, res) {
+ const { query, operation, duration } = req.query;
+ try {
+ await connectRedis();
+ const cacheKey = `flashsale_product`;
+ // await client.del(cacheKey);
+ let cachedData = await client.get(cacheKey);
+
+ if (cachedData) {
+ const data = JSON.parse(cachedData);
+ return res.status(200).json({ data });
+ } else {
+ const dataProductSearch = await axios(
+ `${process.env.NEXT_PUBLIC_SELF_HOST}/api/shop/search?${query}&operation=${operation}]`
+ );
+
+ await client.set(
+ cacheKey,
+ JSON.stringify(dataProductSearch.data),
+ 'EX',
+ duration
+ );
+ cachedData = await client.get(cacheKey);
+ return res.status(200).json({ data: cachedData });
+ }
+ } catch (error) {
+ console.error('Error interacting with Redis or fetching data:', error);
+ return res.status(500).json({ error: 'Internal Server Error' });
+ }
+}
diff --git a/src/pages/api/shop/brands.js b/src/pages/api/shop/brands.js
index 9c2824b3..d56e4b13 100644
--- a/src/pages/api/shop/brands.js
+++ b/src/pages/api/shop/brands.js
@@ -1,8 +1,20 @@
import axios from 'axios';
+import { createClient } from 'redis';
const SOLR_HOST = process.env.SOLR_HOST;
+const client = createClient();
+
+client.on('error', (err) => console.error('Redis Client Error', err));
+
+const connectRedis = async () => {
+ if (!client.isOpen) {
+ await client.connect();
+ }
+};
export default async function handler(req, res) {
+ await connectRedis();
+
try {
let params = '*:*';
let sort =
@@ -11,12 +23,12 @@ export default async function handler(req, res) {
if (req.query.params) {
rows = 100;
- switch (req?.query?.params) {
+ switch (req.query.params) {
case 'level_s':
params = 'level_s:prioritas';
break;
case 'search':
- params = `name_s:"${req?.query?.q.toLowerCase()}"`;
+ params = `name_s:"${req.query.q.toLowerCase()}"`;
sort = '';
rows = 1;
break;
@@ -24,11 +36,11 @@ export default async function handler(req, res) {
params = `name_s:${req.query.params}`.toLowerCase();
}
}
- if(req.query.rows) rows = req.query.rows;
-
+ if (req.query.rows) rows = req.query.rows;
+
const url = `${SOLR_HOST}/solr/brands/select?q=${params}&q.op=OR&indent=true&rows=${rows}&${sort}`;
- let brands = await axios(url);
- let dataBrands = responseMap(brands.data.response.docs);
+ const brands = await axios(url);
+ const dataBrands = responseMap(brands.data.response.docs);
res.status(200).json(dataBrands);
} catch (error) {
@@ -39,13 +51,11 @@ export default async function handler(req, res) {
const responseMap = (brands) => {
return brands.map((brand) => {
- let brandMapping = {
+ return {
id: brand.id,
name: brand.display_name_s,
logo: brand.image_s || '',
- sequance: brand.sequence_i || '',
+ sequence: brand.sequence_i || '',
};
-
- return brandMapping;
});
};
diff --git a/src/pages/api/shop/preferredBrand.js b/src/pages/api/shop/preferredBrand.js
new file mode 100644
index 00000000..4cb35c84
--- /dev/null
+++ b/src/pages/api/shop/preferredBrand.js
@@ -0,0 +1,61 @@
+import axios from 'axios';
+import { createClient } from 'redis';
+
+const SOLR_HOST = process.env.SOLR_HOST;
+const client = createClient();
+
+client.on('error', (err) => console.error('Redis Client Error', err));
+
+const connectRedis = async () => {
+ if (!client.isOpen) {
+ await client.connect();
+ }
+};
+
+export default async function handler(req, res) {
+ await connectRedis();
+
+ try {
+ let params = '*:*';
+ let sort =
+ 'sort=if(exists(sequence_i),0,1) asc,sequence_i asc, if(exists(image_s),0,1) asc ';
+ let rows = 20;
+
+ if (req.query.params) {
+ rows = 20;
+ switch (req.query.params) {
+ case 'level_s':
+ params = 'level_s:prioritas';
+ break;
+ case 'search':
+ params = `name_s:"${req.query.q.toLowerCase()}"`;
+ sort = '';
+ rows = 1;
+ break;
+ default:
+ params = `name_s:${req.query.params}`.toLowerCase();
+ }
+ }
+ if (req.query.rows) rows = req.query.rows;
+
+ const url = `${SOLR_HOST}/solr/brands/select?q=${params}&q.op=OR&indent=true&rows=${rows}&${sort}`;
+ const brands = await axios(url);
+ const dataBrands = responseMap(brands.data.response.docs);
+
+ res.status(200).json(dataBrands);
+ } catch (error) {
+ console.error('Error fetching data from Solr:', error);
+ res.status(500).json({ error: 'Internal Server Error' });
+ }
+}
+
+const responseMap = (brands) => {
+ return brands.map((brand) => {
+ return {
+ id: brand.id,
+ name: brand.display_name_s,
+ logo: brand.image_s || '',
+ sequence: brand.sequence_i || '',
+ };
+ });
+};
diff --git a/src/pages/api/shop/product-detail.js b/src/pages/api/shop/product-detail.js
index 247f2a04..faa96028 100644
--- a/src/pages/api/shop/product-detail.js
+++ b/src/pages/api/shop/product-detail.js
@@ -8,7 +8,7 @@ export default async function handler(req, res) {
)
let productVariants = await axios(
process.env.SOLR_HOST +
- `/solr/variants/select?q=template_id_i:${req.query.id}&q.op=OR&indent=true&rows=100&fq=-publish_b:false`
+ `/solr/variants/select?q=template_id_i:${req.query.id}&q.op=OR&indent=true&rows=100&fq=-publish_b:false AND price_tier1_v2_f:[1 TO *]`
)
let auth = req.query.auth === 'false' ? JSON.parse(req.query.auth) : req.query.auth
let result = productMappingSolr(productTemplate.data.response.docs, auth || false)
diff --git a/src/pages/api/shop/search.js b/src/pages/api/shop/search.js
index 6269d3ed..63ec7ca0 100644
--- a/src/pages/api/shop/search.js
+++ b/src/pages/api/shop/search.js
@@ -20,9 +20,11 @@ export default async function handler(req, res) {
} = req.query;
let { stock = '' } = req.query;
-
let paramOrderBy = '';
switch (orderBy) {
+ case 'flashsale-discount-desc':
+ paramOrderBy += 'flashsale_discount_f DESC';
+ break;
case 'price-asc':
paramOrderBy += 'price_tier1_v2_f ASC';
break;
@@ -68,16 +70,40 @@ export default async function handler(req, res) {
let checkQ = q.trim().split(/[\s\+\-\!\(\)\{\}\[\]\^"~\*\?:\\\/]+/);
let newQ = escapeSolrQuery(q);
- const formattedQuery = `(${newQ.split(' ').map(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}*`)) // Tambahkan '*' hanya jika panjang kata >= 2
+ .join(' ')})`;
+
+ const mm =
+ checkQ.length > 2
+ ? checkQ.length > 5
+ ? '55%'
+ : '85%'
+ : `${checkQ.length}`;
const filterQueries = [
'-publish_b:false',
'product_rating_f:[8 TO *]',
- 'price_tier1_v2_f:[1 TO *]'
+ 'price_tier1_v2_f:[1 TO *]',
];
-
- const fq_ = filterQueries.join('AND ');
+
+ if (fq && source != 'similar' && typeof fq != 'string') {
+ // filterQueries.push(fq);
+ fq.push(...filterQueries);
+ }
+ 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 + '*';
+ }
+ } else {
+ keywords = formattedQuery;
+ }
let offset = (page - 1) * limit;
let parameter = [
@@ -87,9 +113,9 @@ export default async function handler(req, res) {
'indent=true',
`facet.query=${escapeSolrQuery(q)}`,
`q.op=OR`,
- `q=${source == 'similar' || checkQ.length < 3 ? checkQ.length < 2 ? newQ : newQ + '*' : formattedQuery }`,
+ `q=${keywords}`,
`defType=edismax`,
- 'qf=name_s description_clean_t category_name manufacture_name_s variants_code_t variants_name_t category_id_ids default_code_s',
+ 'qf=name_s description_clean_t category_name manufacture_name_s variants_code_t variants_name_t category_id_ids default_code_s manufacture_id_i category_id_i ',
`start=${parseInt(offset)}`,
`rows=${limit}`,
`sort=${paramOrderBy}`,
@@ -135,12 +161,13 @@ export default async function handler(req, res) {
if (typeof fq === 'string') parameter.push(`fq=${encodeURIComponent(fq)}`);
// Multi fq in url params
if (Array.isArray(fq))
- parameter = parameter.concat(fq.map((val) => `fq=${encodeURIComponent(val)}`));
-
+ parameter = parameter.concat(
+ fq.map((val) => `fq=${encodeURIComponent(val)}`)
+ );
let result = await axios(
process.env.SOLR_HOST + '/solr/product/select?' + parameter.join('&')
);
-
+
try {
result.data.response.products = productMappingSolr(
result.data.response.docs,
diff --git a/src/pages/api/shop/url-category_brand.js b/src/pages/api/shop/url-category_brand.js
new file mode 100644
index 00000000..160aa166
--- /dev/null
+++ b/src/pages/api/shop/url-category_brand.js
@@ -0,0 +1,20 @@
+import axios from 'axios';
+
+export default async function handler(req, res) {
+ const { url = '', page = 1, limit = 30 } = req.query;
+
+ let offset = (page - 1) * limit;
+
+ const params = [`q.op=AND`, `q=${url ? `"${url}"` : '*'}`, `indent=true`, `rows=${limit}`, `start=${offset}`];
+
+ try {
+ let result = await axios(
+ process.env.SOLR_HOST +
+ `/solr/url_category_brand/select?` +
+ params.join('&')
+ );
+ res.status(200).json(result.data);
+ } catch (error) {
+ res.status(500).json({ error: 'Internal Server Error' });
+ }
+}
diff --git a/src/pages/api/shop/variant-detail.js b/src/pages/api/shop/variant-detail.js
index 08ce75b8..af3525b3 100644
--- a/src/pages/api/shop/variant-detail.js
+++ b/src/pages/api/shop/variant-detail.js
@@ -1,21 +1,28 @@
-import { productMappingSolr, variantsMappingSolr } from '@/utils/solrMapping'
-import axios from 'axios'
+import { productMappingSolr, variantsMappingSolr } from '@/utils/solrMapping';
+import axios from 'axios';
export default async function handler(req, res) {
try {
let productVariants = await axios(
process.env.SOLR_HOST +
`/solr/variants/select?q=id:${req.query.id}&q.op=OR&indent=true`
- )
- let auth = req.query.auth === 'false' ? JSON.parse(req.query.auth) : req.query.auth
+ );
+ let template_id = productVariants.data.response.docs[0].template_id_i;
+ let auth =
+ req.query.auth === 'false' ? JSON.parse(req.query.auth) : req.query.auth;
let productTemplate = await axios(
- process.env.SOLR_HOST + `/solr/product/select?q=id:${req.query.id}&q.op=OR&indent=true`
- )
- let result = variantsMappingSolr(productTemplate.data.response.docs, productVariants.data.response.docs, auth || false)
-
- res.status(200).json(result)
+ process.env.SOLR_HOST +
+ `/solr/product/select?q=id:${template_id}&q.op=OR&indent=true`
+ );
+ let result = variantsMappingSolr(
+ productTemplate.data.response.docs,
+ productVariants.data.response.docs,
+ auth || false
+ );
+
+ res.status(200).json(result);
} catch (error) {
- console.error('Error fetching data from Solr:', error)
- res.status(500).json({ error: 'Internal Server Error' })
+ console.error('Error fetching data from Solr:', error);
+ res.status(500).json({ error: 'Internal Server Error' });
}
-} \ No newline at end of file
+}
diff --git a/src/pages/garansi-resmi.jsx b/src/pages/garansi-resmi.jsx
new file mode 100644
index 00000000..7384a89d
--- /dev/null
+++ b/src/pages/garansi-resmi.jsx
@@ -0,0 +1,13 @@
+import Seo from '@/core/components/Seo'
+import BasicLayout from '@/core/components/layouts/BasicLayout'
+import IframeContent from '@/lib/iframe/components/IframeContent'
+
+export default function GaransiResmi() {
+ return (
+ <BasicLayout>
+ <Seo title='Garansi Resmi - Indoteknik.com' />
+
+ <IframeContent url={`${process.env.NEXT_PUBLIC_ODOO_HOST}/content?url=garansi-resmi`} />
+ </BasicLayout>
+ )
+}
diff --git a/src/pages/index.jsx b/src/pages/index.jsx
index 6077c192..2ec1231a 100644
--- a/src/pages/index.jsx
+++ b/src/pages/index.jsx
@@ -1,21 +1,19 @@
-import dynamic from 'next/dynamic';
-import { useEffect, useRef, useState } from 'react';
import { HeroBannerSkeleton } from '@/components/skeleton/BannerSkeleton';
import { PopularProductSkeleton } from '@/components/skeleton/PopularProductSkeleton';
+import odooApi from '@/core/api/odooApi';
import Seo from '@/core/components/Seo';
import DelayRender from '@/core/components/elements/DelayRender/DelayRender';
import DesktopView from '@/core/components/views/DesktopView';
import MobileView from '@/core/components/views/MobileView';
import { FlashSaleSkeleton } from '@/lib/flashSale/skeleton/FlashSaleSkeleton';
-import PreferredBrandSkeleton from '@/lib/home/components/Skeleton/PreferredBrandSkeleton';
import BannerPromoSkeleton from '@/lib/home/components/Skeleton/BannerPromoSkeleton';
-import PromotinProgram from '@/lib/promotinProgram/components/HomePage';
+import PreferredBrandSkeleton from '@/lib/home/components/Skeleton/PreferredBrandSkeleton';
+import dynamic from 'next/dynamic';
+import { useEffect, useRef, useState } from 'react';
+import { getAuth } from '~/libs/auth';
import PagePopupIformation from '~/modules/popup-information'; // need change to dynamic and ssr : false
import CategoryPilihan from '../lib/home/components/CategoryPilihan';
-import odooApi from '@/core/api/odooApi';
-import { getAuth } from '~/libs/auth';
// import { getAuth } from '~/libs/auth';
-import useProductDetail from '~/modules/product-detail/stores/useProductDetail';
const BasicLayout = dynamic(() =>
import('@/core/components/layouts/BasicLayout'),{ssr: false}
@@ -47,36 +45,38 @@ const FlashSale = dynamic(
}
);
-const ProgramPromotion = dynamic(() =>
- import('@/lib/home/components/PromotionProgram'),
-{
- loading: () => <BannerPromoSkeleton />,
-}
+const ProgramPromotion = dynamic(
+ () => import('@/lib/home/components/PromotionProgram'),
+ {
+ loading: () => <BannerPromoSkeleton />,
+ }
);
const BannerSection = dynamic(() =>
- import('@/lib/home/components/BannerSection'), {ssr: false}
-);
-const CategoryHomeId = dynamic(() =>
- import('@/lib/home/components/CategoryHomeId'), {ssr: false}
+ import('@/lib/home/components/BannerSection')
+);
+const CategoryHomeId = dynamic(
+ () => import('@/lib/home/components/CategoryHomeId'),
+ { ssr: false }
);
const CategoryDynamic = dynamic(() =>
- import('@/lib/home/components/CategoryDynamic'), {ssr: false}
+ import('@/lib/home/components/CategoryDynamic')
);
const CategoryDynamicMobile = dynamic(() =>
-import('@/lib/home/components/CategoryDynamicMobile'), {ssr: false}
+ import('@/lib/home/components/CategoryDynamicMobile')
);
-const CustomerReviews = dynamic(() =>
- import('@/lib/review/components/CustomerReviews'), {ssr: false}
+const CustomerReviews = dynamic(
+ () => import('@/lib/review/components/CustomerReviews'),
+ { ssr: false }
); // need to ssr:false
-const ServiceList = dynamic(() => import('@/lib/home/components/ServiceList'), {ssr: false}); // need to ssr: false
+const ServiceList = dynamic(() => import('@/lib/home/components/ServiceList'), {
+ ssr: false,
+}); // need to ssr: false
-
-
-export default function Home({categoryId}) {
+export default function Home({ categoryId }) {
const bannerRef = useRef(null);
const wrapperRef = useRef(null);
@@ -87,123 +87,110 @@ export default function Home({categoryId}) {
bannerRef.current?.querySelector(':first-child')?.clientHeight + 'px';
};
- useEffect(() => {
- const loadCategories = async () => {
- const getCategories = await odooApi('GET', '/api/v1/category/child?partner_id='+{categoryId})
- if(getCategories){
- setDataCategories(getCategories)
- }
- }
- loadCategories()
- }, [])
-
- const [dataCategories, setDataCategories] = useState([])
return (
<>
- <BasicLayout>
- <Seo
- title='Indoteknik.com: B2B Industrial Supply & Solution'
- description='Temukan pilihan produk B2B Industri &amp; Alat Teknik untuk Perusahaan, UMKM &amp; Pemerintah dengan lengkap, mudah dan transparan.'
- additionalMetaTags={[
- {
- name: 'keywords',
- content: 'indoteknik, indoteknik.com, toko teknik, toko perkakas, jual genset, jual fogging, jual krisbow, harga krisbow, harga alat safety, harga pompa air',
- },
- ]} />
-
- <PagePopupIformation />
-
- <DesktopView>
- <div className='container mx-auto'>
- <div
- className='flex min-h-[400px] h-[460px]'
- ref={wrapperRef}
- onLoad={handleOnLoad}
- >
- <div className='w-2/12'>
- <HeroBannerSecondary />
- </div>
- <div className='w-7/12 px-1' ref={bannerRef}>
- <HeroBanner />
- </div>
- <div className='w-3/12'>
- <DelayRender renderAfter={200}>
- <PopularProduct />
- </DelayRender>
+ <BasicLayout>
+ <Seo
+ title='Indoteknik.com: B2B Industrial Supply & Solution'
+ description='Temukan pilihan produk B2B Industri &amp; Alat Teknik untuk Perusahaan, UMKM &amp; Pemerintah dengan lengkap, mudah dan transparan.'
+ additionalMetaTags={[
+ {
+ name: 'keywords',
+ content:
+ 'indoteknik, indoteknik.com, toko teknik, toko perkakas, jual genset, jual fogging, jual krisbow, harga krisbow, harga alat safety, harga pompa air',
+ },
+ ]}
+ />
+
+ <PagePopupIformation />
+
+ <DesktopView>
+ <div className='container mx-auto'>
+ <div
+ className='flex min-h-[400px] h-[460px]'
+ ref={wrapperRef}
+ onLoad={handleOnLoad}
+ >
+ <div className='w-2/12'>
+ <HeroBannerSecondary />
+ </div>
+ <div className='w-7/12 px-1' ref={bannerRef}>
+ <HeroBanner />
+ </div>
+ <div className='w-3/12'>
+ <DelayRender renderAfter={200}>
+ <PopularProduct />
+ </DelayRender>
+ </div>
</div>
- </div>
- <div className='my-16 flex flex-col gap-y-8'>
- <ServiceList />
- <div id='flashsale'>
- <PreferredBrand />
+ <div className='my-16 flex flex-col gap-y-8'>
+ <ServiceList />
+ <div id='flashsale'>
+ <PreferredBrand />
+ </div>
+ {!auth?.feature?.soApproval && (
+ <>
+ <DelayRender renderAfter={200}>
+ <ProgramPromotion />
+ </DelayRender>
+ <DelayRender renderAfter={200}>
+ <FlashSale />
+ </DelayRender>
+ </>
+ )}
+ {/* <PromotinProgram /> */}
+ <CategoryPilihan />
+ <CategoryDynamic />
+ <CategoryHomeId />
+ <BannerSection />
+ <CustomerReviews />
</div>
+ </div>
+ </DesktopView>
+ <MobileView>
+ <DelayRender renderAfter={200}>
+ <HeroBanner />
+ </DelayRender>
+ <div className='flex flex-col gap-y-4 my-6'>
+ <DelayRender renderAfter={400}>
+ <ServiceList />
+ </DelayRender>
+ <DelayRender renderAfter={400}>
+ <div id='flashsale'>
+ <PreferredBrand />
+ </div>
+ </DelayRender>
{!auth?.feature?.soApproval && (
<>
- <DelayRender renderAfter={200}>
- <ProgramPromotion />
- </DelayRender>
- <DelayRender renderAfter={200}>
- <FlashSale />
- </DelayRender>
+ <DelayRender renderAfter={400}>
+ <ProgramPromotion />
+ </DelayRender>
+ <DelayRender renderAfter={600}>
+ <FlashSale />
+ </DelayRender>
</>
)}
- {/* <PromotinProgram /> */}
- {dataCategories &&(
- <CategoryPilihan categories={dataCategories} />
- )}
- <CategoryDynamic />
- <CategoryHomeId />
- <BannerSection />
- <CustomerReviews />
+ <DelayRender renderAfter={600}>
+ {/* <PromotinProgram /> */}
+ </DelayRender>
+ <DelayRender renderAfter={600}>
+ <CategoryPilihan />
+ <CategoryDynamicMobile />
+ </DelayRender>
+ <DelayRender renderAfter={800}>
+ <PopularProduct />
+ </DelayRender>
+ <DelayRender renderAfter={1000}>
+ <CategoryHomeId />
+ <BannerSection />
+ </DelayRender>
+ <DelayRender renderAfter={1200}>
+ <CustomerReviews />
+ </DelayRender>
</div>
- </div>
- </DesktopView>
- <MobileView>
- <DelayRender renderAfter={200}>
- <HeroBanner />
- </DelayRender>
- <div className='flex flex-col gap-y-4 my-6'>
- <DelayRender renderAfter={400}>
- <ServiceList />
- </DelayRender>
- <DelayRender renderAfter={400}>
- <div id='flashsale'>
- <PreferredBrand />
- </div>
- </DelayRender>
- {!auth?.feature?.soApproval && (
- <>
- <DelayRender renderAfter={400}>
- <ProgramPromotion />
- </DelayRender>
- <DelayRender renderAfter={600}>
- <FlashSale />
- </DelayRender>
- </>
- )}
- <DelayRender renderAfter={600}>
- {/* <PromotinProgram /> */}
- </DelayRender>
- <DelayRender renderAfter={600}>
- {dataCategories &&(
- <CategoryPilihan categories={dataCategories} />
- )}
- <CategoryDynamicMobile />
- </DelayRender>
- <DelayRender renderAfter={800}>
- <PopularProduct />
- </DelayRender>
- <DelayRender renderAfter={1000}>
- <CategoryHomeId />
- <BannerSection />
- </DelayRender>
- <DelayRender renderAfter={1200}>
- <CustomerReviews />
- </DelayRender>
- </div>
- </MobileView>
- </BasicLayout>
- </>
+ </MobileView>
+ </BasicLayout>
+ </>
);
-} \ No newline at end of file
+}
diff --git a/src/pages/my/address/[id]/edit.jsx b/src/pages/my/address/[id]/edit.jsx
index c552659b..19d7af41 100644
--- a/src/pages/my/address/[id]/edit.jsx
+++ b/src/pages/my/address/[id]/edit.jsx
@@ -37,12 +37,15 @@ export async function getServerSideProps(context) {
mobile: address.mobile,
street: address.street,
zip: address.zip,
- city: address.city?.id || '',
+ state: address.stateId?.id || '',
+ oldCity: address.city?.id || '',
+ city: '',
oldDistrict: address.district?.id || '',
district: '',
oldSubDistrict: address.subDistrict?.id || '',
subDistrict: '',
business_name: '',
};
+ // console.log('ini default',defaultValues);
return { props: { id, defaultValues } };
}
diff --git a/src/pages/pembayaran-tempo.jsx b/src/pages/pembayaran-tempo.jsx
new file mode 100644
index 00000000..363e3099
--- /dev/null
+++ b/src/pages/pembayaran-tempo.jsx
@@ -0,0 +1,13 @@
+import Seo from '@/core/components/Seo'
+import BasicLayout from '@/core/components/layouts/BasicLayout'
+import IframeContent from '@/lib/iframe/components/IframeContent'
+
+export default function PembnayaranTempo() {
+ return (
+ <BasicLayout>
+ <Seo title='Pambayaran Tempo - Indoteknik.com' />
+
+ <IframeContent url={`${process.env.NEXT_PUBLIC_ODOO_HOST}/content?url=pembayaran-tempo`} />
+ </BasicLayout>
+ )
+}
diff --git a/src/pages/shop/checkout/[status].jsx b/src/pages/shop/checkout/[status].jsx
index 2c3bebcf..0d5cffe8 100644
--- a/src/pages/shop/checkout/[status].jsx
+++ b/src/pages/shop/checkout/[status].jsx
@@ -1,22 +1,22 @@
-import BasicLayout from '@/core/components/layouts/BasicLayout'
-import IsAuth from '@/lib/auth/components/IsAuth'
-import FinishCheckoutComponent from '@/lib/checkout/components/FinishCheckout'
-import { useRouter } from 'next/router'
-import axios from 'axios'
-import Seo from '@/core/components/Seo'
+import BasicLayout from '@/core/components/layouts/BasicLayout';
+import IsAuth from '@/lib/auth/components/IsAuth';
+import FinishCheckoutComponent from '@/lib/checkout/components/FinishCheckout';
+import { useRouter } from 'next/router';
+import axios from 'axios';
+import Seo from '@/core/components/Seo';
export async function getServerSideProps(context) {
- const { order_id } = context.query
+ const { order_id } = context.query;
await axios.post(
`${process.env.NEXT_PUBLIC_SELF_HOST}/api/shop/finish-checkout?orderName=${order_id}`,
{},
{ headers: context.req.headers }
- )
- return { props: {} }
+ );
+ return { props: {} };
}
export default function Finish() {
- const router = useRouter()
+ const router = useRouter();
return (
<>
@@ -28,5 +28,5 @@ export default function Finish() {
</BasicLayout>
</IsAuth>
</>
- )
+ );
}
diff --git a/src/pages/shop/find/[slug].jsx b/src/pages/shop/find/[slug].jsx
new file mode 100644
index 00000000..268b1e56
--- /dev/null
+++ b/src/pages/shop/find/[slug].jsx
@@ -0,0 +1,69 @@
+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 { get } from 'lodash-contrib';
+import { getIdFromSlug, 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')
+);
+
+const BASE_URL = 'https://indoteknik.com';
+export default function FindPage() {
+ const route = useRouter();
+ const qSlug = route?.query?.slug || null;
+ const url = BASE_URL + route.asPath.split('?')[0];
+ const [result, setResult] = useState(null);
+ const [query, setQuery] = useState(null);
+
+ const __slug = qSlug ? getNameFromSlug(route?.query?.slug) +' '+ getIdFromSlug(route?.query?.slug) : '';
+ const slug = capitalizeEachWord(__slug);
+
+ const getUrls = async (url) => {
+ try {
+ let response = await axios(
+ `${process.env.NEXT_PUBLIC_SELF_HOST}/api/shop/url-category_brand?url=${url}`
+ );
+ let result = response?.data?.response?.docs[0] || null;
+ setResult(result);
+ } catch (error) {
+ console.error('Error fetching data:', error);
+ }
+ };
+
+ useEffect(() => {
+ getUrls(url);
+ }, []);
+
+ useEffect(() => {
+ if (result) {
+ let fq = `category_parent_ids:${result.category_id_i} AND manufacture_id_i:${result.brand_id_i}`;
+ setQuery({
+ fq: fq,
+ });
+ }
+ }, [result]);
+
+ return (
+ <BasicLayout>
+ <Seo
+ title={`Beli ${slug} Original & Harga Terjangkau - indoteknik.com`}
+ description={`Beli ${slug} Kirim Jakarta Surabaya Semarang Makassar Manado Denpasar Balikpapan Medan Palembang Lampung Bali Bandung Makassar Manado.`}
+ additionalMetaTags={[
+ {
+ property: 'keywords',
+ content: `Beli ${slug}, harga ${slug}, ${slug} murah, toko ${slug}, ${slug} jakarta, ${slug} surabaya`,
+
+ },
+ ]}
+ />
+ {query && <ProductSearch query={query} prefixUrl={`${route.asPath}`} />}
+ </BasicLayout>
+ );
+}
diff --git a/src/pages/shop/product/variant/[slug].jsx b/src/pages/shop/product/variant/[slug].jsx
index 42f38774..2c0dd64b 100644
--- a/src/pages/shop/product/variant/[slug].jsx
+++ b/src/pages/shop/product/variant/[slug].jsx
@@ -32,16 +32,9 @@ export async function getServerSideProps(context) {
tier
);
let product = response.data;
- // let product = await variantApi({ id: getIdFromSlug(slug), headers: { Token: authToken } })
if (product?.length == 1) {
product = product[0];
- /* const regexHtmlTags = /(<([^>]+)>)/gi
- const regexHtmlTagsExceptP = /<\/?(?!p\b)[^>]*>/g
- product.description = product.description
- .replace(regexHtmlTagsExceptP, ' ')
- .replace(regexHtmlTags, ' ')
- .trim()*/
} else {
product = null;
}
diff --git a/src/pages/sitemap/categories-brand.xml.js b/src/pages/sitemap/categories-brand.xml.js
new file mode 100644
index 00000000..b23363e9
--- /dev/null
+++ b/src/pages/sitemap/categories-brand.xml.js
@@ -0,0 +1,35 @@
+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/categories-brand'
+ const limit = 500
+ const categories = await axios(
+ `${process.env.NEXT_PUBLIC_SELF_HOST}/api/shop/url-category_brand?limit=${limit}`
+ )
+ const pageCount = Math.ceil(categories.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()
+ 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/categories-brand/[page].js b/src/pages/sitemap/categories-brand/[page].js
new file mode 100644
index 00000000..6b55e426
--- /dev/null
+++ b/src/pages/sitemap/categories-brand/[page].js
@@ -0,0 +1,43 @@
+
+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 categories = await axios(
+ `${process.env.NEXT_PUBLIC_SELF_HOST}/api/shop/url-category_brand?limit=${limit}&page=${page.replace(
+ '.xml',
+ ''
+ )}`
+ )
+
+ const sitemap = create('urlset', { encoding: 'utf-8' }).att(
+ 'xmlns',
+ 'http://www.sitemaps.org/schemas/sitemap/0.9'
+ )
+
+ const date = new Date()
+ categories.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
+}