feat:

This commit is contained in:
john 2024-07-19 17:05:29 +08:00
parent 173048e8b2
commit cb5f785a24
22 changed files with 472 additions and 114 deletions

View File

@ -12,6 +12,11 @@ html,
src: url("./assets/font/Roboto-Medium.ttf") format("truetype"); src: url("./assets/font/Roboto-Medium.ttf") format("truetype");
} }
@font-face {
font-family: "YouSheBiaoTiHei";
src: url("./assets/font/YouSheBiaoTiHei.ttf") format("truetype");
}
* { * {
-webkit-overflow-scrolling: touch; -webkit-overflow-scrolling: touch;
} }

View File

@ -1,7 +1,7 @@
/* /*
* @LastEditors: John * @LastEditors: John
* @Date: 2024-07-13 10:21:58 * @Date: 2024-07-13 10:21:58
* @LastEditTime: 2024-07-18 18:25:39 * @LastEditTime: 2024-07-19 14:15:42
* @Author: John * @Author: John
*/ */
import { MemoryRouter, Route, Routes } from "react-router-dom"; import { MemoryRouter, Route, Routes } from "react-router-dom";
@ -54,7 +54,7 @@ function App() {
return ( return (
<> <>
{!Token ? ( {Token ? (
<MemoryRouter> <MemoryRouter>
<Routes> <Routes>
<Route path="/*" element={<Index />} /> <Route path="/*" element={<Index />} />

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="345.0001220703125" height="48" viewBox="0 0 345.0001220703125 48"><g><path d="M0,34L13.6896,48L345,48L345,14L331.31,0L0,0L0,34Z" fill="#FFFFFF" fill-opacity="1"/></g></svg>

After

Width:  |  Height:  |  Size: 288 B

1
src/assets/buttom_bg.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="86" height="30" viewBox="0 0 86 30"><g><path d="M0,21.25L8.59347,30L86,30L86,8.75L77.4065,0L0,0L0,21.25Z" fill="#5858FF" fill-opacity="1"/></g></svg>

After

Width:  |  Height:  |  Size: 265 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="86" height="30" viewBox="0 0 86 30"><g><path d="M0,21.25L8.59347,30L86,30L86,8.75L77.4065,0L0,0L0,21.25Z" fill="#8D8B8B" fill-opacity="1"/></g></svg>

After

Width:  |  Height:  |  Size: 265 B

Binary file not shown.

1
src/assets/kuang.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="215" height="157" viewBox="0 0 215 157"><g><g><path d="M0,0L0,15.5L1,15.5L1,1L15.5,1L15.5,0L0,0Z" fill-rule="evenodd" fill="#D8D8D8" fill-opacity="1"/></g><g transform="matrix(-1,0,0,1,429,0)"><path d="M214,0L214,15.5L215,15.5L215,1L229.5,1L229.5,0L214,0Z" fill-rule="evenodd" fill="#D8D8D8" fill-opacity="1"/></g><g transform="matrix(1,0,0,-1,0,313)"><path d="M0,156L0,171.5L1,171.5L1,157L15.5,157L15.5,156L0,156Z" fill-rule="evenodd" fill="#D8D8D8" fill-opacity="1"/></g><g transform="matrix(-1,0,0,-1,429,313)"><path d="M214,156L214,171.5L215,171.5L215,157L229.5,157L229.5,156L214,156Z" fill-rule="evenodd" fill="#D8D8D8" fill-opacity="1"/></g></g></svg>

After

Width:  |  Height:  |  Size: 773 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="346" height="779" viewBox="0 0 346 779"><g><g><g><path d="M0.5,778.5L12.8582,778.5L0.5,766.5L0.5,778.5Z" fill="#5858FF" fill-opacity="1"/><path d="M0,765.31756L0,778.5L0,779L14.0909,779L0,765.31756ZM1,778L11.6255,778L1,767.68244L1,778Z" fill-rule="evenodd" fill="#5858FF" fill-opacity="1"/></g><g transform="matrix(-1,-5.2146120310681e-8,5.2146120310681e-8,-1,690.9999993481736,25.000018016484567)"><path d="M345.5,24.5L357.8582,24.5L345.5,12.5L345.5,24.5Z" fill="#5858FF" fill-opacity="1"/><path d="M345,11.31756L345,24.5L345,25L359.0909,25L345,11.31756ZM346,24L356.6255,24L346,13.68244L346,24Z" fill-rule="evenodd" fill="#5858FF" fill-opacity="1"/></g></g><g><path d="M346,17.789L327.734,0L327.531,0L0,0L0,760.711L18.2655,778.5L346,778.5L346,17.789ZM327.328,1L1,1L1,760.289L18.672,777.5L345,777.5L345,18.211L327.328,1Z" fill-rule="evenodd" fill="#5858FF" fill-opacity="1"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1005 B

1
src/assets/tg_white.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="30" height="30" viewBox="0 0 30 30"><defs><clipPath id="master_svg0_5_4502"><rect x="6" y="6" width="18" height="18" rx="0"/></clipPath></defs><g><g><rect x="0" y="0" width="30" height="30" rx="15" fill="#FFFFFF" fill-opacity="1"/></g><g clip-path="url(#master_svg0_5_4502)"><g><path d="M13.32553,20.5048L13.53979,17.35537L19.3052,12.21589C19.558500000000002,11.98404,19.2468,11.86811,18.9157,12.080639999999999L11.80626,16.524549999999998L8.728749,15.558489999999999C8.0665,15.365269999999999,8.0665,14.92088,8.884572,14.59242L20.844,10.0132582C21.389400000000002,9.762081,21.915300000000002,10.148508,21.701,10.979330000000001L19.6753,20.5048C19.539,21.180999999999997,19.1299,21.3549,18.5456,21.026400000000002L15.44862,18.74651L13.948820000000001,20.1956C13.773520000000001,20.369500000000002,13.63718,20.5048,13.32553,20.5048Z" fill="#000000" fill-opacity="1"/></g></g></g></svg>

After

Width:  |  Height:  |  Size: 1000 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="30" height="30" viewBox="0 0 30 30"><g><g><rect x="0" y="0" width="30" height="30" rx="15" fill="#FFFFFF" fill-opacity="1"/></g><g><path d="M9.0316328,9L14.05078,15.61869L9,21L10.13682,21L14.558869999999999,16.28847L18.13163,21L22,21L16.69834,14.00909L21.3996,9L20.2628,9L16.19047,13.339089999999999L12.9,9L9.0316328,9ZM10.70337,9.825776L12.48048,9.825776L20.328,20.1742L18.55093,20.1742L10.70337,9.825776Z" fill="#000000" fill-opacity="1"/></g></g></svg>

After

Width:  |  Height:  |  Size: 571 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="345.0001220703125" height="68" viewBox="0 0 345.0001220703125 68"><g><path d="M0,54L13.6897,68L345,68L345,14L331.31,0L0,0L0,54Z" fill="#5858FF" fill-opacity="1"/></g></svg>

After

Width:  |  Height:  |  Size: 288 B

View File

@ -6,13 +6,14 @@
justify-content: space-between; justify-content: space-between;
width: 100%; width: 100%;
height: 83px; height: 83px;
padding: 0 39px;
background-color: #000000; background-color: #000000;
z-index: 999; z-index: 999;
li { li {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
justify-content: center;
flex: 1;
span { span {
/* 自动布局子元素 */ /* 自动布局子元素 */
opacity: 1; opacity: 1;

View File

@ -1,7 +1,7 @@
/* /*
* @LastEditors: John * @LastEditors: John
* @Date: 2024-07-13 18:07:43 * @Date: 2024-07-13 18:07:43
* @LastEditTime: 2024-07-15 15:36:30 * @LastEditTime: 2024-07-19 15:42:36
* @Author: John * @Author: John
*/ */
import { useLocation, useNavigate } from "react-router-dom"; import { useLocation, useNavigate } from "react-router-dom";
@ -27,6 +27,16 @@ export default function () {
Home Home
</span> </span>
</li> </li>
<li onClick={() => navigate("/friends")}>
<TeamFill
color={currentpathname == "/friends" ? "#ffffff" : "#adadad"}
/>
<span className={currentpathname == "/friends" ? classes.active : ""}>
Friends
</span>
</li>
<li onClick={() => navigate("/leaderboard")}> <li onClick={() => navigate("/leaderboard")}>
<HistogramOutline <HistogramOutline
color={currentpathname == "/leaderboard" ? "#ffffff" : "#adadad"} color={currentpathname == "/leaderboard" ? "#ffffff" : "#adadad"}
@ -37,14 +47,6 @@ export default function () {
Leaderboard Leaderboard
</span> </span>
</li> </li>
<li onClick={() => navigate("/frends")}>
<TeamFill
color={currentpathname == "/frends" ? "#ffffff" : "#adadad"}
/>
<span className={currentpathname == "/frends" ? classes.active : ""}>
Frends
</span>
</li>
</ul> </ul>
</> </>
); );

View File

@ -25,6 +25,9 @@
/* width: 141px; */ /* width: 141px; */
height: 149px; height: 149px;
margin-top: 31px; margin-top: 31px;
background-image: url("../assets/kuang.svg");
background-repeat: no-repeat;
background-size: contain;
} }
.tip { .tip {
/* 自动布局子元素 */ /* 自动布局子元素 */
@ -53,6 +56,9 @@
gap: 30px; gap: 30px;
margin-top: 17px; margin-top: 17px;
padding-bottom: 165px; padding-bottom: 165px;
.frends_list_tabs {
display: flex;
gap: 10px;
.frends_list_title { .frends_list_title {
opacity: 1; opacity: 1;
@ -64,8 +70,12 @@
font-variation-settings: "opsz" auto; font-variation-settings: "opsz" auto;
font-feature-settings: "kern" on; font-feature-settings: "kern" on;
color: #adadad;
&.frends_list_title_active {
color: #ffffff; color: #ffffff;
} }
}
}
.frends_list_item { .frends_list_item {
display: flex; display: flex;
@ -119,14 +129,16 @@
padding: 17px 15px; padding: 17px 15px;
position: fixed; position: fixed;
bottom: 83px; bottom: 83px;
background-color: #000000; /* background-color: #000000; */
z-index: 999; z-index: 999;
button { button {
width: 345px; width: 345px;
height: 48px; height: 48px;
border-radius: 8px; border-radius: 0px;
opacity: 1; opacity: 1;
background: #ffffff; background-image: url("../assets/big_buttom_bg.svg");
background-repeat: no-repeat;
background-size: contain;
> span { > span {
opacity: 1; opacity: 1;

View File

@ -1,7 +1,7 @@
/* /*
* @LastEditors: John * @LastEditors: John
* @Date: 2024-07-13 16:08:30 * @Date: 2024-07-13 16:08:30
* @LastEditTime: 2024-07-18 18:29:05 * @LastEditTime: 2024-07-19 15:57:27
* @Author: John * @Author: John
*/ */
/* /*
@ -18,35 +18,72 @@ import useUserStore from "@/store/User";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { api_homepage_subordinates_users } from "@/server/api"; import { api_homepage_subordinates_users } from "@/server/api";
import { subordinatesUsers } from "@/server/module"; import { subordinatesUsers } from "@/server/module";
import { cn } from "@/utils";
export default function () { export default function () {
const WebApp = useWebApp(); const WebApp = useWebApp();
const { InvitationCode } = useUserStore(); const { InvitationCode } = useUserStore();
const [frends, setFrends] = useState<subordinatesUsers[]>(); const [frends, setFrends] = useState<subordinatesUsers[]>();
const [currentLevel, setCurrentLevel] = useState(1);
useEffect(() => { useEffect(() => {
(async () => { (async () => {
const { data } = await api_homepage_subordinates_users().send({}); updateFriends(1);
setFrends(data?.data);
})(); })();
return () => {}; return () => {};
}, []); }, []);
async function updateFriends(level: number) {
const { data } = await api_homepage_subordinates_users().send({
queryParams: { level },
});
setFrends(data?.data);
}
return ( return (
<> <>
<div className={classes.frends}> <div className={classes.frends}>
<span className={classes.top_title}> <span className={classes.top_title}>
Invite friends and get more PIONEER Invite friends and get more SCTT
</span> </span>
<img className={classes.logo} src={logo} alt="" /> <img className={classes.logo} src={logo} alt="" />
{frends?.length == 0 ? (
<span className={classes.tip}> <span className={classes.tip}>
Tap on the button to invite your friends Tap on the button to invite your friends
</span> </span>
) : (
<ul className={classes.frends_list}> <ul className={classes.frends_list}>
<span className={classes.frends_list_title}>0 friends</span> <div className={classes.frends_list_tabs}>
<span
className={cn(
classes.frends_list_title,
currentLevel == 1 ? classes.frends_list_title_active : ""
)}
onClick={() => {
setCurrentLevel(1);
updateFriends(1);
}}
>
Level 1
</span>
<span
className={cn(
classes.frends_list_title,
currentLevel == 2 ? classes.frends_list_title_active : ""
)}
onClick={() => {
setCurrentLevel(2);
updateFriends(2);
}}
>
Level 2
</span>
</div>
{frends?.map((v, i) => ( {frends?.map((v, i) => (
<FrendsItem key={i} userName={v.account} point={v.amount} /> <FrendsItem key={i} userName={v.account} point={v.amount} />
))} ))}
</ul> </ul>
)}
<div className={classes.bottom_btn}> <div className={classes.bottom_btn}>
<Button <Button
onClick={() => { onClick={() => {
@ -55,6 +92,7 @@ export default function () {
}?startapp=${InvitationCode}`; }?startapp=${InvitationCode}`;
WebApp.openTelegramLink(`https://t.me/share/url?url=${url}`); WebApp.openTelegramLink(`https://t.me/share/url?url=${url}`);
}} }}
fill="none"
> >
Invite friends Invite friends
</Button> </Button>
@ -69,7 +107,7 @@ function FrendsItem({ userName, point }: { userName: string; point: string }) {
<li className={classes.frends_list_item}> <li className={classes.frends_list_item}>
<Avatar src="" /> <Avatar src="" />
<span>{userName}</span> <span>{userName}</span>
<span>+{point} PIONEER</span> <span>+{point} SCTT</span>
</li> </li>
); );
} }

View File

@ -59,6 +59,155 @@
margin-top: 14px; margin-top: 14px;
} }
.social_task {
background-image: url("../assets/social_task_bg.svg");
background-repeat: no-repeat;
background-size: contain;
width: 345px;
height: 778px;
margin-top: 28px;
padding: 0 19px;
display: flex;
flex-direction: column;
> span {
opacity: 1;
font-family: Roboto;
font-size: 16px;
font-weight: 600;
line-height: normal;
letter-spacing: 0em;
font-variation-settings: "opsz" auto;
font-feature-settings: "kern" on;
color: #9292ff;
margin-top: 21px;
display: block;
}
> ul {
display: flex;
flex-direction: column;
flex: auto;
gap: 8px;
margin-top: 16px;
li {
display: flex;
flex-direction: column;
justify-content: center;
width: 315px;
/* height: 108px; */
border-radius: 12px;
opacity: 1;
background: rgba(132, 132, 144, 0.1);
backdrop-filter: blur(10px);
padding: 0 10px;
.social_task_item_top {
display: flex;
align-items: center;
gap: 8px;
border-bottom: 1px solid #2b2b2e;
height: 59px;
> img {
width: 30px;
height: 30px;
}
> span {
/* 自动布局子元素 */
opacity: 1;
font-family: Roboto;
font-size: 14px;
font-weight: normal;
line-height: 24px;
letter-spacing: 0em;
font-variation-settings: "opsz" auto;
font-feature-settings: "kern" on;
color: #ffffff;
z-index: 0;
}
> button {
background-image: url("../assets/buttom_bg.svg");
background-repeat: no-repeat;
background-size: cover;
width: 86px;
height: 30px;
display: flex;
align-items: center;
justify-content: center;
margin-left: auto;
> span {
opacity: 1;
font-family: YouSheBiaoTiHei;
font-size: 14px;
font-weight: normal;
line-height: 24px;
text-align: center;
text-transform: capitalize;
letter-spacing: 0em;
font-variation-settings: "opsz" auto;
color: #ffffff;
}
&.button_disable {
background-image: url("../assets/buttom_disable.svg");
> span {
color: #2a2a2a;
}
}
}
}
.social_task_item_bottom {
display: flex;
align-items: center;
justify-content: space-between;
height: 49px;
> span {
&:nth-of-type(1) {
opacity: 1;
font-family: Roboto;
font-size: 14px;
font-weight: normal;
line-height: 24px;
letter-spacing: 0em;
font-variation-settings: "opsz" auto;
font-feature-settings: "kern" on;
color: #adadad;
}
&:nth-of-type(2) {
opacity: 1;
font-family: Roboto;
font-size: 14px;
font-weight: bold;
line-height: 24px;
text-align: right;
letter-spacing: 0em;
font-variation-settings: "opsz" auto;
font-feature-settings: "kern" on;
color: #ffffff;
}
}
}
}
}
}
.join_card { .join_card {
width: 345px; width: 345px;
height: 132px; height: 132px;
@ -162,14 +311,14 @@
opacity: 1; opacity: 1;
font-family: Roboto; font-family: YouSheBiaoTiHei;
font-size: 20px; font-size: 24px;
font-weight: 600; font-weight: normal;
line-height: 24px; line-height: 24px;
text-transform: uppercase;
letter-spacing: 0em; letter-spacing: 0em;
font-variation-settings: "opsz" auto; font-variation-settings: "opsz" auto;
font-feature-settings: "kern" on;
color: #ffffff; color: #ffffff;
} }

View File

@ -1,12 +1,14 @@
/* /*
* @LastEditors: John * @LastEditors: John
* @Date: 2024-07-13 10:50:24 * @Date: 2024-07-13 10:50:24
* @LastEditTime: 2024-07-18 18:45:32 * @LastEditTime: 2024-07-19 17:05:08
* @Author: John * @Author: John
*/ */
import classes from "./Home-m.module.css"; import classes from "./Home-m.module.css";
import { Routes, useNavigate } from "react-router-dom"; import { Routes, useNavigate } from "react-router-dom";
import home_top_bg from "@/assets/home_top_bg.svg"; import home_top_bg from "@/assets/home_top_bg.svg";
import tg_white from "@/assets/tg_white.svg";
import tuite_white from "@/assets/tuite_white.svg";
import logo from "@/assets/logo.png"; import logo from "@/assets/logo.png";
import { import {
CheckOutline, CheckOutline,
@ -19,37 +21,48 @@ import { useEffect, useState } from "react";
import { import {
api_follow_twitter, api_follow_twitter,
api_homepage_query_user_income, api_homepage_query_user_income,
api_query_task_configuration_list,
api_query_whether_the_user_receives_the_registration_reward, api_query_whether_the_user_receives_the_registration_reward,
api_start_task,
} from "@/server/api"; } from "@/server/api";
import { useWebApp } from "@vkruglikov/react-telegram-web-app"; import { useWebApp } from "@vkruglikov/react-telegram-web-app";
import IconFont from "@/components/iconfont"; import IconFont from "@/components/iconfont";
import { taskConfigurationListItem } from "@/server/module";
export default function () { export default function () {
const WebApp = useWebApp(); const WebApp = useWebApp();
const navigate = useNavigate(); const navigate = useNavigate();
const [totalPoint, setTotalPoint] = useState<string | undefined>(); const [totalPoint, setTotalPoint] = useState(0);
const [signReward, setSignReward] = useState<string | undefined>(); const [signReward, setSignReward] = useState<string | undefined>();
const [tgReward, setTgReward] = useState<string | undefined>(); const [tgReward, setTgReward] = useState<string | undefined>();
const [xReward, setXReward] = useState<string | undefined>(); const [xReward, setXReward] = useState<string | undefined>();
const [myReward, setMyReward] = useState<string | undefined>();
const [inviteReward, setInviteReward] = useState<string | undefined>();
const [tasksList, setTasksList] = useState<taskConfigurationListItem[]>();
useEffect(() => { useEffect(() => {
WebApp.setHeaderColor("#000000"); WebApp.setHeaderColor("#000000");
(async () => { (async () => {
UpdateHomeData(); UpdateHomeData();
UpdateTaskList();
})(); })();
return () => {}; return () => {};
}, []); }, []);
async function UpdateHomeData() { async function UpdateHomeData() {
const { data: totalDataRes } =
await api_query_whether_the_user_receives_the_registration_reward().send(
{}
);
setTotalPoint(totalDataRes?.data);
const { data: incomeRes } = await api_homepage_query_user_income().send({}); const { data: incomeRes } = await api_homepage_query_user_income().send({});
const list = incomeRes?.data || []; setMyReward(incomeRes?.data.wordRewar);
setSignReward(list.find((v) => v.opType == 4)?.opValue); setInviteReward(incomeRes?.data.teamRewar);
setTgReward(list.find((v) => v.opType == 5)?.opValue); setTotalPoint(
setXReward(list.find((v) => v.opType == 6)?.opValue); parseInt(`${incomeRes?.data.wordRewar || 0}`) +
parseInt(`${incomeRes?.data.teamRewar || 0}`)
);
}
async function UpdateTaskList() {
const { data } = await api_query_task_configuration_list().send({});
setTasksList(data?.data);
} }
return ( return (
<> <>
@ -60,36 +73,103 @@ export default function () {
</div> </div>
<img src={logo} alt="" className={classes.logo} /> <img src={logo} alt="" className={classes.logo} />
<span className={classes.pepes}>{totalPoint || 0} PIONEER</span> <span className={classes.pepes}>{totalPoint || 0} SCTT</span>
<div className={classes.join_card}> <div className={classes.social_task}>
<span>PIONEER COMMUNITY</span> <span>
<span>Home for Telegram OGs</span> Complete social media tasks to increase your chances in the raffle.
<Button </span>
fill="none"
onClick={() => {
WebApp.openTelegramLink(
`https://t.me/${import.meta.env.VITE_TG_COMMUNITY}`
);
}}
>
join
</Button>
</div>
<div className={classes.join_card}> <ul className={classes.social_task_list}>
<span>Follow X @PioneerPortal</span> {tasksList?.map((v, i) => (
<span>Follow X To Get Reward</span> <>
<Button {v.type == 1 && (
fill="none" <TaskItem
onClick={async () => { task_id={v.id}
await api_follow_twitter().send({}); task_url={v.taskUrl}
WebApp.openLink(`https://x.com/pioneerportal`); type={v.type}
title="Follow starcraft Telegram"
buttom_text="Follow"
button_disable={v.taskType == 1}
onTaskSuccess={() => {
UpdateHomeData(); UpdateHomeData();
UpdateTaskList();
}} }}
> />
Follow )}
</Button> {v.type == 2 && (
<TaskItem
task_id={v.id}
task_url={v.taskUrl}
type={v.type}
title="Join starcraft Telegram"
buttom_text="Joined"
button_disable={v.taskType == 1}
onTaskSuccess={() => {
UpdateHomeData();
UpdateTaskList();
}}
/>
)}
{v.type == 5 && (
<TaskItem
task_id={v.id}
task_url={v.taskUrl}
type={v.type}
title="Follow @starcraft Twitter"
buttom_text="Follow"
button_disable={v.taskType == 1}
onTaskSuccess={() => {
UpdateHomeData();
UpdateTaskList();
}}
/>
)}
{v.type == 6 && (
<TaskItem
task_id={v.id}
task_url={v.taskUrl}
type={v.type}
title="Like on @starcraft Twitter"
buttom_text="Like"
button_disable={v.taskType == 1}
onTaskSuccess={() => {
UpdateHomeData();
UpdateTaskList();
}}
/>
)}
{v.type == 7 && (
<TaskItem
task_id={v.id}
task_url={v.taskUrl}
type={v.type}
title="Retweet @starcraft Twitter"
buttom_text="Follow"
button_disable={v.taskType == 1}
onTaskSuccess={() => {
UpdateHomeData();
UpdateTaskList();
}}
/>
)}
{v.type == 8 && (
<TaskItem
task_id={v.id}
task_url={v.taskUrl}
type={v.type}
title="Quote @starcraft Twitter"
buttom_text="Quote"
button_disable={v.taskType == 1}
onTaskSuccess={() => {
UpdateHomeData();
UpdateTaskList();
}}
/>
)}
</>
))}
</ul>
</div> </div>
<div className={classes.rewards}> <div className={classes.rewards}>
@ -98,31 +178,62 @@ export default function () {
<div className={classes.reward_list}> <div className={classes.reward_list}>
<StarOutline color="#ffffff" /> <StarOutline color="#ffffff" />
<span>Your rewards</span> <span>Your rewards</span>
<span>+{signReward || 0} PIONEER</span> <span>+{myReward || 0} SCTT</span>
</div> </div>
<div className={classes.reward_list}> <div className={classes.reward_list}>
{/* <CheckOutline color="#ffffff" /> */}
<IconFont name="dianbao" color="#ffffff" /> <IconFont name="dianbao" color="#ffffff" />
<span>Join Telegram</span>
<span>{tgReward || 0}</span>
</div>
<div className={classes.reward_list}>
{/* <CheckOutline color="#ffffff" /> */}
<IconFont name="tuite" color="#ffffff" />
<span>Follow X @PioneerPortal</span>
<span>{xReward || 0}</span>
</div>
<div className={classes.reward_list}>
{/* <CheckOutline color="#ffffff" /> */}
<UserAddOutline color="#ffffff" />
<span>Invite friends</span> <span>Invite friends</span>
<span>{0}</span> <span>{inviteReward || 0}</span>
</div> </div>
</div> </div>
</div> </div>
</> </>
); );
} }
function TaskItem({
title,
task_id,
task_url,
type,
buttom_text,
button_disable,
onTaskSuccess,
}: {
task_id: string;
task_url: string;
title: string;
type: taskConfigurationListItem["type"];
buttom_text: string;
button_disable?: boolean;
onTaskSuccess?: () => void;
}) {
const WebApp = useWebApp();
return (
<li>
<div className={classes.social_task_item_top}>
{(type == 1 || type == 2) && <img src={tg_white} alt="" />}
{(type == 5 || type == 6 || type == 7 || type == 8) && (
<img src={tuite_white} alt="" />
)}
<span>{title}</span>
<Button
fill="none"
className={button_disable ? classes.button_disable : ""}
onClick={async () => {
await api_start_task().send({ queryParams: { id: task_id } });
WebApp.openLink(task_url);
onTaskSuccess?.();
}}
>
{buttom_text}
</Button>
</div>
<div className={classes.social_task_item_bottom}>
<span>Reward</span>
<span>+1,000 SCTT</span>
</div>
</li>
);
}

View File

@ -25,7 +25,7 @@ const tabs = [
}, },
{ {
key: "2", key: "2",
title: "Frends", title: "friends",
icon: <MessageOutline />, icon: <MessageOutline />,
}, },
]; ];
@ -38,7 +38,7 @@ export default function () {
<Routes> <Routes>
<Route path="/" element={<Home />} /> <Route path="/" element={<Home />} />
<Route path="/leaderboard" element={<Leaderboard />} /> <Route path="/leaderboard" element={<Leaderboard />} />
<Route path="/frends" element={<Frends />} /> <Route path="/friends" element={<Frends />} />
</Routes> </Routes>
</div> </div>

View File

@ -30,7 +30,11 @@
align-items: center; align-items: center;
padding: 13px 15px; padding: 13px 15px;
background: #1e1e1e; /* background: #1e1e1e; */
background-image: url("../assets/user_rank_bg.svg");
background-repeat: no-repeat;
background-size: contain;
border-radius: 0px;
gap: 12px; gap: 12px;
margin-top: 38px; margin-top: 38px;
> div { > div {

View File

@ -1,7 +1,7 @@
/* /*
* @LastEditors: John * @LastEditors: John
* @Date: 2024-07-13 16:08:04 * @Date: 2024-07-13 16:08:04
* @LastEditTime: 2024-07-17 09:51:09 * @LastEditTime: 2024-07-19 14:55:57
* @Author: John * @Author: John
*/ */
import { Avatar, Button } from "antd-mobile"; import { Avatar, Button } from "antd-mobile";
@ -37,15 +37,11 @@ export default function () {
<Avatar src="" /> <Avatar src="" />
<div> <div>
<span>{userRank?.tgName}</span> <span>{userRank?.tgName}</span>
<span>{userRank?.amount} PIONEER</span> <span>{userRank?.amount || 0} SCTT</span>
</div> </div>
<span>#{userRank?.ranking}</span> <span>#{userRank?.ranking}</span>
</div> </div>
<Button block fill="none">
<StarOutline color="#ffffff" />
<span>Boost score</span>
</Button>
<span className={classes.rank_title}>{totalUser || 0} holders</span> <span className={classes.rank_title}>{totalUser || 0} holders</span>
<ul className={classes.rank_list}> <ul className={classes.rank_list}>
{ranks?.map((v, i) => ( {ranks?.map((v, i) => (
@ -76,7 +72,7 @@ function RankItem({
<Avatar src="" /> <Avatar src="" />
<div> <div>
<span>{userName}</span> <span>{userName}</span>
<span>{point} PIONEER</span> <span>{point} SCTT</span>
</div> </div>
{index == 1 && ( {index == 1 && (
<img className={classes.rank_item_icon} src={rank1} alt="" /> <img className={classes.rank_item_icon} src={rank1} alt="" />

View File

@ -1,11 +1,16 @@
/* /*
* @LastEditors: John * @LastEditors: John
* @Date: 2024-07-15 10:35:20 * @Date: 2024-07-15 10:35:20
* @LastEditTime: 2024-07-16 16:04:49 * @LastEditTime: 2024-07-19 15:50:19
* @Author: John * @Author: John
*/ */
import { GET, POST } from "./client"; import { GET, POST } from "./client";
import { RewardVo, subordinatesUsers, userBenefits } from "./module"; import {
RewardVo,
subordinatesUsers,
taskConfigurationListItem,
userBenefits,
} from "./module";
// 登录 // 登录
export function api_login() { export function api_login() {
@ -50,7 +55,7 @@ export function api_ranking() {
// 首页查询用户收益 // 首页查询用户收益
export function api_homepage_query_user_income() { export function api_homepage_query_user_income() {
return GET<any, userBenefits[]>({ return GET<any, { wordRewar: string; teamRewar: string }>({
url: "/api/reward/userBenefits", url: "/api/reward/userBenefits",
}); });
} }
@ -90,7 +95,7 @@ export function api_get_user_information() {
// 首页下级用户 // 首页下级用户
export function api_homepage_subordinates_users() { export function api_homepage_subordinates_users() {
return GET<any, subordinatesUsers[]>({ return GET<{ level: number }, subordinatesUsers[]>({
url: "/api/reward/subordinateUsers", url: "/api/reward/subordinateUsers",
}); });
} }
@ -101,3 +106,17 @@ export function api_follow_twitter() {
url: "/api/reward/followTwitter", url: "/api/reward/followTwitter",
}); });
} }
// 查询任务配置列表
export function api_query_task_configuration_list() {
return GET<any, taskConfigurationListItem[]>({
url: "/api/task-config",
});
}
export function api_start_task() {
return POST<any, {}, { id: string }>({
url: "/api/task-config",
});
}

View File

@ -30,9 +30,9 @@ export type userBenefits = {
export type subordinatesUsers = { export type subordinatesUsers = {
account: string; account: string;
amount: string;
accountType: number; accountType: number;
allPid: string; allPid: string;
amount: string;
chainType: number; chainType: number;
codePrompt: number; codePrompt: number;
createTime: string; createTime: string;
@ -53,3 +53,16 @@ export type subordinatesUsers = {
userImg: string; userImg: string;
userType: number; userType: number;
}; };
export type taskConfigurationListItem = {
createTime: string;
externalId: string;
flag: 0 | 1; // 标记删除0 / 1
id: string;
opValue: string;
status: 0 | 1 | 2; // 0:已下架(前端不在显示) 1:进行中 2:已结束
taskType: 0 | 1; // 0:任务为完成 1任务已完成
taskUrl: string;
type: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8; // 1:加入TG频道 2:加入TG群 3:直推积分 4:间推积分 5:关注推特 6:推特点赞 7:转发推特 8:引用推特
updateTime: string;
};