year 19 時間 前
コミット
1980b3da16

BIN
public/vip/d1.webp


BIN
public/vip/d2.webp


BIN
public/vip/d3.webp


BIN
public_original/vip/d1.png


BIN
public_original/vip/d2.png


BIN
public_original/vip/d3.png


+ 186 - 17
src/app/[locale]/(navbar)/vip/page.tsx

@@ -1,12 +1,15 @@
 "use client";
-import { getNewVip, LevelInfoItem, RewardInfoItem } from "@/api/user";
+import { claimVip, getNewVip, LevelInfoItem, RewardInfoItem, RewordItem } from "@/api/user";
 import CustomButton from "@/components/CustomButton";
 import HeaderBack from "@/components/HeaderBack";
 import VipProgress from "@/components/VipProgress";
 import feedback from "@/feedback";
+import useCountdown from "@/hooks/useCountdown";
 import { formatAmount } from "@/utils";
 import { useRequest } from "ahooks";
+import { Toast } from "antd-mobile";
 import clsx from "clsx";
+import { useTranslations } from "next-intl";
 import React from "react";
 import List from "./List";
 import styles from "./page.module.scss";
@@ -18,14 +21,42 @@ export interface RewardItemData extends RewardInfoItem {
     img?: string;
     endTime?: number;
     typeStr?: string;
+    interval?: number;
 }
 
 const renderType1 = [2, 3, 4];
 
+const TimeDown = ({
+    endTime,
+    type,
+    interval = 1000,
+}: {
+    endTime: number;
+    type?: string;
+    interval?: number;
+}) => {
+    const [_, time] = useCountdown({ leftTime: endTime, interval });
+    return (
+        <div className="flex items-center">
+            {type !== "day" && <span>{time.days > 9 ? time.days : `0${time.days}`}d</span>}
+            <span>{time.hours > 9 ? time.hours : `0${time.hours}`}:</span>
+            <span>{time.minutes > 9 ? time.minutes : `0${time.minutes}`}</span>
+            {type === "day" && (
+                <>
+                    :<span>{time.seconds > 9 ? time.seconds : `0${time.seconds}`}</span>
+                </>
+            )}
+            {type}
+        </div>
+    );
+};
+
 const Page = () => {
     const [actLevel, setActLevel] = React.useState<number>(0);
     const [opacity, setOpacity] = React.useState<number>(0);
     const containerRef = React.useRef<HTMLDivElement | null>(null);
+    const curReward = React.useRef<RewardItemData | any>(null);
+    const t = useTranslations();
 
     const { data: userVip, run: runVip } = useRequest<any, any>(getNewVip, {
         pollingErrorRetryCount: 1,
@@ -74,16 +105,19 @@ const Page = () => {
                 title: "Bônus Diária",
                 typeStr: "day",
                 img: "/vip/vip_bs_icon.webp",
+                interval: 1000,
             },
             3: {
                 title: "Bônus Semanal",
                 typeStr: "week",
                 img: "/vip/vip_bs_icon.webp",
+                interval: 60 * 1000,
             },
             4: {
                 title: "Bônus Mensal",
                 typeStr: "month",
                 img: "/vip/vip_bm_icon.webp",
+                interval: 60 * 1000,
             },
             5: {
                 title: "Auxílio de falência",
@@ -127,34 +161,158 @@ const Page = () => {
         return result;
     }, [vipInfo, actVipInfo]);
 
-    const doClaim = async () => {
-        const res = await feedback.showModal({
-            content: (props) => {
-                return (
-                    <div className="relative">
-                        <div>23232</div>
-                        <div onClick={() => props.doClose({ sdsds: 123123 })}>点击</div>
-                        <div></div>
+    const multClick = (dialogProps: any) => {
+        console.log(dialogProps);
+    };
+
+    const multRender = (dialogProps: any) => {
+        return (
+            <div className="relative">
+                <div className="mb-[.1rem] text-center text-[.12rem] text-[var(--textColor1)]">
+                    <i className="iconfont icon-gantanhao text-[.14rem] text-[#ecc720]"></i> ocê
+                    está quase lá! Recarregue{" "}
+                    <span className="text-[#11de68]">R${curReward.current?.double_pay}</span>
+                    (progresso:{" "}
+                    <span className="text-[#11de68]">
+                        R${curReward.current?.cur_pay}/R${curReward.current?.double_pay}
+                    </span>
+                    )para desbloquear recompensas incríveis!
+                </div>
+                <div className="relative flex justify-between rounded-[.1rem] bg-[var(--main-background)] p-[.1rem]">
+                    <div>
+                        <div className="font-bold">Sem upgrade e resgatar</div>
+                        {!!curReward.current?.reward?.length &&
+                            curReward.current?.reward.map((item: RewordItem) => {
+                                return (
+                                    <div
+                                        key={item.coin_type}
+                                        className="mt-[.06rem] text-[.18rem] font-black text-[var(--textColor4)]"
+                                    >
+                                        R$ {formatAmount(item.amount)}
+                                    </div>
+                                );
+                            })}
+                        <CustomButton
+                            onClick={doRealClaim}
+                            disabled={
+                                (curReward.current?.cur_pay || 0) >=
+                                (curReward.current?.double_pay || 0)
+                            }
+                            className="!min-w-[120px] !px-[12px] !py-[6px] !text-[12px]"
+                        >
+                            check in
+                        </CustomButton>
                     </div>
-                );
-            },
+                    <img
+                        src="/vip/d1.webp"
+                        className="absolute right-[.1rem] top-[50%] !h-[auto] w-[.9rem] translate-y-[-50%] transform"
+                        alt=""
+                    />
+                </div>
+                <div className="relative mt-[.1rem] flex justify-between rounded-[.1rem] bg-[var(--main-background)] p-[.1rem]">
+                    <div>
+                        <div className="font-bold">Deposite e ganhe upgrade</div>
+                        {!!curReward.current?.reward?.length &&
+                            curReward.current?.reward.map((item: RewordItem) => {
+                                return (
+                                    <div
+                                        key={item.coin_type}
+                                        className="mt-[.06rem] text-[.32rem] font-black text-[var(--textColor4)]"
+                                    >
+                                        {formatAmount(
+                                            (item.amount || 0) * (curReward.current?.multiple || 0)
+                                        )}
+                                    </div>
+                                );
+                            })}
+                        <CustomButton
+                            onClick={() => multClick(dialogProps)}
+                            className="!min-w-[120px] !px-[12px] !py-[6px] !text-[12px]"
+                        >
+                            {(curReward.current?.cur_pay || 0) >=
+                            (curReward.current?.double_pay || 0)
+                                ? "check in"
+                                : `R$ ${formatAmount((curReward.current?.double_pay || 0) - (curReward.current?.cur_pay || 0))} Ativa`}
+                        </CustomButton>
+                    </div>
+                    <img
+                        src="/vip/d2.webp"
+                        className="absolute right-[.1rem] top-[50%] !h-[auto] w-[1.2rem] translate-y-[-50%] transform"
+                        alt=""
+                    />
+                </div>
+                <div className="absolute right-[.05rem] top-[60%] translate-y-[-50%] transform">
+                    <img src="/vip/d3.webp" className="w-[1.1rem]" alt="" />
+                    <div
+                        className="absolute right-[.15rem] top-[55%] translate-y-[-50%] text-[.12rem] text-[.3rem] font-black leading-[1] text-[#e8ed08]"
+                        style={{
+                            textShadow: `2px 0 #11de68,0 2px  #11de68,-2px 0 #11de68,-2px -2px #11de68`,
+                        }}
+                    >
+                        x10
+                    </div>
+                </div>
+            </div>
+        );
+    };
+
+    const doClaim = async (rewardData: RewardItemData) => {
+        curReward.current = rewardData;
+        const res = await feedback.showModal({
+            content: multRender,
             width: "80%",
             useDefaultFooter: false,
         });
     };
+
+    const doRealClaim = async () => {
+        if (!curReward.current) return;
+        try {
+            const res = await claimVip({ type: curReward.current?.type });
+            if (res.code === 200) {
+                runVip();
+                Toast.show(t(`code.200`));
+
+                return;
+            }
+            throw new Error(`${res?.code || 400}`);
+        } catch (err) {
+            Toast.show({
+                icon: "fail",
+                content: t(`code.${err}`),
+            });
+        }
+    };
+
     const getBtn = (data: RewardItemData) => {
         if (data.status === 2) {
             return <img src="/vip/vip_claimed_icon.webp" alt="" className="w-[80px]" />;
         }
-        let text = data.status === 1 ? "Unopened" : "Receber";
+        let text: any = data.status === 1 ? "Unopened" : "Receber";
+        let status: any = data.status !== 1 ? "disable2" : "primary";
+        if (data.renderType === 1) {
+            if (data?.endTime && data.endTime > 0) {
+                text = (
+                    <TimeDown
+                        endTime={data.endTime}
+                        type={data.typeStr}
+                        interval={data.interval || 1000}
+                    />
+                );
+            }
+            if (Date.now() > data.end_time * 1000) {
+                text = "Expired";
+                status = "disable2";
+            }
+        }
         return (
             <CustomButton
                 className={clsx("!py-[8px] !text-[12px]", {
                     "w-[157px]": data.renderType === 1,
                     "w-full": data.renderType === 2,
                 })}
-                onClick={doClaim}
-                type={data.status !== 1 ? "disable2" : "primary"}
+                onClick={() => doClaim(data)}
+                type={status}
             >
                 {text}
             </CustomButton>
@@ -186,6 +344,19 @@ const Page = () => {
                     <div className={styles.giftBox}>
                         {!!rewardsList?.length &&
                             rewardsList.map((item) => {
+                                let isGray = false;
+
+                                if ([5, 6].includes(item.type)) {
+                                    let hasAmount = false;
+                                    item.reward.forEach((citem) => {
+                                        if (citem.amount > 0) {
+                                            hasAmount = true;
+                                        }
+                                    });
+                                    if (!hasAmount) {
+                                        isGray = true;
+                                    }
+                                }
                                 return (
                                     <div
                                         key={item.title}
@@ -196,9 +367,7 @@ const Page = () => {
                                                 "w-full": item.renderType === 1,
                                                 "col-span-2": item.renderType === 1,
                                                 [styles.claimed]: item.status === 2,
-                                                [styles.gray]:
-                                                    vipInfo.vip_level <= 0 &&
-                                                    [5, 6].includes(item.type),
+                                                [styles.gray]: isGray,
                                             }
                                         )}
                                     >