year 1 deň pred
rodič
commit
4dc445fc97

BIN
public/vip/vip_claimed_icon.webp


BIN
public_original/vip/vip_claimed_icon.webp


+ 31 - 0
src/api/activity.ts

@@ -296,3 +296,34 @@ export const refreshRank = async (params: { area_id: number }) => {
         data: params,
     });
 };
+
+export interface RelieRewardItem {
+    loss_amount: number;
+    pay_amount: number;
+    normal_rate: number;
+    double_rate: number;
+}
+export interface RelieItem {
+    loss_amount: number;
+    normal_amount: number;
+    double_amount: number;
+    double_num: number;
+    double_pay_amount: number;
+    status: number;
+    start_time: string;
+    end_time: string;
+}
+
+export interface RelieInfo {
+    double_enable: boolean;
+    this_week: RelieItem;
+    last_week: RelieItem;
+    rewards: RelieRewardItem[];
+}
+
+//周亏损  /v1/api/user/activity/getVipReliefInfo  weekAidFund
+export const getVipReliefInfo = async () => {
+    return server.post<RelieInfo>({
+        url: "/v1/api/user/activity/getVipReliefInfo",
+    });
+};

+ 60 - 0
src/api/user.ts

@@ -425,3 +425,63 @@ export const changeUserInfo = (data: { nick_name: string; avatar: number }) => {
         data,
     });
 };
+
+export interface RewordItem {
+    coin_type: number;
+    amount: number;
+    rollover: number;
+    ratio: number;
+}
+export interface LevelInfoItem {
+    id: number;
+    bet: number;
+    pay: number;
+    type: number;
+    status: number;
+    reward: RewordItem[];
+}
+export interface RewardInfoItem {
+    type: 1 | 2 | 3 | 4 | 5 | 6;
+    status: number;
+    is_double: boolean;
+    is_double_notify: boolean;
+    reward: RewordItem[];
+    cur_pay: number;
+    double_pay: number;
+    cur_bet: number;
+    target_bet: number;
+    start_time: number;
+    end_time: number;
+    multiple: number;
+}
+
+export interface NewVip {
+    vip_level: number;
+    vip_exp: number;
+    vip_pay_exp: number;
+    sub_daily_bet: number;
+    keep_vip_level_rule: number;
+    max_down: number;
+    level_info: LevelInfoItem[];
+    reward_info: RewardInfoItem[];
+    keep_level_condition: {
+        cur_bet: number;
+        cur_pay: number;
+        bet: number;
+        pay: number;
+        end_time: number;
+    };
+}
+
+export const getNewVip = () => {
+    return server.post({
+        url: "/v1/api/user/new_vip/getNewVipInfo",
+    });
+};
+
+export const claimVip = (data: { type: 1 | 2 | 3 | 4 | 5 | 6 }) => {
+    return server.post({
+        url: "/v1/api/user/new_vip/claimNewVipReward",
+        data,
+    });
+};

+ 47 - 45
src/app/[locale]/(doings)/rank/history/page.tsx

@@ -37,54 +37,56 @@ const Page = () => {
                 }
                 showService={false}
             ></HeaderBack>
-            <main className={"main-header hasFlag stickyFlag flex flex-col p-[.1rem]"} id="mainBox">
-                <div className={styles.tabBox}>
-                    <Tabs items={Tab2Cfg}></Tabs>
-                </div>
-                <div
-                    className={clsx(
-                        "mt-[10px] flex w-full flex-col gap-[15px] rounded-[var(--borderRadius)] py-[15px]",
-                        styles.historyPrice
-                    )}
-                >
-                    <div className="flex flex-row items-center justify-center gap-[4px] text-[20px]">
-                        <span className="font-black">JACKPOT:</span>
-                        <CustomButton className="!px-[12px] !py-[4px] !text-[20px]">
-                            R$124545.00
-                        </CustomButton>
-                    </div>
-                    <div className="text flex flex-row items-center justify-center text-[12px]">
-                        2025-07-29 00:00 ~ 2025-07-30 00:00
+            <main className={"main-header hasFlag stickyFlag"} id="mainBox">
+                <div className="flex h-[100%] flex-col p-[.1rem]">
+                    <div className={styles.tabBox}>
+                        <Tabs items={Tab2Cfg}></Tabs>
                     </div>
-                </div>
-                <div className="rounde-[var(--borderRadius)] mt-[10px] min-h-[0] flex-1 bg-[#fff]">
-                    <div className="flex items-center px-[10px] py-[10px] text-[.13rem] font-black">
-                        <div className="w-[40px] text-center">Rank</div>
-                        <div className="w-[100px] text-center">Jogador</div>
-                        <div className="w-[80px] text-center">Apostas</div>
-                        <div className="flex-1 text-right">Prêmio</div>
+                    <div
+                        className={clsx(
+                            "mt-[10px] flex w-full flex-col gap-[15px] rounded-[var(--borderRadius)] py-[15px]",
+                            styles.historyPrice
+                        )}
+                    >
+                        <div className="flex flex-row items-center justify-center gap-[4px] text-[20px]">
+                            <span className="font-black">JACKPOT:</span>
+                            <CustomButton className="!px-[12px] !py-[4px] !text-[20px]">
+                                R$124545.00
+                            </CustomButton>
+                        </div>
+                        <div className="text flex flex-row items-center justify-center text-[12px]">
+                            2025-07-29 00:00 ~ 2025-07-30 00:00
+                        </div>
                     </div>
-                    <div className="min-h-[0] flex-1 overflow-auto">
-                        {[{ rank: 1 }, { rank: 2 }, { rank: 3 }].map((item) => {
-                            return (
-                                <div
-                                    key={item.rank}
-                                    className="flex items-center px-[10px] py-[10px] text-[.12rem] font-normal"
-                                >
-                                    <div className="w-[40px] text-center">{item.rank}</div>
-                                    <div className="w-[100px] text-center">
-                                        {cryptoStr("sadasdsadsads")}
-                                    </div>
-                                    <div className="w-[80px] text-center text-[var(--textColor4)]">
-                                        Apostas
-                                    </div>
-                                    <div className="flex-1 text-right text-[var(--textColor4)]">
-                                        sdsdsds{" "}
-                                        <span className="text-[var(--textColor1)]">(1%)</span>
+                    <div className="rounde-[var(--borderRadius)] mt-[10px] min-h-[0] flex-1 bg-[#fff]">
+                        <div className="flex items-center px-[10px] py-[10px] text-[.13rem] font-black">
+                            <div className="w-[40px] text-center">Rank</div>
+                            <div className="w-[100px] text-center">Jogador</div>
+                            <div className="w-[80px] text-center">Apostas</div>
+                            <div className="flex-1 text-right">Prêmio</div>
+                        </div>
+                        <div className="min-h-[0] flex-1 overflow-auto">
+                            {[{ rank: 1 }, { rank: 2 }, { rank: 3 }].map((item) => {
+                                return (
+                                    <div
+                                        key={item.rank}
+                                        className="flex items-center px-[10px] py-[10px] text-[.12rem] font-normal"
+                                    >
+                                        <div className="w-[40px] text-center">{item.rank}</div>
+                                        <div className="w-[100px] text-center">
+                                            {cryptoStr("sadasdsadsads")}
+                                        </div>
+                                        <div className="w-[80px] text-center text-[var(--textColor4)]">
+                                            Apostas
+                                        </div>
+                                        <div className="flex-1 text-right text-[var(--textColor4)]">
+                                            sdsdsds{" "}
+                                            <span className="text-[var(--textColor1)]">(1%)</span>
+                                        </div>
                                     </div>
-                                </div>
-                            );
-                        })}
+                                );
+                            })}
+                        </div>
                     </div>
                 </div>
             </main>

+ 143 - 136
src/app/[locale]/(doings)/rank/page.tsx

@@ -151,155 +151,162 @@ const Page = () => {
                     </div>
                 }
             />
-            <main className={"main-header hasFlag stickyFlag p-[.1rem]"} id="mainBox">
-                <div className={styles.pageContainer}>
-                    <div className={styles.tabTop}>
-                        <Tabs items={Tab1Cfg}></Tabs>
-                    </div>
-                    <div className={styles.tabType}>
-                        <Tabs items={Tab2Cfg}></Tabs>
-                    </div>
-                    <div className="min-h-[0] flex-1 overflow-auto">
-                        <div
-                            className={clsx(
-                                styles.total,
-                                "flex w-full flex-row items-stretch gap-[15px] rounded-[var(--borderRadius)] p-[15px]"
-                            )}
-                        >
-                            <img
-                                src="/rank/H7_jackpot_jiangbei_icon.webp"
-                                alt=""
-                                className="w-[100px]"
-                            />
-                            <div className="flex flex-1 flex-col justify-between leading-[1]">
-                                <div className="flex items-center">
-                                    <img
-                                        className="w-[10px]"
-                                        src="/rank/H7_jackpot_yezi_icon.webp"
-                                        style={{
-                                            transform: "rotateY(180deg)",
-                                            transformOrigin: "center",
-                                        }}
-                                        alt=""
-                                    />
-                                    <span className="mx-[.1rem] text-[14px] font-black">
-                                        Daily Contest
-                                    </span>
-                                    <img
-                                        className="w-[10px]"
-                                        src="/rank/H7_jackpot_yezi_icon.webp"
-                                        alt=""
-                                    />
-                                </div>
-                                <div className="text text-[14px]">Contest prize pool</div>
-                                <div
-                                    style={{
-                                        boxShadow: "0 0 0 1px var(--primary-button) inset",
-                                    }}
-                                    className="flex items-center rounded-[var(--borderRadius)] bg-[#fff] py-[6px] pl-[20px] text-[17px] font-black tracking-[2px] text-[var(--textColor4)]"
-                                >
-                                    R$ {data?.total || 0}
-                                </div>
-                                <div className="text-[12px]">
-                                    2025-07-30 00:00 ~ 2025-07-31 00:00
-                                </div>
-                            </div>
+            <main className={"main-header hasFlag stickyFlag"} id="mainBox">
+                <div className="h-[100%] p-[.1rem]">
+                    <div className={styles.pageContainer}>
+                        <div className={styles.tabTop}>
+                            <Tabs items={Tab1Cfg}></Tabs>
+                        </div>
+                        <div className={styles.tabType}>
+                            <Tabs items={Tab2Cfg}></Tabs>
                         </div>
-                        <div className="mt-[.1rem] rounded-[var(--borderRadius)] bg-[var(--main-background)] px-[15px] py-[10px]">
-                            <div className="flex items-center justify-between border-b-[1px] border-[var(--primary-button)] pb-[.1rem]">
-                                <Image
-                                    src={HeaderImageMap.get(1)?.img || "/img/avatar.webp"}
-                                    className={"mr-[.1rem] h-[58px] w-[58px] rounded-[50%]"}
-                                    alt={"avatar"}
-                                    width={120}
-                                    height={120}
+                        <div className="min-h-[0] flex-1 overflow-auto">
+                            <div
+                                className={clsx(
+                                    styles.total,
+                                    "flex w-full flex-row items-stretch gap-[15px] rounded-[var(--borderRadius)] p-[15px]"
+                                )}
+                            >
+                                <img
+                                    src="/rank/H7_jackpot_jiangbei_icon.webp"
+                                    alt=""
+                                    className="w-[100px]"
                                 />
-                                <div className="flex flex-1 flex-col justify-between">
-                                    <div className="font-black">
-                                        {cryptoStr(data?.self_rank?.nickName)}
+                                <div className="flex flex-1 flex-col justify-between leading-[1]">
+                                    <div className="flex items-center">
+                                        <img
+                                            className="w-[10px]"
+                                            src="/rank/H7_jackpot_yezi_icon.webp"
+                                            style={{
+                                                transform: "rotateY(180deg)",
+                                                transformOrigin: "center",
+                                            }}
+                                            alt=""
+                                        />
+                                        <span className="mx-[.1rem] text-[14px] font-black">
+                                            Daily Contest
+                                        </span>
+                                        <img
+                                            className="w-[10px]"
+                                            src="/rank/H7_jackpot_yezi_icon.webp"
+                                            alt=""
+                                        />
+                                    </div>
+                                    <div className="text text-[14px]">Contest prize pool</div>
+                                    <div
+                                        style={{
+                                            boxShadow: "0 0 0 1px var(--primary-button) inset",
+                                        }}
+                                        className="flex items-center rounded-[var(--borderRadius)] bg-[#fff] py-[6px] pl-[20px] text-[17px] font-black tracking-[2px] text-[var(--textColor4)]"
+                                    >
+                                        R$ {data?.total || 0}
+                                    </div>
+                                    <div className="text-[12px]">
+                                        2025-07-30 00:00 ~ 2025-07-31 00:00
                                     </div>
-                                    <div>Apostas: 0</div>
                                 </div>
-                                <CustomButton className="!px-[.1rem] !py-[.08rem]">
-                                    Aposte
-                                </CustomButton>
                             </div>
-                            <div className="mt-[10px] flex items-center">
-                                <div className="flex flex-1 flex-col items-center justify-between border-r-[1px] border-[var(--primary-button)]">
-                                    <div className="text-[14px] font-black">Meu ranking</div>
-                                    <div className="mt-[8px] text-[16px] font-black">
-                                        Fora do ranking
+                            <div className="mt-[.1rem] rounded-[var(--borderRadius)] bg-[var(--main-background)] px-[15px] py-[10px]">
+                                <div className="flex items-center justify-between border-b-[1px] border-[var(--primary-button)] pb-[.1rem]">
+                                    <Image
+                                        src={HeaderImageMap.get(1)?.img || "/img/avatar.webp"}
+                                        className={"mr-[.1rem] h-[58px] w-[58px] rounded-[50%]"}
+                                        alt={"avatar"}
+                                        width={120}
+                                        height={120}
+                                    />
+                                    <div className="flex flex-1 flex-col justify-between">
+                                        <div className="font-black">
+                                            {cryptoStr(data?.self_rank?.nickName)}
+                                        </div>
+                                        <div>Apostas: 0</div>
                                     </div>
+                                    <CustomButton className="!px-[.1rem] !py-[.08rem]">
+                                        Aposte
+                                    </CustomButton>
                                 </div>
-                                <div className="flex flex-1 flex-col items-center justify-between">
-                                    <div className="text-[14px] font-black">Prêmio</div>
-                                    <div className="mt-[8px] text-[14px] font-black">
-                                        {data?.self_rank?.reward && data.self_rank.reward[0]
-                                            ? data.self_rank.reward[0].amount
-                                            : 0}{" "}
-                                        <span className="text-[var(--textColor4)]">
-                                            (
+                                <div className="mt-[10px] flex items-center">
+                                    <div className="flex flex-1 flex-col items-center justify-between border-r-[1px] border-[var(--primary-button)]">
+                                        <div className="text-[14px] font-black">Meu ranking</div>
+                                        <div className="mt-[8px] text-[16px] font-black">
+                                            Fora do ranking
+                                        </div>
+                                    </div>
+                                    <div className="flex flex-1 flex-col items-center justify-between">
+                                        <div className="text-[14px] font-black">Prêmio</div>
+                                        <div className="mt-[8px] text-[14px] font-black">
                                             {data?.self_rank?.reward && data.self_rank.reward[0]
-                                                ? data.self_rank.reward[0].ratio
-                                                : 0}
-                                            %)
-                                        </span>
+                                                ? data.self_rank.reward[0].amount
+                                                : 0}{" "}
+                                            <span className="text-[var(--textColor4)]">
+                                                (
+                                                {data?.self_rank?.reward && data.self_rank.reward[0]
+                                                    ? data.self_rank.reward[0].ratio
+                                                    : 0}
+                                                %)
+                                            </span>
+                                        </div>
                                     </div>
                                 </div>
                             </div>
-                        </div>
-                        <h3 className="py-[.1rem] text-center text-[14px] text-[var(--textColor2)]">
-                            Aposte para subir no ranking
-                        </h3>
-                        <div className="mt-[.1rem] flex items-center justify-between">
-                            <CustomButton
-                                className={styles.agentBtn}
-                                onClick={() => router.push("/rank/history")}
-                            >
-                                <i className="iconfont icon-huodejiangli mr-[.1rem] scale-[1.4] transform text-[var(--primary-button)]"></i>
-                                <span className="text-[var(--textColor1)]">Prêmio histórico</span>
-                            </CustomButton>
-                            <CustomButton className={styles.agentBtn}>
-                                <i className="iconfont icon-wenjian mr-[.1rem] scale-[1.4] transform text-[var(--primary-button)]"></i>
-                                <span className="text-[var(--textColor1)]">Regras</span>
-                            </CustomButton>
-                        </div>
-                        <div>
-                            <div className="flex items-center px-[10px] py-[10px] text-[.13rem] font-black">
-                                <div className="w-[40px] text-center">Rank</div>
-                                <div className="w-[100px] text-center">Jogador</div>
-                                <div className="w-[80px] text-center">Apostas</div>
-                                <div className="flex-1 text-right">Prêmio</div>
+                            <h3 className="py-[.1rem] text-center text-[14px] text-[var(--textColor2)]">
+                                Aposte para subir no ranking
+                            </h3>
+                            <div className="mt-[.1rem] flex items-center justify-between">
+                                <CustomButton
+                                    className={styles.agentBtn}
+                                    onClick={() => router.push("/rank/history")}
+                                >
+                                    <i className="iconfont icon-huodejiangli mr-[.1rem] scale-[1.4] transform text-[var(--primary-button)]"></i>
+                                    <span className="text-[var(--textColor1)]">
+                                        Prêmio histórico
+                                    </span>
+                                </CustomButton>
+                                <CustomButton
+                                    className={styles.agentBtn}
+                                    onClick={() => router.push("/rank/rules")}
+                                >
+                                    <i className="iconfont icon-wenjian mr-[.1rem] scale-[1.4] transform text-[var(--primary-button)]"></i>
+                                    <span className="text-[var(--textColor1)]">Regras</span>
+                                </CustomButton>
                             </div>
-                            {!!rankList?.length &&
-                                rankList.map((item) => {
-                                    let curReward: RankReward = {} as RankReward;
-                                    if (item?.reward?.length) {
-                                        curReward = item?.reward[0];
-                                    }
-                                    return (
-                                        <div
-                                            key={item.rank}
-                                            className="flex items-center px-[10px] py-[10px] text-[.12rem] font-normal"
-                                        >
-                                            <div className="w-[40px] text-center">
-                                                {getNumber(item.rank)}
-                                            </div>
-                                            <div className="w-[100px] text-center">
-                                                {cryptoStr(item?.nickName)}
-                                            </div>
-                                            <div className="w-[80px] text-center text-[var(--textColor4)]">
-                                                {item.score}
-                                            </div>
-                                            <div className="flex-1 text-right text-[var(--textColor4)]">
-                                                R${curReward?.amount || 0}
-                                                <span className="text-[var(--textColor1)]">
-                                                    ({curReward?.ratio || 0}%)
-                                                </span>
+                            <div>
+                                <div className="flex items-center px-[10px] py-[10px] text-[.13rem] font-black">
+                                    <div className="w-[40px] text-center">Rank</div>
+                                    <div className="w-[100px] text-center">Jogador</div>
+                                    <div className="w-[80px] text-center">Apostas</div>
+                                    <div className="flex-1 text-right">Prêmio</div>
+                                </div>
+                                {!!rankList?.length &&
+                                    rankList.map((item) => {
+                                        let curReward: RankReward = {} as RankReward;
+                                        if (item?.reward?.length) {
+                                            curReward = item?.reward[0];
+                                        }
+                                        return (
+                                            <div
+                                                key={item.rank}
+                                                className="flex items-center px-[10px] py-[10px] text-[.12rem] font-normal"
+                                            >
+                                                <div className="w-[40px] text-center">
+                                                    {getNumber(item.rank)}
+                                                </div>
+                                                <div className="w-[100px] text-center">
+                                                    {cryptoStr(item?.nickName)}
+                                                </div>
+                                                <div className="w-[80px] text-center text-[var(--textColor4)]">
+                                                    {item.score}
+                                                </div>
+                                                <div className="flex-1 text-right text-[var(--textColor4)]">
+                                                    R${curReward?.amount || 0}
+                                                    <span className="text-[var(--textColor1)]">
+                                                        ({curReward?.ratio || 0}%)
+                                                    </span>
+                                                </div>
                                             </div>
-                                        </div>
-                                    );
-                                })}
+                                        );
+                                    })}
+                            </div>
                         </div>
                     </div>
                 </div>

+ 0 - 0
src/app/[locale]/(doings)/rank/rules/page.module.scss


+ 157 - 0
src/app/[locale]/(doings)/rank/rules/page.tsx

@@ -0,0 +1,157 @@
+import HeaderBack from "@/components/HeaderBack";
+import React from "react";
+
+const Page = () => {
+    const rules = React.useMemo(() => {
+        return [
+            { rank: "1", day: "10%", week: "10%", month: "10%" },
+            { rank: "1", day: "10%", week: "10%", month: "10%" },
+            { rank: "1", day: "10%", week: "10%", month: "10%" },
+            { rank: "1", day: "10%", week: "10%", month: "10%" },
+            { rank: "1", day: "10%", week: "10%", month: "10%" },
+            { rank: "1", day: "10%", week: "10%", month: "10%" },
+            { rank: "1", day: "10%", week: "10%", month: "10%" },
+            { rank: "1", day: "10%", week: "10%", month: "10%" },
+        ];
+    }, []);
+
+    return (
+        <div className="flex h-[100%] flex-col">
+            <HeaderBack
+                showBack={true}
+                title={
+                    <div className="flex items-center justify-center">
+                        {/* <i className="iconfont icon-huodejiangli mr-[.04rem] text-[.18rem] text-[var(--textColor4)]"></i> */}
+                        <span className="leading-[1]">Rules</span>
+                    </div>
+                }
+                showService={false}
+            ></HeaderBack>
+            <main className={"main-header hasFlag stickyFlag"} id="mainBox">
+                <div className="p-[.1rem]">
+                    <div className="py-[10px] font-black text-[14]">Total bet</div>
+                    <div className="w-full rounded-[var(--borderRadius)] bg-[var(--main-background)]">
+                        <div className="grid w-full grid-cols-4 text-[var(--textColor1)]">
+                            <div className="flex flex-1 items-center justify-center py-[10px] text-[12px]">
+                                Rank
+                            </div>
+                            <div className="flex flex-1 items-center justify-center py-[10px] text-[12px]">
+                                DIA
+                            </div>
+                            <div className="flex flex-1 items-center justify-center py-[10px] text-[12px]">
+                                SEM
+                            </div>
+                            <div className="flex flex-1 items-center justify-center py-[10px] text-[12px]">
+                                MÊS
+                            </div>
+                        </div>
+                        {rules.map((item) => {
+                            return (
+                                <div
+                                    key={item.rank}
+                                    className="grid w-full grid-cols-4 text-[var(--textColor2)]"
+                                >
+                                    <div className="flex flex-1 items-center justify-center py-[10px] text-[12px]">
+                                        {item.rank}
+                                    </div>
+                                    <div className="flex flex-1 items-center justify-center py-[10px] text-[12px]">
+                                        {item.day}
+                                    </div>
+                                    <div className="flex flex-1 items-center justify-center py-[10px] text-[12px]">
+                                        {item.week}
+                                    </div>
+                                    <div className="flex flex-1 items-center justify-center py-[10px] text-[12px]">
+                                        {item.month}
+                                    </div>
+                                </div>
+                            );
+                        })}
+                    </div>
+                    <div className="rules-info mt-[10px] flex w-full flex-col gap-[20px] px-[10px] pb-[20px]">
+                        <div>
+                            <div className="title text-[14px] font-black">
+                                Recompensas diárias de classificação:
+                            </div>
+                            <div className="flex w-full pt-[10px] text-[12px] text-[var(--textColor2)]">
+                                2% do total do volume diário de negócios da plataforma é contribuído
+                                para o Prêmio Diário. O Prêmio Diário será distribuído diariamente
+                                aos jogadores com base em sua posição na Classificação Diária.
+                            </div>
+                        </div>
+                        <div>
+                            <div className="title text-[14px] font-black">
+                                Recompensas semanais de classificação:
+                            </div>
+                            <div className="flex w-full pt-[10px] text-[12px] text-[var(--textColor2)]">
+                                1,5% do total do volume semanal de negócios da plataforma é
+                                destinado ao Prêmio Semanal, que é distribuído automaticamente toda
+                                semana aos jogadores com base em sua posição na Classificação
+                                Semanal.
+                            </div>
+                        </div>
+                        <div>
+                            <div className="title text-[14px] font-black">
+                                Recompensas mensais de classificação:
+                            </div>
+                            <div className="flex w-full pt-[10px] text-[12px] text-[var(--textColor2)]">
+                                1% do total do volume mensal de negócios da plataforma é contribuído
+                                para o Prêmio Mensal, que será distribuído automaticamente e
+                                mensalmente aos jogadores de acordo com sua posição na Classificação
+                                Mensal.
+                            </div>
+                        </div>
+                        <div>
+                            <div className="title text-[14px] font-black">Regras da atividade:</div>
+                            <div className="flex w-full pt-[10px] text-[12px] text-[var(--textColor2)]">
+                                A classificação dos jogadores nas tabelas de classificação Diária,
+                                Semanal e Mensal é determinada pelo valor total de suas apostas nos
+                                respectivos períodos de tempo.
+                            </div>
+                            <div className="flex w-full pt-[10px] text-[12px] text-[var(--textColor2)]">
+                                As recompensas serão exibidas na página de atividades de
+                                classificação.
+                            </div>
+                            <div className="flex w-full pt-[10px] text-[12px] text-[var(--textColor2)]">
+                                O cálculo da Classificação Diária começa às 00:00 no horário local e
+                                termina às 24:00 no mesmo dia. As recompensas diárias serão
+                                distribuídas dentro de meia hora após o ciclo diário.
+                            </div>
+                            <div className="flex w-full pt-[10px] text-[12px] text-[var(--textColor2)]">
+                                O cálculo da Classificação Semanal começa às 00:00 na segunda-feira
+                                no horário local e termina às 24:00 no domingo no horário local da
+                                mesma semana. As recompensas semanais serão distribuídas dentro de
+                                meia hora após o ciclo semanal.
+                            </div>
+                            <div className="flex w-full pt-[10px] text-[12px] text-[var(--textColor2)]">
+                                O cálculo da Classificação Mensal começa às 00:00 no horário local
+                                no primeiro dia do mês e termina às 00:00 no horário local no
+                                primeiro dia do mês seguinte. As recompensas mensais serão
+                                distribuídas dentro de meia hora após o ciclo mensal.
+                            </div>
+                            <div className="flex w-full pt-[10px] text-[12px] text-[var(--textColor2)]">
+                                Todos os jogadores devem vincular seus números de telefone celular
+                                para serem elegíveis às recompensas.
+                            </div>
+                            <div className="flex w-full pt-[10px] text-[12px] text-[var(--textColor2)]">
+                                Se o prêmio total não for totalmente distribuído, o valor restante
+                                será adicionado ao próximo prêmio.
+                            </div>
+                        </div>
+
+                        <div>
+                            <div className="flex w-full pt-[10px] text-[12px] text-[var(--textColor2)]">
+                                Para serem elegíveis às recompensas, os jogadores devem fornecer seu
+                                número de telefone celular e os dados da conta bancária, que devem
+                                corresponder à sua região e ao seu perfil. Além disso, seus
+                                endereços IP serão verificados, e qualquer atividade incomum pode
+                                levar ao cancelamento dos ganhos ou lucros.
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </main>
+        </div>
+    );
+};
+
+export default Page;

+ 33 - 1
src/app/[locale]/(doings)/weekAidFund/page.tsx

@@ -1,9 +1,39 @@
 "use client";
+import { getVipReliefInfo, RelieInfo } from "@/api/activity";
 import CustomButton from "@/components/CustomButton";
+import feedback from "@/feedback";
 import clsx from "clsx";
+import React from "react";
 import styles from "./page.module.scss";
 
 const Page = () => {
+    const [data, setData] = React.useState<RelieInfo>();
+
+    React.useEffect(() => {
+        getData();
+    }, []);
+
+    const getData = async () => {
+        const res = await getVipReliefInfo();
+        if (res?.code === 200) {
+            setData(res.data);
+        }
+    };
+
+    const openDialog = async () => {
+        feedback.showModal({
+            content: (
+                <div className="relative">
+                    <div>23232</div>
+                    <div></div>
+                    <div></div>
+                </div>
+            ),
+            width: "80%",
+            useDefaultFooter: false,
+        });
+    };
+
     return (
         <>
             <div className={styles.top}>
@@ -62,7 +92,9 @@ const Page = () => {
                     <div className="flex w-full flex-row items-center justify-center gap-[8px] text-[22px] font-black text-[var(--textColor1)]">
                         R$ 0,00 / R$ 0,00
                     </div>
-                    <CustomButton className="mt-[8px] w-full">Unopened</CustomButton>
+                    <CustomButton className="mt-[8px] w-full" onClick={openDialog}>
+                        Unopened
+                    </CustomButton>
                 </div>
                 <div className="mt-[.1rem] flex flex-col gap-[8px] rounded-[var(--borderRadius)] bg-[var(--primary13)] p-[15px] text-[12px] font-normal">
                     <div className={clsx("flex items-center py-[.08rem]")}>

+ 0 - 2
src/app/[locale]/(navbar)/vip/List.tsx

@@ -46,8 +46,6 @@ const List = () => {
         ];
     }, []);
 
-    console.log(vipData?.vip_level);
-
     return (
         <div className={"px-[10px]"}>
             <div className="flex rounded-[var(--borderRadius)] bg-[#fff]">

+ 118 - 77
src/app/[locale]/(navbar)/vip/VipCard.tsx

@@ -1,5 +1,6 @@
-import { VipProgressMap } from "@/enums";
-import { useVipStore } from "@/stores/useVipStore";
+import { NewVip } from "@/api/user";
+import { VipItem, VipProgressMap } from "@/enums";
+import { formatAmount } from "@/utils";
 import { ProgressBar } from "antd-mobile";
 import clsx from "clsx";
 import React from "react";
@@ -9,31 +10,38 @@ import styles from "./page.module.scss";
 interface Props {
     actKey: number;
     onChange?: (key: number) => void;
+    vipInfo?: NewVip;
 }
 
-const VipCard: React.FC<Props> = ({ actKey = 0, onChange }) => {
-    const { vipData } = useVipStore();
+const VipCard: React.FC<Props> = ({ actKey = 0, onChange, vipInfo }) => {
     const [act, setAct] = React.useState<number>(0);
     const [cache, setCache] = React.useState<any>(null);
     const swiperRef = React.useRef<any>(null);
-    const VipList = React.useMemo(() => {
-        const result = [];
-        for (let [key, value] of VipProgressMap) {
-            result.push({
-                key,
-                ...value,
-            });
-        }
-        return result;
-    }, []);
+    const [showInfo, setShowInfo] = React.useState<any>({
+        pay: 0,
+        bet: 0,
+    });
+
     React.useEffect(() => {
-        if (JSON.stringify(vipData) !== JSON.stringify(cache)) {
-            const initAct = vipData?.vip_level || 2;
-            swiperRef.current?.slideTo(initAct);
-            setAct(initAct);
-        }
-        setCache(vipData);
-    }, [vipData]);
+        if (!vipInfo?.level_info) return;
+        let pay = 0,
+            bet = 0;
+        vipInfo.level_info.forEach((item, idx) => {
+            if (item.bet > bet) {
+                bet = item.bet;
+            }
+            if (item.pay > pay) {
+                pay = item.pay;
+            }
+        });
+        setShowInfo({
+            pay,
+            bet,
+        });
+        if (!vipInfo?.vip_level) return;
+        setAct(vipInfo.vip_level);
+        swiperRef.current?.slideTo(vipInfo.vip_level);
+    }, [vipInfo]);
     React.useEffect(() => {
         setAct(actKey);
         swiperRef.current?.slideTo(actKey);
@@ -46,6 +54,15 @@ const VipCard: React.FC<Props> = ({ actKey = 0, onChange }) => {
             onChange(curIdx);
         }
     };
+    const getNextVip = (curId: number) => {
+        const nextId = curId + 1;
+        let result = vipInfo?.level_info.find((item) => item.id === nextId);
+
+        if (!result) {
+            result = vipInfo?.level_info.find((item) => item.id === curId);
+        }
+        return result;
+    };
 
     return (
         <div className={styles.vipCardBox}>
@@ -57,67 +74,91 @@ const VipCard: React.FC<Props> = ({ actKey = 0, onChange }) => {
                 className="rounded-[.1rem]"
                 onSlideChange={swiperChange}
             >
-                {VipList.map((item) => {
-                    return (
-                        <SwiperSlide key={item.key}>
-                            <div
-                                className={clsx(styles.vipCard, {
-                                    [styles.disabled]: item.key > (vipData?.vip_level || 0),
-                                })}
-                                style={{
-                                    background: `linear-gradient(60deg, var(--primary1) 10%, ${item.startColor} 100%)`,
-                                }}
-                            >
-                                <div className="w-[70%] text-[.12rem]">
-                                    <div className="py-[10px] text-[30px] font-black">
-                                        VIP {item.key}
-                                    </div>
-                                    <div className="flex items-center justify-between text-[.1rem]">
-                                        <div className="uppercase">Depósito</div>
-                                        <div className="uppercase">
-                                            <span className="text-[var(--textColor4)]">0.00</span>
-                                            <span className="text-[var(--textColor1)]">/10</span>
+                {!!vipInfo?.level_info?.length &&
+                    vipInfo.level_info.map((item) => {
+                        const curVipCfg = VipProgressMap.get(item?.id || 0) as VipItem;
+                        const nextVip = getNextVip(item.id);
+                        const payPercent = (vipInfo.vip_pay_exp / (nextVip?.pay || 1)) * 100;
+                        const betPercent = (vipInfo.vip_exp / (nextVip?.bet || 1)) * 100;
+                        return (
+                            <SwiperSlide key={item.id}>
+                                <div
+                                    className={clsx(styles.vipCard, {
+                                        [styles.disabled]: item.id > (vipInfo?.vip_level || 0),
+                                    })}
+                                    style={{
+                                        background: `linear-gradient(60deg, var(--primary1) 10%, ${curVipCfg.startColor} 100%)`,
+                                    }}
+                                >
+                                    <div className="w-[70%] text-[.12rem]">
+                                        <div className="py-[10px] text-[30px] font-black">
+                                            VIP {item.id}
                                         </div>
+                                        {showInfo.pay > 0 && (
+                                            <>
+                                                <div className="flex items-center justify-between text-[.1rem]">
+                                                    <div className="uppercase">Depósito</div>
+                                                    <div className="uppercase">
+                                                        <span className="text-[var(--textColor4)]">
+                                                            {formatAmount(vipInfo.vip_pay_exp)}
+                                                        </span>
+                                                        <span className="text-[var(--textColor1)]">
+                                                            &nbsp;/&nbsp;
+                                                            {formatAmount(nextVip?.pay || 0)}
+                                                        </span>
+                                                    </div>
+                                                </div>
+                                                <ProgressBar
+                                                    percent={payPercent}
+                                                    style={{
+                                                        "--track-color": "var(--primary2)",
+                                                        "--track-width": "6px",
+                                                        "--fill-color": "var(--textColor4)",
+                                                    }}
+                                                />
+                                            </>
+                                        )}
+
+                                        {showInfo.bet > 0 && (
+                                            <>
+                                                <div className="mt-[.1rem] flex items-center justify-between text-[.1rem]">
+                                                    <div className="uppercase">APOSTAS</div>
+                                                    <div className="uppercase">
+                                                        <span className="text-[var(--textColor4)]">
+                                                            {formatAmount(vipInfo.vip_exp)}
+                                                        </span>
+                                                        <span className="text-[var(--textColor1)]">
+                                                            &nbsp;/&nbsp;
+                                                            {formatAmount(nextVip?.bet || 0)}
+                                                        </span>
+                                                    </div>
+                                                </div>
+                                                <ProgressBar
+                                                    percent={betPercent}
+                                                    style={{
+                                                        "--track-color": "var(--primary2)",
+                                                        "--track-width": "6px",
+                                                        "--fill-color": "var(--textColor4)",
+                                                    }}
+                                                />
+                                            </>
+                                        )}
                                     </div>
-                                    <ProgressBar
-                                        percent={20}
-                                        style={{
-                                            "--track-color": "var(--primary2)",
-                                            "--track-width": "6px",
-                                            "--fill-color": "var(--textColor4)",
-                                        }}
+
+                                    <img
+                                        className={styles.vipIcon}
+                                        src={`/vipIcon/${item.id}.webp`}
+                                        alt=""
                                     />
-                                    <div className="mt-[.1rem] flex items-center justify-between text-[.1rem]">
-                                        <div className="uppercase">APOSTAS</div>
-                                        <div className="uppercase">
-                                            <span className="text-[var(--textColor4)]">0.00</span>
-                                            <span className="text-[var(--textColor1)]">/10</span>
-                                        </div>
-                                    </div>
-                                    <ProgressBar
-                                        percent={20}
-                                        style={{
-                                            "--track-color": "var(--primary2)",
-                                            "--track-width": "6px",
-                                            "--fill-color": "var(--textColor4)",
-                                        }}
+                                    <img
+                                        className={styles.vipIconFooter}
+                                        src="/vipIcon/vip_tuodi_bg.webp"
+                                        alt=""
                                     />
                                 </div>
-
-                                <img
-                                    className={styles.vipIcon}
-                                    src={`/vipIcon/${item.key}.webp`}
-                                    alt=""
-                                />
-                                <img
-                                    className={styles.vipIconFooter}
-                                    src="/vipIcon/vip_tuodi_bg.webp"
-                                    alt=""
-                                />
-                            </div>
-                        </SwiperSlide>
-                    );
-                })}
+                            </SwiperSlide>
+                        );
+                    })}
             </Swiper>
             <div className="">
                 <div

+ 3 - 0
src/app/[locale]/(navbar)/vip/page.module.scss

@@ -177,6 +177,9 @@
         &.gray {
             filter: grayscale(1);
         }
+        &.claimed {
+            opacity: 0.5;
+        }
         .img {
             width: 36%;
             position: absolute;

+ 177 - 81
src/app/[locale]/(navbar)/vip/page.tsx

@@ -1,10 +1,10 @@
 "use client";
-import { CashbackTypes } from "@/api/cashback";
-import { UserVipInfo } from "@/api/user";
+import { getNewVip, LevelInfoItem, RewardInfoItem } from "@/api/user";
 import CustomButton from "@/components/CustomButton";
 import HeaderBack from "@/components/HeaderBack";
 import VipProgress from "@/components/VipProgress";
-import { server } from "@/utils/client";
+import feedback from "@/feedback";
+import { formatAmount } from "@/utils";
 import { useRequest } from "ahooks";
 import clsx from "clsx";
 import React from "react";
@@ -12,53 +12,29 @@ import List from "./List";
 import styles from "./page.module.scss";
 import VipCard from "./VipCard";
 
-const getVipApi = async () => {
-    return server
-        .request<UserVipInfo>({
-            url: "/v1/api/user/user_vip_info",
-            method: "POST",
-        })
-        .then((res) => {
-            if (res.code === 200) return res.data;
-        });
-};
-const getCashBackApi = async (): Promise<CashbackTypes> => {
-    return server
-        .request<CashbackTypes>({
-            url: "/v1/api/front/activity_cash",
-            method: "post",
-        })
-        .then((res) => {
-            return res.data;
-        })
-        .catch((error) => {
-            return {
-                rules: [],
-                last_period: { end_time: 0, start_time: 0 },
-                next_period: {
-                    end_time: 0,
-                    start_time: 0,
-                },
-                amount: 0,
-                bet: 0,
-                status: "expired",
-                max_amount: 0,
-            } as CashbackTypes;
-        });
-};
+export interface RewardItemData extends RewardInfoItem {
+    title: string;
+    renderType: 1 | 2;
+    img?: string;
+    endTime?: number;
+    typeStr?: string;
+}
+
+const renderType1 = [2, 3, 4];
 
 const Page = () => {
     const [actLevel, setActLevel] = React.useState<number>(0);
     const [opacity, setOpacity] = React.useState<number>(0);
     const containerRef = React.useRef<HTMLDivElement | null>(null);
 
-    const { data: userVip } = useRequest<any, any>(getVipApi, {
-        pollingErrorRetryCount: 1,
-    });
-    const { data: cashbackInfo } = useRequest<any, any>(getCashBackApi, {
+    const { data: userVip, run: runVip } = useRequest<any, any>(getNewVip, {
         pollingErrorRetryCount: 1,
     });
 
+    const vipInfo = React.useMemo(() => {
+        return userVip?.data || {};
+    }, [userVip]);
+
     React.useEffect(() => {
         setTimeout(() => {
             const dom = containerRef.current;
@@ -84,32 +60,106 @@ const Page = () => {
         }
     };
 
-    const gridBoxCfg = React.useMemo(() => {
-        return [
-            {
+    const actVipInfo = React.useMemo(() => {
+        return vipInfo?.level_info?.find((item: LevelInfoItem) => item.id === actLevel);
+    }, [actLevel, vipInfo]);
+    const rewardsList = React.useMemo(() => {
+        if (!vipInfo?.reward_info?.length) return [];
+        const rewardCfg: any = {
+            1: {
+                title: "VIP Upgrade Bônus",
+                img: "/vip/vip_pdn_icon.webp",
+            },
+            2: {
+                title: "Bônus Diária",
+                typeStr: "day",
+                img: "/vip/vip_bs_icon.webp",
+            },
+            3: {
                 title: "Bônus Semanal",
+                typeStr: "week",
                 img: "/vip/vip_bs_icon.webp",
-                value: "R$ 12.00 / R$ 23.00",
-                type: "full",
             },
-            {
+            4: {
                 title: "Bônus Mensal",
+                typeStr: "month",
                 img: "/vip/vip_bm_icon.webp",
-                value: "R$ 12.00 / R$ 23.00",
-                type: "full",
             },
-            {
-                title: "VIP Upgrade Bônus",
-                img: "/vip/vip_pdn_icon.webp",
-                value: "R$ 12.00",
+            5: {
+                title: "Auxílio de falência",
+                img: "/vip/vip_af_icon.webp",
             },
-            {
+            6: {
                 title: "Auxílio de falência",
                 img: "/vip/vip_af_icon.webp",
-                value: "R$ 12.00",
+            },
+        };
+        const result: RewardItemData[] = [
+            {
+                ...rewardCfg[1],
+                ...actVipInfo,
+                renderType: 2,
             },
         ];
-    }, []);
+        let isFirst = true;
+        vipInfo?.reward_info.forEach((item: any) => {
+            const res: any = {
+                ...item,
+                ...(rewardCfg[item.type] || {}),
+            };
+            if (renderType1.includes(item.type)) {
+                res.renderType = 1;
+            } else {
+                res.renderType = 2;
+            }
+            if (item.type === 5 && item.status == 2) {
+                isFirst = false;
+                return;
+            }
+            if (item.type === 6 && isFirst) {
+                return;
+            }
+
+            res.endTime = item.start_time - Date.now() / 1000;
+            result.push(res);
+        });
+        result.sort((a, b) => a.renderType - b.renderType);
+        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>
+                    </div>
+                );
+            },
+            width: "80%",
+            useDefaultFooter: false,
+        });
+    };
+    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";
+        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"}
+            >
+                {text}
+            </CustomButton>
+        );
+    };
 
     return (
         <div className={clsx("flex h-[100%] flex-col", styles.pageContainer)}>
@@ -124,37 +174,83 @@ const Page = () => {
             />
             <main className={"main-header hasFlag stickyFlag"} ref={containerRef}>
                 <>
-                    <VipCard actKey={actLevel} onChange={(level) => setActLevel(level)}></VipCard>
+                    <VipCard
+                        vipInfo={vipInfo}
+                        actKey={actLevel}
+                        onChange={(level) => setActLevel(level)}
+                    ></VipCard>
                     <VipProgress
                         actKey={actLevel}
                         onChange={(level) => setActLevel(level)}
                     ></VipProgress>
                     <div className={styles.giftBox}>
-                        {gridBoxCfg.map((item) => {
-                            return (
-                                <div
-                                    key={item.title}
-                                    className={clsx(styles.giftItem, "rounded-[10px] py-[6px]", {
-                                        "w-full": item.type === "full",
-                                        "col-span-2": item.type === "full",
-                                    })}
-                                >
-                                    <div className="relative z-[1] flex h-[100%] flex-col items-start justify-between">
-                                        <div className="text-[.13rem] font-bold">{item.title}</div>
-                                        <div className="text-[.17rem] font-bold">{item.value}</div>
-                                        <CustomButton
-                                            className={clsx("!py-[8px] !text-[12px]", {
-                                                "w-full": item.type !== "full",
-                                                "w-[157px]": item.type == "full",
-                                            })}
-                                        >
-                                            Unopened
-                                        </CustomButton>
+                        {!!rewardsList?.length &&
+                            rewardsList.map((item) => {
+                                return (
+                                    <div
+                                        key={item.title}
+                                        className={clsx(
+                                            styles.giftItem,
+                                            "rounded-[10px] py-[6px]",
+                                            {
+                                                "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),
+                                            }
+                                        )}
+                                    >
+                                        <div className="relative z-[1] flex h-[100%] flex-col items-start justify-between">
+                                            <div className="text-[.13rem] font-bold">
+                                                {item.title}
+                                            </div>
+                                            {item.renderType === 1 && (
+                                                <>
+                                                    {!!item?.reward?.length &&
+                                                        item?.reward.map((citem) => {
+                                                            return (
+                                                                <div
+                                                                    key={citem.coin_type}
+                                                                    className="text-[.17rem] font-black"
+                                                                >
+                                                                    R$ {formatAmount(citem.amount)}{" "}
+                                                                    {!!item.double_pay && (
+                                                                        <>
+                                                                            / R${" "}
+                                                                            {formatAmount(
+                                                                                citem.amount *
+                                                                                    item.multiple
+                                                                            )}
+                                                                        </>
+                                                                    )}
+                                                                </div>
+                                                            );
+                                                        })}
+                                                </>
+                                            )}
+                                            {item.renderType === 2 && (
+                                                <>
+                                                    {!!item?.reward?.length &&
+                                                        item?.reward.map((citem) => {
+                                                            return (
+                                                                <div
+                                                                    key={citem.coin_type}
+                                                                    className="text-[.17rem] font-black"
+                                                                >
+                                                                    R$ {formatAmount(citem.amount)}
+                                                                </div>
+                                                            );
+                                                        })}
+                                                </>
+                                            )}
+                                            {getBtn(item)}
+                                        </div>
+                                        <img src={item.img} className={styles.img} alt="" />
                                     </div>
-                                    <img src={item.img} className={styles.img} alt="" />
-                                </div>
-                            );
-                        })}
+                                );
+                            })}
                         <div
                             className={clsx(
                                 styles.giftItem,

+ 88 - 1
src/components/Agent/index.tsx

@@ -50,7 +50,94 @@ export const AgentSuffix = ({ locale = "br" }: { locale?: string }) => {
 const Agent: React.FC<Props> = ({ step = 1, locale = "br" }) => {
     return (
         <div className={clsx(styles.agentBox)}>
-            {step == 1 && (
+            {step === 1 && !getToken() && (
+                <>
+                    <div className="flex justify-center pb-[.1rem] text-[.14rem] text-[16px] font-black">
+                        ❤️ Bem vindo ao 8g.game ❤️
+                    </div>
+                    <div className={clsx(styles.intro)}>
+                        <div className="flex flex-1 flex-col overflow-x-hidden text-[14px]">
+                            <div className="flex flex-col">
+                                <span>
+                                    🔥 Cadastre-se agora e desbloqueie TRÊS SUPER RECOMPENSAS!
+                                </span>
+                                <div className="break-all">
+                                    🎁 Ganhe R$3 ou R$5 imediatamente ao se cadastrar – GRÁTIS!
+                                </div>
+                                <div className="break-all">
+                                    🎟 Além disso, receba uma raspadinha da sorte – prêmio mínimo de
+                                    R$7 e a chance de ganhar até R$77 ou prêmios incríveis como
+                                    iPhone 16 e Nintendo Switch!
+                                </div>
+                                <div className="break-all">
+                                    💰 Bônus de até 150% no seu primeiro depósito – multiplique seus
+                                    ganhos!
+                                </div>
+                            </div>
+                            <div className="flex flex-col">
+                                <span>
+                                    🎁 💎 Benefícios exclusivos – DESBLOQUEIE 5 TIPOS DE RECOMPENSAS
+                                    TODOS OS DIAS!
+                                </span>
+                                <div className="break-all">
+                                    🏆 1. Jackpot Diário – quanto maior sua posição no ranking,
+                                    maior o prêmio!
+                                </div>
+                                <div className="break-all">
+                                    🎡 2. Participe da Roleta da Sorte e concorra a MacBook, Apple
+                                    Watch e mais prêmios exclusivos!
+                                </div>
+                                <div className="break-all">
+                                    💲 3. Colete pontos de missão e troque por dinheiro real – até
+                                    R$1000 em saque imediato!
+                                </div>
+                                <div className="break-all">
+                                    🎫 4. Colete Cartões HAPPY e troque por R$100 na hora!
+                                </div>
+                                <div className="break-all">
+                                    🎁 5. Bônus surpresa em dinheiro real – a qualquer momento, você
+                                    pode ser premiado!
+                                </div>
+                            </div>
+                            <div className="flex flex-col">
+                                <span>❤️ Proteção tripla de bônus – NUNCA SAIA PERDENDO!</span>
+                                <div className="break-all">
+                                    🛡 Fundo de resgate – continue jogando com segurança!
+                                </div>
+                                <div className="break-all">
+                                    🔄 Reembolso diário de perdas – dinheiro de volta todos os dias!
+                                </div>
+                                <div className="break-all">
+                                    💰 Reembolso semanal de perdas – não perca a chance de recuperar
+                                    ainda mais!
+                                </div>
+                            </div>
+                            <div className="flex flex-col">
+                                <span>
+                                    💵 💰 Ganhe MAIS DE R$10.000 por mês com nosso SUPER PROGRAMA DE
+                                    MARKETING!
+                                </span>
+                                <div className="break-all">
+                                    📢 Convide seus amigos e ganhe R$30 para cada um que fizer uma
+                                    recarga!
+                                </div>
+                                <div className="break-all">
+                                    💰 Comissões multinível – pagamentos diários e renda crescente!
+                                </div>
+                                <div className="break-all">
+                                    ⚡️ Saque seu dinheiro na hora – sem burocracia!
+                                </div>
+                            </div>
+                            <div className="flex flex-col">
+                                <span>
+                                    🔥 📢 Jogue, ganhe e retire seu dinheiro instantaneamente!
+                                </span>
+                            </div>
+                        </div>
+                    </div>
+                </>
+            )}
+            {step == 1 && getToken() && (
                 <>
                     <div className="flex justify-center pb-[.1rem] text-[.14rem] text-[16px] font-black">
                         ❤️ Bem vindo ao 8g.game ❤️

+ 3 - 3
src/components/Layout/Sidebar.tsx

@@ -3,7 +3,7 @@ import { ContactType, getContactsApi, getSidebarActivitiesApi } from "@/api/conf
 import { BannerRep, GroupType } from "@/api/home";
 import Box from "@/components/Box";
 import Item from "@/components/Item";
-import { Link, usePathname, useRouter } from "@/i18n/routing";
+import { usePathname, useRouter } from "@/i18n/routing";
 import { useProviderStore } from "@/stores/useProvider";
 import { useSystemStore } from "@/stores/useSystemStore";
 import { useWalletStore } from "@/stores/useWalletStore";
@@ -245,9 +245,9 @@ const Sidebar: FC<PropsWithChildren<Props>> = (props) => {
                 ),
                 renderWrap: ({ children }: any) => {
                     return serviceUrl ? (
-                        <Link target={"_blanl"} href={serviceUrl}>
+                        <a target={"_blank"} href={serviceUrl}>
                             {children}
-                        </Link>
+                        </a>
                     ) : (
                         <div>{children}</div>
                     );

+ 51 - 46
src/components/VipProgress/index.tsx

@@ -1,6 +1,7 @@
 "use client";
-import { VipProgressMap } from "@/enums";
-import { useVipStore } from "@/stores/useVipStore";
+import { getNewVip, NewVip } from "@/api/user";
+import { VipItem, VipProgressMap } from "@/enums";
+import { useRequest } from "ahooks";
 import clsx from "clsx";
 import React from "react";
 import "swiper/css";
@@ -14,30 +15,28 @@ interface Props {
 }
 
 const VipProgress: React.FC<Props> = ({ actKey = 0, onChange }) => {
-    const { vipData } = useVipStore();
+    const { data: userVip, run: runVip } = useRequest<any, any>(getNewVip, {
+        pollingErrorRetryCount: 1,
+    });
+
+    const vipInfo: NewVip = React.useMemo(() => {
+        return userVip?.data || {};
+    }, [userVip]);
+
+    // const { vipData } = useVipStore();
     const [act, setAct] = React.useState<number>(0);
     const swiperRef = React.useRef<SwiperClass | null>(null);
-    const [cache, setCache] = React.useState<any>(null);
+
     React.useEffect(() => {
-        if (JSON.stringify(vipData) !== JSON.stringify(cache)) {
-            setAct(vipData?.vip_level || 0);
-        }
-        setCache(vipData);
-    }, [vipData]);
+        if (!vipInfo?.vip_level) return;
+        setAct(vipInfo.vip_level);
+        swiperRef.current?.slideTo(vipInfo.vip_level);
+    }, [vipInfo]);
     React.useEffect(() => {
         setAct(actKey);
         swiperRef.current?.slideTo(actKey);
     }, [actKey]);
-    const VipList = React.useMemo(() => {
-        const result = [];
-        for (let [key, value] of VipProgressMap) {
-            result.push({
-                key,
-                ...value,
-            });
-        }
-        return result;
-    }, []);
+
     const doChange = (key: number) => {
         if (key !== act && typeof onChange === "function") {
             setAct(key);
@@ -45,7 +44,6 @@ const VipProgress: React.FC<Props> = ({ actKey = 0, onChange }) => {
             onChange(key);
         }
     };
-    //act > 2 && act < VipList.length - 2
     return (
         <div className={styles.VipProgress}>
             <div className="px-[.1rem]">
@@ -60,35 +58,42 @@ const VipProgress: React.FC<Props> = ({ actKey = 0, onChange }) => {
                         swiperRef.current = swiper;
                     }}
                 >
-                    {VipList.map((item) => {
-                        return (
-                            <SwiperSlide key={item.key} className="relative pb-[.15rem]">
-                                <div
-                                    className={clsx(styles.VipItem, {
-                                        [styles.disabled]: item.key > (vipData?.vip_level || 0),
-                                        [styles.active]: item.key === act,
-                                    })}
-                                    onClick={() => doChange(item.key)}
-                                >
+                    {!!vipInfo?.level_info?.length &&
+                        vipInfo.level_info.map((item) => {
+                            const curVipCfg = VipProgressMap.get(item.id) as VipItem;
+
+                            return (
+                                <SwiperSlide key={item.id} className="relative pb-[.15rem]">
                                     <div
-                                        className={clsx(styles.VipItemIcon)}
-                                        style={{
-                                            background: `linear-gradient(180deg, ${item.startColor || "#535e7e"} 0%, ${item.endColor || "#f3d439"} 100%)`,
-                                        }}
+                                        className={clsx(styles.VipItem, {
+                                            [styles.disabled]: item.id > (vipInfo?.vip_level || 0),
+                                            [styles.active]: item.id === act,
+                                        })}
+                                        onClick={() => doChange(item.id)}
                                     >
-                                        <img className={"w-[100%]"} src={item.icon} alt="" />
+                                        <div
+                                            className={clsx(styles.VipItemIcon)}
+                                            style={{
+                                                background: `linear-gradient(180deg, ${curVipCfg.startColor || "#535e7e"} 0%, ${curVipCfg.endColor || "#f3d439"} 100%)`,
+                                            }}
+                                        >
+                                            <img
+                                                className={"w-[100%]"}
+                                                src={curVipCfg.icon}
+                                                alt=""
+                                            />
+                                        </div>
+                                        <div className="text-[.12rem]">Vip {curVipCfg.text}</div>
+                                        <div
+                                            className={clsx(
+                                                "absolute bottom-[0.035rem] z-[1] h-[4px] w-[4px] rounded-[50%] bg-[#7d8582]",
+                                                styles.point
+                                            )}
+                                        ></div>
                                     </div>
-                                    <div className="text-[.12rem]">Vip {item.text}</div>
-                                    <div
-                                        className={clsx(
-                                            "absolute bottom-[0.035rem] z-[1] h-[4px] w-[4px] rounded-[50%] bg-[#7d8582]",
-                                            styles.point
-                                        )}
-                                    ></div>
-                                </div>
-                            </SwiperSlide>
-                        );
-                    })}
+                                </SwiperSlide>
+                            );
+                        })}
                 </Swiper>
             </div>
             <div className="absolute bottom-[0] left-[0] right-[0] h-[.11rem] bg-[#fde997]"></div>

+ 1 - 1
src/enums/index.tsx

@@ -166,7 +166,7 @@ export enum JackpotStatusEnum {
     WAIT_OPEN = "waitOpen",
 }
 
-interface VipItem {
+export interface VipItem {
     text: string;
     icon: string;
     startColor?: string;

+ 6 - 5
src/feedback/dialog/component.tsx

@@ -8,9 +8,9 @@ import { ModalBoxResType } from "./index";
 interface Props {
     callback?: (p: keyof ModalBoxResType) => void;
     className?: string;
-    content?: React.ReactNode;
+    content?: ((p?: any) => React.ReactNode) | React.ReactNode;
     suffix?: React.ReactNode;
-    footer?: React.ReactNode;
+    footer?: (p?: any) => React.ReactNode;
     useDefaultFooter?: boolean;
     confirmText?: string;
     clsssName?: string;
@@ -35,7 +35,7 @@ const Components: React.FC<Props> = ({
         }, 100);
     }, []);
 
-    const doClose = (p: keyof ModalBoxResType) => {
+    const doClose = (p: keyof ModalBoxResType | Record<string, any>) => {
         setAnimateType(0);
         if (typeof props?.close === "function") {
             props.close(p);
@@ -52,7 +52,8 @@ const Components: React.FC<Props> = ({
             }}
         >
             <div className={clsx(styles.modalBoxContainer, className)}>
-                {content}
+                {React.isValidElement(content) && content}
+                {typeof content === "function" && content({ ...props, doClose })}
                 {useDefaultFooter && (
                     <div className={styles.footer}>
                         {!footer && (
@@ -67,7 +68,7 @@ const Components: React.FC<Props> = ({
                     </div>
                 )}
 
-                {footer}
+                {!!footer && footer({ ...props, doClose })}
             </div>
             {suffix}
             <div className={styles.closeBtn} onClick={() => doClose("cancel")}>

+ 12 - 6
src/feedback/dialog/index.tsx

@@ -8,7 +8,7 @@ const siblingKey = "Component";
 
 export interface ModalState {
     title?: string;
-    content?: string | React.ReactNode;
+    content?: ((p?: any) => React.ReactNode) | React.ReactNode;
     confirmText?: string;
     cancelText?: string;
     cancelColor?: string;
@@ -16,6 +16,7 @@ export interface ModalState {
     cancelBgColor?: string;
     confirmBgColor?: string;
     width?: number | string;
+    footer?: React.ReactNode | null;
     showCancel?: boolean;
     titleStyle?: React.CSSProperties;
     contentStyle?: React.CSSProperties;
@@ -25,14 +26,15 @@ export interface ModalState {
 }
 
 export interface ModalBoxResType {
-    cancel: boolean;
-    confirm: boolean;
+    cancel?: boolean;
+    confirm?: boolean;
+    [key: string]: any;
 }
 
 export const showModal = (opts: ModalState = {}): Promise<ModalBoxResType> => {
     return new Promise((resolve) => {
         const siblingCom = feedbackStatus.get(moduleName, siblingKey);
-        const res: ModalBoxResType = {
+        let res: ModalBoxResType = {
             confirm: false,
             cancel: false,
         };
@@ -49,10 +51,14 @@ export const showModal = (opts: ModalState = {}): Promise<ModalBoxResType> => {
             ...defaultProps,
             ...opts,
         };
-        const modalCallback = (cbRes: keyof ModalBoxResType) => {
+        const modalCallback = (cbRes: keyof ModalBoxResType | Record<string, any>) => {
             const sCom = feedbackStatus.get(moduleName, siblingKey);
             sCom.destroy();
-            res[cbRes] = true;
+            if (typeof cbRes === "string") {
+                res[cbRes] = true;
+            } else {
+                res = cbRes as any;
+            }
             feedbackStatus.removeKey(moduleName, siblingKey);
             resolve(res);
         };

+ 3 - 3
src/utils/index.ts

@@ -66,10 +66,10 @@ export const isInStandaloneMode = () =>
     window.matchMedia("(display-mode: standalone)").matches ||
     document.referrer.includes("android-app://");
 
-export const formatAmount = (amount: string | number) => {
-    if (!amount) return new BigNumber(0).toFormat(2);
+export const formatAmount = (amount: string | number, fixed = 2) => {
+    if (!amount) return new BigNumber(0).toFormat(fixed);
 
-    return new BigNumber(amount).toFormat(2);
+    return new BigNumber(amount).toFormat(fixed);
 };
 export const goBlankPage = async (handler: Function | string, target = "_self") => {
     const isFunHanlder = typeof handler === "function";