|
|
@@ -0,0 +1,149 @@
|
|
|
+"use client";
|
|
|
+
|
|
|
+import { useRouter } from 'next/navigation';
|
|
|
+import {useState, type ChangeEvent} from "react";
|
|
|
+import {useSaveCheckoutCart} from "@/utils/hooks/useSaveCheckoutCart";
|
|
|
+import { useCustomToast } from "@/utils/hooks/useToast";
|
|
|
+import {useLoginModal} from "@/providers/LoginModalProvider";
|
|
|
+import { overlayLoading } from "@/components/theme/ui/kernel/loading/api";
|
|
|
+import { formatCartDetail } from "@/utils/cartDetailTools";
|
|
|
+import { confirmDialog } from "@/components/theme/ui/kernel/confirm/api";
|
|
|
+import {CartDetail} from "@/types/cart/type";
|
|
|
+
|
|
|
+// earnableRewardPoints 判断是否开启下单送积分
|
|
|
+
|
|
|
+export default function RewardPointsRedeemMoney({
|
|
|
+ isGuest,
|
|
|
+ cartUsedPoints,
|
|
|
+ hasRewardPoints,
|
|
|
+ formatRewardPointsAmount,
|
|
|
+ onPointsChange
|
|
|
+}: {
|
|
|
+ isGuest: boolean,
|
|
|
+ cartUsedPoints: number, // 当前使用的用于抵扣的积分数
|
|
|
+ hasRewardPoints: number, // 账户中的总的积分数
|
|
|
+ formatRewardPointsAmount: string,
|
|
|
+ onPointsChange: (payload:CartDetail, isUpdateReduxCart?: boolean) => void;
|
|
|
+}) {
|
|
|
+ const cartUsedPointsStr = String(cartUsedPoints);
|
|
|
+ const router = useRouter();
|
|
|
+ const {openLoginModal} = useLoginModal();
|
|
|
+ const {saveCheckoutCart} = useSaveCheckoutCart();
|
|
|
+ const { showToast } = useCustomToast();
|
|
|
+
|
|
|
+ const [usedPoints, setUsedPoints] = useState(cartUsedPointsStr);
|
|
|
+ const amount = Number(formatRewardPointsAmount.replace(/^\D+/ig,''));
|
|
|
+
|
|
|
+
|
|
|
+ const pointsInputChange = (e: ChangeEvent<HTMLInputElement>) => {
|
|
|
+ setUsedPoints(e.target.value);
|
|
|
+ };
|
|
|
+
|
|
|
+ const submitPointsUse = async () => {
|
|
|
+ const points = cartUsedPointsStr && cartUsedPointsStr === usedPoints ? '0' : usedPoints;
|
|
|
+
|
|
|
+ overlayLoading.start();
|
|
|
+ const saveRes = await saveCheckoutCart({
|
|
|
+ rewardPoints: Number(points)
|
|
|
+ });
|
|
|
+ overlayLoading.stop();
|
|
|
+ if(!saveRes.error) {
|
|
|
+ if(!Number(points)) setUsedPoints('');
|
|
|
+ if(saveRes.data) {
|
|
|
+ const newCartDetail = formatCartDetail(saveRes.data);
|
|
|
+ onPointsChange(newCartDetail);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ showToast(saveRes.msg, 'danger');
|
|
|
+ }
|
|
|
+
|
|
|
+ };
|
|
|
+
|
|
|
+ const guestUserClick = () => {
|
|
|
+ openLoginModal({
|
|
|
+ onFinalResult: async (res) => {
|
|
|
+ if(res.mergeCartSuccess) { // 购物车合并成功
|
|
|
+ if(res.cartAfterMerge) {
|
|
|
+ const newCartDetail = formatCartDetail(res.cartAfterMerge);
|
|
|
+ onPointsChange(newCartDetail, false);
|
|
|
+ }
|
|
|
+
|
|
|
+ } 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 (
|
|
|
+ <>
|
|
|
+ {isGuest ?
|
|
|
+ <div className="text-ly-12 p-2.5 bg-ly-middlegray">
|
|
|
+ Please <button className="underline" onClick={guestUserClick}>LOGIN</button> to use reward points
|
|
|
+ </div>
|
|
|
+ :
|
|
|
+ <div className="w-full">
|
|
|
+ <div className="relative box-border w-full flex justify-between items-center">
|
|
|
+ <span className="text-ly-24 font-medium">Reward points redeem</span>
|
|
|
+
|
|
|
+
|
|
|
+ <div className="flex items-center">
|
|
|
+ {amount > 0 &&
|
|
|
+ <span className="flex items-center text-ly-14 px-2 flex-none h-6 bg-ly-gold mr-2">
|
|
|
+ -{formatRewardPointsAmount}
|
|
|
+ </span>
|
|
|
+ }
|
|
|
+
|
|
|
+ <button className="w-6 h-6 flex-none">
|
|
|
+ <svg className="block w-full h-full" xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="0" y="0" width="16" height="16" fill="#FFFFFF" fillOpacity="0"></rect><path stroke="rgba(0, 0, 0, 1)" strokeWidth="1.5" strokeLinejoin="round" strokeLinecap="square" d="M6.32031 4.27051L10.4202 8.37036L6.32031 12.4702"></path></svg>
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div className="w-full mt-3">
|
|
|
+ <div className="box-border w-full bg-ly-middlegray p-3 rounded-md">
|
|
|
+
|
|
|
+ <p className="text-ly-12">
|
|
|
+ You have <span className="font-bold">{hasRewardPoints} Reward Points</span> available. 100 point = $1. Input points value below to redeem.
|
|
|
+ </p>
|
|
|
+ <div className="flex justify-between items-center mt-3 box-border w-full border-1 h-12 rounded-sm pl-3 pr-2 bg-white">
|
|
|
+ <input className="focus:outline-none"
|
|
|
+ type="text"
|
|
|
+ value={usedPoints === '0' ? '' : usedPoints}
|
|
|
+ placeholder="Reward Points"
|
|
|
+ onChange={pointsInputChange}
|
|
|
+ />
|
|
|
+ <button className="flex items-center text-ly-14 rounded-sm bg-ly-green text-white px-2 h-8"
|
|
|
+ onClick={submitPointsUse}
|
|
|
+ >
|
|
|
+ {cartUsedPoints > 0 ? 'Cancel' : 'Apply'}
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ }
|
|
|
+
|
|
|
+ </>
|
|
|
+ );
|
|
|
+}
|