| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- "use client";
- import {useState} from "react";
- import { useRouter } from 'next/navigation';
- import type {CartDetail} from "@/types/cart/type";
- import { useCustomToast } from "@/utils/hooks/useToast";
- import {useSaveCheckoutCart} from "@/utils/hooks/useSaveCheckoutCart";
- import { formatCartDetail } from "@/utils/cartDetailTools";
- import { getLeftDays } from "@/utils/helper";
- import { overlayLoading } from "@/components/theme/ui/kernel/loading/api";
- import { confirmDialog } from "@/components/theme/ui/kernel/confirm/api";
- import { staticVipData } from "@/utils/constants";
- import {useLoginModal} from "@/providers/LoginModalProvider";
- import { VipPlusRulesModal } from "@/components/common/VipPlusRulesModal/VipPlusRulesModal";
- export default function CheckoutVipPlus({
- cartData,
- onSwitchVip
- }:{
- cartData: CartDetail
- onSwitchVip: (payload:CartDetail) => void;
- }) {
- const router = useRouter();
- const {openLoginModal} = useLoginModal();
- const { showToast } = useCustomToast();
- const {saveCheckoutCart} = useSaveCheckoutCart();
- const [isShow, setIsShow] = useState(false);
- const [vipChecked, setVipChecked] = useState(cartData.vipPlusAmount > 0);
-
- const toggleModal = (bool: boolean) => {
- setIsShow(bool);
- };
- const clickSwitchButton = (value: boolean) => {
- if(!cartData.isGuest) { // 登录用户
- const status = value;
- switchVipPlus(status);
- } else { // 游客
- // 弹出登录弹窗
- // 登录注册
- // 登录成功 -> 合并购物车
- //
- // 重新获取 数据
- //
- guestUserClick();
- }
- };
- const switchVipPlus = async (checked:boolean) => {
- const paramVip = checked ? '1' : ''; // '' 表示取消应用
- const res = await setVipPlus(paramVip);
- if(res) {
- setVipChecked(checked);
- }
- };
- const setVipPlus = async (paramVip: string) => {
- overlayLoading.start();
- const saveRes = await saveCheckoutCart({
- // shippingMethod: '-1',
- // paymentMethod: '-1',
- // couponCode: '-1',
- // giftCardNumber: '-1',
- memberDiscount: paramVip
- });
- overlayLoading.stop();
- if(!saveRes.error) {
- if(saveRes.data) {
- const newCartDetail = formatCartDetail(saveRes.data);
- onSwitchVip(newCartDetail);
- }
- return true;
- } else {
- showToast(saveRes.msg, 'danger');
- return false;
- }
- };
- const guestUserClick = () => {
- openLoginModal({
- onFinalResult: async (res) => {
- if(res.mergeCartSuccess) { // 购物车合并成功
- if(!res.cartAfterMerge?.isVip && res.cartAfterMerge?.vipPlusAmount === 0) {
- await switchVipPlus(true);
- }
- } else { // 购物车合并失败
- // 三种 情况: 登录成功; 注册成功;
- if(res.loginSuccess) {
- // 登录成功 需要刷新页面
- showToast('You have logged in successfully. But something wrong','danger');
- await confirmDialog({
- title: "Warning",
- content: "You have logged in successfully. But something wrong. You must refresh the page.",
- noCancel: true,
- });
- window.location.reload();
- }
- if(res.registerSuccess && !res.loginSuccess) {
- // 注册成功,去登录
- await confirmDialog({
- title: "Warning",
- content: "You have registered successfully. But something wrong. You have to login.",
- noCancel: true,
- });
- router.replace('/customer/login');
- }
- }
- }
- });
- };
- return (<>
- {cartData.isVip &&
- <div className="relative box-border w-full ly-vipplus-bg p-3.75">
- <div className="flex items-center justify-between">
- <div className="flex items-center text-ly-12 font-bold">
- Asteriahair Plus
- <button className="flex-none ml-1.5 w-3.5 h-3.5" onClick={() => toggleModal(true)}>
- <svg className="block w-full h-full" xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink" width="14.533447265625" height="14.533340454101562" viewBox="0 0 14.533447265625 14.533340454101562" fill="none"><path d="M7.26676 13.9333C9.1077 13.9333 10.7744 13.1871 11.9808 11.9807C13.1872 10.7743 13.9334 9.10761 13.9334 7.26667C13.9334 5.42574 13.1872 3.75907 11.9808 2.55263C10.7744 1.3462 9.1077 0.600006 7.26676 0.600006C5.42583 0.600006 3.75916 1.3462 2.55272 2.55263C1.34629 3.75907 0.600098 5.42574 0.600098 7.26667C0.600098 9.10761 1.34629 10.7743 2.55272 11.9807C3.75916 13.1871 5.42583 13.9333 7.26676 13.9333Z" stroke="rgba(0, 0, 0, 1)" strokeWidth="1.2" strokeLinejoin="round" ></path><path stroke="rgba(0, 0, 0, 1)" strokeWidth="1.2" strokeLinejoin="round" strokeLinecap="round" d="M7.26807 8.8081L7.26807 7.47476C8.37263 7.47476 9.26807 6.57933 9.26807 5.47476C9.26807 4.3702 8.37263 3.47476 7.26807 3.47476C6.1635 3.47476 5.26807 4.3702 5.26807 5.47476"></path><path d="M7.26937 11.8082C7.7296 11.8082 8.1027 11.4351 8.1027 10.9748C8.1027 10.5146 7.7296 10.1415 7.26937 10.1415C6.80913 10.1415 6.43604 10.5146 6.43604 10.9748C6.43604 11.4351 6.80913 11.8082 7.26937 11.8082Z" fillRule="evenodd" fill="#000000" ></path></svg>
- </button>
- </div>
- <div className="text-ly-12">
- {getLeftDays(cartData.vipExpireDate)} days left
- </div>
- </div>
- <div className="flex justify-between items-center mt-3.75">
- <span className="text-ly-12">Plus Save</span>
- <span className="text-ly-16 font-bold">-{cartData.formattedVipDiscountAmount}</span>
- </div>
- </div>
- }
- {!cartData.isVip &&
- <div className="relative box-border w-full ly-vipplus-bg p-3.75">
-
- <div className="flex items-center text-ly-12 font-bold">
- Asteriahair Plus
- <button className="flex-none ml-1.5 w-3.5 h-3.5" onClick={() => toggleModal(true)}>
- <svg className="block w-full h-full" xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink" width="14.533447265625" height="14.533340454101562" viewBox="0 0 14.533447265625 14.533340454101562" fill="none"><path d="M7.26676 13.9333C9.1077 13.9333 10.7744 13.1871 11.9808 11.9807C13.1872 10.7743 13.9334 9.10761 13.9334 7.26667C13.9334 5.42574 13.1872 3.75907 11.9808 2.55263C10.7744 1.3462 9.1077 0.600006 7.26676 0.600006C5.42583 0.600006 3.75916 1.3462 2.55272 2.55263C1.34629 3.75907 0.600098 5.42574 0.600098 7.26667C0.600098 9.10761 1.34629 10.7743 2.55272 11.9807C3.75916 13.1871 5.42583 13.9333 7.26676 13.9333Z" stroke="rgba(0, 0, 0, 1)" strokeWidth="1.2" strokeLinejoin="round" ></path><path stroke="rgba(0, 0, 0, 1)" strokeWidth="1.2" strokeLinejoin="round" strokeLinecap="round" d="M7.26807 8.8081L7.26807 7.47476C8.37263 7.47476 9.26807 6.57933 9.26807 5.47476C9.26807 4.3702 8.37263 3.47476 7.26807 3.47476C6.1635 3.47476 5.26807 4.3702 5.26807 5.47476"></path><path d="M7.26937 11.8082C7.7296 11.8082 8.1027 11.4351 8.1027 10.9748C8.1027 10.5146 7.7296 10.1415 7.26937 10.1415C6.80913 10.1415 6.43604 10.5146 6.43604 10.9748C6.43604 11.4351 6.80913 11.8082 7.26937 11.8082Z" fillRule="evenodd" fill="#000000" ></path></svg>
- </button>
- </div>
- <div className="mt-3.75 text-ly-16 font-bold">
- <span>Pay {staticVipData.price} save</span>
- <span className="ml-1 text-ly-middlegreen">extra {staticVipData.discount} off every order</span>
- </div>
- <div className="mt-2 text-ly-12">
- {staticVipData.days} days validity
- </div>
- <div className="flex items-center mt-3">
- <span className="text-ly-16 font-bold">{staticVipData.price}</span>
- <span className="ml-2.5 text-ly-12 text-ly-deepgray line-through">{staticVipData.linePrice}</span>
- </div>
-
- <div className="absolute bottom-3.75 right-3.75 flex justify-between items-center">
- <label className="group relative w-9 h-5.5 flex-none">
- <input className="absolute w-full h-full top-0 left-0 opacity-0 z-10"
- type="checkbox" checked={vipChecked}
- onChange={(e) => clickSwitchButton(e.target.checked)}
- />
- <span className="transition-all box-border block px-0.5 w-full h-full rounded-full flex items-center bg-[#c2c2c2] group-has-[:checked]:bg-[#363636]">
- <span className="transition-all block w-4.5 h-4.5 rounded-full bg-white group-has-[:checked]:ml-3.5"></span>
- </span>
- </label>
-
- </div>
- </div>
- }
- <VipPlusRulesModal isShow={isShow} onClose={() => toggleModal(false)} />
- </>);
- }
|