|
@@ -2,6 +2,10 @@
|
|
|
|
|
|
|
|
import { useState, useMemo } from "react";
|
|
import { useState, useMemo } from "react";
|
|
|
import { useRouter } from "next/navigation";
|
|
import { useRouter } from "next/navigation";
|
|
|
|
|
+import type { Swiper as SwiperType } from "swiper";
|
|
|
|
|
+import { Swiper, SwiperSlide } from 'swiper/react';
|
|
|
|
|
+import { FreeMode, Navigation, Thumbs, Pagination } from 'swiper/modules';
|
|
|
|
|
+import Big from 'big.js';
|
|
|
import { useAppDispatch, useAppSelector } from "@/store/hooks";
|
|
import { useAppDispatch, useAppSelector } from "@/store/hooks";
|
|
|
import { useCustomToast } from "@utils/hooks/useToast";
|
|
import { useCustomToast } from "@utils/hooks/useToast";
|
|
|
import {
|
|
import {
|
|
@@ -9,21 +13,14 @@ import {
|
|
|
clearAddToCartProduct
|
|
clearAddToCartProduct
|
|
|
} from '@/store/slices/addToCartDialogSlice';
|
|
} from '@/store/slices/addToCartDialogSlice';
|
|
|
import { useAddProduct } from "@utils/hooks/useAddToCart";
|
|
import { useAddProduct } from "@utils/hooks/useAddToCart";
|
|
|
|
|
+import {useConfig} from "@/utils/hooks/useConfig";
|
|
|
import { overlayLoading } from "@/components/theme/ui/kernel/loading/api";
|
|
import { overlayLoading } from "@/components/theme/ui/kernel/loading/api";
|
|
|
-import {
|
|
|
|
|
- Drawer,
|
|
|
|
|
- DrawerContent,
|
|
|
|
|
- DrawerHeader,
|
|
|
|
|
- DrawerBody,
|
|
|
|
|
- DrawerFooter
|
|
|
|
|
-} from "@heroui/drawer";
|
|
|
|
|
import type {
|
|
import type {
|
|
|
ProductOption,
|
|
ProductOption,
|
|
|
ResolvedVariant
|
|
ResolvedVariant
|
|
|
} from "@/components/catalog/type";
|
|
} from "@/components/catalog/type";
|
|
|
-import ImgSwiperInAddToCartModal from "./ImgSwiperInAddToCartModal";
|
|
|
|
|
|
|
+import CommonModal from "@/components/theme/ui/CommonModal";
|
|
|
import ProductOptionsInAddToCartModal from "./ProductOptionsInAddToCartModal";
|
|
import ProductOptionsInAddToCartModal from "./ProductOptionsInAddToCartModal";
|
|
|
-import FooterBtnInAddToCartModal from "./FooterBtnInAddToCartModal";
|
|
|
|
|
import { Price } from "@components/theme/ui/Price";
|
|
import { Price } from "@components/theme/ui/Price";
|
|
|
import {
|
|
import {
|
|
|
isValueAvailable,
|
|
isValueAvailable,
|
|
@@ -38,8 +35,14 @@ import {
|
|
|
export default function AddToCartModal() {
|
|
export default function AddToCartModal() {
|
|
|
const router = useRouter();
|
|
const router = useRouter();
|
|
|
const dispatch = useAppDispatch();
|
|
const dispatch = useAppDispatch();
|
|
|
|
|
+
|
|
|
|
|
+ const {getCurrentCurrencyItem} = useConfig();
|
|
|
|
|
+ const currentCurrency = getCurrentCurrencyItem();
|
|
|
|
|
+
|
|
|
const {isOpen, product} = useAppSelector((state) => state.addToCartDialog);
|
|
const {isOpen, product} = useAppSelector((state) => state.addToCartDialog);
|
|
|
|
|
|
|
|
|
|
+ const [thumbsSwiper, setThumbsSwiper] = useState<SwiperType | null>(null);
|
|
|
|
|
+
|
|
|
const { appendProductToCart } = useAddProduct();
|
|
const { appendProductToCart } = useAddProduct();
|
|
|
const { showToast } = useCustomToast();
|
|
const { showToast } = useCustomToast();
|
|
|
|
|
|
|
@@ -147,11 +150,11 @@ export default function AddToCartModal() {
|
|
|
return { variant: null, totalLinePrice: 0, totalNowPrice: 0, save: 0 };
|
|
return { variant: null, totalLinePrice: 0, totalNowPrice: 0, save: 0 };
|
|
|
}
|
|
}
|
|
|
if(variant.priceIndices && variant.priceIndices.length > 0) {
|
|
if(variant.priceIndices && variant.priceIndices.length > 0) {
|
|
|
- totalLinePrice = Number(variant.priceIndices[0].regular_min_price) * productQty;
|
|
|
|
|
- totalNowPrice = Number(variant.priceIndices[0].min_price) * productQty;
|
|
|
|
|
|
|
+ totalLinePrice = Big(variant.priceIndices[0].regular_min_price).times(productQty).toNumber();
|
|
|
|
|
+ totalNowPrice = Big(variant.priceIndices[0].min_price).times(productQty).toNumber();
|
|
|
}
|
|
}
|
|
|
if(totalLinePrice !== totalNowPrice) {
|
|
if(totalLinePrice !== totalNowPrice) {
|
|
|
- save = -(totalLinePrice - totalNowPrice);
|
|
|
|
|
|
|
+ save = Big(totalNowPrice).minus(totalLinePrice).toNumber();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
return {
|
|
@@ -202,7 +205,7 @@ export default function AddToCartModal() {
|
|
|
return res;
|
|
return res;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- const addToCartHandler = async (callback: ()=> void) => {
|
|
|
|
|
|
|
+ const addToCartHandler = async () => {
|
|
|
if(!isCurrentSelectionAvailable) {
|
|
if(!isCurrentSelectionAvailable) {
|
|
|
showToast("The selected options are not available!", "warning");
|
|
showToast("The selected options are not available!", "warning");
|
|
|
return;
|
|
return;
|
|
@@ -210,10 +213,10 @@ export default function AddToCartModal() {
|
|
|
|
|
|
|
|
if(currentVariantInfo.variant) {
|
|
if(currentVariantInfo.variant) {
|
|
|
await addProductToCart();
|
|
await addProductToCart();
|
|
|
- callback();
|
|
|
|
|
|
|
+ closeModal();
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
- const buyNowHandler = async (callback: ()=> void) => {
|
|
|
|
|
|
|
+ const buyNowHandler = async () => {
|
|
|
if(!isCurrentSelectionAvailable) {
|
|
if(!isCurrentSelectionAvailable) {
|
|
|
showToast("The selected options are not available!", "warning");
|
|
showToast("The selected options are not available!", "warning");
|
|
|
return;
|
|
return;
|
|
@@ -221,7 +224,7 @@ export default function AddToCartModal() {
|
|
|
|
|
|
|
|
if(currentVariantInfo.variant) {
|
|
if(currentVariantInfo.variant) {
|
|
|
const res = await addProductToCart();
|
|
const res = await addProductToCart();
|
|
|
- callback();
|
|
|
|
|
|
|
+ closeModal();
|
|
|
if(res && !res.error) {
|
|
if(res && !res.error) {
|
|
|
const responseData = res.data;
|
|
const responseData = res.data;
|
|
|
if(responseData && responseData.success) {
|
|
if(responseData && responseData.success) {
|
|
@@ -237,83 +240,136 @@ export default function AddToCartModal() {
|
|
|
dispatch(clearAddToCartProduct());
|
|
dispatch(clearAddToCartProduct());
|
|
|
}, 300);
|
|
}, 300);
|
|
|
};
|
|
};
|
|
|
- const openChange = (e:boolean) => {
|
|
|
|
|
- if(!e) {
|
|
|
|
|
- closeModal();
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- return (
|
|
|
|
|
- <Drawer
|
|
|
|
|
- backdrop={"blur"}
|
|
|
|
|
- placement="bottom"
|
|
|
|
|
- isDismissable={false}
|
|
|
|
|
- isKeyboardDismissDisabled={true}
|
|
|
|
|
- isOpen={isOpen}
|
|
|
|
|
- hideCloseButton
|
|
|
|
|
- onOpenChange={(e) => openChange(e)}
|
|
|
|
|
- >
|
|
|
|
|
- <DrawerContent className="rounded-none h-17/20 max-h-none">
|
|
|
|
|
- {(onClose) => (
|
|
|
|
|
- <>
|
|
|
|
|
- <DrawerHeader className="flex flex-col gap-1">
|
|
|
|
|
- <div>
|
|
|
|
|
- Select Options
|
|
|
|
|
- <button className="absolute top-2.5 right-2.5 w-6 h-6" onClick={onClose}>
|
|
|
|
|
- <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" className="h-6 transition-all ease-in-out hover:scale-110"><path strokeLinecap="round" strokeLinejoin="round" d="M6 18 18 6M6 6l12 12"></path></svg>
|
|
|
|
|
- </button>
|
|
|
|
|
- </div>
|
|
|
|
|
- {/**产品图片 */}
|
|
|
|
|
- {images.length > 0 && (
|
|
|
|
|
- <div>
|
|
|
|
|
- <ImgSwiperInAddToCartModal images={images} />
|
|
|
|
|
- </div>
|
|
|
|
|
- )}
|
|
|
|
|
- </DrawerHeader>
|
|
|
|
|
- <DrawerBody className="drawer-body relative">
|
|
|
|
|
- <div>
|
|
|
|
|
- {/**产品选项 */}
|
|
|
|
|
- <div className="box-border w-full">
|
|
|
|
|
- <ProductOptionsInAddToCartModal
|
|
|
|
|
- productOptions={productOptions}
|
|
|
|
|
- selected={selected}
|
|
|
|
|
- disabledMap={disabledMap}
|
|
|
|
|
- onOptionClick={handleOptionClick}
|
|
|
|
|
- />
|
|
|
|
|
|
|
+ return (<>
|
|
|
|
|
+ <CommonModal
|
|
|
|
|
+ isOpen={isOpen}
|
|
|
|
|
+ onClose={closeModal}
|
|
|
|
|
+ fullyCustomer={true}
|
|
|
|
|
+ contentClassName="min-w-155 max-w-248.5"
|
|
|
|
|
+ body={
|
|
|
|
|
+ <div className="box-border w-full p-6 bg-white rounded-xl">
|
|
|
|
|
+ <div className="flex justify-end">
|
|
|
|
|
+ <button className="flex-none w-6 h-6" onClick={closeModal}>
|
|
|
|
|
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" className="h-6 transition-all ease-in-out hover:scale-110"><path strokeLinecap="round" strokeLinejoin="round" d="M6 18 18 6M6 6l12 12"></path></svg>
|
|
|
|
|
+ </button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div className="box-border mt-1.5 grid h-134 w-full min-w-0 grid-cols-[76px_minmax(0,1fr)_461px]">
|
|
|
|
|
+
|
|
|
|
|
+ <div className="min-w-0 h-full">
|
|
|
|
|
+ <Swiper
|
|
|
|
|
+ onSwiper={setThumbsSwiper}
|
|
|
|
|
+ spaceBetween={10}
|
|
|
|
|
+ slidesPerView={5}
|
|
|
|
|
+ freeMode={true}
|
|
|
|
|
+ watchSlidesProgress={true}
|
|
|
|
|
+ modules={[FreeMode, Navigation, Thumbs]}
|
|
|
|
|
+ direction={'vertical'}
|
|
|
|
|
+ className="w-full h-134 min-w-0 addtocartmodal-thumb-swiper"
|
|
|
|
|
+ >
|
|
|
|
|
+ {images.map((img) => {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <SwiperSlide key={img.id + '_thumbs'} className="box-border h-25 rounded-xs p-0.5 border border-white [&.swiper-slide-thumb-active]:border-ly-middlegreen">
|
|
|
|
|
+ <img className="block w-full h-full object-cover" src={img.publicPath} />
|
|
|
|
|
+ </SwiperSlide>
|
|
|
|
|
+ );
|
|
|
|
|
+ })}
|
|
|
|
|
+
|
|
|
|
|
+ </Swiper>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div className= "relative max-w-100.5 min-w-0 h-full ml-2">
|
|
|
|
|
+ <Swiper
|
|
|
|
|
+ navigation={{
|
|
|
|
|
+ nextEl: '.addtocartmodal-main-swiper-next-btn',
|
|
|
|
|
+ prevEl: '.addtocartmodal-main-swiper-prev-btn',
|
|
|
|
|
+ disabledClass: 'disable'
|
|
|
|
|
+ }}
|
|
|
|
|
+ pagination={{
|
|
|
|
|
+ type: "fraction",
|
|
|
|
|
+ renderFraction: function (currentClass, totalClass) {
|
|
|
|
|
+ return '<span class="' + currentClass + '"></span>' +'/' +'<span class="' + totalClass + '"></span>';
|
|
|
|
|
+ },
|
|
|
|
|
+ }}
|
|
|
|
|
+ thumbs={{ swiper: thumbsSwiper }}
|
|
|
|
|
+ modules={[Navigation, Thumbs,Pagination]}
|
|
|
|
|
+ className="addtocartmodal-main-swiper w-full h-full min-w-0"
|
|
|
|
|
+ >
|
|
|
|
|
+ {images.map((img) => {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <SwiperSlide key={img.id}>
|
|
|
|
|
+ <img className="block w-full h-full object-cover" src={img.publicPath} />
|
|
|
|
|
+ </SwiperSlide>
|
|
|
|
|
+ );
|
|
|
|
|
+ })}
|
|
|
|
|
+
|
|
|
|
|
+ </Swiper>
|
|
|
|
|
+ <button className="addtocartmodal-main-swiper-prev-btn group [&.disable]:bg-black/50 bg-white z-1 absolute left-3 top-1/2 -translate-y-1/2 flex items-center justify-center w-10 h-10 rounded-full">
|
|
|
|
|
+ <svg className="w-6 h-6 stroke-black group-[.disable]:stroke-white" xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24" fill="none"><path strokeWidth="1.5" strokeLinejoin="round" strokeLinecap="square" d="M15 18L9 12L15 6"></path></svg>
|
|
|
|
|
+ </button>
|
|
|
|
|
+ <button className="addtocartmodal-main-swiper-next-btn group [&.disable]:bg-black/50 bg-white z-1 absolute right-3 top-1/2 -translate-y-1/2 flex items-center justify-center w-10 h-10 rounded-full">
|
|
|
|
|
+ <svg className="w-6 h-6 stroke-black group-[.disable]:stroke-white" xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24" fill="none"><path strokeWidth="1.5" strokeLinejoin="round" strokeLinecap="square" d="M9 18L15 12L9 6"></path></svg>
|
|
|
|
|
+ </button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ <div className="box-border px-5 min-w-0 ml-4 flex flex-col">
|
|
|
|
|
+ <div className="flex-none">
|
|
|
|
|
+ <div className="text-ly-14 leading-5 line-clamp-2">
|
|
|
|
|
+ {product?.name}
|
|
|
</div>
|
|
</div>
|
|
|
- </div>
|
|
|
|
|
- </DrawerBody>
|
|
|
|
|
- <DrawerFooter className="flex-col border-t border-gray-200 gap-y-4 p-4">
|
|
|
|
|
- <div className="flex justify-between items-center">
|
|
|
|
|
- <Price
|
|
|
|
|
- className="text-ly-14 text-ly-gray line-through"
|
|
|
|
|
- amount={String(currentVariantInfo.totalLinePrice)}
|
|
|
|
|
- currencyCode="USD"
|
|
|
|
|
- />
|
|
|
|
|
- <div className="flex items-center">
|
|
|
|
|
- <Price
|
|
|
|
|
|
|
+ <div className="mt-4 flex items-center">
|
|
|
|
|
+
|
|
|
|
|
+ {/*<Price
|
|
|
className="text-ly-14 bg-ly-gold py-0.5 px-1"
|
|
className="text-ly-14 bg-ly-gold py-0.5 px-1"
|
|
|
amount={String(currentVariantInfo.save)}
|
|
amount={String(currentVariantInfo.save)}
|
|
|
currencyCode="USD"
|
|
currencyCode="USD"
|
|
|
- />
|
|
|
|
|
|
|
+ /> */}
|
|
|
<Price
|
|
<Price
|
|
|
- className="text-ly-20 font-bold ml-1.5"
|
|
|
|
|
|
|
+ className="text-ly-24 font-bold"
|
|
|
amount={String(currentVariantInfo.totalNowPrice)}
|
|
amount={String(currentVariantInfo.totalNowPrice)}
|
|
|
- currencyCode="USD"
|
|
|
|
|
|
|
+ currencyCode={currentCurrency.code}
|
|
|
/>
|
|
/>
|
|
|
|
|
+ <Price
|
|
|
|
|
+ className="text-ly-14 text-ly-gray line-through ml-2.5"
|
|
|
|
|
+ amount={String(currentVariantInfo.totalLinePrice)}
|
|
|
|
|
+ currencyCode={currentCurrency.code}
|
|
|
|
|
+ />
|
|
|
|
|
+
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
- <div>
|
|
|
|
|
- <FooterBtnInAddToCartModal
|
|
|
|
|
- isAvailable={isCurrentSelectionAvailable}
|
|
|
|
|
- onAddToCart={()=> addToCartHandler(onClose)}
|
|
|
|
|
- onBuyNow={()=> buyNowHandler(onClose)}
|
|
|
|
|
|
|
+ <div className="flex-auto my-6 max-h-92 overflow-y-auto scrollbar-thin scrollbar-thumb-gray-100">
|
|
|
|
|
+
|
|
|
|
|
+ <ProductOptionsInAddToCartModal
|
|
|
|
|
+ productOptions={productOptions}
|
|
|
|
|
+ selected={selected}
|
|
|
|
|
+ disabledMap={disabledMap}
|
|
|
|
|
+ onOptionClick={handleOptionClick}
|
|
|
/>
|
|
/>
|
|
|
</div>
|
|
</div>
|
|
|
- </DrawerFooter>
|
|
|
|
|
- </>
|
|
|
|
|
- )}
|
|
|
|
|
- </DrawerContent>
|
|
|
|
|
- </Drawer>
|
|
|
|
|
- );
|
|
|
|
|
|
|
+ <div className="flex-none">
|
|
|
|
|
+ <div className="flex justify-between gap-3">
|
|
|
|
|
+ <button className="flex-1 flex justify-center items-center h-12 text-ly-16 font-bold text-white rounded-3xl bg-ly-deepgreen"
|
|
|
|
|
+ type="button"
|
|
|
|
|
+ onClick={buyNowHandler}
|
|
|
|
|
+ >
|
|
|
|
|
+ Buy now
|
|
|
|
|
+ </button>
|
|
|
|
|
+ <button className="flex-1 flex justify-center items-center h-12 text-ly-16 font-bold text-white rounded-3xl bg-ly-middlegreen"
|
|
|
|
|
+ type="button"
|
|
|
|
|
+ onClick={addToCartHandler}
|
|
|
|
|
+ >
|
|
|
|
|
+ Add to bag
|
|
|
|
|
+ </button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ {/* <button className="flex justify-center items-center w-full mt-3.75 h-12 text-ly-16 font-bold text-white rounded-3xl bg-[#ffc43a]" type="button">
|
|
|
|
|
+ <img className="h-6 w-18.75" src="/image/payment/paypal-logo.svg" />
|
|
|
|
|
+ </button> */}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+ />
|
|
|
|
|
+ </>);
|
|
|
}
|
|
}
|