Before 10 месяцев назад
Родитель
Сommit
41b42ae1ad

+ 1 - 1
messages/br.json

@@ -259,7 +259,7 @@
     "content6-3":"Aposta válidas em equiper[num] - Total de valor de apostas válidas provenientes de indicações e contribuições de suas equipes. num - Número total de indicações e membros de suas equipes que contribuíram com apostas válidas."
   },
   "cashback": {
-
+    "cashbackTitle": "Cashback 25%"
   },
   "code": {
       "1005": "Nome de usuário ou senha incorreta. ",

+ 3 - 0
messages/en.json

@@ -259,6 +259,9 @@
     "content6-2":"Novos Jogadores - Novos jogadores pagantes entre os usuários registrados de hoje",
     "content6-3":"Aposta válidas em equiper[num] - Total de valor de apostas válidas provenientes de indicações e contribuições de suas equipes. num - Número total de indicações e membros de suas equipes que contribuíram com apostas válidas."
   },
+  "cashback": {
+    "cashbackTitle": "Cashback 25%"
+  },
   "code": {
     "1005": "Invalid username or password.",
     "1009": "There is no such user",

BIN
public/img/free.png


+ 69 - 0
src/api/cashback.ts

@@ -0,0 +1,69 @@
+export interface CashbackTypes {
+    /**
+     * 返现金额
+     */
+    amount: number;
+    /**
+     * 下注数量
+     */
+    bet: number;
+    /**
+     * 上一周期时间
+     */
+    last_period: LastPeriod;
+    /**
+     * 下一周期时间
+     */
+    next_period: NextPeriod;
+    /**
+     * 返现规则
+     */
+    rules: Rule[];
+    /**
+     * 领取状态: 进行中running、待领取pending、已领取received、已过期expired
+     */
+    status: string;
+}
+
+/**
+ * 上一周期时间
+ */
+export interface LastPeriod {
+    /**
+     * 结束时间戳,单位秒
+     */
+    end_time: number;
+    /**
+     * 开始时间戳,单位秒
+     */
+    start_time: number;
+}
+
+/**
+ * 下一周期时间
+ */
+export interface NextPeriod {
+    /**
+     * 结束时间戳,单位秒
+     */
+    end_time: number;
+    /**
+     * 开始时间戳,单位秒
+     */
+    start_time: number;
+}
+
+export interface Rule {
+    /**
+     * 下注金额
+     */
+    aposta: number;
+    /**
+     * 返现百分比
+     */
+    cashback: number;
+    /**
+     * 会员等级
+     */
+    level: number;
+}

+ 2 - 0
src/app/[locale]/(TabBar)/(ordinary)/deposit/DepositData.tsx

@@ -1,6 +1,7 @@
 "use client";
 import { DepositsTypes } from "@/api/depositsApi";
 import { getUserRechargeApi } from "@/api/user";
+import actions from "@/app/[locale]/(TabBar)/(ordinary)/deposit/actions";
 import ButtonOwn from "@/components/ButtonOwn";
 import { Toast } from "antd-mobile";
 import { useTranslations } from "next-intl";
@@ -37,6 +38,7 @@ const DepositData: FC<Props> = (props) => {
         if (res.code === 200) {
             setAmount("");
             Toast.show({ icon: "success", content: t("RechargeSuc"), maskClickable: false });
+            await actions();
         }
     };
     const titleChangeHandler = (item: DepositsTypes, index: number) => {

+ 8 - 0
src/app/[locale]/(TabBar)/(ordinary)/deposit/actions.ts

@@ -0,0 +1,8 @@
+"use server";
+import { revalidatePath } from "next/cache";
+
+const actions = async () => {
+    revalidatePath("/profile");
+};
+
+export default actions;

+ 60 - 0
src/app/[locale]/(navbar)/cashback/@cashbackInfo/CashbackTable.tsx

@@ -0,0 +1,60 @@
+"use client";
+import { CashbackTypes, Rule } from "@/api/cashback";
+import Box from "@/components/Box";
+import Table, { TableHeaderItem } from "@/components/Table";
+import { JSX } from "react";
+
+interface Props {
+    cashbackInfo: CashbackTypes;
+}
+const Page = (props: Props) => {
+    const { cashbackInfo } = props;
+    const columns: TableHeaderItem[] = [
+        {
+            title: <div className={"text-center text-primary-color"}>VIP</div>,
+            dataIndex: "level",
+            align: "center",
+            width: "20%",
+            render: (item: Rule) => (
+                <div className={"text-[0.13rem] font-bold text-[#2b2b2b]"}>{item.level}</div>
+            ),
+        },
+        {
+            title: <div className={"text-center text-primary-color"}>APOSTA</div>,
+            dataIndex: "aposta",
+            align: "center",
+            width: "40%",
+            render: (item: Rule) => (
+                <div className={"text-[0.13rem] font-bold text-[#2b2b2b]"}>{item.aposta} + BRL</div>
+            ),
+        },
+        {
+            title: (
+                <div className={"text-center text-primary-color"}>CASHBACK</div>
+            ) as JSX.Element,
+            dataIndex: "cashback",
+            align: "center",
+            render: (item: Rule) => (
+                <div className={"text-[0.13rem] font-bold text-[#2b2b2b]"}>{item.cashback}%</div>
+            ),
+        },
+    ];
+    const loadMore = async () => {
+        return Promise.resolve();
+    };
+    return (
+        <Box className={"mt-[10px] rounded-[10px] bg-[#ededed]"}>
+            <div> VIP cashback statuses </div>
+            <Table
+                columns={columns}
+                dataSource={cashbackInfo.rules}
+                loadMore={loadMore}
+                hasMore={false}
+                isLoadMore={false}
+                isBackground={true}
+            />
+        </Box>
+    );
+};
+
+export default Page;

+ 55 - 0
src/app/[locale]/(navbar)/cashback/@cashbackInfo/Week.tsx

@@ -0,0 +1,55 @@
+import { CashbackTypes } from "@/api/cashback";
+import Box from "@/components/Box";
+import { timeFormat } from "@/utils/methods";
+import { getLocale } from "next-intl/server";
+import Extract from "./components/Extract";
+
+interface Props {
+    cashbackInfo: CashbackTypes;
+}
+const Page = async (props: Props) => {
+    const { cashbackInfo } = props;
+    const local = await getLocale();
+    console.log(`🚀🚀🚀🚀🚀-> in Week.tsx on 11`, cashbackInfo);
+    return (
+        <Box className={"mt-[10px] rounded-[10px] bg-[#e8e8e8]"}>
+            <div className={"flex"}>
+                <div className={"flex-1"}>
+                    <h1 className={"text-[0.18rem] font-black text-primary-color"}>
+                        Seu Cashback de Semanal
+                    </h1>
+                    <p className={"text-[0.12rem]"}>
+                        <span>Você ganhará </span>
+                        <span className={"text-primary-color"}>{cashbackInfo.amount ?? "???"}</span>
+                        <span> BRL em cashback jogando esta semana.</span>
+                    </p>
+                </div>
+
+                <div className={"relative flex-shrink-0"}>
+                    <img
+                        src="/img/free.png"
+                        alt=""
+                        className={"absolute -left-[0.1rem] bottom-[0.15rem] w-[0.4rem]"}
+                    />
+                    <img src="/img/cash.png" alt="" className={"ml-[0.08rem] w-[0.8rem]"} />
+                </div>
+            </div>
+            <p className={"mb-[0.05rem] text-[0.12rem] text-[#ff9323]"}>
+                <span>
+                    Periodo {timeFormat(cashbackInfo.last_period.start_time, local)} ~{" "}
+                    {timeFormat(cashbackInfo.last_period.end_time, local)}
+                </span>
+            </p>
+            <Extract />
+
+            <div className={"mt-[0.05rem]"}>
+                <p>Tempo de reivindicação</p>
+                <p>
+                    {timeFormat(cashbackInfo.next_period.start_time, local)} ~{" "}
+                    {timeFormat(cashbackInfo.next_period.end_time, local)}
+                </p>
+            </div>
+        </Box>
+    );
+};
+export default Page;

+ 22 - 0
src/app/[locale]/(navbar)/cashback/@cashbackInfo/components/Extract.tsx

@@ -0,0 +1,22 @@
+"use client";
+import ButtonOwn from "@/components/ButtonOwn";
+import { server } from "@/utils/client";
+
+const Extract = () => {
+    const getCashbackGiveApi = () => {
+        return server.post({
+            url: "/api/v1/front/activity_cash_give",
+        });
+    };
+    return (
+        <ButtonOwn
+            active={true}
+            style={{ height: "0.28rem", lineHeight: "0.28rem" }}
+            callbackFun={getCashbackGiveApi}
+        >
+            <span className={"text-[0.1rem]"}>Reivindicar Agora</span>
+        </ButtonOwn>
+    );
+};
+
+export default Extract;

+ 20 - 0
src/app/[locale]/(navbar)/cashback/@cashbackInfo/components/Progress.tsx

@@ -0,0 +1,20 @@
+"use client";
+import { ProgressBar } from "antd-mobile";
+import { FC } from "react";
+type Props = {
+    num: number;
+};
+const Progress: FC<Props> = (props) => {
+    const { num } = props;
+    return (
+        <ProgressBar
+            percent={num}
+            style={{
+                "--fill-color": "#fb8b05",
+                "--track-width": "0.0694rem",
+            }}
+        />
+    );
+};
+
+export default Progress;

Разница между файлами не показана из-за своего большого размера
+ 42 - 0
src/app/[locale]/(navbar)/cashback/@cashbackInfo/page.tsx


+ 14 - 3
src/app/[locale]/(navbar)/cashback/layout.tsx

@@ -1,3 +1,4 @@
+import Box from "@/components/Box";
 import HeaderBack from "@/components/HeaderBack";
 import { getTranslations } from "next-intl/server";
 import { ReactNode } from "react";
@@ -5,15 +6,25 @@ import { ReactNode } from "react";
 export default async function Layout({
     children,
     params: { locale },
+    cashbackInfo,
+    // cashbackTable,
 }: {
     children: ReactNode;
     params: { locale: string };
+    cashbackInfo: ReactNode;
+    // cashbackTable: ReactNode;
 }) {
-    const t = await getTranslations("ProfilePage");
+    const t = await getTranslations("cashback");
     return (
         <>
-            <HeaderBack showBack={true} title={t("message")} />
-            <main className={"main-header bg-[#282828]"}>{children}</main>
+            <HeaderBack showBack={true} className={"bg-[#0d1933]"} title={t("cashbackTitle")} />
+            <main className={"main-header bg-[#fff] text-[#000]"}>
+                <Box>
+                    {cashbackInfo}
+                    {/*{cashbackTable}*/}
+                    {children}
+                </Box>
+            </main>
         </>
     );
 }

+ 30 - 1
src/app/[locale]/(navbar)/cashback/page.tsx

@@ -1,5 +1,34 @@
 const page = () => {
-    return <div>123</div>;
+    return (
+        <div className={"mt-[0.0694rem]"}>
+            <h1 className={"font-bold"}>TERMOS E REGRAS</h1>
+            <ul className={"text-[0.11rem] leading-[0.18rem]"}>
+                <li>1. O cashback semanal é dado como recompensa todas as semanas. </li>
+                <li>
+                    2. O período sobre o qual é calculado o cashback semanal vai de segunda-feira às
+                    00:00 a domingo às 23:59.
+                </li>
+                <li>
+                    3. Horário de solicitação do cashback: De segunda-feira da próxima semana 06:00
+                    a sexta-feira 23:59, expirará se não for resgatado.
+                </li>
+                <li>
+                    4. O número de Perdas de dinheiro real multiplicado pela % de reembolso é o
+                    reembolso/cashback da semana.
+                </li>
+                <li>
+                    5. Caso você não tenha apostado durante o período em que o cashback estava ativo
+                    ou se seus ganhos da última semana ou ganhos totais são maiores que suas perdas,
+                    você não receberá cashback.
+                </li>
+                <li>6. Limite máximo de recompensa de cashback por pessoa por semana: R$ 10000</li>
+                <li>
+                    7. O valor do cashback pode ser sacar diretamente ou utilizado para continuar
+                    jogando
+                </li>
+            </ul>
+        </div>
+    );
 };
 
 export default page;

+ 26 - 11
src/components/Table/index.tsx

@@ -1,9 +1,9 @@
 import { InfiniteScroll } from "antd-mobile";
 import clsx from "clsx";
-import { FC, ReactNode } from "react";
+import { FC, JSX, ReactNode } from "react";
 type position = "left" | "right" | "center";
-interface TableHeaderItem {
-    title: string;
+export interface TableHeaderItem {
+    title: string | JSX.Element;
     dataIndex: string;
     width?: string | number;
     align?: position;
@@ -21,6 +21,8 @@ interface Props {
     // loadMore 加载更多
     loadMore: (isRetry: boolean) => Promise<void>;
     hasMore: boolean;
+    isLoadMore?: boolean;
+    isBackground?: boolean;
 }
 
 /**
@@ -43,12 +45,25 @@ const TbodyItem = ({ data, config, index, children }: any) => {
 };
 
 const Table: FC<Props> = (props) => {
-    const { columns, loadMore, dataSource, maxHeight, hasMore, threshold = 100 } = props;
+    const {
+        columns,
+        loadMore,
+        dataSource,
+        maxHeight,
+        hasMore,
+        threshold = 100,
+        isLoadMore = true,
+        isBackground = false,
+    } = props;
 
     const cls = clsx(" table-header-group text-[grey] text-[.11rem]");
 
     const bodyCls = clsx(maxHeight ? ` max-h-[${maxHeight}]` : "", "overflow-y-scroll");
 
+    const headerTrCls = clsx(
+        "h-[40px] border-b-1 border-[#e8e8e8]",
+        isBackground && "odd:bg-[#dedede] even:bg-[#d1d1d1]"
+    );
     const colGroup = columns.map((item, index) => {
         return <col key={index} style={{ width: item.width }} />;
     });
@@ -58,7 +73,7 @@ const Table: FC<Props> = (props) => {
             <table className={"w-[100%]"} style={{ tableLayout: "fixed" }}>
                 <colgroup>{colGroup}</colgroup>
                 <thead className={cls}>
-                    <tr className={`h-[40px] border-b-1 border-[#e8e8e8]`}>
+                    <tr className={headerTrCls}>
                         {columns.map((headItem, index) => (
                             <TheadItem headItem={headItem} key={index}></TheadItem>
                         ))}
@@ -69,12 +84,9 @@ const Table: FC<Props> = (props) => {
             <div className={bodyCls} style={{ maxHeight: maxHeight }}>
                 <table className={"w-[100%]"} style={{ tableLayout: "fixed" }}>
                     <colgroup>{colGroup}</colgroup>
-                    <tbody>
+                    <tbody className={""}>
                         {dataSource.map((item, index) => (
-                            <tr
-                                key={index}
-                                className={`h-[40px] border-b-1 border-[#e8e8e8] text-center text-[#999]`}
-                            >
+                            <tr key={index} className={`${headerTrCls} text-center text-[#999]`}>
                                 {columns.map((head, headIndex) => (
                                     <TbodyItem
                                         index={index + 1}
@@ -89,7 +101,10 @@ const Table: FC<Props> = (props) => {
                         ))}
                     </tbody>
                 </table>
-                <InfiniteScroll loadMore={loadMore} hasMore={hasMore}></InfiniteScroll>
+
+                {isLoadMore && (
+                    <InfiniteScroll loadMore={loadMore} hasMore={hasMore}></InfiniteScroll>
+                )}
             </div>
         </div>
     );

+ 1 - 0
tailwind.config.ts

@@ -38,6 +38,7 @@ const config: Config = {
         },
         colors: {
             "primary-color": "#ff6a01",
+            "linear-color": "linear-gradient(180deg, #ffaa30, #ffe6be)",
         },
     },
     plugins: [

Некоторые файлы не были показаны из-за большого количества измененных файлов