summaryrefslogtreecommitdiff
path: root/src/pages
diff options
context:
space:
mode:
authorit-fixcomart <it@fixcomart.co.id>2024-09-25 14:07:26 +0700
committerit-fixcomart <it@fixcomart.co.id>2024-09-25 14:07:26 +0700
commite7313b4d7006bed37a408d26f15028892839b73a (patch)
treed0d6c9455ca6aac305efc094639dd6886b34fb14 /src/pages
parentd1c0e083ac8f64dfaa8505fc11e30728dbd5a58d (diff)
parente8f640d3fd4984fe5854c2faf7ead9b3b5aebbf2 (diff)
Merge branch 'new-release' into bug-product
Diffstat (limited to 'src/pages')
-rw-r--r--src/pages/_document.jsx8
-rw-r--r--src/pages/api/activation-request.js26
-rw-r--r--src/pages/api/shop/brands.js2
-rw-r--r--src/pages/api/shop/finish-checkout.js84
-rw-r--r--src/pages/api/shop/product-homepage.js3
-rw-r--r--src/pages/api/shop/promo.js204
-rw-r--r--src/pages/api/shop/search.js57
-rw-r--r--src/pages/google_merchant/products/[page].js4
-rw-r--r--src/pages/index.jsx77
-rw-r--r--src/pages/login.jsx12
-rw-r--r--src/pages/my/address/[id]/edit.jsx29
-rw-r--r--src/pages/my/profile.jsx69
-rw-r--r--src/pages/shop/brands/[slug].jsx7
-rw-r--r--src/pages/shop/category/[slug].jsx9
-rw-r--r--src/pages/shop/lob/[slug].jsx48
-rw-r--r--src/pages/shop/product/variant/[slug].jsx2
-rw-r--r--src/pages/shop/promo/[slug].jsx394
-rw-r--r--src/pages/shop/promo/[slug].tsx523
-rw-r--r--src/pages/sitemap/brands.xml.js4
-rw-r--r--src/pages/sitemap/products/[page].js2
-rw-r--r--src/pages/tracking-order.jsx27
21 files changed, 923 insertions, 668 deletions
diff --git a/src/pages/_document.jsx b/src/pages/_document.jsx
index cd60bd89..6af6294f 100644
--- a/src/pages/_document.jsx
+++ b/src/pages/_document.jsx
@@ -41,13 +41,13 @@ export default function MyDocument() {
content='328wmjs7hcnz74rwsqzxvq50rmbtm2'
/>
- <Script
+ {/* <Script
async
strategy='beforeInteractive'
src='https://www.googletagmanager.com/gtag/js?id=UA-10501937-1'
- />
+ /> */}
- <Script
+ {/* <Script
async
id='google-analytics-ua'
strategy='beforeInteractive'
@@ -59,7 +59,7 @@ export default function MyDocument() {
gtag('config', 'UA-10501937-1');
`,
}}
- />
+ /> */}
<Script
async
diff --git a/src/pages/api/activation-request.js b/src/pages/api/activation-request.js
index 61dbb597..2b8ccec3 100644
--- a/src/pages/api/activation-request.js
+++ b/src/pages/api/activation-request.js
@@ -1,27 +1,29 @@
-import odooApi from '@/core/api/odooApi'
-import mailer from '@/core/utils/mailer'
+import odooApi from '@/core/api/odooApi';
+import mailer from '@/core/utils/mailer';
export default async function handler(req, res) {
try {
- const { email } = req.body
- let result = await odooApi('POST', '/api/v1/user/activation-request', { email })
+ const { email } = req.body;
+ let result = await odooApi('POST', '/api/v1/user/activation-request', {
+ email,
+ });
if (result.activationRequest) {
mailer.sendMail({
- from: 'sales@indoteknik.com',
+ from: 'noreply@indoteknik.com',
to: result.user.email,
subject: 'Permintaan Aktivasi Akun Indoteknik',
html: `
<h1>Permintaan Aktivasi Akun Indoteknik</h1>
<br>
<p>Aktivasi akun anda melalui link berikut: <a href="${process.env.NEXT_PUBLIC_SELF_HOST}/activate?token=${result.token}">Aktivasi Akun</a></p>
- `
- })
+ `,
+ });
}
- delete result.user
- delete result.token
- res.status(200).json(result)
+ delete result.user;
+ delete result.token;
+ res.status(200).json(result);
} catch (error) {
- console.log(error)
- res.status(400).json({ error: error.message })
+ console.log(error);
+ res.status(400).json({ error: error.message });
}
}
diff --git a/src/pages/api/shop/brands.js b/src/pages/api/shop/brands.js
index cc64a7e7..9c2824b3 100644
--- a/src/pages/api/shop/brands.js
+++ b/src/pages/api/shop/brands.js
@@ -24,6 +24,8 @@ export default async function handler(req, res) {
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}`;
let brands = await axios(url);
let dataBrands = responseMap(brands.data.response.docs);
diff --git a/src/pages/api/shop/finish-checkout.js b/src/pages/api/shop/finish-checkout.js
index 9eaa36db..4dcc915c 100644
--- a/src/pages/api/shop/finish-checkout.js
+++ b/src/pages/api/shop/finish-checkout.js
@@ -1,60 +1,66 @@
-import odooApi from '@/core/api/odooApi'
-import mailer from '@/core/utils/mailer'
-import FinishCheckoutEmail from '@/lib/checkout/email/FinishCheckoutEmail'
-import { render } from '@react-email/render'
-import axios from 'axios'
-import camelcaseObjectDeep from 'camelcase-object-deep'
+import odooApi from '@/core/api/odooApi';
+import mailer from '@/core/utils/mailer';
+import FinishCheckoutEmail from '@/lib/checkout/email/FinishCheckoutEmail';
+import { render } from '@react-email/render';
+import axios from 'axios';
+import camelcaseObjectDeep from 'camelcase-object-deep';
export default async function handler(req, res) {
- const { orderName = null } = req.query
+ const { orderName = null } = req.query;
if (!orderName) {
- return res.status(422).json({ error: 'parameter missing' })
+ return res.status(422).json({ error: 'parameter missing' });
}
- let { auth } = req.cookies
+ let { auth } = req.cookies;
if (!auth) {
- return res.status(401).json({ error: 'Unauthorized' })
+ return res.status(401).json({ error: 'Unauthorized' });
}
- auth = JSON.parse(auth)
+ auth = JSON.parse(auth);
- const midtransAuthKey = btoa(process.env.MIDTRANS_SERVER_KEY + ':')
+ const midtransAuthKey = btoa(process.env.MIDTRANS_SERVER_KEY + ':');
const midtransHeaders = {
Accept: 'application/json',
'Content-Type': 'application/json',
- Authorization: `Basic ${midtransAuthKey}`
- }
- let midtransStatus = {}
+ Authorization: `Basic ${midtransAuthKey}`,
+ };
+ let midtransStatus = {};
try {
- midtransStatus = await axios.get(`${process.env.MIDTRANS_HOST}/v2/${orderName}/status`, {
- headers: midtransHeaders
- })
- midtransStatus = camelcaseObjectDeep(midtransStatus.data)
+ midtransStatus = await axios.get(
+ `${process.env.MIDTRANS_HOST}/v2/${orderName}/status`,
+ {
+ headers: midtransHeaders,
+ }
+ );
+ midtransStatus = camelcaseObjectDeep(midtransStatus.data);
} catch (error) {
- console.log(error)
+ console.log(error);
}
- let statusPayment = 'manual'
+ let statusPayment = 'manual';
if (midtransStatus?.orderId) {
- const transactionStatus = midtransStatus.transactionStatus
- statusPayment = 'failed'
+ const transactionStatus = midtransStatus.transactionStatus;
+ statusPayment = 'failed';
if (['capture', 'settlement'].includes(transactionStatus)) {
- statusPayment = 'success'
+ statusPayment = 'success';
} else if (transactionStatus == 'pending') {
- statusPayment = 'pending'
+ statusPayment = 'pending';
}
}
- const query = `name=${orderName.replaceAll('-', '/')}&limit=1&context=quotation`
+ const query = `name=${orderName.replaceAll(
+ '-',
+ '/'
+ )}&limit=1&context=quotation`;
const searchTransaction = await odooApi(
'GET',
`/api/v1/partner/${auth.partnerId}/sale_order?${query}`,
{},
{ Token: auth.token }
- )
+ );
if (searchTransaction.saleOrderTotal == 0) {
- return res.status(400).json({ error: 'Transaction Not Found' })
+ return res.status(400).json({ error: 'Transaction Not Found' });
}
let transaction = await odooApi(
@@ -62,17 +68,17 @@ export default async function handler(req, res) {
`/api/v1/partner/${auth.partnerId}/sale_order/${searchTransaction.saleOrders[0].id}`,
{},
{ Token: auth.token }
- )
+ );
if (!transaction?.id) {
- return res.status(400).json({ error: 'Transaction Detail Not Found' })
+ return res.status(400).json({ error: 'Transaction Detail Not Found' });
}
- transaction.subtotal = 0
- transaction.discountTotal = 0
+ transaction.subtotal = 0;
+ transaction.discountTotal = 0;
for (const product of transaction.products) {
- transaction.subtotal += product.price.price * product.quantity
+ transaction.subtotal += product.price.price * product.quantity;
transaction.discountTotal -=
- (product.price.price - product.price.priceDiscount) * product.quantity
+ (product.price.price - product.price.priceDiscount) * product.quantity;
}
const emailMessage = render(
@@ -81,14 +87,14 @@ export default async function handler(req, res) {
payment={midtransStatus}
statusPayment={statusPayment}
/>
- )
+ );
mailer.sendMail({
- from: 'sales@indoteknik.com',
+ from: 'noreply@indoteknik.com',
to: transaction.address.customer.email,
subject: 'Pembelian di Indoteknik.com',
- html: emailMessage
- })
+ html: emailMessage,
+ });
- return res.status(200).json({ description: 'success' })
+ return res.status(200).json({ description: 'success' });
}
diff --git a/src/pages/api/shop/product-homepage.js b/src/pages/api/shop/product-homepage.js
index 02c01ee0..61732c77 100644
--- a/src/pages/api/shop/product-homepage.js
+++ b/src/pages/api/shop/product-homepage.js
@@ -36,7 +36,8 @@ const respoonseMap = (productHomepage, products) => {
name: productHomepage.name_s,
image: productHomepage.image_s,
url: productHomepage.url_s,
- products: products
+ products: products,
+ categoryIds: productHomepage.category_id_ids,
}
return productMapped
diff --git a/src/pages/api/shop/promo.js b/src/pages/api/shop/promo.js
new file mode 100644
index 00000000..f90c8559
--- /dev/null
+++ b/src/pages/api/shop/promo.js
@@ -0,0 +1,204 @@
+import { productMappingSolr, promoMappingSolr } from '@/utils/solrMapping';
+import axios from 'axios';
+import camelcaseObjectDeep from 'camelcase-object-deep';
+
+export default async function handler(req, res) {
+ const {
+ q = '*',
+ page = 1,
+ brand = '',
+ category = '',
+ priceFrom = 0,
+ priceTo = 0,
+ orderBy = 'if(exists(sequence_i),0,1) asc, sequence_i asc,',
+ operation = 'AND',
+ fq = '',
+ limit = 30,
+ } = req.query;
+
+ let { stock = '' } = req.query;
+
+ let paramOrderBy = 'if(exists(sequence_i),0,1) asc, sequence_i asc,';
+ switch (orderBy) {
+ 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 = checkQ.length > 1 ? escapeSolrQuery(q) + '*' : escapeSolrQuery(q);
+
+ let offset = (page - 1) * limit;
+ let parameter = [
+ 'facet.field=manufacture_name_s',
+ 'facet.field=category_name',
+ 'facet=true',
+ 'indent=true',
+ `facet.limit=-1`,
+ // `facet.query=${escapeSolrQuery(q)}`,
+ `q.op=${operation}`,
+ `q=${q}`,
+ // 'qf=name_s',
+ `start=${parseInt(offset)}`,
+ `rows=${limit}`,
+ `sort=${paramOrderBy}`,
+ `fq=product_ids:[* TO *]`,
+ `fq=active_b:true`,
+ ];
+
+ if (priceFrom > 0 || priceTo > 0) {
+ parameter.push(
+ `fq=price_tier1_v2_f:[${priceFrom == '' ? '*' : priceFrom} TO ${
+ priceTo == '' ? '*' : priceTo
+ }]`
+ );
+ }
+
+ let { auth } = req.cookies;
+ if (auth) {
+ auth = JSON.parse(auth);
+ if (auth.feature.onlyReadyStock) stock = true;
+ }
+
+ if (brand)
+ parameter.push(
+ `fq=${brand
+ .split(',')
+ .map(
+ (manufacturer) =>
+ `manufacture_name_s:"${encodeURIComponent(manufacturer)}"`
+ )
+ .join(' OR ')}`
+ );
+ if (category)
+ parameter.push(
+ `fq=${category
+ .split(',')
+ .map((cat) => `category_name:"${encodeURIComponent(cat)}"`)
+ .join(' OR ')}`
+ );
+ // if (category) parameter.push(`fq=category_name:${capitalizeFirstLetter(category.replace(/,/g, ' OR '))}`)
+ if (stock) parameter.push(`fq=stock_total_f:{1 TO *}`);
+
+ // Single fq in url params
+ if (typeof fq === 'string') parameter.push(`fq=${fq}`);
+ // Multi fq in url params
+ if (Array.isArray(fq))
+ parameter = parameter.concat(fq.map((val) => `fq=${val}`));
+
+ let result = await axios(
+ process.env.SOLR_HOST + '/solr/promotion_program_lines/select?' + parameter.join('&')
+ );
+ try {
+ result.data.response.products = promoMappingSolr(
+ result.data.response.docs
+ );
+
+ 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);
+ result.data = result.data;
+ res.status(200).json(result.data);
+ } catch (error) {
+ res.status(400).json({ error: error.message });
+ }
+}
+
+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(' ');
+};
+
+
+/*const productResponseMap = (products, pricelist) => {
+ return products.map((product) => {
+ let price = product.price_tier1_v2_f || 0
+ let priceDiscount = product.price_discount_f || 0
+ let discountPercentage = product.discount_f || 0
+
+ if (pricelist) {
+ // const pricelistDiscount = product?.[`price_${pricelist}_f`] || false
+ // const pricelistDiscountPerc = product?.[`discount_${pricelist}_f`] || false
+
+ // if (pricelistDiscount && pricelistDiscount > 0) priceDiscount = pricelistDiscount
+ // if (pricelistDiscountPerc && pricelistDiscountPerc > 0)
+ // discountPercentage = pricelistDiscountPerc
+
+ price = product?.[`price_${pricelist}_f`] || 0
+ }
+
+ if (product?.flashsale_id_i > 0) {
+ price = product?.flashsale_base_price_f || 0
+ priceDiscount = product?.flashsale_price_f || 0
+ discountPercentage = product?.flashsale_discount_f || 0
+ }
+
+ let productMapped = {
+ id: product.product_id_i || '',
+ image: product.image_s || '',
+ code: product.default_code_s || '',
+ name: product.name_s || '',
+ lowestPrice: { price, priceDiscount, discountPercentage },
+ variantTotal: product.variant_total_i || 0,
+ stockTotal: product.stock_total_f || 0,
+ weight: product.weight_f || 0,
+ manufacture: {},
+ categories: [],
+ flashSale: {
+ id: product?.flashsale_id_i,
+ name: product?.product?.flashsale_name_s,
+ tag : product?.flashsale_tag_s || 'FLASH SALE'
+ }
+ }
+
+ if (product.manufacture_id_i && product.manufacture_name_s) {
+ productMapped.manufacture = {
+ id: product.manufacture_id_i || '',
+ name: product.manufacture_name_s || ''
+ }
+ }
+
+ productMapped.categories = [
+ {
+ id: product.category_id_i || '',
+ name: product.category_name_s || ''
+ }
+ ]
+ return productMapped
+ })
+}*/
diff --git a/src/pages/api/shop/search.js b/src/pages/api/shop/search.js
index 6f98efcb..6269d3ed 100644
--- a/src/pages/api/shop/search.js
+++ b/src/pages/api/shop/search.js
@@ -1,6 +1,8 @@
import { productMappingSolr } from '@/utils/solrMapping';
import axios from 'axios';
import camelcaseObjectDeep from 'camelcase-object-deep';
+import searchSuggestApi from '@/core/api/searchSuggestApi';
+import { ECDH } from 'crypto';
export default async function handler(req, res) {
const {
@@ -14,6 +16,7 @@ export default async function handler(req, res) {
operation = 'AND',
fq = '',
limit = 30,
+ source = '',
} = req.query;
let { stock = '' } = req.query;
@@ -42,10 +45,40 @@ export default async function handler(req, res) {
paramOrderBy += '';
break;
}
-
+
+ // let suggestWord = null;
+ // let keywords = q;
+ // let checkQ = null;
+
+ // if (q != '*') {
+ // checkQ = q.trim().split(/[\s\+\-\!\(\)\{\}\[\]\^"~\*\?:\\\/]+/);
+ // if (checkQ.length > 1) {
+ // const dataSearchSuggest = await axios(
+ // `${process.env.NEXT_PUBLIC_SELF_HOST}/api/shop/suggest?q=${checkQ[1]}`
+ // );
+ // suggestWord = dataSearchSuggest.data.suggestions[0];
+ // }
+ // if (suggestWord && suggestWord?.term.split(' ').length <= 1) {
+ // keywords = `"${escapeSolrQuery(checkQ[0] + ' ' + suggestWord?.term)}"`;
+ // }
+ // }
+
+ // let newQ = keywords;
+
let checkQ = q.trim().split(/[\s\+\-\!\(\)\{\}\[\]\^"~\*\?:\\\/]+/);
- let newQ = checkQ.length > 1 ? escapeSolrQuery(q) + '*' : escapeSolrQuery(q);
+ 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 filterQueries = [
+ '-publish_b:false',
+ 'product_rating_f:[8 TO *]',
+ 'price_tier1_v2_f:[1 TO *]'
+ ];
+ const fq_ = filterQueries.join('AND ');
+
let offset = (page - 1) * limit;
let parameter = [
'facet.field=manufacture_name_s',
@@ -53,13 +86,15 @@ export default async function handler(req, res) {
'facet=true',
'indent=true',
`facet.query=${escapeSolrQuery(q)}`,
- `q.op=${operation}`,
- `q=${newQ}`,
- 'qf=name_s',
+ `q.op=OR`,
+ `q=${source == 'similar' || checkQ.length < 3 ? checkQ.length < 2 ? newQ : newQ + '*' : formattedQuery }`,
+ `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',
`start=${parseInt(offset)}`,
`rows=${limit}`,
`sort=${paramOrderBy}`,
- `fq=-publish_b:false, product_rating_f:[8 TO *], price_tier1_v2_f:[1 TO *]`,
+ `fq=${encodeURIComponent(fq_)}`,
+ `mm=${encodeURIComponent(mm)}`,
];
if (priceFrom > 0 || priceTo > 0) {
@@ -97,14 +132,15 @@ export default async function handler(req, res) {
if (stock) parameter.push(`fq=stock_total_f:{1 TO *}`);
// Single fq in url params
- if (typeof fq === 'string') parameter.push(`fq=${fq}`);
+ 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=${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,
@@ -126,7 +162,7 @@ export default async function handler(req, res) {
const escapeSolrQuery = (query) => {
if (query == '*') return query;
-
+
query = query.replace(/-/g, ' ');
const specialChars = /([\+\!\(\)\{\}\[\]\^"~\*\?:\\\/])/g;
@@ -141,7 +177,6 @@ const escapeSolrQuery = (query) => {
return escapedWords.join(' ');
};
-
/*const productResponseMap = (products, pricelist) => {
return products.map((product) => {
let price = product.price_tier1_v2_f || 0
diff --git a/src/pages/google_merchant/products/[page].js b/src/pages/google_merchant/products/[page].js
index 6e0eb703..0c2cf3c5 100644
--- a/src/pages/google_merchant/products/[page].js
+++ b/src/pages/google_merchant/products/[page].js
@@ -50,7 +50,7 @@ export async function getServerSideProps({ res, query }) {
let categoryId = null;
if (brandId && brandId in brandsData) {
- categoryId = brandsData[brandId].category_ids?.[0] ?? null;
+ categoryId = brandsData[brandId]?.category_ids?.[0] ?? null;
} else {
const solrBrand = await getBrandById(brandId);
brandsData[brandId] = solrBrand;
@@ -58,7 +58,7 @@ export async function getServerSideProps({ res, query }) {
}
if (categoryId && categoryId in categoriesData) {
- categoryName = categoriesData[categoryId].name_s ?? null;
+ categoryName = categoriesData[categoryId]?.name_s ?? null;
} else {
const solrCategory = await getCategoryById(categoryId);
categoriesData[categoryId] = solrCategory;
diff --git a/src/pages/index.jsx b/src/pages/index.jsx
index 4493fe31..6077c192 100644
--- a/src/pages/index.jsx
+++ b/src/pages/index.jsx
@@ -1,6 +1,5 @@
import dynamic from 'next/dynamic';
-import { useRef } from 'react';
-
+import { useEffect, useRef, useState } from 'react';
import { HeroBannerSkeleton } from '@/components/skeleton/BannerSkeleton';
import { PopularProductSkeleton } from '@/components/skeleton/PopularProductSkeleton';
import Seo from '@/core/components/Seo';
@@ -11,12 +10,15 @@ 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 PagePopupIformation from '~/modules/popup-information';
-import useProductDetail from '~/modules/product-detail/stores/useProductDetail';
+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')
+ import('@/core/components/layouts/BasicLayout'),{ssr: false}
);
const HeroBanner = dynamic(() => import('@/components/ui/HeroBanner'), {
loading: () => <HeroBannerSkeleton />,
@@ -53,17 +55,28 @@ const ProgramPromotion = dynamic(() =>
);
const BannerSection = dynamic(() =>
- import('@/lib/home/components/BannerSection')
-);
+ import('@/lib/home/components/BannerSection'), {ssr: false}
+);
const CategoryHomeId = dynamic(() =>
- import('@/lib/home/components/CategoryHomeId')
+ import('@/lib/home/components/CategoryHomeId'), {ssr: false}
);
-const CustomerReviews = dynamic(() =>
- import('@/lib/review/components/CustomerReviews')
+
+const CategoryDynamic = dynamic(() =>
+ import('@/lib/home/components/CategoryDynamic'), {ssr: false}
+);
+
+const CategoryDynamicMobile = dynamic(() =>
+import('@/lib/home/components/CategoryDynamicMobile'), {ssr: false}
);
-const ServiceList = dynamic(() => import('@/lib/home/components/ServiceList'));
-export default function Home() {
+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
+
+
+
+export default function Home({categoryId}) {
const bannerRef = useRef(null);
const wrapperRef = useRef(null);
@@ -74,7 +87,19 @@ export default function Home() {
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'
@@ -82,11 +107,9 @@ export default function Home() {
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',
+ content: 'indoteknik, indoteknik.com, toko teknik, toko perkakas, jual genset, jual fogging, jual krisbow, harga krisbow, harga alat safety, harga pompa air',
},
- ]}
- />
+ ]} />
<PagePopupIformation />
@@ -125,19 +148,22 @@ export default function Home() {
</DelayRender>
</>
)}
- <PromotinProgram />
+ {/* <PromotinProgram /> */}
+ {dataCategories &&(
+ <CategoryPilihan categories={dataCategories} />
+ )}
+ <CategoryDynamic />
<CategoryHomeId />
<BannerSection />
<CustomerReviews />
</div>
</div>
- </DesktopView>
-
- <MobileView>
+ </DesktopView>
+ <MobileView>
<DelayRender renderAfter={200}>
<HeroBanner />
</DelayRender>
- <div className='flex flex-col gap-y-12 my-6'>
+ <div className='flex flex-col gap-y-4 my-6'>
<DelayRender renderAfter={400}>
<ServiceList />
</DelayRender>
@@ -157,7 +183,13 @@ export default function Home() {
</>
)}
<DelayRender renderAfter={600}>
- <PromotinProgram />
+ {/* <PromotinProgram /> */}
+ </DelayRender>
+ <DelayRender renderAfter={600}>
+ {dataCategories &&(
+ <CategoryPilihan categories={dataCategories} />
+ )}
+ <CategoryDynamicMobile />
</DelayRender>
<DelayRender renderAfter={800}>
<PopularProduct />
@@ -172,5 +204,6 @@ export default function Home() {
</div>
</MobileView>
</BasicLayout>
+ </>
);
} \ No newline at end of file
diff --git a/src/pages/login.jsx b/src/pages/login.jsx
index 9a1aa85b..07d13784 100644
--- a/src/pages/login.jsx
+++ b/src/pages/login.jsx
@@ -1,3 +1,5 @@
+import { useEffect } from 'react';
+import { useRouter } from 'next/router';
import Seo from '@/core/components/Seo';
import SimpleFooter from '@/core/components/elements/Footer/SimpleFooter';
import BasicLayout from '@/core/components/layouts/BasicLayout';
@@ -5,8 +7,18 @@ import DesktopView from '@/core/components/views/DesktopView';
import MobileView from '@/core/components/views/MobileView';
import LoginComponent from '@/lib/auth/components/Login';
import AccountActivation from '~/modules/account-activation';
+import useAuth from '@/core/hooks/useAuth';
export default function Login() {
+ const router = useRouter();
+ const auth = useAuth();
+
+ useEffect(() => {
+ if (auth) {
+ router.push('/');
+ }
+ }, [auth, router]);
+
return (
<>
<Seo title='Login - Indoteknik.com' />
diff --git a/src/pages/my/address/[id]/edit.jsx b/src/pages/my/address/[id]/edit.jsx
index bd680b90..c552659b 100644
--- a/src/pages/my/address/[id]/edit.jsx
+++ b/src/pages/my/address/[id]/edit.jsx
@@ -1,11 +1,11 @@
-import Seo from '@/core/components/Seo'
-import AppLayout from '@/core/components/layouts/AppLayout'
-import BasicLayout from '@/core/components/layouts/BasicLayout'
-import DesktopView from '@/core/components/views/DesktopView'
-import MobileView from '@/core/components/views/MobileView'
-import addressApi from '@/lib/address/api/addressApi'
-import EditAddressComponent from '@/lib/address/components/EditAddress'
-import IsAuth from '@/lib/auth/components/IsAuth'
+import Seo from '@/core/components/Seo';
+import AppLayout from '@/core/components/layouts/AppLayout';
+import BasicLayout from '@/core/components/layouts/BasicLayout';
+import DesktopView from '@/core/components/views/DesktopView';
+import MobileView from '@/core/components/views/MobileView';
+import addressApi from '@/lib/address/api/addressApi';
+import EditAddressComponent from '@/lib/address/components/EditAddress';
+import IsAuth from '@/lib/auth/components/IsAuth';
export default function EditAddress({ id, defaultValues }) {
return (
@@ -24,12 +24,12 @@ export default function EditAddress({ id, defaultValues }) {
</BasicLayout>
</DesktopView>
</IsAuth>
- )
+ );
}
export async function getServerSideProps(context) {
- const { id } = context.query
- const address = await addressApi({ id })
+ const { id } = context.query;
+ const address = await addressApi({ id });
const defaultValues = {
type: address.type,
name: address.name,
@@ -41,7 +41,8 @@ export async function getServerSideProps(context) {
oldDistrict: address.district?.id || '',
district: '',
oldSubDistrict: address.subDistrict?.id || '',
- subDistrict: ''
- }
- return { props: { id, defaultValues } }
+ subDistrict: '',
+ business_name: '',
+ };
+ return { props: { id, defaultValues } };
}
diff --git a/src/pages/my/profile.jsx b/src/pages/my/profile.jsx
index 25c3a608..7cf1bcbb 100644
--- a/src/pages/my/profile.jsx
+++ b/src/pages/my/profile.jsx
@@ -1,41 +1,44 @@
-import Divider from '@/core/components/elements/Divider/Divider'
-import AppLayout from '@/core/components/layouts/AppLayout'
-import BasicLayout from '@/core/components/layouts/BasicLayout'
-import DesktopView from '@/core/components/views/DesktopView'
-import MobileView from '@/core/components/views/MobileView'
-import useAuth from '@/core/hooks/useAuth'
-import CompanyProfile from '@/lib/auth/components/CompanyProfile'
-import IsAuth from '@/lib/auth/components/IsAuth'
-import Menu from '@/lib/auth/components/Menu'
-import PersonalProfile from '@/lib/auth/components/PersonalProfile'
+import Divider from '@/core/components/elements/Divider/Divider';
+import AppLayout from '@/core/components/layouts/AppLayout';
+import BasicLayout from '@/core/components/layouts/BasicLayout';
+import DesktopView from '@/core/components/views/DesktopView';
+import MobileView from '@/core/components/views/MobileView';
+import useAuth from '@/core/hooks/useAuth';
+import CompanyProfile from '@/lib/auth/components/CompanyProfile';
+import IsAuth from '@/lib/auth/components/IsAuth';
+import Menu from '@/lib/auth/components/Menu';
+import PersonalProfile from '@/lib/auth/components/PersonalProfile';
+import Seo from '@/core/components/Seo';
export default function Profile() {
- const auth = useAuth()
+ const auth = useAuth();
return (
- <IsAuth>
- <MobileView>
- <AppLayout title='Akun Saya'>
- <PersonalProfile />
- <Divider />
- {auth?.parentId && <CompanyProfile />}
- </AppLayout>
- </MobileView>
-
- <DesktopView>
- <BasicLayout>
- <div className='container mx-auto flex py-10'>
- <div className='w-3/12 pr-4'>
- <Menu />
- </div>
- <div className='w-9/12 bg-white border border-gray_r-6 rounded'>
+ <>
+ <Seo title='Profile - Indoteknik.com' />
+ <IsAuth>
+ <MobileView>
+ <AppLayout title='Akun Saya'>
<PersonalProfile />
<Divider />
{auth?.parentId && <CompanyProfile />}
+ </AppLayout>
+ </MobileView>
- </div>
- </div>
- </BasicLayout>
- </DesktopView>
- </IsAuth>
- )
+ <DesktopView>
+ <BasicLayout>
+ <div className='container mx-auto flex py-10'>
+ <div className='w-3/12 pr-4'>
+ <Menu />
+ </div>
+ <div className='w-9/12 bg-white border border-gray_r-6 rounded'>
+ <PersonalProfile />
+ <Divider />
+ {auth?.parentId && <CompanyProfile />}
+ </div>
+ </div>
+ </BasicLayout>
+ </DesktopView>
+ </IsAuth>
+ </>
+ );
}
diff --git a/src/pages/shop/brands/[slug].jsx b/src/pages/shop/brands/[slug].jsx
index e786ef78..ed6724ea 100644
--- a/src/pages/shop/brands/[slug].jsx
+++ b/src/pages/shop/brands/[slug].jsx
@@ -18,9 +18,10 @@ export default function BrandDetail() {
const brandName = getNameFromSlug(slug)
const id = getIdFromSlug(slug)
const {brand} = useBrand({id})
- if (!brand || !brand.data || _.isEmpty(brand.data)) {
- return <PageNotFound />;
- }
+ // if ( !brand.isLoading && _.isEmpty(brand.data)) {
+ // console.log('ini masuk pak')
+ // return <PageNotFound />;
+ // }
return (
<BasicLayout>
<Seo
diff --git a/src/pages/shop/category/[slug].jsx b/src/pages/shop/category/[slug].jsx
index 1afe30bf..11840d47 100644
--- a/src/pages/shop/category/[slug].jsx
+++ b/src/pages/shop/category/[slug].jsx
@@ -5,6 +5,8 @@ import { useRouter } from 'next/router';
import Seo from '@/core/components/Seo';
import { getIdFromSlug, getNameFromSlug } from '@/core/utils/slug';
import Breadcrumb from '@/lib/category/components/Breadcrumb';
+import { useEffect, useState } from 'react';
+import odooApi from '@/core/api/odooApi';
const BasicLayout = dynamic(() =>
import('@/core/components/layouts/BasicLayout')
@@ -12,10 +14,14 @@ const BasicLayout = dynamic(() =>
const ProductSearch = dynamic(() =>
import('@/lib/product/components/ProductSearch')
);
+const CategorySection = dynamic(() =>
+ import('@/lib/product/components/CategorySection')
+)
export default function CategoryDetail() {
const router = useRouter();
const { slug = '', page = 1 } = router.query;
+ const [dataCategories, setDataCategories] = useState([])
const categoryName = getNameFromSlug(slug);
const categoryId = getIdFromSlug(slug);
@@ -43,8 +49,9 @@ export default function CategoryDetail() {
<Breadcrumb categoryId={categoryId} />
+
{!_.isEmpty(router.query) && (
- <ProductSearch query={query} prefixUrl={`/shop/category/${slug}`} />
+ <ProductSearch query={query} categories ={categoryId} prefixUrl={`/shop/category/${slug}`} />
)}
</BasicLayout>
);
diff --git a/src/pages/shop/lob/[slug].jsx b/src/pages/shop/lob/[slug].jsx
new file mode 100644
index 00000000..d939c25c
--- /dev/null
+++ b/src/pages/shop/lob/[slug].jsx
@@ -0,0 +1,48 @@
+import _ from 'lodash';
+import dynamic from 'next/dynamic';
+import { useRouter } from 'next/router';
+import Seo from '@/core/components/Seo';
+import { getIdFromSlug, getNameFromSlug } from '@/core/utils/slug';
+import Breadcrumb from '../../../lib/lob/components/Breadcrumb';
+import { useEffect, useState } from 'react';
+import odooApi from '@/core/api/odooApi';
+import { div } from 'lodash-contrib';
+
+const BasicLayout = dynamic(() => import('@/core/components/layouts/BasicLayout'));
+const ProductSearch = dynamic(() => import('@/lib/product/components/ProductSearch'));
+const CategorySection = dynamic(() => import('@/lib/product/components/CategorySection'));
+
+export default function CategoryDetail() {
+ const router = useRouter();
+ const { slug = '', page = 1 } = router.query;
+ const [dataLob, setDataLob] = useState([]);
+ const [finalQuery, setFinalQuery] = useState({});
+ const [dataCategoriesProduct, setDataCategoriesProduct] = useState([])
+ const [data, setData] = useState([])
+ const dataIdCategories = []
+
+ const categoryName = getNameFromSlug(slug);
+ const lobId = getIdFromSlug(slug);
+ const q = router?.query.q || null;
+
+ return (
+ <BasicLayout>
+ <Seo
+ title={`Beli ${categoryName} di Indoteknik`}
+ description={`Jual ${categoryName} Kirim Jakarta Surabaya Semarang Makassar Manado Denpasar Balikpapan Medan Palembang Lampung Bali Bandung Makassar Manado.`}
+ additionalMetaTags={[
+ {
+ property: 'keywords',
+ content: `Jual ${categoryName}, harga ${categoryName}, ${categoryName} murah, toko ${categoryName}, ${categoryName} jakarta, ${categoryName} surabaya`,
+ },
+ ]}
+ />
+
+ <Breadcrumb categoryId={getIdFromSlug(slug)} />
+
+ {!_.isEmpty(router.query) && (
+ <ProductSearch query={router.query} categories={getIdFromSlug(slug)} prefixUrl={`/shop/lob/${slug}`} />
+ )}
+ </BasicLayout>
+ );
+}
diff --git a/src/pages/shop/product/variant/[slug].jsx b/src/pages/shop/product/variant/[slug].jsx
index cb335e0a..42f38774 100644
--- a/src/pages/shop/product/variant/[slug].jsx
+++ b/src/pages/shop/product/variant/[slug].jsx
@@ -69,6 +69,8 @@ export default function ProductDetail({ product }) {
<Seo
title={product?.name || '' + ' - Indoteknik.com' || ''}
description='Temukan pilihan produk B2B Industri &amp; Alat Teknik untuk Perusahaan, UMKM &amp; Pemerintah dengan lengkap, mudah dan transparan.'
+ noindex={true}
+ nofollow={true}
openGraph={{
url: process.env.NEXT_PUBLIC_SELF_HOST + router.asPath,
images: [
diff --git a/src/pages/shop/promo/[slug].jsx b/src/pages/shop/promo/[slug].jsx
new file mode 100644
index 00000000..cfb2c841
--- /dev/null
+++ b/src/pages/shop/promo/[slug].jsx
@@ -0,0 +1,394 @@
+import dynamic from 'next/dynamic'
+import NextImage from 'next/image';
+import { useEffect, useState } from 'react'
+import { useRouter } from 'next/router'
+import Seo from '../../../core/components/Seo.jsx'
+import Promocrumb from '../../../lib/promo/components/Promocrumb.jsx'
+import LogoSpinner from '../../../core/components/elements/Spinner/LogoSpinner.jsx'
+import ProductPromoCard from '../../../../src-migrate/modules/product-promo/components/Card.tsx'
+import React from 'react'
+import DesktopView from '../../../core/components/views/DesktopView.jsx';
+import MobileView from '../../../core/components/views/MobileView.jsx';
+import 'swiper/swiper-bundle.css';
+import useDevice from '../../../core/hooks/useDevice.js'
+import ProductFilterDesktop from '../../../lib/product/components/ProductFilterDesktopPromotion.jsx';
+import ProductFilter from '../../../lib/product/components/ProductFilter.jsx';
+import { HStack, Image, Tag, TagCloseButton, TagLabel } from '@chakra-ui/react';
+import { formatCurrency } from '../../../core/utils/formatValue.js';
+import Pagination from '../../../core/components/elements/Pagination/Pagination.js';
+import whatsappUrl from '../../../core/utils/whatsappUrl.js';
+import _ from 'lodash';
+import useActive from '../../../core/hooks/useActive.js';
+import useProductSearch from '../../../lib/promo/hooks/usePromotionSearch.js';
+
+const BasicLayout = dynamic(() => import('../../../core/components/layouts/BasicLayout.jsx'))
+
+export default function PromoDetail() {
+ const router = useRouter()
+ const { slug = '', brand ='', category='', page = '1' } = router.query
+ const [currentPage, setCurrentPage] = useState(parseInt(10) || 1);
+ const [orderBy, setOrderBy] = useState(router.query?.orderBy);
+ const popup = useActive();
+ const prefixUrl = `/shop/promo/${slug}`
+ const [queryFinal, setQueryFinal] = useState({});
+ const [limit, setLimit] = useState(30);
+ const [q, setQ] = useState('*');
+ const [finalQuery, setFinalQuery] = useState({});
+ const [products, setProducts] = useState(null);
+ const [brandValues, setBrand] = useState(
+ !router.pathname.includes('brands')
+ ? router.query.brand
+ ? router.query.brand.split(',')
+ : []
+ : []
+ );
+
+ const [categoryValues, setCategory] = useState(
+ router.query?.category?.split(',') || router.query?.category?.split(',')
+ );
+
+ const [priceFrom, setPriceFrom] = useState(router.query?.priceFrom || null);
+ const [priceTo, setPriceTo] = useState(router.query?.priceTo || null);
+
+
+ useEffect(() => {
+ const newQuery = {
+ fq: `type_value_s:${slug}`,
+ page : router.query.page? router.query.page : 1,
+ brand : router.query.brand? router.query.brand : '',
+ category : router.query.category? router.query.category : '',
+ priceFrom : router.query.priceFrom? router.query.priceFrom : '',
+ priceTo : router.query.priceTo? router.query.priceTo : '',
+ limit : router.query.limit? router.query.limit : '',
+ orderBy : router.query.orderBy? router.query.orderBy : ''
+ };
+ setFinalQuery(newQuery);
+}, [router.query, prefixUrl, slug, brand, category, priceFrom, priceTo, currentPage]);
+ useEffect(() => {
+ setQueryFinal({ ...finalQuery, q, limit, orderBy });
+ }, [router.query, prefixUrl, slug, brand, category, priceFrom, priceTo, currentPage, finalQuery]);
+
+ const { productSearch } = useProductSearch({
+ query: queryFinal,
+ operation: 'OR',
+ });
+
+
+ const pageCount = Math.ceil(productSearch.data?.response.numFound / limit);
+ const productStart = productSearch.data?.responseHeader.params.start;
+ const productRows = limit;
+ const productFound = productSearch.data?.response.numFound;
+
+ useEffect(() => {
+ setProducts(productSearch.data?.response?.products);
+ }, [productSearch]);
+
+ const brands = [];
+ for (
+ let i = 0;
+ i < productSearch.data?.facet_counts?.facet_fields?.manufacture_name_s.length;
+ i += 2
+ ) {
+ const brand =
+ productSearch.data?.facet_counts?.facet_fields?.manufacture_name_s[i];
+ const qty =
+ productSearch.data?.facet_counts?.facet_fields?.manufacture_name_s[i + 1];
+ if (qty > 0) {
+ brands.push({ brand, qty });
+ }
+ }
+
+ const categories = [];
+ for (
+ let i = 0;
+ i < productSearch.data?.facet_counts?.facet_fields?.category_name.length;
+ i += 2
+ ) {
+ const name = productSearch.data?.facet_counts?.facet_fields?.category_name[i];
+ const qty =
+ productSearch.data?.facet_counts?.facet_fields?.category_name[i + 1];
+ if (qty > 0) {
+ categories.push({ name, qty });
+ }
+ }
+
+ function capitalizeFirstLetter(string) {
+ string = string.replace(/_/g, ' ');
+ return string.replace(/(^\w|\s\w)/g, function(match) {
+ return match.toUpperCase();
+ });
+ }
+
+ const handleDeleteFilter = async (source, value) => {
+ let params = {
+ q: router.query.q,
+ orderBy: '',
+ brand: brandValues.join(','),
+ category: categoryValues?.join(','),
+ priceFrom: priceFrom || '',
+ priceTo: priceTo || '',
+ };
+
+ let brands = brandValues;
+ let catagories = categoryValues;
+ switch (source) {
+ case 'brands':
+ brands = brandValues.filter((item) => item !== value);
+ params.brand = brands.join(',');
+ await setBrandValues(brands);
+ break;
+ case 'category':
+ catagories = categoryValues.filter((item) => item !== value);
+ params.category = catagories.join(',');
+ await setCategoryValues(catagories);
+ break;
+ case 'price':
+ params.priceFrom = '';
+ params.priceTo = '';
+ break;
+ case 'delete':
+ params = {
+ q: router.query.q,
+ orderBy: '',
+ brand: '',
+ category: '',
+ priceFrom: '',
+ priceTo: '',
+ };
+ break;
+ }
+
+ handleSubmitFilter(params);
+ };
+ const handleSubmitFilter = (params) => {
+ params = _.pickBy(params, _.identity);
+ params = toQuery(params);
+ router.push(`${slug}?${params}`);
+ };
+
+
+ const toQuery = (obj) => {
+ const str = Object.keys(obj)
+ .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(obj[key])}`)
+ .join('&')
+ return str
+ }
+
+ const whatPromo = capitalizeFirstLetter(slug)
+ const queryWithoutSlug = _.omit(router.query, ['slug'])
+
+ return (
+ <BasicLayout>
+ <Seo
+ title={`Promo ${Array.isArray(slug) ? slug[0] : slug} Terkini`}
+ description='B2B Marketplace MRO & Industri dengan Layanan Pembayaran Tempo, Faktur Pajak, Online Quotation, Garansi Resmi & Harga Kompetitif'
+ />
+ <Promocrumb brandName={whatPromo} />
+ <MobileView>
+ <div className='p-4 pt-0'>
+ <h1 className='mb-2 font-semibold text-h-sm'>Promo {whatPromo}</h1>
+
+ <FilterChoicesComponent
+ brandValues={brandValues}
+ categoryValues={categoryValues}
+ priceFrom={priceFrom}
+ priceTo={priceTo}
+ handleDeleteFilter={handleDeleteFilter}
+ />
+ {products?.length >= 1 && (
+ <div className='flex items-center gap-x-2 mb-5 justify-between'>
+ <div>
+ <button
+ className='btn-light py-2 px-5 h-[40px]'
+ onClick={popup.activate}
+ >
+ Filter
+ </button>
+ </div>
+ </div>
+ )}
+ {productSearch.isLoading && <div className='container flex justify-center my-4'>
+ <LogoSpinner width={48} height={48} />
+ </div>}
+ {products && (
+ <>
+ <div className='grid grid-cols-1 gap-x-1 gap-y-1'>
+ {products?.map((promotion) => (
+ <div key={promotion.id} className="min-w-36 max-w-[400px] mb-[20px] sm:w-full md:w-1/2 lg:w-1/3 xl:w-1/4 ">
+ <ProductPromoCard promotion={promotion}/>
+ </div>
+ ))}
+ </div>
+ </>
+ ) }
+
+ <Pagination
+ pageCount={pageCount}
+ currentPage={parseInt(page)}
+ url={`${prefixUrl}?${toQuery(_.omit(queryWithoutSlug, ['page']))}`}
+ className='mt-6 mb-2'
+ />
+ <ProductFilter
+ active={popup.active}
+ close={popup.deactivate}
+ brands={brands || []}
+ categories={categories || []}
+ prefixUrl={router.asPath.includes('?') ? `${router.asPath}` : `${router.asPath}?`}
+ defaultBrand={null}
+ />
+ </div>
+
+ </MobileView>
+ <DesktopView>
+ <div className='container mx-auto flex mb-3 flex-col'>
+ <div className='w-full pl-6'>
+ <h1 className='text-2xl mb-2 font-semibold'>Promo {whatPromo}</h1>
+ <div className=' w-full h-full flex flex-row items-center '>
+
+ <div className='detail-filter w-1/2 flex justify-start items-center mt-4'>
+
+ <FilterChoicesComponent
+ brandValues={brandValues}
+ categoryValues={categoryValues}
+ priceFrom={priceFrom}
+ priceTo={priceTo}
+ handleDeleteFilter={handleDeleteFilter}
+ />
+ </div>
+ <div className='Filter w-1/2 flex flex-col'>
+
+ <ProductFilterDesktop
+ brands={brands || []}
+ categories={categories || []}
+ prefixUrl={'/shop/promo'}
+ // defaultBrand={null}
+ />
+ </div>
+ </div>
+ {productSearch.isLoading ? (
+ <div className='container flex justify-center my-4'>
+ <LogoSpinner width={48} height={48} />
+ </div>
+ ) : products && products.length >= 1 ? (
+ <>
+ <div className='grid grid-cols-1 gap-x-6 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-2 xl:grid-cols-3'>
+ {products?.map((promotion) => (
+ <div key={promotion.id} className="min-w-[400px] max-w-[400px] mb-[20px] sm:min-w-[350px] md:min-w-[380px] lg:min-w-[400px] xl:min-w-[400px] ">
+ <ProductPromoCard promotion={promotion}/>
+ </div>
+ ))}
+ </div>
+ </>
+ ) : (
+ <div className="text-center my-8">
+ <p>Belum ada promo pada kategori ini</p>
+ </div>
+ )}
+ <div className='flex justify-between items-center mt-6 mb-2'>
+ <div className='pt-2 pb-6 flex items-center gap-x-3'>
+ <NextImage
+ src='/images/logo-question.png'
+ alt='Logo Question Indoteknik'
+ width={60}
+ height={60}
+ />
+ <div className='text-gray_r-12/90'>
+ <span>
+ Barang yang anda cari tidak ada?{' '}
+ <a
+ href={
+ router.query?.q
+ ? whatsappUrl('productSearch', {
+ name: router.query.q,
+ })
+ : whatsappUrl()
+ }
+ className='text-danger-500'
+ >
+ Hubungi Kami
+ </a>
+ </span>
+ </div>
+ </div>
+
+
+
+ <Pagination
+ pageCount={pageCount}
+ currentPage={parseInt(page)}
+ url={`${prefixUrl}?${toQuery(_.omit(queryWithoutSlug, ['page']))}`}
+ className='mt-6 mb-2'
+ />
+ </div>
+
+ </div>
+ </div>
+ </DesktopView>
+ </BasicLayout>
+ )
+ }
+
+const FilterChoicesComponent = ({
+ brandValues,
+ categoryValues,
+ priceFrom,
+ priceTo,
+ handleDeleteFilter,
+ }) => (
+ <div className='flex items-center mb-4'>
+ <HStack spacing={2} className='flex-wrap'>
+ {brandValues?.map((value, index) => (
+ <Tag
+ size='lg'
+ key={index}
+ borderRadius='lg'
+ variant='outline'
+ colorScheme='gray'
+ >
+ <TagLabel>{value}</TagLabel>
+ <TagCloseButton onClick={() => handleDeleteFilter('brands', value)} />
+ </Tag>
+ ))}
+
+ {categoryValues?.map((value, index) => (
+ <Tag
+ size='lg'
+ key={index}
+ borderRadius='lg'
+ variant='outline'
+ colorScheme='gray'
+ >
+ <TagLabel>{value}</TagLabel>
+ <TagCloseButton
+ onClick={() => handleDeleteFilter('category', value)}
+ />
+ </Tag>
+ ))}
+ {priceFrom && priceTo && (
+ <Tag size='lg' borderRadius='lg' variant='outline' colorScheme='gray'>
+ <TagLabel>
+ {formatCurrency(priceFrom) + '-' + formatCurrency(priceTo)}
+ </TagLabel>
+ <TagCloseButton
+ onClick={() => handleDeleteFilter('price', priceFrom)}
+ />
+ </Tag>
+ )}
+ {brandValues?.length > 0 ||
+ categoryValues?.length > 0 ||
+ priceFrom ||
+ priceTo ? (
+ <span>
+ <button
+ className='btn-transparent py-2 px-5 h-[40px] text-red-700'
+ onClick={() => handleDeleteFilter('delete')}
+ >
+ Hapus Semua
+ </button>
+ </span>
+ ) : (
+ ''
+ )}
+ </HStack>
+ </div>
+);
diff --git a/src/pages/shop/promo/[slug].tsx b/src/pages/shop/promo/[slug].tsx
deleted file mode 100644
index aaee1249..00000000
--- a/src/pages/shop/promo/[slug].tsx
+++ /dev/null
@@ -1,523 +0,0 @@
-import dynamic from 'next/dynamic'
-import NextImage from 'next/image';
-import { useEffect, useState } from 'react'
-import { useRouter } from 'next/router'
-import Seo from '../../../core/components/Seo'
-import Promocrumb from '../../../lib/promo/components/Promocrumb'
-import { fetchPromoItemsSolr, fetchVariantSolr } from '../../../api/promoApi'
-import LogoSpinner from '../../../core/components/elements/Spinner/LogoSpinner.jsx'
-import ProductPromoCard from '../../../../src-migrate/modules/product-promo/components/Card'
-import { IPromotion } from '../../../../src-migrate/types/promotion'
-import React from 'react'
-import { SolrResponse } from "../../../../src-migrate/types/solr.ts";
-import DesktopView from '../../../core/components/views/DesktopView';
-import MobileView from '../../../core/components/views/MobileView';
-import 'swiper/swiper-bundle.css';
-import useDevice from '../../../core/hooks/useDevice'
-import ProductFilterDesktop from '../../../lib/product/components/ProductFilterDesktopPromotion';
-import ProductFilter from '../../../lib/product/components/ProductFilter';
-import { HStack, Image, Tag, TagCloseButton, TagLabel } from '@chakra-ui/react';
-import { formatCurrency } from '../../../core/utils/formatValue';
-import Pagination from '../../../core/components/elements/Pagination/Pagination';
-import SideBanner from '../../../../src-migrate/modules/side-banner';
-import whatsappUrl from '../../../core/utils/whatsappUrl';
-import { cons, toQuery } from 'lodash-contrib';
-import _ from 'lodash';
-import useActive from '../../../core/hooks/useActive';
-
-const BasicLayout = dynamic(() => import('../../../core/components/layouts/BasicLayout'))
-
-export default function PromoDetail() {
- const router = useRouter()
- const { slug = '', brand ='', category='', priceFrom = '', priceTo = '', page = '1' } = router.query
- const [promoItems, setPromoItems] = useState<any[]>([])
- const [promoData, setPromoData] = useState<IPromotion[] | null>(null)
- const [currentPage, setCurrentPage] = useState(parseInt(page as string, 10) || 1);
- const itemsPerPage = 12; // Jumlah item yang ingin ditampilkan per halaman
- const [loading, setLoading] = useState(true);
- const { isMobile, isDesktop } = useDevice()
- const [brands, setBrands] = useState<Brand[]>([]);
- const [categories, setCategories] = useState<Category[]>([]);
- const [brandValues, setBrandValues] = useState<string[]>([]);
- const [categoryValues, setCategoryValues] = useState<string[]>([]);
- const [orderBy, setOrderBy] = useState(router.query?.orderBy || 'popular');
- const popup = useActive();
- const prefixUrl = `/shop/promo/${slug}`
-
- useEffect(() => {
- if (router.query.brand) {
- let brandsArray: string[] = [];
- if (Array.isArray(router.query.brand)) {
- brandsArray = router.query.brand;
- } else if (typeof router.query.brand === 'string') {
- brandsArray = router.query.brand.split(',').map((brand) => brand.trim());
- }
- setBrandValues(brandsArray);
- } else {
- setBrandValues([]);
- }
-
- if (router.query.category) {
- let categoriesArray: string[] = [];
-
- if (Array.isArray(router.query.category)) {
- categoriesArray = router.query.category;
- } else if (typeof router.query.category === 'string') {
- categoriesArray = router.query.category.split(',').map((category) => category.trim());
- }
- setCategoryValues(categoriesArray);
- } else {
- setCategoryValues([]);
- }
- }, [router.query.brand, router.query.category]);
-
- interface Brand {
- brand: string;
- qty: number;
- }
-
- interface Category {
- name: string;
- qty: number;
- }
-
- useEffect(() => {
- const loadPromo = async () => {
- setLoading(true);
- const brandsData: Brand[] = [];
- const categoriesData: Category[] = [];
-
- const pageNumber = Array.isArray(page) ? parseInt(page[0], 10) : parseInt(page, 10);
- setCurrentPage(pageNumber)
-
- try {
- const items = await fetchPromoItemsSolr(`type_value_s:${Array.isArray(slug) ? slug[0] : slug}`,0,100);
- setPromoItems(items);
-
- if (items.length === 0) {
- setPromoData([])
- setLoading(false);
- return;
- }
-
- const brandArray = Array.isArray(brand) ? brand : brand.split(',');
- const categoryArray = Array.isArray(category) ? category : category.split(',');
-
- const promoDataPromises = items.map(async (item) => {
-
- try {
- let brandQuery = '';
- if (brand) {
- brandQuery = brandArray.map(b => `manufacture_name_s:${b}`).join(' OR ');
- brandQuery = `(${brandQuery})`;
- }
-
- let categoryQuery = '';
- if (category) {
- categoryQuery = categoryArray.map(c => `category_name:${c}`).join(' OR ');
- categoryQuery = `(${categoryQuery})`;
- }
-
- let priceQuery = '';
- if (priceFrom && priceTo) {
- priceQuery = `price_f:[${priceFrom} TO ${priceTo}]`;
- } else if (priceFrom) {
- priceQuery = `price_f:[${priceFrom} TO *]`;
- } else if (priceTo) {
- priceQuery = `price_f:[* TO ${priceTo}]`;
- }
-
- let combinedQuery = '';
- let combinedQueryPrice = `${priceQuery}`;
- if (brand && category && priceFrom || priceTo) {
- combinedQuery = `${brandQuery} AND ${categoryQuery} `;
- } else if (brand && category) {
- combinedQuery = `${brandQuery} AND ${categoryQuery}`;
- } else if (brand && priceFrom || priceTo) {
- combinedQuery = `${brandQuery}`;
- } else if (category && priceFrom || priceTo) {
- combinedQuery = `${categoryQuery}`;
- } else if (brand) {
- combinedQuery = brandQuery;
- } else if (category) {
- combinedQuery = categoryQuery;
- }
-
- if (combinedQuery && priceFrom || priceTo) {
- const response = await fetchVariantSolr(`id:${item.product_id} AND ${combinedQuery}`);
- const product = response.response.docs[0];
- const product_id = product.id;
- const response2 = await fetchPromoItemsSolr(`type_value_s:${Array.isArray(slug) ? slug[0] : slug} AND product_ids:${product_id} AND ${combinedQueryPrice}`,0,100);
- return response2;
- }else if(combinedQuery){
- const response = await fetchVariantSolr(`id:${item.product_id} AND ${combinedQuery}`);
- const product = response.response.docs[0];
- const product_id = product.id;
- const response2 = await fetchPromoItemsSolr(`type_value_s:${Array.isArray(slug) ? slug[0] : slug} AND product_ids:${product_id} `,0,100);
- return response2;
- } else {
- const response = await fetchPromoItemsSolr(`id:${item.id}`,0,100);
- return response;
- }
- } catch (fetchError) {
- return [];
- }
- });
-
- const promoDataArray = await Promise.all(promoDataPromises);
- const mergedPromoData = promoDataArray.reduce((accumulator, currentValue) => accumulator.concat(currentValue), []);
- setPromoData(mergedPromoData);
-
- const dataBrandCategoryPromises = promoDataArray.map(async (promoData) => {
- if (promoData) {
- const dataBrandCategory = promoData.map(async (item) => {
- let response;
- if(category){
- const categoryQuery = categoryArray.map(c => `category_name:${c}`).join(' OR ');
- response = await fetchVariantSolr(`id:${item.products[0].product_id} AND (${categoryQuery})`);
- }else{
- response = await fetchVariantSolr(`id:${item.products[0].product_id}`)
- }
-
-
- if (response.response?.docs?.length > 0) {
- const product = response.response.docs[0];
- const manufactureNameS = product.manufacture_name;
- if (Array.isArray(manufactureNameS)) {
- for (let i = 0; i < manufactureNameS.length; i += 2) {
- const brand = manufactureNameS[i];
- const qty = 1;
- const existingBrandIndex = brandsData.findIndex(b => b.brand === brand);
- if (existingBrandIndex !== -1) {
- brandsData[existingBrandIndex].qty += qty;
- } else {
- brandsData.push({ brand, qty });
- }
- }
- }
-
- const categoryNameS = product.category_name;
- if (Array.isArray(categoryNameS)) {
- for (let i = 0; i < categoryNameS.length; i += 2) {
- const name = categoryNameS[i];
- const qty = 1;
- const existingCategoryIndex = categoriesData.findIndex(c => c.name === name);
- if (existingCategoryIndex !== -1) {
- categoriesData[existingCategoryIndex].qty += qty;
- } else {
- categoriesData.push({ name, qty });
- }
- }
- }
- }
- });
-
- return Promise.all(dataBrandCategory);
- }
- });
-
- await Promise.all(dataBrandCategoryPromises);
- setBrands(brandsData);
- setCategories(categoriesData);
- setLoading(false);
-
- } catch (loadError) {
- // console.error("Error loading promo items:", loadError)
- setLoading(false);
- }
- }
-
- if (slug) {
- loadPromo()
- }
- },[slug, brand, category, priceFrom, priceTo, currentPage]);
-
-
- function capitalizeFirstLetter(string) {
- string = string.replace(/_/g, ' ');
- return string.replace(/(^\w|\s\w)/g, function(match) {
- return match.toUpperCase();
- });
- }
-
- const handleDeleteFilter = async (source, value) => {
- let params = {
- q: router.query.q,
- orderBy: '',
- brand: brandValues.join(','),
- category: categoryValues.join(','),
- priceFrom: priceFrom || '',
- priceTo: priceTo || '',
- };
-
- let brands = brandValues;
- let catagories = categoryValues;
- switch (source) {
- case 'brands':
- brands = brandValues.filter((item) => item !== value);
- params.brand = brands.join(',');
- await setBrandValues(brands);
- break;
- case 'category':
- catagories = categoryValues.filter((item) => item !== value);
- params.category = catagories.join(',');
- await setCategoryValues(catagories);
- break;
- case 'price':
- params.priceFrom = '';
- params.priceTo = '';
- break;
- case 'delete':
- params = {
- q: router.query.q,
- orderBy: '',
- brand: '',
- category: '',
- priceFrom: '',
- priceTo: '',
- };
- break;
- }
-
- handleSubmitFilter(params);
- };
- const handleSubmitFilter = (params) => {
- params = _.pickBy(params, _.identity);
- params = toQuery(params);
- router.push(`${slug}?${params}`);
- };
-
- const visiblePromotions = promoData?.slice( (currentPage-1) * itemsPerPage, currentPage * 12)
-
- const toQuery = (obj) => {
- const str = Object.keys(obj)
- .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(obj[key])}`)
- .join('&')
- return str
- }
-
- const whatPromo = capitalizeFirstLetter(slug)
- const queryWithoutSlug = _.omit(router.query, ['slug'])
- const queryString = toQuery(queryWithoutSlug)
-
- return (
- <BasicLayout>
- <Seo
- title={`Promo ${Array.isArray(slug) ? slug[0] : slug} Terkini`}
- description='B2B Marketplace MRO & Industri dengan Layanan Pembayaran Tempo, Faktur Pajak, Online Quotation, Garansi Resmi & Harga Kompetitif'
- />
- <Promocrumb brandName={whatPromo} />
- <MobileView>
- <div className='p-4 pt-0'>
- <h1 className='mb-2 font-semibold text-h-sm'>Promo {whatPromo}</h1>
-
- <FilterChoicesComponent
- brandValues={brandValues}
- categoryValues={categoryValues}
- priceFrom={priceFrom}
- priceTo={priceTo}
- handleDeleteFilter={handleDeleteFilter}
- />
- {promoItems.length >= 1 && (
- <div className='flex items-center gap-x-2 mb-5 justify-between'>
- <div>
- <button
- className='btn-light py-2 px-5 h-[40px]'
- onClick={popup.activate}
- >
- Filter
- </button>
- </div>
- </div>
- )}
-
- {loading ? (
- <div className='container flex justify-center my-4'>
- <LogoSpinner width={48} height={48} />
- </div>
- ) : promoData && promoItems.length >= 1 ? (
- <>
- <div className='grid grid-cols-1 gap-x-1 gap-y-1'>
- {visiblePromotions?.map((promotion) => (
- <div key={promotion.id} className="min-w-36 max-w-[400px] mb-[20px] sm:w-full md:w-1/2 lg:w-1/3 xl:w-1/4 ">
- <ProductPromoCard promotion={promotion}/>
- </div>
- ))}
- </div>
- </>
- ) : (
- <div className="text-center my-8">
- <p>Belum ada promo pada kategori ini</p>
- </div>
- )}
-
- <Pagination
- pageCount={Math.ceil((promoData?.length ?? 0) / itemsPerPage)}
- currentPage={currentPage}
- url={`${prefixUrl}?${toQuery(_.omit(queryWithoutSlug, ['page']))}`}
- className='mt-6 mb-2'
- />
- <ProductFilter
- active={popup.active}
- close={popup.deactivate}
- brands={brands || []}
- categories={categories || []}
- prefixUrl={router.asPath.includes('?') ? `${router.asPath}` : `${router.asPath}?`}
- defaultBrand={null}
- />
- </div>
-
- </MobileView>
- <DesktopView>
- <div className='container mx-auto flex mb-3 flex-col'>
- <div className='w-full pl-6'>
- <h1 className='text-2xl mb-2 font-semibold'>Promo {whatPromo}</h1>
- <div className=' w-full h-full flex flex-row items-center '>
-
- <div className='detail-filter w-1/2 flex justify-start items-center mt-4'>
-
- <FilterChoicesComponent
- brandValues={brandValues}
- categoryValues={categoryValues}
- priceFrom={priceFrom}
- priceTo={priceTo}
- handleDeleteFilter={handleDeleteFilter}
- />
- </div>
- <div className='Filter w-1/2 flex flex-col'>
-
- <ProductFilterDesktop
- brands={brands || []}
- categories={categories || []}
- prefixUrl={'/shop/promo'}
- // defaultBrand={null}
- />
- </div>
- </div>
- {loading ? (
- <div className='container flex justify-center my-4'>
- <LogoSpinner width={48} height={48} />
- </div>
- ) : promoData && promoItems.length >= 1 ? (
- <>
- <div className='grid grid-cols-1 gap-x-6 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-2 xl:grid-cols-3'>
- {visiblePromotions?.map((promotion) => (
- <div key={promotion.id} className="min-w-[400px] max-w-[400px] mb-[20px] sm:min-w-[350px] md:min-w-[380px] lg:min-w-[400px] xl:min-w-[400px] ">
- <ProductPromoCard promotion={promotion}/>
- </div>
- ))}
- </div>
- </>
- ) : (
- <div className="text-center my-8">
- <p>Belum ada promo pada kategori ini</p>
- </div>
- )}
- <div className='flex justify-between items-center mt-6 mb-2'>
- <div className='pt-2 pb-6 flex items-center gap-x-3'>
- <NextImage
- src='/images/logo-question.png'
- alt='Logo Question Indoteknik'
- width={60}
- height={60}
- />
- <div className='text-gray_r-12/90'>
- <span>
- Barang yang anda cari tidak ada?{' '}
- <a
- href={
- router.query?.q
- ? whatsappUrl('productSearch', {
- name: router.query.q,
- })
- : whatsappUrl()
- }
- className='text-danger-500'
- >
- Hubungi Kami
- </a>
- </span>
- </div>
- </div>
-
-
-
- <Pagination
- pageCount={Math.ceil((promoData?.length ?? 0) / itemsPerPage)}
- currentPage={currentPage}
- url={`${prefixUrl}?${toQuery(_.omit(queryWithoutSlug, ['page']))}`}
- className='mt-6 mb-2'
- />
- </div>
-
- </div>
- </div>
- </DesktopView>
- </BasicLayout>
- )
- }
-
-const FilterChoicesComponent = ({
- brandValues,
- categoryValues,
- priceFrom,
- priceTo,
- handleDeleteFilter,
- }) => (
- <div className='flex items-center mb-4'>
- <HStack spacing={2} className='flex-wrap'>
- {brandValues?.map((value, index) => (
- <Tag
- size='lg'
- key={index}
- borderRadius='lg'
- variant='outline'
- colorScheme='gray'
- >
- <TagLabel>{value}</TagLabel>
- <TagCloseButton onClick={() => handleDeleteFilter('brands', value)} />
- </Tag>
- ))}
-
- {categoryValues?.map((value, index) => (
- <Tag
- size='lg'
- key={index}
- borderRadius='lg'
- variant='outline'
- colorScheme='gray'
- >
- <TagLabel>{value}</TagLabel>
- <TagCloseButton
- onClick={() => handleDeleteFilter('category', value)}
- />
- </Tag>
- ))}
- {priceFrom && priceTo && (
- <Tag size='lg' borderRadius='lg' variant='outline' colorScheme='gray'>
- <TagLabel>
- {formatCurrency(priceFrom) + '-' + formatCurrency(priceTo)}
- </TagLabel>
- <TagCloseButton
- onClick={() => handleDeleteFilter('price', priceFrom)}
- />
- </Tag>
- )}
- {brandValues?.length > 0 ||
- categoryValues?.length > 0 ||
- priceFrom ||
- priceTo ? (
- <span>
- <button
- className='btn-transparent py-2 px-5 h-[40px] text-red-700'
- onClick={() => handleDeleteFilter('delete')}
- >
- Hapus Semua
- </button>
- </span>
- ) : (
- ''
- )}
- </HStack>
- </div>
-);
diff --git a/src/pages/sitemap/brands.xml.js b/src/pages/sitemap/brands.xml.js
index c85c40e9..65a84e97 100644
--- a/src/pages/sitemap/brands.xml.js
+++ b/src/pages/sitemap/brands.xml.js
@@ -15,8 +15,8 @@ export async function getServerSideProps({ res }) {
const url = sitemap.ele('url')
url.ele('loc', createSlug(baseUrl, brand.name, brand.id))
url.ele('lastmod', date.toISOString().slice(0, 10))
- url.ele('changefreq', 'weekly')
- url.ele('priority', '0.6')
+ url.ele('changefreq', 'daily')
+ url.ele('priority', '1.0')
})
res.setHeader('Content-Type', 'text/xml')
diff --git a/src/pages/sitemap/products/[page].js b/src/pages/sitemap/products/[page].js
index 2f9c3198..e39755d6 100644
--- a/src/pages/sitemap/products/[page].js
+++ b/src/pages/sitemap/products/[page].js
@@ -19,7 +19,7 @@ export async function getServerSideProps({ query, res }) {
const url = sitemap.ele('url')
url.ele('loc', createSlug(baseUrl, product.name, product.id))
url.ele('lastmod', date.toISOString().slice(0, 10))
- url.ele('changefreq', 'weekly')
+ url.ele('changefreq', 'daily')
url.ele('priority', '0.8')
})
diff --git a/src/pages/tracking-order.jsx b/src/pages/tracking-order.jsx
new file mode 100644
index 00000000..002acd42
--- /dev/null
+++ b/src/pages/tracking-order.jsx
@@ -0,0 +1,27 @@
+import Seo from '@/core/components/Seo'
+import dynamic from 'next/dynamic'
+import SimpleFooter from '@/core/components/elements/Footer/SimpleFooter';
+import BasicLayout from '@/core/components/layouts/BasicLayout';
+import DesktopView from '@/core/components/views/DesktopView';
+import MobileView from '@/core/components/views/MobileView';
+const PageTrackingOrder = dynamic(() => import('@/lib/tracking-order/component/TrackingOrder'))
+
+export default function TrackingOrder() {
+ return (
+ <>
+ <Seo title='Tracking Order - Indoteknik.com' />
+
+ <DesktopView>
+ <BasicLayout>
+ <PageTrackingOrder/>
+ </BasicLayout>
+ </DesktopView>
+
+ <MobileView>
+ <BasicLayout>
+ <PageTrackingOrder/>
+ </BasicLayout>
+ </MobileView>
+ </>
+ );
+}