feat:

This commit is contained in:
john 2024-06-28 18:00:45 +08:00
parent c1a8cfd6d6
commit a58b225544
15 changed files with 582 additions and 422 deletions

View File

@ -1,7 +1,7 @@
/*
* @LastEditors: John
* @Date: 2024-06-17 18:25:10
* @LastEditTime: 2024-06-19 16:14:06
* @LastEditTime: 2024-06-28 17:46:23
* @Author: John
*/
export default {
@ -11,7 +11,7 @@ export default {
rootValue: 37.5,
propList: ["*"],
exclude: (e) => {
if (/.*-m\.css$/.test(e) || /.module\.css$/.test(e)) {
if (/.*-m\.css$/.test(e) || /.*-m.module\.css$/.test(e)) {
// console.log(e);
return false;
}

View File

@ -1,7 +1,7 @@
/*
* @LastEditors: John
* @Date: 2024-06-17 17:20:03
* @LastEditTime: 2024-06-26 16:00:00
* @LastEditTime: 2024-06-28 17:44:02
* @Author: John
*/
import { Route, Routes } from "react-router-dom";
@ -16,7 +16,7 @@ import InvitationList from "./pages/InvitationList";
import { useEffect } from "react";
import { useTranslation } from "react-i18next";
import useUserStore from "./store/User";
import { getUrlQueryParam } from "./utils";
import { getUrlQueryParam, isMobile } from "./utils";
import { UrlQueryParamsKey } from "./constants";
import { signAndLogin } from "./utils/wallet";
import { useAccount } from "wagmi";
@ -45,12 +45,30 @@ function App() {
return (
<>
<RouterLogProvider>
<Header />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/mint" element={<Mint />} />
<Route path="/invitationlist" element={<InvitationList />}></Route>
</Routes>
{isMobile ? (
<>
<Header.Mobile />
<Routes>
<>
<Route path="/" element={<Home.Mobile />} />
<Route path="/mint" element={<Mint />} />
<Route
path="/invitationlist"
element={<InvitationList />}
></Route>
</>
</Routes>
</>
) : (
<>
<Header.Desktop />
<Routes>
<>
<Route path="/" element={<Home.Desktop />} />
</>
</Routes>
</>
)}
</RouterLogProvider>
</>
);

View File

@ -1,7 +1,7 @@
/*
* @LastEditors: John
* @Date: 2024-06-18 15:16:31
* @LastEditTime: 2024-06-27 15:29:00
* @LastEditTime: 2024-06-28 14:05:29
* @Author: John
*/
import Picker, {
@ -11,7 +11,7 @@ import Picker, {
import { useContext, useEffect, useMemo, useState } from "react";
import IconFont from "./iconfont";
import logo from "@/assets/logo.svg";
import classes from "./Header.module.css";
import classes from "./Header-m.module.css";
import { useLocation, useNavigate, useNavigation } from "react-router-dom";
import { RouterLogContext } from "@/context/RouterContext";
import { useTranslation } from "react-i18next";
@ -27,7 +27,7 @@ const langColums: Action[] = [
{ text: "日本語", key: Lang.jp },
{ text: "DEUTSCH", key: Lang.de },
];
export default function () {
function Mobile() {
const { UpdateLang } = useUserStore();
const route = useContext(RouterLogContext);
@ -79,3 +79,12 @@ export default function () {
</>
);
}
function Desktop() {
return <></>;
}
export default {
Mobile,
Desktop,
};

View File

@ -1,10 +1,10 @@
/*
* @LastEditors: John
* @Date: 2024-06-19 10:49:42
* @LastEditTime: 2024-06-19 10:52:32
* @LastEditTime: 2024-06-28 14:05:45
* @Author: John
*/
import classes from "./RecordsItem.module.css";
import classes from "./RecordsItem-m.module.css";
export default function RecordsItem({
itemList,
}: {

View File

@ -0,0 +1,103 @@
/*
* @LastEditors: John
* @Date: 2024-06-28 14:09:55
* @LastEditTime: 2024-06-28 14:14:29
* @Author: John
*/
import useUserStore from "@/store/User";
import { useWeb3Modal } from "@web3modal/wagmi/react";
import { useEffect, useMemo, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
import { useAccount } from "wagmi";
import { useNavigate } from "react-router-dom";
import { Dialog } from "antd-mobile";
import {
api_get_homepage_user_data,
api_query_user_invitation_code,
} from "@/server/api";
import { UserHomeData } from "@/server/module";
import { UrlQueryParamsKey } from "@/constants";
import usePollingCheckBuyStatus from "@/hook/usePollingCheckBuyStatus";
import { ToastHandler } from "antd-mobile/es/components/toast";
import { PullStatus } from "antd-mobile/es/components/pull-to-refresh";
export default function () {
const { Token, UpdateToken } = useUserStore();
const { open } = useWeb3Modal();
const { t } = useTranslation();
const { address } = useAccount();
const [tabIndex, setTabIndex] = useState(0);
const navigate = useNavigate();
const [userData, setUserData] = useState<UserHomeData>();
const [inviteCode, setInviteCode] = useState("");
const userInviteLink = useMemo(
() =>
`${location.origin}/#/?${UrlQueryParamsKey.INVITE_CODE}=${inviteCode}`,
[inviteCode]
);
const receiveLoadingToast = useRef<ToastHandler>();
const {
transcationStatus,
startPollingCheckBuyStatus,
stopPollingCheckBuyStatus,
} = usePollingCheckBuyStatus("NORMAL");
const statusRecord: Record<PullStatus, string> = {
pulling: "Pull down to refresh",
canRelease: "Release to refresh immediately",
refreshing: "Loading...",
complete: "Refresh complete",
};
useEffect(() => {
if (Token) {
getHomeData();
getInviteCode();
}
return () => {};
}, [Token]);
useEffect(() => {
if (transcationStatus == "success") {
receiveLoadingToast.current?.close();
stopPollingCheckBuyStatus();
Dialog.alert({
content: `${t("领取成功,前往钱包查看")}`,
confirmText: "OK",
});
}
return () => {};
}, [transcationStatus]);
async function getHomeData() {
const { data } = await api_get_homepage_user_data().send({});
setUserData(data?.data);
}
async function getInviteCode() {
const { data } = await api_query_user_invitation_code().send({});
setInviteCode(data?.data.invitationCode || "");
}
useEffect(() => {
console.log("user token:", Token);
return () => {};
}, [Token]);
return {
getHomeData,
statusRecord,
Token,
address,
setUserData,
userData,
tabIndex,
t,
setTabIndex,
navigate,
userInviteLink,
};
}

View File

@ -0,0 +1,41 @@
import usePagination from "@/hook/usePagination";
import { api_recommended_list } from "@/server/api";
import { RecommendedListItem } from "@/server/module";
import { Empty, InfiniteScroll } from "antd-mobile";
import DataTable, { TableColumn } from "react-data-table-component";
import { useTranslation } from "react-i18next";
export default function () {
const { t } = useTranslation();
const columns: TableColumn<RecommendedListItem>[] = [
{
name: t("地址"),
selector: (row) => row.walletAddress,
grow: 9,
},
{
name: "Node",
selector: (row) => row.nodeNumber,
grow: 1,
// @ts-ignore
right: "true",
},
];
const { list, hasMore, loadMore } = usePagination<RecommendedListItem>({
service({ pageNum, pageSize }) {
return new Promise(async (reslove) => {
const { data } = await api_recommended_list().send({
queryParams: { pageNum, pageSize },
});
reslove(data?.data.records || []);
});
},
});
return {
columns,
list,
loadMore,
hasMore,
};
}

View File

@ -0,0 +1,118 @@
import { cn, filterAddressBeforeZero, filterAmountBeforeZero } from "@/utils";
import classes from "./Mint-m.module.css";
import nft_bg from "@/assets/nft_bg.svg";
import Button from "antd-mobile/es/components/button";
import Space from "antd-mobile/es/components/space";
import { useTranslation } from "react-i18next";
import { useEffect, useMemo, useRef, useState } from "react";
import {
api_get_homepage_user_data,
api_get_nft_configuration_data,
api_node_order,
api_users_cancel_orders,
} from "@/server/api";
import {
NftConfigurationData,
NftOrder,
NodeOrder,
UserHomeData,
} from "@/server/module";
import {
authorizedU,
getApproveUsdt,
getBalance,
payByContract,
} from "@/contract/utils";
import { Dialog, Modal, Stepper, Toast } from "antd-mobile";
import useUserStore from "@/store/User";
import usePollingCheckBuyStatus from "@/hook/usePollingCheckBuyStatus";
import { ToastHandler } from "antd-mobile/es/components/toast";
import { BaseError } from "wagmi";
import { useNavigate } from "react-router-dom";
import { toWei } from "web3-utils";
export default function () {
const { t } = useTranslation();
const { Token } = useUserStore();
const [nodeConfig, setNodeConfig] = useState<UserHomeData>();
const [approveUsdt, setApproveUsdt] = useState<bigint>(0n);
const [balance, setBalance] = useState<bigint>(0n);
const orderInfo = useRef<NodeOrder>();
const navigate = useNavigate();
const [num, setNum] = useState(1);
const buyLoadingToast = useRef<ToastHandler>();
const approveLoadingToast = useRef<ToastHandler>();
const {
transcationStatus,
startPollingCheckBuyStatus,
stopPollingCheckBuyStatus,
} = usePollingCheckBuyStatus("NORMAL");
const costNum = useMemo(
() =>
BigInt(
toWei(`${parseFloat(`${nodeConfig?.nodePrice || "0"}`) * num}`, "ether")
),
[nodeConfig?.nodePrice, num]
);
useEffect(() => {
updateNodeConfig();
return () => {};
}, []);
useEffect(() => {
(async () => {
Toast.show({ icon: "loading", content: t("正在获取已授权金额") });
setBalance(await getBalance());
setApproveUsdt(await getApproveUsdt());
Toast.clear();
})();
return () => {};
}, [Token]);
async function updateNodeConfig() {
const { data } = await api_get_homepage_user_data().send({});
setNodeConfig(data?.data);
}
useEffect(() => {
if (transcationStatus == "success") {
buyLoadingToast.current?.close();
stopPollingCheckBuyStatus();
Dialog.alert({
content: `${t(
"Buy successful. Please return to the homepage to view."
)}`,
confirmText: "OK",
onConfirm() {
navigate("/");
},
});
}
return () => {};
}, [transcationStatus]);
useEffect(() => {
return () => {};
}, []);
return {
nodeConfig,
num,
setNum,
approveUsdt,
t,
balance,
approveLoadingToast,
costNum,
setApproveUsdt,
buyLoadingToast,
orderInfo,
updateNodeConfig,
startPollingCheckBuyStatus,
};
}

View File

@ -1,314 +1,287 @@
import classes from "./Home.module.css";
import useUserStore from "@/store/User";
/*
* @LastEditors: John
* @Date: 2024-06-26 15:04:10
* @LastEditTime: 2024-06-28 14:36:37
* @Author: John
*/
import classes from "./Home-m.module.css";
import { cn, copyText, getLevelName, shortenString } from "@/utils";
import { useWeb3Modal } from "@web3modal/wagmi/react";
import { useEffect, useMemo, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
import logo from "@/assets/logo.svg";
import nftBg from "@/assets/nft_bg.svg";
import usdtBg from "@/assets/usdt_bg.svg";
import IconFont from "@/components/iconfont";
import { BaseError, useAccount } from "wagmi";
import { config } from "@/components/WalletProvider";
import { createSearchParams, useNavigate } from "react-router-dom";
import { Button, Dialog, Empty, PullToRefresh, Toast } from "antd-mobile";
import { PullToRefresh } from "antd-mobile";
import { loginOut } from "@/utils/wallet";
import {
api_claim_income,
api_get_homepage_user_data,
api_query_user_invitation_code,
} from "@/server/api";
import { UserHomeData } from "@/server/module";
import { UrlQueryParamsKey } from "@/constants";
import usePollingCheckBuyStatus from "@/hook/usePollingCheckBuyStatus";
import { ToastHandler } from "antd-mobile/es/components/toast";
import { disconnect, getAccount } from "@wagmi/core";
import { PullStatus } from "antd-mobile/es/components/pull-to-refresh";
export default function () {
const { Token, UpdateToken } = useUserStore();
const { open } = useWeb3Modal();
const { t } = useTranslation();
const { address } = useAccount();
const [tabIndex, setTabIndex] = useState(0);
const navigate = useNavigate();
const [userData, setUserData] = useState<UserHomeData>();
const [inviteCode, setInviteCode] = useState("");
const userInviteLink = useMemo(
() =>
`${location.origin}/#/?${UrlQueryParamsKey.INVITE_CODE}=${inviteCode}`,
[inviteCode]
);
const receiveLoadingToast = useRef<ToastHandler>();
import useHome from "./Feature/useHome";
import useMint from "./Feature/useMint";
import useInvitationList from "./Feature/useInvitationList";
function Mobile() {
const {
transcationStatus,
startPollingCheckBuyStatus,
stopPollingCheckBuyStatus,
} = usePollingCheckBuyStatus("NORMAL");
const statusRecord: Record<PullStatus, string> = {
pulling: "Pull down to refresh",
canRelease: "Release to refresh immediately",
refreshing: "Loading...",
complete: "Refresh complete",
};
useEffect(() => {
if (Token) {
getHomeData();
getInviteCode();
}
return () => {};
}, [Token]);
useEffect(() => {
if (transcationStatus == "success") {
receiveLoadingToast.current?.close();
stopPollingCheckBuyStatus();
Dialog.alert({
content: `${t("领取成功,前往钱包查看")}`,
confirmText: "OK",
});
}
return () => {};
}, [transcationStatus]);
async function getHomeData() {
const { data } = await api_get_homepage_user_data().send({});
setUserData(data?.data);
}
async function getInviteCode() {
const { data } = await api_query_user_invitation_code().send({});
setInviteCode(data?.data.invitationCode || "");
}
useEffect(() => {
console.log("user token:", Token);
return () => {};
}, [Token]);
getHomeData,
statusRecord,
Token,
address,
setUserData,
userData,
tabIndex,
t,
setTabIndex,
navigate,
userInviteLink,
} = useHome();
return (
<>
<PullToRefresh
onRefresh={async () => {
await getHomeData();
}}
renderText={(status) => {
return <div>{statusRecord[status]}</div>;
}}
disabled={!Token}
>
<div className={cn(classes.Home, classes.container)}>
<div className={classes.userinfo}>
<div className={classes.userinfo_top}>
<img className={classes.userinfo_top_left} src={logo} alt="" />
<PullToRefresh
onRefresh={async () => {
await getHomeData();
}}
renderText={(status) => {
return <div>{statusRecord[status]}</div>;
}}
disabled={!Token}
>
<div className={cn(classes.Home, classes.container)}>
<div className={classes.userinfo}>
<div className={classes.userinfo_top}>
<img className={classes.userinfo_top_left} src={logo} alt="" />
{address ? (
<div className={classes.userinfo_top_right}>
<div className={classes.userinfo_top_right_wallet}>
<span>{shortenString(address, 6, 4)}</span>
<IconFont
onClick={async () => {
loginOut();
setUserData(undefined);
}}
name="tuichu"
className={classes.userinfo_top_right_wallet_disconnect}
color={"#fff"}
/>
</div>
<div className={classes.userinfo_top_right_btns}>
{userData && (
<>
<div className={classes.userinfo_top_right_btns_item}>
<span>{getLevelName(userData.level)}</span>
</div>
</>
)}
</div>
</div>
) : (
<>
<div
className={classes.userinfo_top_right_connect}
onClick={() => {
open();
{address ? (
<div className={classes.userinfo_top_right}>
<div className={classes.userinfo_top_right_wallet}>
<span>{shortenString(address, 6, 4)}</span>
<IconFont
onClick={async () => {
loginOut();
setUserData(undefined);
}}
>
<span>{t("链接钱包")}</span>
</div>
</>
)}
</div>
<ul className={classes.userinfo_data}>
<li>
<span className={classes.userinfo_data_num}>
{userData?.directPushNode || 0}
</span>
<span className={classes.userinfo_data_des}>
{t("Direct Node")}
</span>
</li>
<li>
<span className={classes.userinfo_data_num}>
{userData?.teamNode || 0}
</span>
<span className={classes.userinfo_data_des}>
{t("Team Node")}
</span>
</li>
<li>
<span className={classes.userinfo_data_num}>
{userData?.revenueUsdt || 0}
<p>USDT</p>
</span>
<span className={classes.userinfo_data_des}>
{t("Push income")}
</span>
</li>
</ul>
</div>
<div className={classes.nftToken}>
<ul className={classes.nftToken_tab}>
<li
className={tabIndex == 0 ? classes.nftToken_tab_active : ""}
onClick={() => setTabIndex(0)}
>
NODE
</li>
</ul>
<div className={classes.nftToken_content}>
{tabIndex == 0 && (
<>
{address ? (
name="tuichu"
className={classes.userinfo_top_right_wallet_disconnect}
color={"#fff"}
/>
</div>
<div className={classes.userinfo_top_right_btns}>
{userData && (
<>
{userData?.nodeNumber && userData?.nodeNumber > 0 ? (
<div className={classes.nftToken_content_nft}>
<div className={classes.nftToken_content_nft_top}>
<span>You own {userData.nodeNumber} nodes</span>
<span
onClick={() => {
navigate("/mint");
}}
>
{t("Buy Node")}
<IconFont
name="chevronsrightshuangyoujiantou"
color={"#2DFCFC"}
/>
</span>
</div>
<img
className={classes.nftToken_content_nft_img}
src={nftBg}
alt=""
/>
<span className={classes.nftToken_content_nft_des}>
{t("Start mining after node subscription ends.")}
</span>
</div>
) : (
<div className={classes.nftToken_content_nft_mint}>
<div
className={classes.nftToken_content_nft_mint_btn}
<div className={classes.userinfo_top_right_btns_item}>
<span>{getLevelName(userData.level)}</span>
</div>
</>
)}
</div>
</div>
) : (
<>
<div
className={classes.userinfo_top_right_connect}
onClick={() => {
open();
}}
>
<span>{t("链接钱包")}</span>
</div>
</>
)}
</div>
<ul className={classes.userinfo_data}>
<li>
<span className={classes.userinfo_data_num}>
{userData?.directPushNode || 0}
</span>
<span className={classes.userinfo_data_des}>
{t("Direct Node")}
</span>
</li>
<li>
<span className={classes.userinfo_data_num}>
{userData?.teamNode || 0}
</span>
<span className={classes.userinfo_data_des}>
{t("Team Node")}
</span>
</li>
<li>
<span className={classes.userinfo_data_num}>
{userData?.revenueUsdt || 0}
<p>USDT</p>
</span>
<span className={classes.userinfo_data_des}>
{t("Push income")}
</span>
</li>
</ul>
</div>
<div className={classes.nftToken}>
<ul className={classes.nftToken_tab}>
<li
className={tabIndex == 0 ? classes.nftToken_tab_active : ""}
onClick={() => setTabIndex(0)}
>
NODE
</li>
</ul>
<div className={classes.nftToken_content}>
{tabIndex == 0 && (
<>
{address ? (
<>
{userData?.nodeNumber && userData?.nodeNumber > 0 ? (
<div className={classes.nftToken_content_nft}>
<div className={classes.nftToken_content_nft_top}>
<span>You own {userData.nodeNumber} nodes</span>
<span
onClick={() => {
navigate("/mint");
}}
>
<span>{t("Buy Node")}</span>
{t("Buy Node")}
<IconFont
className={
classes.nftToken_content_nft_mint_btn_icon
}
name="chevronsrightshuangyoujiantou"
color={"#101010"}
color={"#2DFCFC"}
/>
</div>
<span>{t("Buy Edge AI Node.")}</span>
</span>
</div>
)}
</>
) : (
<>
<div className={classes.nftToken_content_userDisconnect}>
<span>
{t(
"The wallet is not linked and cannot show you the Node."
)}
<img
className={classes.nftToken_content_nft_img}
src={nftBg}
alt=""
/>
<span className={classes.nftToken_content_nft_des}>
{t("Start mining after node subscription ends.")}
</span>
</div>
</>
)}
</>
)}
</div>
</div>
<div className={classes.invite}>
<div className={classes.invite_top}>
<span>{t("邀请")}</span>
{address && (
<span
onClick={() => {
navigate("/invitationlist");
}}
>
{t("邀请列表")}{" "}
<IconFont
name="chevronsrightshuangyoujiantou"
color={"#2DFCFC"}
/>
</span>
)}
</div>
<div className={classes.invite_content}>
<span>{t("邀请链接")}</span>
<div className={classes.invite_content_link}>
{address ? (
<>
{userData?.nodeNumber && userData?.nodeNumber > 0 ? (
<>
<span>{shortenString(userInviteLink, 15, 15)}</span>
<IconFont
onClick={() => {
copyText(userInviteLink);
}}
className={classes.invite_content_icon}
name="fuzhi"
color={"#fff"}
/>{" "}
</>
) : (
<>
<span>
{t("Buy Edge AI Node to get invitation link")}
</span>
</>
<div className={classes.nftToken_content_nft_mint}>
<div
className={classes.nftToken_content_nft_mint_btn}
onClick={() => {
navigate("/mint");
}}
>
<span>{t("Buy Node")}</span>
<IconFont
className={
classes.nftToken_content_nft_mint_btn_icon
}
name="chevronsrightshuangyoujiantou"
color={"#101010"}
/>
</div>
<span>{t("Buy Edge AI Node.")}</span>
</div>
)}
</>
) : (
<>
<span>{t("Link wallet to get invitation link")}</span>
<div className={classes.nftToken_content_userDisconnect}>
<span>
{t(
"The wallet is not linked and cannot show you the Node."
)}
</span>
</div>
</>
)}
</div>
<span>
{t(
"Invite your friends to become YOTTA nodes and you will get a 20% rebate."
)}
</span>
</div>
</>
)}
</div>
</div>
</PullToRefresh>
</>
<div className={classes.invite}>
<div className={classes.invite_top}>
<span>{t("邀请")}</span>
{address && (
<span
onClick={() => {
navigate("/invitationlist");
}}
>
{t("邀请列表")}{" "}
<IconFont
name="chevronsrightshuangyoujiantou"
color={"#2DFCFC"}
/>
</span>
)}
</div>
<div className={classes.invite_content}>
<span>{t("邀请链接")}</span>
<div className={classes.invite_content_link}>
{address ? (
<>
{userData?.nodeNumber && userData?.nodeNumber > 0 ? (
<>
<span>{shortenString(userInviteLink, 15, 15)}</span>
<IconFont
onClick={() => {
copyText(userInviteLink);
}}
className={classes.invite_content_icon}
name="fuzhi"
color={"#fff"}
/>{" "}
</>
) : (
<>
<span>
{t("Buy Edge AI Node to get invitation link")}
</span>
</>
)}
</>
) : (
<>
<span>{t("Link wallet to get invitation link")}</span>
</>
)}
</div>
<span>
{t(
"Invite your friends to become YOTTA nodes and you will get a 20% rebate."
)}
</span>
</div>
</div>
</div>
</PullToRefresh>
);
}
function Desktop() {
const {
getHomeData,
statusRecord,
Token,
address,
setUserData,
userData,
tabIndex,
t,
setTabIndex,
navigate,
userInviteLink,
} = useHome();
const {
nodeConfig,
num,
setNum,
approveUsdt,
balance,
approveLoadingToast,
costNum,
setApproveUsdt,
buyLoadingToast,
orderInfo,
updateNodeConfig,
startPollingCheckBuyStatus,
} = useMint();
const { columns, list, loadMore, hasMore } = useInvitationList();
return <></>;
}
export default {
Mobile,
Desktop,
};

View File

@ -4,40 +4,12 @@
* @LastEditTime: 2024-06-27 15:33:01
* @Author: John
*/
import usePagination from "@/hook/usePagination";
import { api_recommended_list } from "@/server/api";
import { RecommendedListItem } from "@/server/module";
import { Empty, InfiniteScroll } from "antd-mobile";
import DataTable, { TableColumn } from "react-data-table-component";
import { useTranslation } from "react-i18next";
import DataTable from "react-data-table-component";
import useInvitationList from "./Feature/useInvitationList";
export default function () {
const { t } = useTranslation();
const columns: TableColumn<RecommendedListItem>[] = [
{
name: t("地址"),
selector: (row) => row.walletAddress,
grow: 9,
},
{
name: "Node",
selector: (row) => row.nodeNumber,
grow: 1,
// @ts-ignore
right: "true",
},
];
const { list, hasMore, loadMore } = usePagination<RecommendedListItem>({
service({ pageNum, pageSize }) {
return new Promise(async (reslove) => {
const { data } = await api_recommended_list().send({
queryParams: { pageNum, pageSize },
});
reslove(data?.data.records || []);
});
},
});
const { columns, list, loadMore, hasMore } = useInvitationList();
return (
<>

View File

@ -1,110 +1,36 @@
/*
* @LastEditors: John
* @Date: 2024-06-18 15:28:03
* @LastEditTime: 2024-06-27 17:17:09
* @LastEditTime: 2024-06-28 14:33:02
* @Author: John
*/
import { cn, filterAddressBeforeZero, filterAmountBeforeZero } from "@/utils";
import classes from "./Mint.module.css";
import classes from "./Mint-m.module.css";
import nft_bg from "@/assets/nft_bg.svg";
import Button from "antd-mobile/es/components/button";
import Space from "antd-mobile/es/components/space";
import { useTranslation } from "react-i18next";
import { useEffect, useMemo, useRef, useState } from "react";
import {
api_get_homepage_user_data,
api_get_nft_configuration_data,
api_node_order,
api_users_cancel_orders,
} from "@/server/api";
import {
NftConfigurationData,
NftOrder,
NodeOrder,
UserHomeData,
} from "@/server/module";
import {
authorizedU,
getApproveUsdt,
getBalance,
payByContract,
} from "@/contract/utils";
import { Dialog, Modal, Stepper, Toast } from "antd-mobile";
import useUserStore from "@/store/User";
import usePollingCheckBuyStatus from "@/hook/usePollingCheckBuyStatus";
import { ToastHandler } from "antd-mobile/es/components/toast";
import { api_node_order } from "@/server/api";
import { authorizedU, getApproveUsdt, payByContract } from "@/contract/utils";
import { Stepper, Toast } from "antd-mobile";
import { BaseError } from "wagmi";
import { useNavigate } from "react-router-dom";
import { toWei } from "web3-utils";
import useMint from "./Feature/useMint";
export default function () {
const { t } = useTranslation();
const { Token } = useUserStore();
const [nodeConfig, setNodeConfig] = useState<UserHomeData>();
const [approveUsdt, setApproveUsdt] = useState<bigint>(0n);
const [balance, setBalance] = useState<bigint>(0n);
const orderInfo = useRef<NodeOrder>();
const navigate = useNavigate();
const [num, setNum] = useState(1);
const buyLoadingToast = useRef<ToastHandler>();
const approveLoadingToast = useRef<ToastHandler>();
const {
transcationStatus,
nodeConfig,
num,
setNum,
approveUsdt,
t,
balance,
approveLoadingToast,
costNum,
setApproveUsdt,
buyLoadingToast,
orderInfo,
updateNodeConfig,
startPollingCheckBuyStatus,
stopPollingCheckBuyStatus,
} = usePollingCheckBuyStatus("NORMAL");
const costNum = useMemo(
() =>
BigInt(
toWei(`${parseFloat(`${nodeConfig?.nodePrice || "0"}`) * num}`, "ether")
),
[nodeConfig?.nodePrice, num]
);
useEffect(() => {
updateNodeConfig();
return () => {};
}, []);
useEffect(() => {
(async () => {
Toast.show({ icon: "loading", content: t("正在获取已授权金额") });
setBalance(await getBalance());
setApproveUsdt(await getApproveUsdt());
Toast.clear();
})();
return () => {};
}, [Token]);
async function updateNodeConfig() {
const { data } = await api_get_homepage_user_data().send({});
setNodeConfig(data?.data);
}
useEffect(() => {
if (transcationStatus == "success") {
buyLoadingToast.current?.close();
stopPollingCheckBuyStatus();
Dialog.alert({
content: `${t(
"Buy successful. Please return to the homepage to view."
)}`,
confirmText: "OK",
onConfirm() {
navigate("/");
},
});
}
return () => {};
}, [transcationStatus]);
useEffect(() => {
return () => {};
}, []);
} = useMint();
return (
<>
<div className={cn(classes.Mint, classes.container)}>

View File

@ -1,7 +1,7 @@
/*
* @LastEditors: John
* @Date: 2024-06-17 18:19:27
* @LastEditTime: 2024-06-27 11:40:59
* @LastEditTime: 2024-06-28 15:32:57
* @Author: John
*/
import { type ClassValue, clsx } from "clsx";