summaryrefslogtreecommitdiff
path: root/src/lib/promotinProgram
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/promotinProgram')
-rw-r--r--src/lib/promotinProgram/api/homepageApi.js11
-rw-r--r--src/lib/promotinProgram/components/HomePage.jsx152
-rw-r--r--src/lib/promotinProgram/components/PromotionType.jsx254
3 files changed, 301 insertions, 116 deletions
diff --git a/src/lib/promotinProgram/api/homepageApi.js b/src/lib/promotinProgram/api/homepageApi.js
new file mode 100644
index 00000000..d839101a
--- /dev/null
+++ b/src/lib/promotinProgram/api/homepageApi.js
@@ -0,0 +1,11 @@
+import odooApi from "@/core/api/odooApi"
+
+export const getPromotionHome = async () => {
+ const response = await odooApi('GET', '/api/v1/promotion/home')
+ return response
+}
+
+export const getProductPromotionHome = async ({id}) => {
+ const response = await odooApi('GET', `/api/v1/promotion/home/${id}`)
+ return response
+} \ No newline at end of file
diff --git a/src/lib/promotinProgram/components/HomePage.jsx b/src/lib/promotinProgram/components/HomePage.jsx
index 93134117..9ebd82dc 100644
--- a/src/lib/promotinProgram/components/HomePage.jsx
+++ b/src/lib/promotinProgram/components/HomePage.jsx
@@ -1,68 +1,116 @@
-import React, { useState } from 'react'
+import React, { use, useEffect, useState } from 'react'
import { Swiper, SwiperSlide } from 'swiper/react'
import 'swiper/swiper.min.css'
import Image from '@/core/components/elements/Image/Image'
import useDevice from '@/core/hooks/useDevice'
+import odooApi from '@/core/api/odooApi'
+import { LazyLoadComponent } from 'react-lazy-load-image-component'
+import ProductSlider from '@/lib/product/components/ProductSlider'
+import ProductCard from '@/lib/product/components/ProductCard'
+import { PopularProductSkeleton } from '@/components/skeleton/PopularProductSkeleton'
+
+const { useQuery } = require('react-query')
+const { getPromotionHome } = require('../api/homepageApi')
+const { getProductPromotionHome } = require('../api/homepageApi')
const HomePage = () => {
- const [activeTab, setActiveTab] = useState('Tab 1')
+ const [activeTab, setActiveTab] = useState(null)
+ const [activeId, setActiveId] = useState(null)
+ const [activeBanner, setActiveBanner] = useState(null)
+ const [parentPromotions, setparentPromotions] = useState(null)
+
+ const { data: titlePromotion } = useQuery('titlePromotion', getPromotionHome)
+ const { data: productPromotion, refetch: productPromotionRefetch } = useQuery(
+ ['productPromotion', activeId],
+ async () => {
+ if (!activeId) return null
+ return await getProductPromotionHome({ id: activeId })
+ }
+ )
+
+ useEffect(() => {
+ if (titlePromotion) {
+ setActiveTab(titlePromotion[0].name)
+ setActiveId(titlePromotion[0].id)
+ setparentPromotions(titlePromotion)
+ setActiveBanner(titlePromotion[0].banner)
+ productPromotionRefetch()
+ }
+ }, [titlePromotion])
+
+ useEffect(() => {
+ if (productPromotion) {
+ setparentPromotions(() => {
+ return parentPromotions.map((title) => {
+ if (title.id === activeId && title.products === undefined) {
+ return {
+ ...title,
+ products: productPromotion
+ }
+ }
+ return title
+ })
+ })
+ }
+ }, [productPromotion, parentPromotions, activeId])
const { isMobile, isDesktop } = useDevice()
- const handleTabClick = (label) => {
+ const handleTabClick = (id, label, banner) => {
setActiveTab(label)
+ setActiveId(id)
+ setActiveBanner(banner)
}
- const tabItems = [
- { label: 'Tab 1', content: 'Content for Tab 1' },
- { label: 'Tab 2', content: 'Content for Tab 2' },
- { label: 'Tab 3', content: 'Content for Tab 3' },
- { label: 'Tab 4', content: 'Content for Tab 4' },
- { label: 'Tab 5', content: 'Content for Tab 5' },
- { label: 'Tab 6', content: 'Content for Tab 6' },
- { label: 'Tab 7', content: 'Content for Tab 7' },
- { label: 'Tab 8', content: 'Content for Tab 8' },
- { label: 'Tab 9', content: 'Content for Tab 9' },
- { label: 'Tab 10', content: 'Content for Tab 10' }
- ]
-
return (
- <div className='px-4 sm:px-0'>
- <div className='flex justify-between items-center mb-4'>
- <div className='font-medium sm:text-h-lg'>{activeTab}</div>
- </div>
- <Swiper slidesPerView={isMobile ? 3.5 : 7.5} spaceBetween={isMobile ? 12 : 20}>
- {tabItems.map((item, index) => (
- <SwiperSlide key={index}>
- <button
- className={`py-1 px-2 rounded border flex justify-center items-center h-30 ${
- activeTab === item.label ? 'border-red-500' : 'border-gray_r-6'
- }`}
- onClick={() => handleTabClick(item.label)}
- >
- {' '}
- <Image
- src='https://erp.indoteknik.com/api/image/x_manufactures/x_logo_manufacture/10'
- alt=''
- className='h-full w-full object-contain object-center'
- />
- </button>
- </SwiperSlide>
- ))}
- </Swiper>
-
- <div className='mt-4'>
- {tabItems.map((item, index) => (
- <div
- key={index}
- className={`${
- activeTab === item.label ? 'block' : 'hidden'
- } bg-gray-100 p-4 rounded-md`}
- >
- {item.content}
- </div>
- ))}
+ activeBanner && (
+ <div className='px-4 sm:px-0'>
+ <div className='flex justify-between items-center mb-4'>
+ <div className='font-medium sm:text-h-lg'>{activeTab}</div>
+ </div>
+ <div className='mb-4'>
+ <Image src={activeBanner} alt='' className='h-full w-full object-contain object-center' />
+ </div>
+ <Swiper slidesPerView={isMobile ? 3.5 : 7.5} spaceBetween={isMobile ? 12 : 20}>
+ {titlePromotion?.map((item, index) => (
+ <SwiperSlide key={index}>
+ <button
+ className={`py-1 px-2 rounded border flex justify-center items-center h-30 ${
+ activeTab === item.name ? 'border-red-500' : 'border-gray_r-6'
+ }`}
+ onClick={() => handleTabClick(item.id, item.name, item.banner)}
+ >
+ {' '}
+ <Image
+ src={item.icon}
+ alt=''
+ className='h-full w-full object-contain object-center'
+ />
+ </button>
+ </SwiperSlide>
+ ))}
+ </Swiper>
+ <div className='mt-4 relative min-h-[150px]'>
+ {parentPromotions &&
+ parentPromotions?.map((item, index) => (
+ <div
+ key={index}
+ className={`${activeId === item.id ? 'block' : 'hidden'} rounded-md`}
+ >
+ {item.products ? (
+ <ProductSlider
+ key={index}
+ products={{
+ products: item.products
+ }}
+ />
+ ) : (
+ <PopularProductSkeleton />
+ )}
+ </div>
+ ))}
+ </div>
</div>
- </div>
+ )
)
}
diff --git a/src/lib/promotinProgram/components/PromotionType.jsx b/src/lib/promotinProgram/components/PromotionType.jsx
index 371aa952..a6382cb1 100644
--- a/src/lib/promotinProgram/components/PromotionType.jsx
+++ b/src/lib/promotinProgram/components/PromotionType.jsx
@@ -1,47 +1,72 @@
import React, { useEffect, useState } from 'react'
import Image from '@/core/components/elements/Image/Image'
+import BottomPopup from '@/core/components/elements/Popup/BottomPopup'
+import { Tabs } from 'flowbite-react'
+import CountDown from '@/core/components/elements/CountDown/CountDown'
+import CountDown2 from '@/core/components/elements/CountDown/CountDown2'
-const PromotionType = ({ isModal = true }) => {
+const PromotionType = ({ isModal = false }) => {
const [selectedPromo, setSelectedPromo] = useState(null)
+ const [promotionType, setPromotionType] = useState(false)
+
const promos = [
{
id: 1,
- title: 'Promo 1',
+ title: 'Promo Bundling',
description: 'Deskripsi Promo 1',
- image: '/path/to/image1.jpg'
+ image: '/path/to/image1.jpg',
+ type: 'Promo Bundling'
},
{
id: 2,
- title: 'Promo 2',
+ title: 'Promo Special',
description: 'Deskripsi Promo 2',
- image: '/path/to/image2.jpg'
+ image: '/path/to/image2.jpg',
+ type: 'Promo Special'
},
{
id: 3,
- title: 'Promo 3',
+ title: 'Promo Free Merchandise',
description: 'Deskripsi Promo 3',
- image: '/path/to/image3.jpg'
+ image: '/path/to/image3.jpg',
+ type: 'Promo Free Merchandise'
},
{
id: 4,
- title: 'Promo 1',
+ title: 'Promo 4',
description: 'Deskripsi Promo 1',
- image: '/path/to/image1.jpg'
+ image: '/path/to/image1.jpg',
+ type: 'Promo Bundling'
},
{
id: 5,
- title: 'Promo 2',
+ title: 'Promo 5',
description: 'Deskripsi Promo 2',
- image: '/path/to/image2.jpg'
+ image: '/path/to/image2.jpg',
+ type: 'Promo Bundling'
},
{
id: 6,
- title: 'Promo 3',
+ title: 'Promo 6',
description: 'Deskripsi Promo 3',
- image: '/path/to/image3.jpg'
+ image: '/path/to/image3.jpg',
+ type: 'Promo Special'
}
]
+
+ const [activeTitle, setActiveTitle] = useState(promos[0].type)
+
+ const groupingData = promos.reduce((groups, item) => {
+ const promoType = item.type
+ if (!groups[promoType]) {
+ groups[promoType] = []
+ }
+ groups[promoType].push(item)
+
+ return groups
+ }, {})
+
const handlePromoClick = (promoId) => {
if (promoId == selectedPromo) {
setSelectedPromo(null)
@@ -49,60 +74,161 @@ const PromotionType = ({ isModal = true }) => {
setSelectedPromo(promoId)
}
}
+
+ const handlePopUp = () => {
+ if(isModal == false){
+ setPromotionType(true)
+ }
+ }
return (
- <div className={`w-full ${isModal == true ? '' : 'grid grid-cols-3 gap-1'}`}>
- {promos.map((promo) => (
- <div
- key={promo.id}
- onClick={() => handlePromoClick(promo.id)}
- className={`p-2 rounded-lg border border-solid border-gray-300 mb-5 w-full hover:cursor-pointer ${
- selectedPromo
- ? selectedPromo === promo.id
- ? 'opacity-100 border-red-500 bg-red-100'
- : 'opacity-50 pointer-events-none'
- : 'opacity-100'
- } `}
- >
- <div className={`${isModal == true ? 'flex' : ''} items-center`}>
- <div className=''>
- <Image
- src='https://placehold.co/400x400.png'
- alt=''
- className={`flex-1 w-full object-cover rounded-md ${isModal == true ? 'h-[100px]' : ''}`}
- />
- </div>
- <div className='p-2'>
- <h2 className='text-xl font-semibold'>{promo.title}</h2>
- {isModal == true && <p className='text-gray-500'>{promo.description}</p>}
+ <div className='h-[50%]'>
+ <div className='relative rounded-lg border border-solid border-gray-300 mb-2 w-full'>
+ <Image src='https://placehold.co/537x50.png' alt='' layout='fill' objectFit='cover' />
+ <div className='h-full absolute top-0 left-0 w-full flex items-center justify-between p-2'>
+ <span className='font-semibold text-lg text-white'>Promo Tersedia</span>
+ <button type='button' onClick={() => handlePopUp()} className='py-2 btn-yellow'>
+ Lihat Semua
+ </button>
+ </div>
+ </div>
+ <div
+ className={`w-full ${
+ isModal == true ? '' : 'grid grid-cols-3 gap-1 bg-gray-200 '
+ } p-2 rounded-lg`}
+ >
+ {isModal === true ? (
+ <div>
+ <div className='flex gap-2 mb-3'>
+ {Object.keys(groupingData).map((index) => {
+ return (
+ <>
+ <button
+ onClick={() => setActiveTitle(index)}
+ className={`py-1 px-2 rounded-lg flex justify-center items-center text-sm ${
+ activeTitle === index ? 'badge-yellow text-black' : ''
+ } `}
+ >
+ {index}
+ </button>
+ </>
+ )
+ })}
</div>
+ {activeTitle &&
+ groupingData[activeTitle].map((item, i) => (
+ <div
+ key={i}
+ onClick={() => handlePromoClick(item.id)}
+ className={`border border-solid bg-white mb-5 w-full hover:cursor-pointer ${
+ selectedPromo
+ ? selectedPromo === item.id
+ ? 'opacity-100 border-red-500 bg-red-100'
+ : 'opacity-50 pointer-events-none'
+ : 'opacity-100'
+ } `}
+ >
+ <div className={`flex`}>
+ <div className=''>
+ <Image
+ src='https://placehold.co/120x120.png'
+ alt=''
+ className={`flex-1 w-[170px] object-cover`}
+ />
+ </div>
+ <div className='p-2 w-full'>
+ <div className='flex justify-between mb-1'>
+ <div className='text-danger-500 font-semibold mb-1 mt-1'>Waktu Tersisa</div>
+ <div>
+ <CountDown2 initialTime={3600}></CountDown2>
+ </div>
+ </div>
+ <p className='text-justify text-gray-500 line-clamp-3'>
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed ut nibh at arcu
+ commodo auctor. Maecenas efficitur, ipsum sed mollis fermentum, nulla sem ada lah ini ditu kamu dia merek
+ </p>
+ <div className='text-danger-500 font-semibold mb-1 mt-2'>Rp. 999.000</div>
+ </div>
+ </div>
+ </div>
+ ))}
</div>
- </div>
- // <div
- // key={promo.id}
- // onClick={() => handlePromoClick(promo.id)}
- // className={`p-2 rounded-lg border border-solid border-gray-300 mb-5 w-full hover:cursor-pointer ${
- // selectedPromo
- // ? selectedPromo === promo.id
- // ? 'opacity-100 border-red-400 bg-red-100'
- // : 'opacity-50 pointer-events-none'
- // : 'opacity-100'
- // } `}
- // >
- // <div className='items-center'>
- // <div className=''>
- // <Image
- // src='https://placehold.co/600x600.png'
- // alt=''
- // className='flex-1 w-full object-cover rounded-md'
- // />
- // </div>
- // <div className='mt-1'>
- // <h2 className='text-xl font-semibold'>{promo.title}</h2>
- // {/* <p className='text-gray-500'>{promo.description}</p> */}
- // </div>
- // </div>
- // </div>
- ))}
+ ) : (
+ promos.map((promo, index) => {
+ if (index > 2) {
+ return null
+ } else {
+ if (index === 2) {
+ return (
+ <>
+ <div
+ onClick={() => setPromotionType(true)}
+ className={` border border-solid bg-white mb-5 w-full hover:cursor-pointer opacity-100 flex flex-col justify-center items-center`}
+ >
+ <div className='flex justify-center items-center'>
+ <div className='rounded-full shadow-lg w-10 h-10 flex justify-center items-center'>
+ <svg
+ aria-hidden='true'
+ fill='none'
+ stroke='currentColor'
+ stroke-width='1.5'
+ viewBox='0 0 24 24'
+ className='text-red-500 w-20 h-20'
+ >
+ <path
+ d='M12 6v12m6-6H6'
+ stroke-linecap='round'
+ stroke-linejoin='round'
+ ></path>
+ </svg>
+ </div>
+ </div>
+
+ <span className='mt-2 text-sm'>Lihat Promo Lainya</span>
+ </div>
+ </>
+ )
+ }
+ return (
+ <>
+ <div
+ key={promo.id}
+ onClick={() => setPromotionType(true)}
+ className={`border border-solid bg-white mb-5 w-full hover:cursor-pointer`}
+ >
+ <div className={`items-center`}>
+ <div className=''>
+ <Image
+ src='https://placehold.co/120x120.png'
+ alt=''
+ className={`flex-1 w-full object-cover`}
+ />
+ </div>
+ <div className='p-2'>
+ <div className='badge-yellow text-black mb-1'>{promo.title}</div>
+ <p className='text-justify line-clamp-2'>Lorem ipsum dolor sit amet, consectetur ...</p>
+ <div className='text-danger-500 font-semibold mb-1 mt-1'>999900</div>
+ <div>
+ <CountDown2 initialTime={360}></CountDown2>
+ </div>
+ </div>
+ </div>
+ </div>
+ </>
+ )
+ }
+ })
+ )}
+ <BottomPopup
+ className=' !h-[75%]'
+ title='Pakai Promo'
+ active={promotionType}
+ close={() => setPromotionType(false)}
+ >
+ <div className='flex mt-4'>
+ <PromotionType isModal={true}></PromotionType>
+ </div>
+ </BottomPopup>
+ </div>
</div>
)
}