Compare commits

..

3 Commits

Author SHA1 Message Date
john 66bc4cd97d 🐞 fix: 2024-07-20 10:46:57 +08:00
john 9ce033624f feat: 2024-07-19 19:33:22 +08:00
john cb5f785a24 feat: 2024-07-19 17:05:29 +08:00
30 changed files with 550 additions and 137 deletions

11
.env.test Normal file
View File

@ -0,0 +1,11 @@
###
# @LastEditors: John
# @Date: 2024-07-19 17:45:49
# @LastEditTime: 2024-07-20 10:45:15
# @Author: John
###
VITE_BASE_URL=
VITE_BASE_API_URL=
VITE_TG_COMMUNITY=sctSCT_bot
VITE_TG_BOT_NAME=sctSCT_bot
VITE_TG_BOT_WEBAPP_NAME=STC

View File

@ -6,6 +6,7 @@
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"build:test": "tsc -b && vite build --mode test",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview",
"iconfont": "npx iconfont-h5"

View File

@ -1,7 +1,7 @@
body,
html,
#root {
height: var(--tg-viewport-height);
min-height: var(--tg-viewport-height);
background-image: url("./assets/home_bg.svg");
background-repeat: no-repeat;
background-size: cover;
@ -12,6 +12,11 @@ html,
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;
}

View File

@ -1,7 +1,7 @@
/*
* @LastEditors: John
* @Date: 2024-07-13 10:21:58
* @LastEditTime: 2024-07-18 18:25:39
* @LastEditTime: 2024-07-19 19:10:34
* @Author: John
*/
import { MemoryRouter, Route, Routes } from "react-router-dom";
@ -54,7 +54,7 @@ function App() {
return (
<>
{!Token ? (
{Token ? (
<MemoryRouter>
<Routes>
<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;
width: 100%;
height: 83px;
padding: 0 39px;
background-color: #000000;
z-index: 999;
li {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
flex: 1;
span {
/* 自动布局子元素 */
opacity: 1;

View File

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

View File

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

View File

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

View File

@ -1,5 +1,5 @@
.guide {
height: 100%;
height: var(--tg-viewport-height);
background-image: url("../assets/guide_bg.svg");
background-repeat: no-repeat;
background-size: cover;

View File

@ -1,7 +1,7 @@
/*
* @LastEditors: John
* @Date: 2024-07-18 14:42:58
* @LastEditTime: 2024-07-18 17:07:14
* @LastEditTime: 2024-07-19 19:13:27
* @Author: John
*/
import {
@ -15,7 +15,7 @@ import guide_icon from "@/assets/guide_icon.svg";
import dianbao from "@/assets/dianbao.svg";
import youguang from "@/assets/youguang.svg";
import tuite from "@/assets/tuite.svg";
import { api_login } from "@/server/api";
import { api_get_user_information, api_login } from "@/server/api";
import useUserStore from "@/store/User";
export default function () {
@ -66,6 +66,9 @@ export default function () {
},
});
if (data?.data.token) UpdateToken(data?.data.token);
const { data: userData } = await api_get_user_information().send({});
UpdateInvitationCode(userData?.data.shareCode || "");
}}
/>
</>

View File

@ -59,6 +59,155 @@
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 {
width: 345px;
height: 132px;
@ -162,14 +311,14 @@
opacity: 1;
font-family: Roboto;
font-size: 20px;
font-weight: 600;
font-family: YouSheBiaoTiHei;
font-size: 24px;
font-weight: normal;
line-height: 24px;
text-transform: uppercase;
letter-spacing: 0em;
font-variation-settings: "opsz" auto;
font-feature-settings: "kern" on;
color: #ffffff;
}

View File

@ -1,12 +1,14 @@
/*
* @LastEditors: John
* @Date: 2024-07-13 10:50:24
* @LastEditTime: 2024-07-18 18:45:32
* @LastEditTime: 2024-07-19 19:03:45
* @Author: John
*/
import classes from "./Home-m.module.css";
import { Routes, useNavigate } from "react-router-dom";
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 {
CheckOutline,
@ -19,37 +21,48 @@ import { useEffect, useState } from "react";
import {
api_follow_twitter,
api_homepage_query_user_income,
api_query_task_configuration_list,
api_query_whether_the_user_receives_the_registration_reward,
api_start_task,
} from "@/server/api";
import { useWebApp } from "@vkruglikov/react-telegram-web-app";
import IconFont from "@/components/iconfont";
import { taskConfigurationListItem } from "@/server/module";
export default function () {
const WebApp = useWebApp();
const navigate = useNavigate();
const [totalPoint, setTotalPoint] = useState<string | undefined>();
const [totalPoint, setTotalPoint] = useState(0);
const [signReward, setSignReward] = useState<string | undefined>();
const [tgReward, setTgReward] = 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(() => {
WebApp.setHeaderColor("#000000");
(async () => {
UpdateHomeData();
UpdateTaskList();
})();
return () => {};
}, []);
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 list = incomeRes?.data || [];
setSignReward(list.find((v) => v.opType == 4)?.opValue);
setTgReward(list.find((v) => v.opType == 5)?.opValue);
setXReward(list.find((v) => v.opType == 6)?.opValue);
setMyReward(incomeRes?.data.wordRewar);
setInviteReward(incomeRes?.data.teamRewar);
setTotalPoint(
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 (
<>
@ -60,36 +73,109 @@ export default function () {
</div>
<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}>
<span>PIONEER COMMUNITY</span>
<span>Home for Telegram OGs</span>
<Button
fill="none"
onClick={() => {
WebApp.openTelegramLink(
`https://t.me/${import.meta.env.VITE_TG_COMMUNITY}`
);
}}
>
join
</Button>
</div>
<div className={classes.social_task}>
<span>
Complete social media tasks to increase your chances in the raffle.
</span>
<div className={classes.join_card}>
<span>Follow X @PioneerPortal</span>
<span>Follow X To Get Reward</span>
<Button
fill="none"
onClick={async () => {
await api_follow_twitter().send({});
WebApp.openLink(`https://x.com/pioneerportal`);
UpdateHomeData();
}}
>
Follow
</Button>
<ul className={classes.social_task_list}>
{tasksList?.map((v, i) => (
<>
{v.type == 1 && (
<TaskItem
task_id={v.id}
task_url={v.taskUrl}
type={v.type}
title="Follow starcraft Telegram"
buttom_text="Follow"
button_disable={v.taskType == 1}
reward={v.opValue}
onTaskSuccess={() => {
UpdateHomeData();
UpdateTaskList();
}}
/>
)}
{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}
reward={v.opValue}
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}
reward={v.opValue}
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}
reward={v.opValue}
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}
reward={v.opValue}
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}
reward={v.opValue}
onTaskSuccess={() => {
UpdateHomeData();
UpdateTaskList();
}}
/>
)}
</>
))}
</ul>
</div>
<div className={classes.rewards}>
@ -98,31 +184,64 @@ export default function () {
<div className={classes.reward_list}>
<StarOutline color="#ffffff" />
<span>Your rewards</span>
<span>+{signReward || 0} PIONEER</span>
<span>+{myReward || 0} SCTT</span>
</div>
<div className={classes.reward_list}>
{/* <CheckOutline 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>{0}</span>
<span>{inviteReward || 0}</span>
</div>
</div>
</div>
</>
);
}
function TaskItem({
title,
task_id,
task_url,
type,
buttom_text,
reward,
button_disable,
onTaskSuccess,
}: {
task_id: string;
task_url: string;
title: string;
type: taskConfigurationListItem["type"];
buttom_text: string;
reward: 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>+{reward} SCTT</span>
</div>
</li>
);
}

View File

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

View File

@ -30,7 +30,11 @@
align-items: center;
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;
margin-top: 38px;
> div {

View File

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

View File

@ -1,11 +1,16 @@
/*
* @LastEditors: John
* @Date: 2024-07-15 10:35:20
* @LastEditTime: 2024-07-16 16:04:49
* @LastEditTime: 2024-07-19 15:50:19
* @Author: John
*/
import { GET, POST } from "./client";
import { RewardVo, subordinatesUsers, userBenefits } from "./module";
import {
RewardVo,
subordinatesUsers,
taskConfigurationListItem,
userBenefits,
} from "./module";
// 登录
export function api_login() {
@ -50,7 +55,7 @@ export function api_ranking() {
// 首页查询用户收益
export function api_homepage_query_user_income() {
return GET<any, userBenefits[]>({
return GET<any, { wordRewar: string; teamRewar: string }>({
url: "/api/reward/userBenefits",
});
}
@ -90,7 +95,7 @@ export function api_get_user_information() {
// 首页下级用户
export function api_homepage_subordinates_users() {
return GET<any, subordinatesUsers[]>({
return GET<{ level: number }, subordinatesUsers[]>({
url: "/api/reward/subordinateUsers",
});
}
@ -101,3 +106,17 @@ export function api_follow_twitter() {
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 = {
account: string;
amount: string;
accountType: number;
allPid: string;
amount: string;
chainType: number;
codePrompt: number;
createTime: string;
@ -53,3 +53,16 @@ export type subordinatesUsers = {
userImg: string;
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;
};

View File

@ -7,5 +7,5 @@
"allowSyntheticDefaultImports": true,
"strict": true
},
"include": ["vite.config.ts"]
"include": ["./vite.config.ts"]
}

File diff suppressed because one or more lines are too long

View File

@ -9,24 +9,24 @@ import react from "@vitejs/plugin-react";
import path from "path";
// https://vitejs.dev/config/
export default defineConfig({
server: {
host: "192.168.10.167",
port: 8082,
proxy: {
"/dev": {
target: "http://192.168.10.100:8096",
changeOrigin: true,
rewrite: function (path) {
return path.replace(/^\/dev/, "");
server: {
host: "192.168.10.167",
port: 8082,
proxy: {
"/dev": {
target: "http://192.168.10.100:8096",
changeOrigin: true,
rewrite: function (path) {
return path.replace(/^\/dev/, "");
},
},
},
},
},
},
plugins: [react()],
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
plugins: [react()],
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
},
},
},
css: {},
css: {},
});

32
vite.config.ts Normal file
View File

@ -0,0 +1,32 @@
/*
* @LastEditors: John
* @Date: 2024-07-13 10:21:58
* @LastEditTime: 2024-07-18 14:47:48
* @Author: John
*/
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import path from "path";
// https://vitejs.dev/config/
export default defineConfig({
server: {
host: "192.168.10.167",
port: 8082,
proxy: {
"/dev": {
target: "http://192.168.10.100:8096",
changeOrigin: true,
rewrite: function (path) {
return path.replace(/^\/dev/, "");
},
},
},
},
plugins: [react()],
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
},
},
css: {},
});