summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorit-fixcomart <it@fixcomart.co.id>2024-06-10 16:53:28 +0700
committerit-fixcomart <it@fixcomart.co.id>2024-06-10 16:53:28 +0700
commit5e5b67e5b98d3183044dc5149fe67a29feeb3c41 (patch)
tree11776ab7470ef0a555c6eec93bd79dca1189721e
parentc88d98f06a6301bad6dd6d2e58b4908d8562638c (diff)
<iman> update promotion-program
-rw-r--r--next.config.js26
-rw-r--r--src/api/promoApi.js43
-rw-r--r--src/lib/home/components/PromotionProgram.jsx22
-rw-r--r--src/pages/shop/promo/[slug].jsx46
-rw-r--r--src/pages/shop/promo/[slug].tsx161
-rw-r--r--src/pages/shop/promo/index.jsx0
6 files changed, 244 insertions, 54 deletions
diff --git a/next.config.js b/next.config.js
index 8e1ceda3..12aa2f3e 100644
--- a/next.config.js
+++ b/next.config.js
@@ -1,9 +1,9 @@
/** @type {import('next').NextConfig} */
const withPWA = require('next-pwa')({
dest: 'public',
- register: true,
- disable: process.env.NODE_ENV === 'development',
- skipWaiting: true
+ register: true,
+ disable: process.env.NODE_ENV === 'development',
+ skipWaiting: true
})
const nextConfig = {
@@ -30,6 +30,26 @@ const nextConfig = {
hostname: 'erp.indoteknik.com'
}
]
+ },
+ async rewrites() {
+ return [
+ {
+ source: '/solr/:path*',
+ destination: 'http://34.101.189.218:8983/solr/:path*' // Proxy to Solr
+ }
+ ]
+ },
+ async headers() {
+ return [
+ {
+ source: '/solr/:path*',
+ headers: [
+ { key: 'Access-Control-Allow-Origin', value: '*' },
+ { key: 'Access-Control-Allow-Methods', value: 'GET, POST, OPTIONS, PUT, DELETE' },
+ { key: 'Access-Control-Allow-Headers', value: '*' }
+ ]
+ }
+ ]
}
}
diff --git a/src/api/promoApi.js b/src/api/promoApi.js
index a4acc768..535df021 100644
--- a/src/api/promoApi.js
+++ b/src/api/promoApi.js
@@ -1,5 +1,6 @@
// src/api/promoApi.js
import odooApi from '@/core/api/odooApi';
+// import { SolrResponse } from "../../../../src-migrate/types/solr.ts";
export const fetchPromoItems = async (type) => {
try {
@@ -10,3 +11,45 @@ export const fetchPromoItems = async (type) => {
return [];
}
};
+
+export const fetchPromoItemsSolr = async (type) => {
+ let start = 0
+ let rows = 120
+ try {
+ const queryParams = new URLSearchParams({ q: `type_value_s:${type}` });
+ const response = await fetch(`/solr/promotion_program_lines/select?${queryParams.toString()}&rows=${rows}&start=${start}`);
+ 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) => {
+ const result = [];
+ for (const promotion of promotions) {
+ const data = {
+ id: promotion.id,
+ program_id: promotion.program_id_i,
+ name: promotion.name_s,
+ type: {
+ value: promotion.type_value_s,
+ label: promotion.type_label_s,
+ },
+ limit: promotion.package_limit_i,
+ limit_user: promotion.package_limit_user_i,
+ limit_trx: promotion.package_limit_trx_i,
+ price: promotion.price_f,
+ total_qty: promotion.total_qty_i,
+ products: JSON.parse(promotion.products_s),
+ free_products: JSON.parse(promotion.free_products_s),
+ };
+ result.push(data);
+ }
+ return result;
+}; \ No newline at end of file
diff --git a/src/lib/home/components/PromotionProgram.jsx b/src/lib/home/components/PromotionProgram.jsx
index 461383a1..a3c09a9b 100644
--- a/src/lib/home/components/PromotionProgram.jsx
+++ b/src/lib/home/components/PromotionProgram.jsx
@@ -1,16 +1,25 @@
import Link from '@/core/components/elements/Link/Link'
import Image from 'next/image'
import { bannerApi } from '@/api/bannerApi';
-
+import useDevice from '@/core/hooks/useDevice'
const { useQuery } = require('react-query')
-
const BannerSection = () => {
const promotionProgram = useQuery('promotionProgram', bannerApi({ type: 'banner-promotion' }));
+ const { isMobile, isDesktop } = useDevice()
return (
- promotionProgram.data &&
+ <div className='px-4 sm:px-0'>
+ <div className='flex justify-between items-center mb-4'>
+ <div className='font-semibold sm:text-h-lg'>Promo Tersedia</div>
+ {isDesktop && (
+ <Link href='/shop/promo' className='!text-red-500 font-semibold'>
+ Lihat Semua
+ </Link>
+ )}
+ </div>
+ {promotionProgram.data &&
promotionProgram.data?.length > 0 && (
- <div className='grid grid-cols-3 sm:grid-cols-3 gap-4 rounded rounded-md'>
+ <div className='bg-red-300 grid grid-cols-3 sm:grid-cols-3 gap-4 rounded-md'>
{promotionProgram.data?.map((banner) => (
<Link key={banner.id} href={banner.url}>
<Image
@@ -24,7 +33,10 @@ const BannerSection = () => {
</Link>
))}
</div>
- )
+
+ )}
+ </div>
+
)
}
diff --git a/src/pages/shop/promo/[slug].jsx b/src/pages/shop/promo/[slug].jsx
deleted file mode 100644
index 4211ceb8..00000000
--- a/src/pages/shop/promo/[slug].jsx
+++ /dev/null
@@ -1,46 +0,0 @@
-import dynamic from 'next/dynamic'
-import { getIdFromSlug, getNameFromSlug } from '@/core/utils/slug'
-import { useRouter } from 'next/router'
-import _ from 'lodash'
-import Seo from '@/core/components/Seo'
-import Promocrumb from '@/lib/promo/components/Promocrumb'
-import useBrand from '@/lib/brand/hooks/useBrand'
-
-const BasicLayout = dynamic(() => import('@/core/components/layouts/BasicLayout'))
-const ProductSearch = dynamic(() => import('@/lib/product/components/ProductSearch'))
-const Brand = dynamic(() => import('@/lib/brand/components/Brand'))
-
-export default function BrandDetail() {
- const router = useRouter()
- const { slug = '' } = router.query
- console.log("apa itu slug",slug)
- const brandName = getNameFromSlug(slug)
- const id = getIdFromSlug(slug)
- const {brand} = useBrand({id})
- return (
- <BasicLayout>
- {/* seakarang arahkan web untuk menampilkan daftar promo sesuai slug */}
-
- <Seo
- title={`Promo ${slug} Terkini`}
- description='B2B Marketplace MRO &amp; Industri dengan Layanan Pembayaran Tempo, Faktur Pajak, Online Quotation, Garansi Resmi &amp; Harga Kompetitif'
-
- />
-
- <Promocrumb brandName={slug} />
-
- harusnya disini menampilkan barang promosimya {slug}
-
-
- {/* <Brand brand={brand} />
- {!_.isEmpty(router.query) && (
- <ProductSearch
- query={_.omit(router.query, 'slug')}
- prefixUrl={`/shop/promo/${slug}`}
- defaultBrand={getNameFromSlug(slug)}
- brand={brand}
- />
- )} */}
- </BasicLayout>
- )
-}
diff --git a/src/pages/shop/promo/[slug].tsx b/src/pages/shop/promo/[slug].tsx
new file mode 100644
index 00000000..cd3e93c4
--- /dev/null
+++ b/src/pages/shop/promo/[slug].tsx
@@ -0,0 +1,161 @@
+import dynamic from 'next/dynamic'
+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 } 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";
+
+
+const BasicLayout = dynamic(() => import('../../../core/components/layouts/BasicLayout'))
+
+export default function PromoDetail() {
+ const router = useRouter()
+ const { slug = '' } = router.query
+ const [promoItems, setPromoItems] = useState<any[]>([])
+ const [promoData, setPromoData] = useState<IPromotion[] | null>(null)
+ const [currentPage, setCurrentPage] = useState(1);
+ const itemsPerPage = 12; // Jumlah item yang ingin ditampilkan per halaman
+ const startIndex = (currentPage - 1) * itemsPerPage;
+ const endIndex = Math.min(startIndex + itemsPerPage, promoData?.length || 0);
+ const visiblePromotions = promoData?.slice(startIndex, endIndex);
+ const [loading, setLoading] = useState(true); // Menambahkan status loading
+
+
+ useEffect(() => {
+ const loadPromo = async () => {
+ try {
+ const items = await fetchPromoItemsSolr(Array.isArray(slug) ? slug[0] : slug)
+ console.log("slug sekarang ", slug)
+
+ setPromoItems(items)
+ console.log("data dari promotion pakai SOLR", items)
+
+ if (items.length === 0) {
+ setPromoData([])
+ setLoading(false);
+ return;
+ }
+
+ const promoDataPromises = items.map(async (item) => {
+ const queryParams = new URLSearchParams({ q: `id:${item.id}` })
+ console.log("Constructed URL:", `/solr/promotion_program_lines/select?${queryParams.toString()}`)
+
+ try {
+ const response = await fetch(`/solr/promotion_program_lines/select?${queryParams.toString()}`)
+ console.log("respon data ", response)
+ if (!response.ok) {
+ throw new Error(`HTTP error! status: ${response.status}`)
+ }
+
+ const data: SolrResponse<any[]> = await response.json()
+ console.log("data promo IPromotion[]", data)
+
+ const promotions = await map(data.response.docs)
+ return promotions;
+ } catch (fetchError) {
+ console.error("Error fetching promotion data:", fetchError)
+ return [];
+ }
+ });
+
+ const promoDataArray = await Promise.all(promoDataPromises);
+ const mergedPromoData = promoDataArray.reduce((accumulator, currentValue) => accumulator.concat(currentValue), []);
+ setPromoData(mergedPromoData);
+ setTimeout(() => setLoading(false), 120); // Menambahkan delay 200ms sebelum mengubah status loading
+ } catch (loadError) {
+ console.error("Error loading promo items:", loadError)
+ setLoading(false);
+ }
+ }
+
+ if (slug) {
+ loadPromo()
+ }
+ }, [slug])
+
+ useEffect(() => {
+ window.scrollTo({ top: 0, behavior: 'auto' }); // Auto scroll to top when component mounts or updates
+ }, []); // Run only once when component mounts
+
+
+ const map = async (promotions: any[]): Promise<IPromotion[]> => {
+ const result: IPromotion[] = []
+
+ for (const promotion of promotions) {
+ const data: IPromotion = {
+ id: promotion.id,
+ program_id: promotion.program_id_i,
+ name: promotion.name_s,
+ type: {
+ value: promotion.type_value_s,
+ label: promotion.type_label_s,
+ },
+ limit: promotion.package_limit_i,
+ limit_user: promotion.package_limit_user_i,
+ limit_trx: promotion.package_limit_trx_i,
+ price: promotion.price_f,
+ total_qty: promotion.total_qty_i,
+ products: JSON.parse(promotion.products_s),
+ free_products: JSON.parse(promotion.free_products_s),
+ }
+
+ result.push(data)
+ }
+
+ return result
+ }
+
+ console.log("data yg dikirim ke ProductPromoCard", promoData)
+ function capitalizeFirstLetter(string) {
+ return string.charAt(0).toUpperCase() + string.slice(1);
+ }
+
+ const goToNextPage = () => {
+ setCurrentPage((prevPage) => prevPage + 1);
+ window.scrollTo({ top: 0, behavior: 'smooth' });
+ };
+
+ const goToPreviousPage = () => {
+ setCurrentPage((prevPage) => Math.max(prevPage - 1, 1));
+ window.scrollTo({ top: 0, behavior: 'smooth' });
+ };
+
+ 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={capitalizeFirstLetter(Array.isArray(slug) ? slug[0] : slug)} />
+
+ {loading ? (
+ <div className='container flex justify-center my-4'>
+ <LogoSpinner width={48} height={48} />
+ </div>
+ ) : promoData && promoItems.length >= 1 ? (
+ <>
+ <div className='flex flex-wrap justify-center'>
+ {visiblePromotions?.map((promotion) => (
+ <div key={promotion.id} className="min-w-[40px] max-w-[400px] mr-[20px] mb-[20px] sm:w-full md:w-1/2 lg:w-1/3 xl:w-1/4">
+ <ProductPromoCard promotion={promotion} slug={Array.isArray(slug) ? slug[0] : slug} />
+ </div>
+ ))}
+ </div>
+ <div className="flex justify-center mt-4">
+ <button onClick={goToPreviousPage} disabled={currentPage === 1} className="mr-2 px-4 py-2 bg-gray-200 rounded">Back</button>
+ <button onClick={goToNextPage} disabled={endIndex >= promoData.length} className="px-4 py-2 bg-gray-200 rounded">Next</button>
+ </div>
+ </>
+ ) : (
+ <div className="text-center my-8">
+ <p>Belum ada promo pada kategori ini</p>
+ </div>
+ )}
+ </BasicLayout>
+ )
+} \ No newline at end of file
diff --git a/src/pages/shop/promo/index.jsx b/src/pages/shop/promo/index.jsx
deleted file mode 100644
index e69de29b..00000000
--- a/src/pages/shop/promo/index.jsx
+++ /dev/null