diff --git a/.env.development b/.env.development index 3524682..15515fd 100644 --- a/.env.development +++ b/.env.development @@ -1 +1,10 @@ -VITE_BASE_API_URL=/dev \ No newline at end of file +### + # @LastEditors: John + # @Date: 2024-06-18 10:12:21 + # @LastEditTime: 2024-06-19 15:52:17 + # @Author: John +### +VITE_BASE_API_URL=/dev +VITE_PARTICIPATE_CHAIN_ID=97 +VITE_NETWORK_USDT_ADDRESS=0x204074AD198E7c6e79E195DAf576bc7D53967B45 +VITE_CHECK_TRANSACTION_DETAILS_URL=https://testnet.bscscan.com/ \ No newline at end of file diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..aef567a --- /dev/null +++ b/.env.production @@ -0,0 +1,4 @@ +VITE_BASE_API_URL=/dev +VITE_PARTICIPATE_CHAIN_ID=56 +VITE_NETWORK_USDT_ADDRESS=0x55d398326f99059ff775485246999027b3197955 +VITE_CHECK_TRANSACTION_DETAILS_URL=https://bscscan.com/ \ No newline at end of file diff --git a/.yarn/install-state.gz b/.yarn/install-state.gz index a6b513c..0bc04b3 100644 Binary files a/.yarn/install-state.gz and b/.yarn/install-state.gz differ diff --git a/iconfont.json b/iconfont.json index d6898b2..879baf1 100644 --- a/iconfont.json +++ b/iconfont.json @@ -1,8 +1,8 @@ { - "symbol_url": "请参考README.md,复制官网提供的JS链接", - "use_typescript": false, - "save_dir": "./src/components/iconfont", - "trim_icon_prefix": "icon", - "unit": "px", - "default_icon_size": 18 + "symbol_url": "//at.alicdn.com/t/c/font_4589567_vzk80gocu8s.js", + "use_typescript": true, + "save_dir": "./src/components/iconfont", + "trim_icon_prefix": "icon", + "unit": "px", + "default_icon_size": 18 } diff --git a/package.json b/package.json index 3dd2ea9..deaebd6 100644 --- a/package.json +++ b/package.json @@ -16,12 +16,16 @@ "@tanstack/react-query": "^5.45.1", "@web3modal/wagmi": "^5.0.2", "antd-mobile": "^5.36.1", + "clsx": "^2.1.1", "i18next": "^23.11.5", "normalize.css": "^8.0.1", "react": "^18.2.0", + "react-data-table-component": "^7.6.2", "react-dom": "^18.2.0", "react-i18next": "^14.1.2", "react-router-dom": "^6.23.1", + "tailwind-merge": "^2.3.0", + "vconsole": "^3.15.1", "viem": "^2.14.2", "wagmi": "^2.10.2", "zustand": "^4.5.2" @@ -41,6 +45,7 @@ "postcss": "^8.4.38", "postcss-pxtorem": "5.1.1", "react-iconfont-cli": "^2.0.2", + "styled-components": "^6.1.11", "typescript": "^5.2.2", "vite": "^5.2.0", "vite-plugin-compression": "^0.5.1", diff --git a/postcss.config.js b/postcss.config.js index 777d88d..f39d419 100644 --- a/postcss.config.js +++ b/postcss.config.js @@ -1,7 +1,7 @@ /* * @LastEditors: John * @Date: 2024-06-17 18:25:10 - * @LastEditTime: 2024-06-17 18:45:37 + * @LastEditTime: 2024-06-19 16:14:06 * @Author: John */ export default { @@ -11,8 +11,8 @@ export default { rootValue: 37.5, propList: ["*"], exclude: (e) => { - if (/.module\.css$/.test(e)) { - console.log(e); + if (/.*-m\.css$/.test(e) || /.module\.css$/.test(e)) { + // console.log(e); return false; } return true; diff --git a/src/App.css b/src/App.css index 6e04333..1b4bf02 100644 --- a/src/App.css +++ b/src/App.css @@ -1,4 +1,176 @@ -body { +body, +html, +#root { width: 100%; height: 100%; + background: url("./assets/home_bg.png"); +} + +@font-face { + font-family: "DM Sans"; + src: url("./assets/font/DMSans_18pt-Medium.ttf") format("truetype"); +} + +* { + -webkit-overflow-scrolling: touch; +} + +html, +body { + height: 100%; +} +html, +body, +h1, +h2, +h3, +h4, +h5, +h6, +div, +dl, +dt, +dd, +ul, +ol, +li, +p, +blockquote, +pre, +hr, +figure, +table, +caption, +th, +td, +form, +fieldset, +legend, +input, +button, +textarea, +menu { + margin: 0; + padding: 0; +} +header, +footer, +section, +article, +aside, +nav, +hgroup, +address, +figure, +figcaption, +menu, +details { + display: block; +} +table { + border-collapse: collapse; + border-spacing: 0; +} +caption, +th { + text-align: left; + font-weight: normal; +} +html, +body, +fieldset, +img, +iframe, +abbr { + border: 0; +} +i, +cite, +em, +var, +address, +dfn { + font-style: normal; +} +[hidefocus], +summary { + outline: 0; +} +li { + list-style: none; +} +h1, +h2, +h3, +h4, +h5, +h6, +small { + font-size: 100%; +} +sup, +sub { + font-size: 83%; +} +pre, +code, +kbd, +samp { + font-family: inherit; +} +q:before, +q:after { + content: none; +} +textarea { + overflow: auto; + resize: none; +} +label, +summary { + cursor: default; +} +a, +button { + cursor: pointer; +} +h1, +h2, +h3, +h4, +h5, +h6, +em, +strong, +b { + font-weight: bold; +} +del, +ins, +u, +s, +a, +a:hover { + text-decoration: none; +} +body, +textarea, +input, +button, +select, +keygen, +legend { + font: 12px/1.14 Microsoft YaHei, arial, \5b8b\4f53; + color: #333; + outline: 0; +} +body { + background: #fff; +} +a, +a:hover { + color: #333; +} +* { + box-sizing: border-box; } diff --git a/src/App.tsx b/src/App.tsx index dba3a63..0efb6ee 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,18 +1,45 @@ /* * @LastEditors: John * @Date: 2024-06-17 17:20:03 - * @LastEditTime: 2024-06-17 17:36:20 + * @LastEditTime: 2024-06-19 16:59:21 * @Author: John */ -import { Route, Routes } from "react-router-dom"; +import { Route, Router, Routes } from "react-router-dom"; +import "./style/ant-cover-m.css"; +import "./style/react-data-table-component-cover-m.css"; import "./App.css"; import Home from "./pages/Home"; +import Header from "./components/Header"; +import Mint from "./pages/Mint"; +import RouterLogProvider from "./context/RouterContext"; +import LevelUp from "./pages/LevelUp"; +import AssetRecord from "./pages/AssetRecord"; +import AirDropRecord from "./pages/AirDropRecord"; +import InvitationList from "./pages/InvitationList"; +import { useEffect } from "react"; +import { useTranslation } from "react-i18next"; +import useUserStore from "./store/User"; function App() { + const { i18n } = useTranslation(); + const { Lang: currantLang } = useUserStore(); + useEffect(() => { + i18n.changeLanguage(currantLang); + return () => {}; + }, []); + return ( <> - - } /> - + +
+ + } /> + } /> + } /> + } /> + } /> + }> + + ); } diff --git a/src/assets/font/DMSans_18pt-Medium.ttf b/src/assets/font/DMSans_18pt-Medium.ttf new file mode 100644 index 0000000..188957b Binary files /dev/null and b/src/assets/font/DMSans_18pt-Medium.ttf differ diff --git a/src/assets/home_bg.png b/src/assets/home_bg.png new file mode 100644 index 0000000..ad63290 Binary files /dev/null and b/src/assets/home_bg.png differ diff --git a/src/assets/logo.svg b/src/assets/logo.svg new file mode 100644 index 0000000..c5ba3c4 --- /dev/null +++ b/src/assets/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/nft_bg.svg b/src/assets/nft_bg.svg new file mode 100644 index 0000000..75cf827 --- /dev/null +++ b/src/assets/nft_bg.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/usdt_bg.svg b/src/assets/usdt_bg.svg new file mode 100644 index 0000000..d327c92 --- /dev/null +++ b/src/assets/usdt_bg.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/Header.module.css b/src/components/Header.module.css new file mode 100644 index 0000000..516acbb --- /dev/null +++ b/src/components/Header.module.css @@ -0,0 +1,70 @@ +/* + * @LastEditors: John + * @Date: 2024-06-18 15:19:21 + * @LastEditTime: 2024-06-18 18:49:40 + * @Author: John + */ +.header { + background-color: #101010; + padding: 0 15px; + .header_top { + display: flex; + align-items: center; + gap: 8px; + border-bottom: 0.25px solid #333333; + padding: 10px 0; + + .header_logo { + width: 24px; + height: 24px; + } + .header_title { + /* 自动布局子元素 */ + opacity: 1; + + font-family: DM Sans; + font-size: 16px; + font-weight: bold; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + + z-index: 1; + } + .header_lang { + width: 24px; + height: 24px; + margin-left: auto; + } + } + + .header_nav { + display: flex; + align-items: center; + padding: 10px 0; + span { + /* 自动布局子元素 */ + opacity: 1; + + font-family: DM Sans; + font-size: 14px; + font-weight: bold; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + + z-index: 1; + } + + .header_nav_icon { + width: 18px; + height: 18px; + } + } +} diff --git a/src/components/Header.tsx b/src/components/Header.tsx new file mode 100644 index 0000000..46b6b50 --- /dev/null +++ b/src/components/Header.tsx @@ -0,0 +1,165 @@ +/* + * @LastEditors: John + * @Date: 2024-06-18 15:16:31 + * @LastEditTime: 2024-06-19 18:30:52 + * @Author: John + */ +import Picker, { + PickerColumn, + PickerValue, +} from "antd-mobile/es/components/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 { useLocation, useNavigate, useNavigation } from "react-router-dom"; +import { RouterLogContext } from "@/context/RouterContext"; +import { useTranslation } from "react-i18next"; +import { Lang } from "@/constants"; +import useUserStore from "@/store/User"; +import { Popover } from "antd-mobile"; +import { Action } from "antd-mobile/es/components/popover"; + +const langColums: Action[] = [ + { text: "English", key: Lang.en }, + { text: "中文(简体)", key: Lang.cn }, + { text: "中文(繁体)", key: Lang.tw }, + { text: "日本語", key: Lang.jp }, + { text: "DEUTSCH", key: Lang.de }, +]; +export default function () { + const { UpdateLang } = useUserStore(); + + const route = useContext(RouterLogContext); + const navigate = useNavigate(); + const { t, i18n } = useTranslation(); + const location = useLocation(); + + const navTitle = useMemo(() => { + switch (location.pathname) { + case "/mint": + return t("铸造 NFT"); + case "/levelup": + return t("级别提升"); + case "/assetrecord": + return t("资产记录"); + case "/airdroprecord": + return t("RMOB记录"); + case "/invitationlist": + return t("直推列表"); + default: + return t("返回"); + } + }, [location]); + + return ( + <> +
+
+ + {t("红魔NFT")} + { + switch (node.key) { + case Lang.en: + i18n.changeLanguage(Lang.en); + UpdateLang(Lang.en); + break; + case Lang.cn: + i18n.changeLanguage(Lang.cn); + UpdateLang(Lang.cn); + break; + case Lang.tw: + i18n.changeLanguage(Lang.tw); + UpdateLang(Lang.tw); + break; + case Lang.jp: + i18n.changeLanguage(Lang.jp); + UpdateLang(Lang.jp); + break; + case Lang.de: + i18n.changeLanguage(Lang.de); + UpdateLang(Lang.de); + break; + default: + break; + } + }} + trigger="click" + > + + +
+ + {location.pathname != "/" && ( +
{ + if (route.current == route.from) { + navigate("/"); + return; + } + navigate(-1); + }} + > + + {navTitle} +
+ )} +
+ {/* + { + setLangPickVisble(false); + }} + value={langPickValue} + onConfirm={(v) => { + setLangPickValue(v); + // console.log("Current lang:", v[0]); + switch (v[0]) { + case Lang.en: + i18n.changeLanguage(Lang.en); + UpdateLang(Lang.en); + break; + case Lang.cn: + i18n.changeLanguage(Lang.cn); + UpdateLang(Lang.cn); + break; + case Lang.tw: + i18n.changeLanguage(Lang.tw); + UpdateLang(Lang.tw); + break; + case Lang.jp: + i18n.changeLanguage(Lang.jp); + UpdateLang(Lang.jp); + break; + case Lang.de: + i18n.changeLanguage(Lang.de); + UpdateLang(Lang.de); + break; + default: + break; + } + + // console.log("i18n lang:", i18n.language); + }} + confirmText={t("确定")} + cancelText={t("取消")} + /> */} + + ); +} diff --git a/src/components/RecordsItem.module.css b/src/components/RecordsItem.module.css new file mode 100644 index 0000000..0d1a3b9 --- /dev/null +++ b/src/components/RecordsItem.module.css @@ -0,0 +1,30 @@ +.recordsItem { + display: flex; + flex-direction: column; + gap: 6px; + padding-bottom: 10px; + border-bottom: 0.25px solid #333333; + > li { + display: flex; + align-items: center; + span { + /* 自动布局子元素 */ + opacity: 1; + + font-family: DM Sans; + font-size: 12px; + font-weight: 500; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + + z-index: 0; + &:nth-of-type(2) { + margin-left: auto; + } + } + } +} diff --git a/src/components/RecordsItem.tsx b/src/components/RecordsItem.tsx new file mode 100644 index 0000000..f66746a --- /dev/null +++ b/src/components/RecordsItem.tsx @@ -0,0 +1,25 @@ +/* + * @LastEditors: John + * @Date: 2024-06-19 10:49:42 + * @LastEditTime: 2024-06-19 10:52:32 + * @Author: John + */ +import classes from "./RecordsItem.module.css"; +export default function RecordsItem({ + itemList, +}: { + itemList: { title: string; value: string; valueColor?: string }[]; +}) { + return ( + <> +
    + {itemList.map((v, i) => ( +
  • + {v.title} + {v.value} +
  • + ))} +
+ + ); +} diff --git a/src/components/iconfont/IconChevronsrightshuangyoujiantou.tsx b/src/components/iconfont/IconChevronsrightshuangyoujiantou.tsx new file mode 100644 index 0000000..f7dad68 --- /dev/null +++ b/src/components/iconfont/IconChevronsrightshuangyoujiantou.tsx @@ -0,0 +1,29 @@ +/* tslint:disable */ +/* eslint-disable */ + +import React, { CSSProperties, SVGAttributes, FunctionComponent } from 'react'; +import { getIconColor } from './helper'; + +interface Props extends Omit, 'color'> { + size?: number; + color?: string | string[]; +} + +const DEFAULT_STYLE: CSSProperties = { + display: 'block', +}; + +const IconChevronsrightshuangyoujiantou: FunctionComponent = ({ size = 18, color, style: _style, ...rest }) => { + const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; + + return ( + + + + ); +}; + +export default IconChevronsrightshuangyoujiantou; diff --git a/src/components/iconfont/IconDiqiu.tsx b/src/components/iconfont/IconDiqiu.tsx new file mode 100644 index 0000000..fae6854 --- /dev/null +++ b/src/components/iconfont/IconDiqiu.tsx @@ -0,0 +1,53 @@ +/* tslint:disable */ +/* eslint-disable */ + +import React, { CSSProperties, SVGAttributes, FunctionComponent } from 'react'; +import { getIconColor } from './helper'; + +interface Props extends Omit, 'color'> { + size?: number; + color?: string | string[]; +} + +const DEFAULT_STYLE: CSSProperties = { + display: 'block', +}; + +const IconDiqiu: FunctionComponent = ({ size = 18, color, style: _style, ...rest }) => { + const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; + + return ( + + + + + + + + + + ); +}; + +export default IconDiqiu; diff --git a/src/components/iconfont/IconFuzhi.tsx b/src/components/iconfont/IconFuzhi.tsx new file mode 100644 index 0000000..04fba2d --- /dev/null +++ b/src/components/iconfont/IconFuzhi.tsx @@ -0,0 +1,33 @@ +/* tslint:disable */ +/* eslint-disable */ + +import React, { CSSProperties, SVGAttributes, FunctionComponent } from 'react'; +import { getIconColor } from './helper'; + +interface Props extends Omit, 'color'> { + size?: number; + color?: string | string[]; +} + +const DEFAULT_STYLE: CSSProperties = { + display: 'block', +}; + +const IconFuzhi: FunctionComponent = ({ size = 18, color, style: _style, ...rest }) => { + const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; + + return ( + + + + + ); +}; + +export default IconFuzhi; diff --git a/src/components/iconfont/IconGuanjun.tsx b/src/components/iconfont/IconGuanjun.tsx new file mode 100644 index 0000000..6ab8893 --- /dev/null +++ b/src/components/iconfont/IconGuanjun.tsx @@ -0,0 +1,761 @@ +/* tslint:disable */ +/* eslint-disable */ + +import React, { CSSProperties, SVGAttributes, FunctionComponent } from 'react'; +import { getIconColor } from './helper'; + +interface Props extends Omit, 'color'> { + size?: number; + color?: string | string[]; +} + +const DEFAULT_STYLE: CSSProperties = { + display: 'block', +}; + +const IconGuanjun: FunctionComponent = ({ size = 18, color, style: _style, ...rest }) => { + const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; + + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +}; + +export default IconGuanjun; diff --git a/src/components/iconfont/IconIconArrowLeft.tsx b/src/components/iconfont/IconIconArrowLeft.tsx new file mode 100644 index 0000000..7133d92 --- /dev/null +++ b/src/components/iconfont/IconIconArrowLeft.tsx @@ -0,0 +1,29 @@ +/* tslint:disable */ +/* eslint-disable */ + +import React, { CSSProperties, SVGAttributes, FunctionComponent } from 'react'; +import { getIconColor } from './helper'; + +interface Props extends Omit, 'color'> { + size?: number; + color?: string | string[]; +} + +const DEFAULT_STYLE: CSSProperties = { + display: 'block', +}; + +const IconIconArrowLeft: FunctionComponent = ({ size = 18, color, style: _style, ...rest }) => { + const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; + + return ( + + + + ); +}; + +export default IconIconArrowLeft; diff --git a/src/components/iconfont/IconJindun.tsx b/src/components/iconfont/IconJindun.tsx new file mode 100644 index 0000000..5154c8f --- /dev/null +++ b/src/components/iconfont/IconJindun.tsx @@ -0,0 +1,249 @@ +/* tslint:disable */ +/* eslint-disable */ + +import React, { CSSProperties, SVGAttributes, FunctionComponent } from 'react'; +import { getIconColor } from './helper'; + +interface Props extends Omit, 'color'> { + size?: number; + color?: string | string[]; +} + +const DEFAULT_STYLE: CSSProperties = { + display: 'block', +}; + +const IconJindun: FunctionComponent = ({ size = 18, color, style: _style, ...rest }) => { + const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; + + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +}; + +export default IconJindun; diff --git a/src/components/iconfont/IconTongdun.tsx b/src/components/iconfont/IconTongdun.tsx new file mode 100644 index 0000000..ef8c418 --- /dev/null +++ b/src/components/iconfont/IconTongdun.tsx @@ -0,0 +1,145 @@ +/* tslint:disable */ +/* eslint-disable */ + +import React, { CSSProperties, SVGAttributes, FunctionComponent } from 'react'; +import { getIconColor } from './helper'; + +interface Props extends Omit, 'color'> { + size?: number; + color?: string | string[]; +} + +const DEFAULT_STYLE: CSSProperties = { + display: 'block', +}; + +const IconTongdun: FunctionComponent = ({ size = 18, color, style: _style, ...rest }) => { + const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; + + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +}; + +export default IconTongdun; diff --git a/src/components/iconfont/IconTuichu.tsx b/src/components/iconfont/IconTuichu.tsx new file mode 100644 index 0000000..8592ae1 --- /dev/null +++ b/src/components/iconfont/IconTuichu.tsx @@ -0,0 +1,29 @@ +/* tslint:disable */ +/* eslint-disable */ + +import React, { CSSProperties, SVGAttributes, FunctionComponent } from 'react'; +import { getIconColor } from './helper'; + +interface Props extends Omit, 'color'> { + size?: number; + color?: string | string[]; +} + +const DEFAULT_STYLE: CSSProperties = { + display: 'block', +}; + +const IconTuichu: FunctionComponent = ({ size = 18, color, style: _style, ...rest }) => { + const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; + + return ( + + + + ); +}; + +export default IconTuichu; diff --git a/src/components/iconfont/IconXingdun.tsx b/src/components/iconfont/IconXingdun.tsx new file mode 100644 index 0000000..671b23a --- /dev/null +++ b/src/components/iconfont/IconXingdun.tsx @@ -0,0 +1,601 @@ +/* tslint:disable */ +/* eslint-disable */ + +import React, { CSSProperties, SVGAttributes, FunctionComponent } from 'react'; +import { getIconColor } from './helper'; + +interface Props extends Omit, 'color'> { + size?: number; + color?: string | string[]; +} + +const DEFAULT_STYLE: CSSProperties = { + display: 'block', +}; + +const IconXingdun: FunctionComponent = ({ size = 18, color, style: _style, ...rest }) => { + const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; + + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +}; + +export default IconXingdun; diff --git a/src/components/iconfont/helper.ts b/src/components/iconfont/helper.ts new file mode 100644 index 0000000..60d6d71 --- /dev/null +++ b/src/components/iconfont/helper.ts @@ -0,0 +1,12 @@ +/* tslint:disable */ +/* eslint-disable */ + +export const getIconColor = (color: string | string[] | undefined, index: number, defaultColor: string) => { + return color + ? ( + typeof color === 'string' + ? color + : color[index] || defaultColor + ) + : defaultColor; +}; diff --git a/src/components/iconfont/index.tsx b/src/components/iconfont/index.tsx new file mode 100644 index 0000000..26ab637 --- /dev/null +++ b/src/components/iconfont/index.tsx @@ -0,0 +1,58 @@ +/* tslint:disable */ +/* eslint-disable */ + +import React, { SVGAttributes, FunctionComponent } from 'react'; +import IconDiqiu from './IconDiqiu'; +import IconTuichu from './IconTuichu'; +import IconChevronsrightshuangyoujiantou from './IconChevronsrightshuangyoujiantou'; +import IconFuzhi from './IconFuzhi'; +import IconIconArrowLeft from './IconIconArrowLeft'; +import IconTongdun from './IconTongdun'; +import IconJindun from './IconJindun'; +import IconXingdun from './IconXingdun'; +import IconGuanjun from './IconGuanjun'; +export { default as IconDiqiu } from './IconDiqiu'; +export { default as IconTuichu } from './IconTuichu'; +export { default as IconChevronsrightshuangyoujiantou } from './IconChevronsrightshuangyoujiantou'; +export { default as IconFuzhi } from './IconFuzhi'; +export { default as IconIconArrowLeft } from './IconIconArrowLeft'; +export { default as IconTongdun } from './IconTongdun'; +export { default as IconJindun } from './IconJindun'; +export { default as IconXingdun } from './IconXingdun'; +export { default as IconGuanjun } from './IconGuanjun'; + +export type IconNames = 'diqiu' | 'tuichu' | 'chevronsrightshuangyoujiantou' | 'fuzhi' | 'icon_arrow_left' | 'tongdun' | 'jindun' | 'xingdun' | 'guanjun'; + +interface Props extends Omit, 'color'> { + name: IconNames; + size?: number; + color?: string | string[]; +} + +const IconFont: FunctionComponent = ({ name, ...rest }) => { + switch (name) { + case 'diqiu': + return ; + case 'tuichu': + return ; + case 'chevronsrightshuangyoujiantou': + return ; + case 'fuzhi': + return ; + case 'icon_arrow_left': + return ; + case 'tongdun': + return ; + case 'jindun': + return ; + case 'xingdun': + return ; + case 'guanjun': + return ; + + } + + return null; +}; + +export default IconFont; diff --git a/src/constants/index.ts b/src/constants/index.ts index 912ffcb..d46d0d7 100644 --- a/src/constants/index.ts +++ b/src/constants/index.ts @@ -1,9 +1,17 @@ /* * @LastEditors: John * @Date: 2024-06-17 17:57:13 - * @LastEditTime: 2024-06-17 17:57:30 + * @LastEditTime: 2024-06-19 16:26:15 * @Author: John */ export enum ASYNC_STORAGE_KEY { - Token = "user.token", + Store = "user.store", +} + +export enum Lang { + en = "en", + cn = "cn", + tw = "tw", + jp = "jp", + de = "de", } diff --git a/src/context/RouterContext.tsx b/src/context/RouterContext.tsx new file mode 100644 index 0000000..e6cfaed --- /dev/null +++ b/src/context/RouterContext.tsx @@ -0,0 +1,45 @@ +/* + * @LastEditors: John + * @Date: 2024-06-18 15:51:13 + * @LastEditTime: 2024-06-18 15:59:23 + * @Author: John + */ +import { PropsWithChildren, createContext, useEffect, useState } from "react"; +import { useLocation } from "react-router-dom"; + +type RouteLog = { + current: string; + from: string; +}; + +export const RouterLogContext = createContext({ + current: "", + from: "", +}); + +const RouterLogProvider = ({ children }: PropsWithChildren) => { + const location = useLocation(); + const [route, setRoute] = useState({ + //--> It can be replaced with useRef or localStorage + current: location.pathname, + from: location.pathname, + }); + + useEffect(() => { + setRoute((prev) => ({ current: location.pathname, from: prev.current })); + }, [location]); + + useEffect(() => { + console.log("route:", route); + + return () => {}; + }, [route]); + + return ( + + {children} + + ); +}; + +export default RouterLogProvider; diff --git a/src/contract/abi/USDT.json b/src/contract/abi/USDT.json new file mode 100644 index 0000000..405d6b3 --- /dev/null +++ b/src/contract/abi/USDT.json @@ -0,0 +1,222 @@ +[ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "balance", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + } +] diff --git a/src/contract/abi/erc20abi.json b/src/contract/abi/erc20abi.json new file mode 100644 index 0000000..a0cb0ac --- /dev/null +++ b/src/contract/abi/erc20abi.json @@ -0,0 +1,272 @@ +[ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "success", + "type": "bool" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "success", + "type": "bool" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "version", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "balance", + "type": "uint256" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "success", + "type": "bool" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + }, + { + "name": "_extraData", + "type": "bytes" + } + ], + "name": "approveAndCall", + "outputs": [ + { + "name": "success", + "type": "bool" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "remaining", + "type": "uint256" + } + ], + "payable": false, + "type": "function" + }, + { + "inputs": [ + { + "name": "_initialAmount", + "type": "uint256" + }, + { + "name": "_tokenName", + "type": "string" + }, + { + "name": "_decimalUnits", + "type": "uint8" + }, + { + "name": "_tokenSymbol", + "type": "string" + } + ], + "type": "constructor" + }, + { + "payable": false, + "type": "fallback" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "_from", + "type": "address" + }, + { + "indexed": true, + "name": "_to", + "type": "address" + }, + { + "indexed": false, + "name": "_value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "_owner", + "type": "address" + }, + { + "indexed": true, + "name": "_spender", + "type": "address" + }, + { + "indexed": false, + "name": "_value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + } +] diff --git a/src/contract/utils.ts b/src/contract/utils.ts new file mode 100644 index 0000000..d3b291a --- /dev/null +++ b/src/contract/utils.ts @@ -0,0 +1,135 @@ +/* + * @LastEditors: John + * @Date: 2024-06-19 15:48:57 + * @LastEditTime: 2024-06-19 16:13:14 + * @Author: John + */ +import { config } from "@/components/WalletProvider"; +import { + readContract, + estimateGas, + writeContract, + waitForTransactionReceipt, +} from "@wagmi/core"; +import { encodeFunctionData } from "viem/utils"; +import erc20Abi from "@/contract/abi/erc20abi.json"; +import usdtAbi from "@/contract/abi/USDT.json"; +import Toast from "antd-mobile/es/components/toast"; + +/** + * @description 获取代币余额 + * @param {string} fromAddress + * @return {*} + */ +export const getBalance = async (fromAddress: string): Promise => { + return new Promise((reslove, reject) => { + readContract(config, { + abi: erc20Abi, + address: import.meta.env.VITE_NETWORK_USDT_ADDRESS, + functionName: "balanceOf", + args: [fromAddress], + }) + .then((res: any) => { + console.log("U余额:", res); + if (typeof res == "undefined") { + // 获取授权U失败 + Toast.show({ + icon: "fail", + content: "get balance of usdt error!", + }); + return; + } + reslove(res); + }) + .catch((err) => { + console.log("get balance of usdt err", err); + reject(err); + }); + }); +}; + +/** + * @description: 获取已经授权的U + * @param {string} fromAddress + * @return {*} + */ +export const getApproveUsdt = async ( + contractAddress: string, + fromAddress: string +): Promise => { + return new Promise((reslove, reject) => { + readContract(config, { + abi: erc20Abi, + address: import.meta.env.VITE_NETWORK_USDT_ADDRESS, + functionName: "allowance", + args: [fromAddress, contractAddress], + }) + .then((res: any) => { + console.log("上次授权的U:", res); + if (typeof res == "undefined") { + // 获取授权U失败 + Toast.show({ + icon: "fail", + content: "get approve usdt error!", + }); + return; + } + reslove(res); + }) + .catch((err) => { + console.log("get approve usdt err", err); + reject(err); + }); + }); +}; + +/** + * @description: 授权U + * @param {bigint} uNum + * @return {*} + */ +export const authorizedU = async (uNum: bigint, contractAddress: string) => { + console.log("授权金额参数:", contractAddress, uNum); + return new Promise((reslove, reject) => { + estimateGas(config, { + to: import.meta.env.VITE_NETWORK_USDT_ADDRESS, + data: encodeFunctionData({ + abi: usdtAbi, + functionName: "approve", + args: [contractAddress, uNum], + }), + }) + .then((gas) => { + const gasPrice = (gas * 12n) / 10n; + console.log( + "estimate approve gas:%d , my approve gas: %d", + gas, + gasPrice + ); + + writeContract(config, { + abi: usdtAbi, + address: import.meta.env.VITE_NETWORK_USDT_ADDRESS, + functionName: "approve", + args: [contractAddress, uNum], + gas: gasPrice, + // gas, + }) + .then(async (hash) => { + console.log("approve res", hash); + const transactionReceipt = await waitForTransactionReceipt(config, { + hash, + }); + if (transactionReceipt.status == "success") reslove(); + }) + .catch((err) => { + console.log("approve error", err); + reject(err); + }); + }) + .catch((err) => { + console.log("estimate approve gas error", err); + reject(err); + }); + }); +}; diff --git a/src/i18n/init.ts b/src/i18n/init.ts index 7f4d7d9..d672f56 100644 --- a/src/i18n/init.ts +++ b/src/i18n/init.ts @@ -1,21 +1,36 @@ /* * @LastEditors: John * @Date: 2024-06-18 10:30:43 - * @LastEditTime: 2024-06-18 10:34:19 + * @LastEditTime: 2024-06-19 16:55:26 * @Author: John */ import i18next from "i18next"; import { initReactI18next } from "react-i18next"; import en from "./translation/en.json"; +import cn from "./translation/cn.json"; +import tw from "./translation/tw.json"; +import jp from "./translation/jp.json"; +import de from "./translation/de.json"; i18next.use(initReactI18next).init({ compatibilityJSON: "v3", // <--- add this line. lng: "en", // if you're using a language detector, do not define the lng option - // lng: LANGUAGE["en-US"], debug: false, resources: { en: { translation: en, }, + cn: { + translation: cn, + }, + tw: { + translation: tw, + }, + jp: { + translation: jp, + }, + de: { + translation: de, + }, }, // if you see an error like: "Argument of type 'DefaultTFuncReturn' is not assignable to parameter of type xyz" // set returnNull to false (and also in the i18next.d.ts options) diff --git a/src/i18n/translation/cn.json b/src/i18n/translation/cn.json new file mode 100644 index 0000000..a5db48a --- /dev/null +++ b/src/i18n/translation/cn.json @@ -0,0 +1,91 @@ +{ + "AppName": "红魔", + "红魔NFT": "红魔NFT", + "铸造 NFT": "铸造 NFT", + "级别提升": "级别提升", + "资产记录": "资产记录", + "RMOB记录": "RMOB记录", + "直推列表": "直推列表", + "返回": "返回", + "选择语言": "选择语言", + "确定": "确定", + "取消": "取消", + "普通非活跃": "普通非活跃", + "升级": "升级", + "链接钱包": "链接钱包", + "邀请铸造": "邀请铸造", + "团队社长": "团队社长", + "邀请空投": "邀请空投", + "代币": "代币", + "Min结束后按照规则进行空投。": "Min结束后按照规则进行空投。", + "铸造 NFT 获得代币空投": "铸造 NFT 获得代币空投", + "资产金额 = 已领取 + 待处理": "资产金额 = 已领取 + 待处理", + "邀请": "邀请", + "邀请链接": "邀请链接", + "普通会员每邀请铸造一个NFT可获得一份空投福利;推荐铸造20个NFT的可升级为会长;团队中拥有20位会长可升级为基金会社长;邀请越多级别越高福利越多。": "普通会员每邀请铸造一个NFT可获得一份空投福利;推荐铸造20个NFT的可升级为会长;团队中拥有20位会长可升级为基金会社长;邀请越多级别越高福利越多。", + "数据披露": "数据披露", + "资金池": "资金池", + "社长席位": "社长席位", + "基金会社长席位": "基金会社长席位", + "待领取": "待领取", + "领取": "领取", + "钱包未链接,无法向您显示 NFT": "钱包未链接,无法向您显示 NFT", + "邀请列表": "邀请列表", + "NFT总量:": "NFT总量:", + "MINT余量:": "MINT余量:", + "当前MINT价格:": "当前MINT价格:", + "价格说明:": "价格说明:", + "100USDT起,每增加100名普通会员,NFT价格上涨1%,既:前100名价格为100USDT/枚,101-200名价格为100u+100u*1%=101USDT/枚,以此类推。": "100USDT起,每增加100名普通会员,NFT价格上涨1%,既:前100名价格为100USDT/枚,101-200名价格为100u+100u*1%=101USDT/枚,以此类推。", + "授权USDT": "授权USDT", + "当前级别": "当前级别", + "普通活跃": "普通活跃", + "提升级别": "提升级别", + "社长": "社长", + "当前升级价格:": "当前升级价格:", + "升级费用100USDT起,其中gas费2USDT,剩余部分50%进入资金池,另外50%平均分给所有升级成功的社长和基金会社长。自第二个社长升级开始,每升级一名社长所需铸造费用增加10%,既第二位社长升级铸造费用为100u+100*10%=110USDT,以此类推。": "升级费用100USDT起,其中gas费2USDT,剩余部分50%进入资金池,另外50%平均分给所有升级成功的社长和基金会社长。自第二个社长升级开始,每升级一名社长所需铸造费用增加10%,既第二位社长升级铸造费用为100u+100*10%=110USDT,以此类推。", + "升级条件": "升级条件", + "普通会员": "普通会员", + "(限量20000个)": "(限量20000个)", + "1. MINT一枚NFT成为非活跃普通会员": "1. MINT一枚NFT成为非活跃普通会员", + "2. MINT NFT并推荐MINT成为活跃普通会员": "2. MINT NFT并推荐MINT成为活跃普通会员", + "3. 享1%代币空投平分(所有普通会员)": "3. 享1%代币空投平分(所有普通会员)", + "4. 活跃普通会员根据推荐MINT数量额外有空投权益。": "4. 活跃普通会员根据推荐MINT数量额外有空投权益。", + "(限量500个)": "(限量500个)", + "1. 先成为活跃普通会员,并推荐MINT 20枚NFT": "1. 先成为活跃普通会员,并推荐MINT 20枚NFT", + "2. 需支付100USDT起升级费用成为社长(第二个起递增10%)": "2. 需支付100USDT起升级费用成为社长(第二个起递增10%)", + "3. 享普通会员权益+0.5%空投代币平分(所有社长)": "3. 享普通会员权益+0.5%空投代币平分(所有社长)", + "4. 享社长升级费用50%平分(扣除2USDT GAS费后)": "4. 享社长升级费用50%平分(扣除2USDT GAS费后)", + "5. 从推荐MINT 21枚开始直推的铸造费用归社长所有": "5. 从推荐MINT 21枚开始直推的铸造费用归社长所有", + "基金会社长": "基金会社长", + "(限量20个)": "(限量20个)", + "1. 先成为社长,并团队中有20个社长": "1. 先成为社长,并团队中有20个社长", + "2. 享社长权益+0.5%空投代币平分(所有基金会社长)": "2. 享社长权益+0.5%空投代币平分(所有基金会社长)", + "3. 另外基金会社长参与所有项目分成": "3. 另外基金会社长参与所有项目分成", + "发放记录": "发放记录", + "升级费平分": "升级费平分", + "直推>20NFT": "直推>20NFT", + "空投记录": "空投记录", + "所有": "所有", + "NFT空投": "NFT空投", + "社长空投": "社长空投", + "直推空投": "直推空投", + "奖励类型": "奖励类型", + "NFT控投": "NFT控投", + "发放时间": "发放时间", + "发放数量": "发放数量", + "领取记录": "领取记录", + "领取时间": "领取时间", + "领取数量": "领取数量", + "领取状态": "领取状态", + "确认中": "确认中", + "领取成功": "领取成功", + "交易取消": "交易取消", + "地址": "地址", + "级别": "级别", + "直推NFT": "直推NFT", + "非活跃普通": "非活跃普通", + "活跃普通": "活跃普通", + + "复制成功": "复制成功", + "领取成功,前往钱包查看": "领取成功,前往钱包查看" +} diff --git a/src/i18n/translation/de.json b/src/i18n/translation/de.json new file mode 100644 index 0000000..b4d9452 --- /dev/null +++ b/src/i18n/translation/de.json @@ -0,0 +1,91 @@ +{ + "AppName": "Der Rote Teufel", + "红魔NFT": "Der Rote Teufel NFT", + "铸造 NFT": "NFT Prägen", + "级别提升": "Stufenaufstieg", + "资产记录": "Vermögensaufzeichnung", + "RMOB记录": "RMOB Aufzeichnung", + "直推列表": "Direktempfehlungsliste", + "返回": "Zurück", + "选择语言": "Sprache wählen", + "确定": "Bestätigen", + "取消": "Abbrechen", + "普通非活跃": "Inaktiv Mitglied", + "升级": "Upgrade", + "链接钱包": "Wallet verbinden", + "邀请铸造": "Prägen einladen", + "团队社长": "Teamleiter", + "邀请空投": "Airdrop einladen", + "代币": "Token", + "Min结束后按照规则进行空投。": "Airdrop nach dem Ende des Min gemäß den Regeln.", + "铸造 NFT 获得代币空投": "Token-Airdrop durch NFT-Prägung erhalten", + "资产金额 = 已领取 + 待处理": "Vermögenswert = Empfang + Ausstehend", + "邀请": "Einladen", + "邀请链接": "Einladungslink", + "普通会员每邀请铸造一个NFT可获得一份空投福利;推荐铸造20个NFT的可升级为会长;团队中拥有20位会长可升级为基金会社长;邀请越多级别越高福利越多。": "Normale Mitglieder erhalten für jede Einladung zur Prägung eines NFTs einen Airdrop-Bonus; 20 empfohlene Prägungen führen zum Aufstieg zum Vorsitzenden; 20 Vorsitzende im Team ermöglichen den Aufstieg zum Fundmanager; je mehr Einladungen, desto höher das Level und die Belohnungen.", + "数据披露": "Datenoffenlegung", + "资金池": "Liquiditätspool", + "社长席位": "Vorsitzenderplatz", + "基金会社长席位": "Fundmanagerplatz", + "待领取": "Ausstehend", + "领取": "Erhalten", + "钱包未链接,无法向您显示 NFT": "Wallet nicht verbunden, kann NFT nicht anzeigen", + "邀请列表": "Einladungsliste", + "NFT总量:": "Gesamtzahl der NFTs:", + "MINT余量:": "Verbleibende MINT:", + "当前MINT价格:": "Aktueller MINT-Preis:", + "价格说明:": "Preiserklärung:", + "100USDT起,每增加100名普通会员,NFT价格上涨1%,既:前100名价格为100USDT/枚,101-200名价格为100u+100u*1%=101USDT/枚,以此类推。": "Beginnend bei 100USDT steigt der NFT-Preis um 1% für jede zusätzlichen 100 Mitglieder: die ersten 100 kosten 100USDT pro Stück, 101-200 kosten 101USDT pro Stück usw.", + "授权USDT": "USDT autorisieren", + "当前级别": "Aktuelles Level", + "普通活跃": "Aktives Mitglied", + "提升级别": "Levelaufstieg", + "社长": "Vorsitzender", + "当前升级价格:": "Aktueller Upgrade-Preis:", + "升级费用100USDT起,其中gas费2USDT,剩余部分50%进入资金池,另外50%平均分给所有升级成功的社长和基金会社长。自第二个社长升级开始,每升级一名社长所需铸造费用增加10%,既第二位社长升级铸造费用为100u+100*10%=110USDT,以此类推。": "Upgrade-Kosten ab 100USDT, davon 2USDT Gas-Gebühren, 50% des Restbetrags gehen in den Liquiditätspool und die anderen 50% werden auf alle erfolgreichen Vorsitzenden und Fundmanager aufgeteilt. Ab dem zweiten Vorsitzenden steigen die Prägekosten um 10% pro Aufstieg, also 110USDT für den zweiten, usw.", + "升级条件": "Upgrade-Bedingungen", + "普通会员": "Normales Mitglied", + "(限量20000个)": "(Begrenzt auf 20.000 Stück)", + "1. MINT一枚NFT成为非活跃普通会员": "1. Präge ein NFT, um inaktives Mitglied zu werden", + "2. MINT NFT并推荐MINT成为活跃普通会员": "2. Präge und empfehle NFTs, um aktives Mitglied zu werden", + "3. 享1%代币空投平分(所有普通会员)": "3. Erhalte 1% Token-Airdrop gleichmäßig verteilt (alle normalen Mitglieder)", + "4. 活跃普通会员根据推荐MINT数量额外有空投权益。": "4. Aktive Mitglieder erhalten zusätzliche Airdrop-Rechte basierend auf der Anzahl der empfohlenen Prägungen.", + "(限量500个)": "(Begrenzt auf 500 Stück)", + "1. 先成为活跃普通会员,并推荐MINT 20枚NFT": "1. Werde zuerst aktives Mitglied und empfehle die Prägung von 20 NFTs", + "2. 需支付100USDT起升级费用成为社长(第二个起递增10%)": "2. Zahle ab 100USDT für das Upgrade zum Vorsitzenden (ab dem zweiten um 10% steigend)", + "3. 享普通会员权益+0.5%空投代币平分(所有社长)": "3. Erhalte die Rechte eines normalen Mitglieds + 0,5% Token-Airdrop gleichmäßig verteilt (alle Vorsitzenden)", + "4. 享社长升级费用50%平分(扣除2USDT GAS费后)": "4. Erhalte 50% der Upgrade-Kosten des Vorsitzenden gleichmäßig verteilt (abzüglich 2USDT Gas-Gebühr)", + "5. 从推荐MINT 21枚开始直推的铸造费用归社长所有": "5. Ab 21 empfohlenen Prägungen gehen die Prägekosten direkt an den Vorsitzenden", + "基金会社长": "Fundmanager", + "(限量20个)": "(Begrenzt auf 20 Stück)", + "1. 先成为社长,并团队中有20个社长": "1. Werde zuerst Vorsitzender und habe 20 Vorsitzende im Team", + "2. 享社长权益+0.5%空投代币平分(所有基金会社长)": "2. Erhalte die Rechte eines Vorsitzenden + 0,5% Token-Airdrop gleichmäßig verteilt (alle Fundmanager)", + "3. 另外基金会社长参与所有项目分成": "3. Fundmanager nehmen zusätzlich an allen Projektgewinnen teil", + "发放记录": "Verteilungsprotokoll", + "升级费平分": "Upgrade-Gebührenverteilung", + "直推>20NFT": "Direktempfehlung > 20 NFT", + "空投记录": "Airdrop-Protokoll", + "所有": "Alle", + "NFT空投": "NFT-Airdrop", + "社长空投": "Vorsitzender-Airdrop", + "直推空投": "Direktempfehlung Airdrop", + "奖励类型": "Belohnungstyp", + "NFT控投": "NFT-Besitz", + "发放时间": "Verteilungszeit", + "发放数量": "Verteilungsmenge", + "领取记录": "Empfangsprotokoll", + "领取时间": "Empfangszeit", + "领取数量": "Empfangsmenge", + "领取状态": "Empfangsstatus", + "确认中": "Bestätigung läuft", + "领取成功": "Erfolgreich empfangen", + "交易取消": "Transaktion abgebrochen", + "地址": "Adresse", + "级别": "Stufe", + "直推NFT": "Direktempfehlung NFT", + "非活跃普通": "Inaktiv allgemein", + "活跃普通": "Aktiv allgemein", + + "复制成功": "Erfolgreich kopiert", + "领取成功,前往钱包查看": "Erfolgreich abgerufen. Bitte überprüfen Sie Ihre Brieftasche." +} diff --git a/src/i18n/translation/en.json b/src/i18n/translation/en.json index 4b850f4..4b734eb 100644 --- a/src/i18n/translation/en.json +++ b/src/i18n/translation/en.json @@ -1,3 +1,91 @@ { - "AppName": "red devils" + "AppName": "Red Devils", + "红魔NFT": "Red Devils NFT", + "铸造 NFT": "Mint NFT", + "级别提升": "Level Up", + "资产记录": "Asset Records", + "RMOB记录": "RMOB Records", + "直推列表": "Direct Referral List", + "返回": "Back", + "选择语言": "Select Language", + "确定": "Confirm", + "取消": "Cancel", + "普通非活跃": "Inactive Member", + "升级": "Upgrade", + "链接钱包": "Link Wallet", + "邀请铸造": "Invite to Mint", + "团队社长": "Team Leader", + "邀请空投": "Invite Airdrop", + "代币": "Token", + "Min结束后按照规则进行空投。": "Airdrop will follow the rules after Min ends.", + "铸造 NFT 获得代币空投": "Mint NFT for Token Airdrop", + "资产金额 = 已领取 + 待处理": "Asset Amount = Claimed + Pending", + "邀请": "Invite", + "邀请链接": "Invite Link", + "普通会员每邀请铸造一个NFT可获得一份空投福利;推荐铸造20个NFT的可升级为会长;团队中拥有20位会长可升级为基金会社长;邀请越多级别越高福利越多。": "Regular members get an airdrop for each NFT minted through their invite; recommending 20 NFTs upgrades to Leader; having 20 Leaders in the team upgrades to Foundation Leader; more invites lead to higher levels and more benefits.", + "数据披露": "Data Disclosure", + "资金池": "Fund Pool", + "社长席位": "Leader Seats", + "基金会社长席位": "Foundation Leader Seats", + "待领取": "Pending", + "领取": "Claim", + "钱包未链接,无法向您显示 NFT": "Wallet not linked, unable to display NFT", + "邀请列表": "Invite List", + "NFT总量:": "Total NFTs:", + "MINT余量:": "Remaining MINT:", + "当前MINT价格:": "Current MINT Price:", + "价格说明:": "Price Explanation:", + "100USDT起,每增加100名普通会员,NFT价格上涨1%,既:前100名价格为100USDT/枚,101-200名价格为100u+100u*1%=101USDT/枚,以此类推。": "Starting at 100USDT, the NFT price increases by 1% for every 100 new members: first 100 at 100USDT each, 101-200 at 101USDT each, and so on.", + "授权USDT": "Authorize USDT", + "当前级别": "Current Level", + "普通活跃": "Active Member", + "提升级别": "Upgrade Level", + "社长": "Leader", + "当前升级价格:": "Current Upgrade Price:", + "升级费用100USDT起,其中gas费2USDT,剩余部分50%进入资金池,另外50%平均分给所有升级成功的社长和基金会社长。自第二个社长升级开始,每升级一名社长所需铸造费用增加10%,既第二位社长升级铸造费用为100u+100*10%=110USDT,以此类推。": "Upgrade cost starts at 100USDT, including 2USDT gas fee; 50% goes to the fund pool, and 50% is distributed among successful Leaders and Foundation Leaders. From the second Leader onwards, each upgrade cost increases by 10%, i.e., second Leader upgrade costs 110USDT, and so on.", + "升级条件": "Upgrade Conditions", + "普通会员": "Regular Member", + "(限量20000个)": "(Limited to 20000)", + "1. MINT一枚NFT成为非活跃普通会员": "1. MINT an NFT to become an Inactive Member", + "2. MINT NFT并推荐MINT成为活跃普通会员": "2. MINT NFT and recommend MINT to become an Active Member", + "3. 享1%代币空投平分(所有普通会员)": "3. 1% token airdrop shared among all members", + "4. 活跃普通会员根据推荐MINT数量额外有空投权益。": "4. Active members get extra airdrop benefits based on the number of recommended MINTs.", + "(限量500个)": "(Limited to 500)", + "1. 先成为活跃普通会员,并推荐MINT 20枚NFT": "1. Become an Active Member and recommend 20 NFTs", + "2. 需支付100USDT起升级费用成为社长(第二个起递增10%)": "2. Pay 100USDT to upgrade to Leader (10% increment from the second Leader onwards)", + "3. 享普通会员权益+0.5%空投代币平分(所有社长)": "3. Enjoy member benefits + 0.5% token airdrop shared among all Leaders", + "4. 享社长升级费用50%平分(扣除2USDT GAS费后)": "4. Share 50% of Leader upgrade fees (after 2USDT gas fee)", + "5. 从推荐MINT 21枚开始直推的铸造费用归社长所有": "5. Mint fees from direct referrals beyond 21 NFTs go to the Leader", + "基金会社长": "Foundation Leader", + "(限量20个)": "(Limited to 20)", + "1. 先成为社长,并团队中有20个社长": "1. Become a Leader with 20 Leaders in your team", + "2. 享社长权益+0.5%空投代币平分(所有基金会社长)": "2. Enjoy Leader benefits + 0.5% token airdrop shared among all Foundation Leaders", + "3. 另外基金会社长参与所有项目分成": "3. Additionally, Foundation Leaders share in all project profits", + "发放记录": "Distribution Records", + "升级费平分": "Upgrade Fee Distribution", + "直推>20NFT": "Direct Referral >20 NFTs", + "空投记录": "Airdrop Records", + "所有": "All", + "NFT空投": "NFT Airdrop", + "社长空投": "Leader Airdrop", + "直推空投": "Direct Referral Airdrop", + "奖励类型": "Reward Type", + "NFT控投": "NFT Holding", + "发放时间": "Distribution Time", + "发放数量": "Distribution Quantity", + "领取记录": "Claim Records", + "领取时间": "Claim Time", + "领取数量": "Claim Quantity", + "领取状态": "Claim Status", + "确认中": "Confirming", + "领取成功": "Claim Successful", + "交易取消": "Transaction Cancelled", + "地址": "Address", + "级别": "Level", + "直推NFT": "Direct Referral NFT", + "非活跃普通": "Inactive Member", + "活跃普通": "Active Member", + + "复制成功": "Copy successful", + "领取成功,前往钱包查看": "Claim successful, please check your wallet." } diff --git a/src/i18n/translation/jp.json b/src/i18n/translation/jp.json new file mode 100644 index 0000000..30c72a2 --- /dev/null +++ b/src/i18n/translation/jp.json @@ -0,0 +1,91 @@ +{ + "AppName": "紅魔", + "红魔NFT": "紅魔NFT", + "铸造 NFT": "NFT 鋳造", + "级别提升": "レベルアップ", + "资产记录": "資産記録", + "RMOB记录": "RMOB記録", + "直推列表": "ダイレクト推薦リスト", + "返回": "戻る", + "选择语言": "言語選択", + "确定": "確定", + "取消": "キャンセル", + "普通非活跃": "非活躍メンバー", + "升级": "アップグレード", + "链接钱包": "ウォレットを接続", + "邀请铸造": "鋳造を招待", + "团队社长": "チームリーダー", + "邀请空投": "エアドロップ招待", + "代币": "トークン", + "Min结束后按照规则进行空投。": "Min終了後、ルールに従ってエアドロップを行います。", + "铸造 NFT 获得代币空投": "NFTを鋳造してトークンエアドロップを獲得", + "资产金额 = 已领取 + 待处理": "資産額 = 受領済み + 処理中", + "邀请": "招待", + "邀请链接": "招待リンク", + "普通会员每邀请铸造一个NFT可获得一份空投福利;推荐铸造20个NFT的可升级为会长;团队中拥有20位会长可升级为基金会社长;邀请越多级别越高福利越多。": "一般会員はNFT鋳造の招待ごとにエアドロップを獲得;20個のNFTを鋳造することでリーダーに昇格;チーム内に20人のリーダーがいるとファンドリーダーに昇格;招待が多いほどレベルが上がり、特典が増える。", + "数据披露": "データ開示", + "资金池": "資金プール", + "社长席位": "リーダー席", + "基金会社长席位": "ファンドリーダー席", + "待领取": "未受領", + "领取": "受領", + "钱包未链接,无法向您显示 NFT": "ウォレットが接続されていないため、NFTを表示できません", + "邀请列表": "招待リスト", + "NFT总量:": "NFT総量:", + "MINT余量:": "残りのMINT:", + "当前MINT价格:": "現在のMINT価格:", + "价格说明:": "価格説明:", + "100USDT起,每增加100名普通会员,NFT价格上涨1%,既:前100名价格为100USDT/枚,101-200名价格为100u+100u*1%=101USDT/枚,以此类推。": "100USDTから、100人の会員が増えるごとにNFT価格が1%上昇:最初の100人は100USDT/個、101-200人は101USDT/個、以降も同様。", + "授权USDT": "USDTの承認", + "当前级别": "現在のレベル", + "普通活跃": "活躍メンバー", + "提升级别": "レベルアップ", + "社长": "リーダー", + "当前升级价格:": "現在のアップグレード価格:", + "升级费用100USDT起,其中gas费2USDT,剩余部分50%进入资金池,另外50%平均分给所有升级成功的社长和基金会社长。自第二个社长升级开始,每升级一名社长所需铸造费用增加10%,既第二位社长升级铸造费用为100u+100*10%=110USDT,以此类推。": "アップグレード費用は100USDTから、うちガス代2USDT、残りの50%は資金プールに入り、もう50%はアップグレードに成功したリーダーとファンドリーダーに分配。2人目のリーダーからは、アップグレード費用が10%ずつ増加、つまり2人目は110USDT、以降も同様。", + "升级条件": "アップグレード条件", + "普通会员": "一般会員", + "(限量20000个)": "(限定20000個)", + "1. MINT一枚NFT成为非活跃普通会员": "1. NFTを1枚鋳造して非活躍メンバーになる", + "2. MINT NFT并推荐MINT成为活跃普通会员": "2. NFTを鋳造し、他者に鋳造を推奨して活躍メンバーになる", + "3. 享1%代币空投平分(所有普通会员)": "3. 一般会員は1%のトークンエアドロップを均等に分配", + "4. 活跃普通会员根据推荐MINT数量额外有空投权益。": "4. 活躍メンバーは推奨MINT数に応じて追加エアドロップ権を持つ。", + "(限量500个)": "(限定500個)", + "1. 先成为活跃普通会员,并推荐MINT 20枚NFT": "1. まず活躍メンバーになり、20枚のNFTを推奨して鋳造", + "2. 需支付100USDT起升级费用成为社长(第二个起递增10%)": "2. 100USDTからアップグレード費用を支払いリーダーになる(2人目以降は10%増加)", + "3. 享普通会员权益+0.5%空投代币平分(所有社长)": "3. 一般会員の権利に加え、リーダーは0.5%のトークンエアドロップを均等に分配", + "4. 享社长升级费用50%平分(扣除2USDT GAS费后)": "4. リーダーのアップグレード費用の50%を分配(2USDTのガス代を除く)", + "5. 从推荐MINT 21枚开始直推的铸造费用归社长所有": "5. 推奨MINTが21枚以上になると、鋳造費用はリーダーのものとなる", + "基金会社长": "ファンドリーダー", + "(限量20个)": "(限定20個)", + "1. 先成为社长,并团队中有20个社长": "1. まずリーダーになり、チームに20人のリーダーがいる", + "2. 享社长权益+0.5%空投代币平分(所有基金会社长)": "2. リーダーの権利に加え、ファンドリーダーは0.5%のトークンエアドロップを均等に分配", + "3. 另外基金会社长参与所有项目分成": "3. さらにファンドリーダーはすべてのプロジェクトの利益分配に参加", + "发放记录": "配布記録", + "升级费平分": "アップグレード費用分配", + "直推>20NFT": "ダイレクト推薦>20NFT", + "空投记录": "エアドロップ記録", + "所有": "すべて", + "NFT空投": "NFTエアドロップ", + "社长空投": "リーダーエアドロップ", + "直推空投": "ダイレクト推薦エアドロップ", + "奖励类型": "報酬タイプ", + "NFT控投": "NFT保有", + "发放时间": "配布時間", + "发放数量": "配布数量", + "领取记录": "受領記録", + "领取时间": "受領時間", + "领取数量": "受領数量", + "领取状态": "受領状態", + "确认中": "確認中", + "领取成功": "受領成功", + "交易取消": "取引キャンセル", + "地址": "アドレス", + "级别": "レベル", + "直推NFT": "ダイレクト推薦NFT", + "非活跃普通": "非活躍一般", + "活跃普通": "活躍一般", + + "复制成功": "コピーが成功しました", + "领取成功,前往钱包查看": "受け取りが成功しました。ウォレットで確認してください。" +} diff --git a/src/i18n/translation/tw.json b/src/i18n/translation/tw.json new file mode 100644 index 0000000..c1f5011 --- /dev/null +++ b/src/i18n/translation/tw.json @@ -0,0 +1,91 @@ +{ + "AppName": "紅魔", + "红魔NFT": "紅魔NFT", + "铸造 NFT": "鑄造 NFT", + "级别提升": "級別提升", + "资产记录": "資產記錄", + "RMOB记录": "RMOB記錄", + "直推列表": "直推列表", + "返回": "返回", + "选择语言": "選擇語言", + "确定": "確定", + "取消": "取消", + "普通非活跃": "普通非活躍", + "升级": "升級", + "链接钱包": "鏈接錢包", + "邀请铸造": "邀請鑄造", + "团队社长": "團隊社長", + "邀请空投": "邀請空投", + "代币": "代幣", + "Min结束后按照规则进行空投。": "Min結束後按照規則進行空投。", + "铸造 NFT 获得代币空投": "鑄造 NFT 獲得代幣空投", + "资产金额 = 已领取 + 待处理": "資產金額 = 已領取 + 待處理", + "邀请": "邀請", + "邀请链接": "邀請鏈接", + "普通会员每邀请铸造一个NFT可获得一份空投福利;推荐铸造20个NFT的可升级为会长;团队中拥有20位会长可升级为基金会社长;邀请越多级别越高福利越多。": "普通會員每邀請鑄造一個NFT可獲得一份空投福利;推薦鑄造20個NFT的可升級為會長;團隊中擁有20位會長可升級為基金會社長;邀請越多級別越高福利越多。", + "数据披露": "數據披露", + "资金池": "資金池", + "社长席位": "社長席位", + "基金会社长席位": "基金會社長席位", + "待领取": "待領取", + "领取": "領取", + "钱包未链接,无法向您显示 NFT": "錢包未鏈接,無法向您顯示 NFT", + "邀请列表": "邀請列表", + "NFT总量:": "NFT總量:", + "MINT余量:": "MINT餘量:", + "当前MINT价格:": "當前MINT價格:", + "价格说明:": "價格說明:", + "100USDT起,每增加100名普通会员,NFT价格上涨1%,既:前100名价格为100USDT/枚,101-200名价格为100u+100u*1%=101USDT/枚,以此类推。": "100USDT起,每增加100名普通會員,NFT價格上漲1%,即:前100名價格為100USDT/枚,101-200名價格為100u+100u*1%=101USDT/枚,以此類推。", + "授权USDT": "授權USDT", + "当前级别": "當前級別", + "普通活跃": "普通活躍", + "提升级别": "提升級別", + "社长": "社長", + "当前升级价格:": "當前升級價格:", + "升级费用100USDT起,其中gas费2USDT,剩余部分50%进入资金池,另外50%平均分给所有升级成功的社长和基金会社长。自第二个社长升级开始,每升级一名社长所需铸造费用增加10%,既第二位社长升级铸造费用为100u+100*10%=110USDT,以此类推。": "升級費用100USDT起,其中gas費2USDT,剩餘部分50%進入資金池,另外50%平均分給所有升級成功的社長和基金會社長。自第二個社長升級開始,每升級一名社長所需鑄造費用增加10%,即第二位社長升級鑄造費用為100u+100*10%=110USDT,以此類推。", + "升级条件": "升級條件", + "普通会员": "普通會員", + "(限量20000个)": "(限量20000個)", + "1. MINT一枚NFT成为非活跃普通会员": "1. MINT一枚NFT成為非活躍普通會員", + "2. MINT NFT并推荐MINT成为活跃普通会员": "2. MINT NFT並推薦MINT成為活躍普通會員", + "3. 享1%代币空投平分(所有普通会员)": "3. 享1%代幣空投平分(所有普通會員)", + "4. 活跃普通会员根据推荐MINT数量额外有空投权益。": "4. 活躍普通會員根據推薦MINT數量額外有空投權益。", + "(限量500个)": "(限量500個)", + "1. 先成为活跃普通会员,并推荐MINT 20枚NFT": "1. 先成為活躍普通會員,並推薦MINT 20枚NFT", + "2. 需支付100USDT起升级费用成为社长(第二个起递增10%)": "2. 需支付100USDT起升級費用成為社長(第二個起遞增10%)", + "3. 享普通会员权益+0.5%空投代币平分(所有社长)": "3. 享普通會員權益+0.5%空投代幣平分(所有社長)", + "4. 享社长升级费用50%平分(扣除2USDT GAS费后)": "4. 享社長升級費用50%平分(扣除2USDT GAS費後)", + "5. 从推荐MINT 21枚开始直推的铸造费用归社长所有": "5. 從推薦MINT 21枚開始直推的鑄造費用歸社長所有", + "基金会社长": "基金會社長", + "(限量20个)": "(限量20個)", + "1. 先成为社长,并团队中有20个社长": "1. 先成為社長,並團隊中有20個社長", + "2. 享社长权益+0.5%空投代币平分(所有基金会社长)": "2. 享社長權益+0.5%空投代幣平分(所有基金會社長)", + "3. 另外基金会社长参与所有项目分成": "3. 另外基金會社長參與所有項目分成", + "发放记录": "發放記錄", + "升级费平分": "升級費平分", + "直推>20NFT": "直推>20NFT", + "空投记录": "空投記錄", + "所有": "所有", + "NFT空投": "NFT空投", + "社长空投": "社長空投", + "直推空投": "直推空投", + "奖励类型": "獎勵類型", + "NFT控投": "NFT控投", + "发放时间": "發放時間", + "发放数量": "發放數量", + "领取记录": "領取記錄", + "领取时间": "領取時間", + "领取数量": "領取數量", + "领取状态": "領取狀態", + "确认中": "確認中", + "领取成功": "領取成功", + "交易取消": "交易取消", + "地址": "地址", + "级别": "級別", + "直推NFT": "直推NFT", + "非活跃普通": "非活躍普通", + "活跃普通": "活躍普通", + + "复制成功": "複製成功", + "领取成功,前往钱包查看": "領取成功,前往錢包查看" +} diff --git a/src/main.tsx b/src/main.tsx index a339f3b..dc791d6 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,20 +1,24 @@ /* * @LastEditors: John * @Date: 2024-06-17 17:20:03 - * @LastEditTime: 2024-06-18 10:46:11 + * @LastEditTime: 2024-06-19 18:07:46 * @Author: John */ import "@/i18n/init.ts"; import "antd-mobile/es/global"; import ReactDOM from "react-dom/client"; import App from "./App.tsx"; -import "normalize.css"; +// import "normalize.css"; import "./index.css"; import { HashRouter } from "react-router-dom"; import EventBusProvider from "./context/EventBusContext.tsx"; import { WalletProvider } from "./components/WalletProvider.tsx"; import flexible from "./utils/flexible.ts"; +import VConsole from "vconsole"; +if (import.meta.env.DEV) { + new VConsole(); +} flexible(window, document); ReactDOM.createRoot(document.getElementById("root")!).render( <> diff --git a/src/pages/AirDropRecord.module.css b/src/pages/AirDropRecord.module.css new file mode 100644 index 0000000..90c37ec --- /dev/null +++ b/src/pages/AirDropRecord.module.css @@ -0,0 +1,9 @@ +.AirDropRecord { + .recordsList { + display: flex; + flex-direction: column; + gap: 10px; + padding: 0 15px; + margin-top: 20px; + } +} diff --git a/src/pages/AirDropRecord.tsx b/src/pages/AirDropRecord.tsx new file mode 100644 index 0000000..2b70816 --- /dev/null +++ b/src/pages/AirDropRecord.tsx @@ -0,0 +1,97 @@ +/* + * @LastEditors: John + * @Date: 2024-06-19 10:43:03 + * @LastEditTime: 2024-06-19 14:25:41 + * @Author: John + */ +import RecordsItem from "@/components/RecordsItem"; +import CapsuleTabs from "antd-mobile/es/components/capsule-tabs"; +import Tabs from "antd-mobile/es/components/tabs"; +import classes from "./AirDropRecord.module.css"; +import { useTranslation } from "react-i18next"; +export default function () { + const { t } = useTranslation(); + return ( + <> + + + + + + + + + +
    + {Array.from({ length: 20 }).map((v, i) => ( +
  • + +
  • + ))} +
+
+ +
    +
  • + +
  • +
  • + +
  • +
  • + +
  • +
+
+
+ + ); +} diff --git a/src/pages/AssetRecord.module.css b/src/pages/AssetRecord.module.css new file mode 100644 index 0000000..35ca5c2 --- /dev/null +++ b/src/pages/AssetRecord.module.css @@ -0,0 +1,9 @@ +.AssetRecord { + .recordsList { + display: flex; + flex-direction: column; + gap: 10px; + padding: 0 15px; + margin-top: 20px; + } +} diff --git a/src/pages/AssetRecord.tsx b/src/pages/AssetRecord.tsx new file mode 100644 index 0000000..71328e8 --- /dev/null +++ b/src/pages/AssetRecord.tsx @@ -0,0 +1,108 @@ +/* + * @LastEditors: John + * @Date: 2024-06-18 17:57:13 + * @LastEditTime: 2024-06-19 14:19:55 + * @Author: John + */ +import Tabs from "antd-mobile/es/components/tabs"; +import classes from "./AssetRecord.module.css"; +import { cn } from "@/utils"; +import CapsuleTabs from "antd-mobile/es/components/capsule-tabs"; +import RecordsItem from "@/components/RecordsItem"; +import { useTranslation } from "react-i18next"; + +export default function () { + const { t } = useTranslation(); + return ( + <> + + + + + + 20NFT")} key="3" /> + +
    +
  • + +
  • + +
  • + 20NFT"), + }, + { title: t("发放时间"), value: "2024-06-01 12:23:45" }, + { title: t("发放数量"), value: "2.00 USDT" }, + ]} + /> +
  • +
+
+ +
    +
  • + +
  • +
  • + +
  • +
  • + +
  • +
+
+
+ + ); +} diff --git a/src/pages/Home.module.css b/src/pages/Home.module.css index 54005e8..cdf6520 100644 --- a/src/pages/Home.module.css +++ b/src/pages/Home.module.css @@ -1,10 +1,783 @@ +.container { + padding: 0 14px; +} + .Home { display: flex; flex-direction: column; - align-items: center; - justify-content: center; - gap: 10px; - .text { - font-size: 20px; + padding-bottom: 69px; + box-sizing: border-box; + + .userinfo { + width: 345px; + height: 136px; + border-radius: 16px; + opacity: 1; + + background: #171719; + + box-shadow: 0px 4px 10px 0px rgba(138, 29, 19, 0.3), + inset 0px 0px 8px 0px #8a1d13; + + padding: 14px 15px; + box-sizing: border-box; + display: flex; + flex-direction: column; + justify-content: space-between; + + margin-top: 21px; + + .userinfo_top { + display: flex; + flex-direction: row; + align-items: center; + gap: 16px; + .userinfo_top_left { + width: 46px; + height: 46px; + border-radius: 10.12px; + opacity: 1; + } + .userinfo_top_right { + display: flex; + flex-direction: column; + gap: 6px; + .userinfo_top_right_wallet { + display: flex; + align-items: center; + gap: 12px; + span { + opacity: 1; + + font-family: DM Sans; + font-size: 14px; + font-weight: bold; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + + z-index: 0; + } + .userinfo_top_right_wallet_disconnect { + width: 16px; + height: 16px; + } + } + .userinfo_top_right_btns { + display: flex; + align-items: center; + gap: 8px; + .userinfo_top_right_btns_item { + /* 自动布局子元素 */ + border-radius: 6px; + opacity: 1; + + /* 自动布局 */ + display: flex; + flex-direction: row; + align-items: center; + padding: 4px 6px; + gap: 4px; + + background: #67676b; + + z-index: 0; + + display: flex; + align-items: center; + + span { + /* 自动布局子元素 */ + opacity: 1; + + font-family: DM Sans; + font-size: 10px; + font-weight: 500; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + + z-index: 1; + } + .userinfo_top_right_btns_icon { + width: 12px; + height: 12px; + } + } + } + } + .userinfo_top_right_connect { + height: 36px; + border-radius: 10px; + opacity: 1; + + background: #fc872b; + + box-sizing: border-box; + border: 1px solid; + + padding: 0 20px; + + display: flex; + justify-content: center; + align-items: center; + span { + opacity: 1; + + font-family: DM Sans; + font-size: 14px; + font-weight: 500; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + } + } + } + + .userinfo_data { + display: flex; + flex-direction: row; + gap: 10.5px; + li { + width: 98px; + height: 48px; + border-radius: 16px; + opacity: 1; + + background: #212123; + + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 4px; + + .userinfo_data_num { + /* 自动布局子元素 */ + opacity: 1; + + font-family: DM Sans; + font-size: 14px; + font-weight: bold; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + + z-index: 0; + } + .userinfo_data_des { + /* 自动布局子元素 */ + opacity: 1; + + font-family: DM Sans; + font-size: 10px; + font-weight: 500; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + + z-index: 1; + } + } + } + } + + .nftToken { + margin-top: 24px; + .nftToken_tab { + display: flex; + flex-direction: row; + align-items: center; + li { + width: 76px; + height: 34px; + + opacity: 1; + + font-family: DM Sans; + font-size: 14px; + font-weight: bold; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #4d4d4d; + text-align: center; + line-height: 34px; + &.nftToken_tab_active { + border-radius: 10px; + opacity: 1; + + background: #fc872b; + + color: #ffffff; + } + } + } + + .nftToken_content { + margin-top: 10px; + + width: 345px; + min-height: 236px; + border-radius: 16px; + opacity: 1; + + background: #171719; + z-index: 1; + .nftToken_content_nft { + /* 自动布局 */ + display: flex; + flex-direction: column; + padding: 14px 15px; + gap: 6px; + + .nftToken_content_nft_top { + display: flex; + flex-direction: row; + justify-content: space-between; + > span { + &:nth-of-type(1) { + /* 自动布局子元素 */ + opacity: 1; + + font-family: DM Sans; + font-size: 14px; + font-weight: bold; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + + z-index: 0; + } + + &:nth-of-type(2) { + /* 自动布局子元素 */ + opacity: 1; + + font-family: DM Sans; + font-size: 10px; + font-weight: 500; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #f3be3c; + + z-index: 0; + + display: flex; + flex-direction: row; + align-items: center; + gap: 4px; + } + } + } + + .nftToken_content_nft_img { + width: 315px; + height: 160px; + border-radius: 10px; + opacity: 1; + object-fit: cover; + } + + .nftToken_content_nft_des { + /* 自动布局子元素 */ + opacity: 1; + + font-family: DM Sans; + font-size: 14px; + font-weight: 500; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + + z-index: 2; + } + } + + .nftToken_content_token { + display: flex; + flex-direction: column; + .nftToken_content_token_top { + padding: 14px 15px; + border-bottom: 1px solid #404040; + span { + opacity: 1; + + font-family: DM Sans; + font-size: 12px; + font-weight: 500; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + } + } + + .nftToken_content_token_list { + display: flex; + flex-direction: column; + gap: 18px; + padding: 19px 15px; + .nftToken_content_token_item { + display: flex; + flex-direction: row; + > img { + width: 30px; + height: 30px; + margin-right: 14px; + } + > div { + &:nth-of-type(1) { + display: flex; + flex-direction: column; + gap: 8px; + .nftToken_content_token_item_tokenName { + /* 自动布局子元素 */ + opacity: 1; + + font-family: DM Sans; + font-size: 16px; + font-weight: bold; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + + z-index: 0; + } + + .nftToken_content_token_item_tokenNum { + /* 自动布局子元素 */ + opacity: 1; + + font-family: DM Sans; + font-size: 14px; + font-weight: 500; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + + z-index: 1; + } + + .nftToken_content_token_item_AssetRecords { + /* 自动布局子元素 */ + opacity: 1; + + font-family: DM Sans; + font-size: 10px; + font-weight: 500; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #3680ff; + + z-index: 0; + + display: flex; + align-items: center; + gap: 4px; + + > svg { + width: 12px; + height: 12px; + } + } + } + + &:nth-of-type(2) { + margin-left: auto; + display: flex; + flex-direction: column; + gap: 8px; + align-items: flex-end; + .nftToken_content_token_item_tokenWaiting { + display: flex; + align-items: center; + gap: 8px; + span { + /* 自动布局子元素 */ + opacity: 1; + + font-family: DM Sans; + font-size: 14px; + font-weight: 500; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + + z-index: 0; + } + } + + .nftToken_content_token_item_tokenReceive { + /* 自动布局子元素 */ + width: 69px; + height: 32px; + border-radius: 6px; + opacity: 1; + + /* 自动布局 */ + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + padding: 8px 12px; + gap: 4px; + + background: #000000; + + z-index: 1; + box-sizing: border-box; + + > span { + /* 自动布局子元素 */ + opacity: 1; + + font-family: DM Sans; + font-size: 12px; + font-weight: 500; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + + z-index: 0; + } + } + } + } + } + } + } + + .nftToken_content_nft_mint { + width: 100%; + height: 236px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 16px; + .nftToken_content_nft_mint_btn { + /* 自动布局子元素 */ + width: 169px; + height: 38px; + border-radius: 10px; + opacity: 1; + + /* 自动布局 */ + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + padding: 10px 42px; + background: #fc872b; + z-index: 0; + gap: 10px; + box-sizing: border-box; + span { + /* 自动布局子元素 */ + font-family: DM Sans; + font-size: 14px; + font-weight: 500; + line-height: normal; + text-align: center; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + + z-index: 0; + + white-space: nowrap; + } + .nftToken_content_nft_mint_btn_icon { + width: 24px; + height: 24px; + } + } + + > span { + /* 自动布局子元素 */ + font-family: DM Sans; + font-size: 18px; + font-weight: bold; + line-height: normal; + text-align: center; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + + z-index: 1; + } + } + + .nftToken_content_userDisconnect { + width: 100%; + height: 236px; + display: flex; + justify-content: center; + align-items: center; + padding: 0 43px; + box-sizing: border-box; + span { + opacity: 1; + + font-family: DM Sans; + font-size: 18px; + font-weight: bold; + line-height: normal; + text-align: center; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + } + } + } + } + + .invite { + margin-top: 25px; + .invite_top { + display: flex; + flex-direction: row; + justify-content: space-between; + span { + &:nth-of-type(1) { + /* 自动布局子元素 */ + opacity: 1; + + font-family: DM Sans; + font-size: 14px; + font-weight: bold; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + + z-index: 0; + } + + &:nth-of-type(2) { + /* 自动布局子元素 */ + + font-family: DM Sans; + font-size: 10px; + font-weight: 500; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #f3be3c; + + z-index: 0; + + display: flex; + align-items: center; + gap: 4px; + } + } + } + + .invite_content { + width: 345px; + border-radius: 16px; + opacity: 1; + + background: #171719; + + display: flex; + flex-direction: column; + gap: 9px; + + padding: 14px 15px; + box-sizing: border-box; + + margin-top: 10px; + span { + &:nth-of-type(1) { + /* 自动布局子元素 */ + opacity: 0.8; + + font-family: DM Sans; + font-size: 10px; + font-weight: 500; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + + z-index: 0; + } + + &:nth-of-type(2) { + /* 自动布局子元素 */ + opacity: 1; + + font-family: DM Sans; + font-size: 14px; + font-weight: 500; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + + z-index: 0; + + display: flex; + align-items: center; + gap: 16px; + + .invite_content_icon { + width: 24px; + height: 24px; + } + } + + &:nth-of-type(3) { + /* 自动布局子元素 */ + opacity: 1; + + font-family: DM Sans; + font-size: 14px; + font-weight: 500; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #eaeaea; + + z-index: 1; + } + } + } + } + + .dataDisclosure { + margin-top: 24px; + > span { + /* 自动布局子元素 */ + font-family: DM Sans; + font-size: 14px; + font-weight: bold; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + + z-index: 0; + } + + .dataDisclosure_content { + width: 345px; + height: 103px; + border-radius: 16px; + opacity: 1; + padding: 14px 15px; + box-sizing: border-box; + + background: #171719; + + margin-top: 10px; + display: flex; + flex-direction: column; + gap: 6px; + .dataDisclosure_content_item { + display: flex; + align-items: center; + justify-content: space-between; + span { + &:nth-of-type(1) { + /* 自动布局子元素 */ + opacity: 1; + + font-family: DM Sans; + font-size: 14px; + font-weight: 500; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + + z-index: 0; + } + + &:nth-of-type(2) { + /* 自动布局子元素 */ + opacity: 1; + + font-family: DM Sans; + font-size: 16px; + font-weight: bold; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + + z-index: 1; + } + } + } + } } } diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx index 0b80e53..4447855 100644 --- a/src/pages/Home.tsx +++ b/src/pages/Home.tsx @@ -1,17 +1,29 @@ import classes from "./Home.module.css"; import useUserStore from "@/store/User"; -import { copyText } from "@/utils"; +import { cn, copyText, shortenString } from "@/utils"; import { useWeb3Modal } from "@web3modal/wagmi/react"; -import Button from "antd-mobile/es/components/button"; -import { useEffect } from "react"; +import { useEffect, 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 { useAccount } from "wagmi"; +import { disconnect } from "wagmi/actions"; +import { config } from "@/components/WalletProvider"; +import { useNavigate } from "react-router-dom"; +import { Toast } from "antd-mobile"; + export default function () { const { Token, UpdateToken } = useUserStore(); const { open } = useWeb3Modal(); const { t } = useTranslation(); + const { address } = useAccount(); + + const [tabIndex, setTabIndex] = useState(0); + const navigate = useNavigate(); useEffect(() => { UpdateToken("user token abc"); - return () => {}; }, []); @@ -23,24 +35,291 @@ export default function () { return ( <> -
- {t("AppName")} - +
+
+
+ - + {address ? ( +
+
+ {shortenString(address, 6, 4)} + { + disconnect(config); + }} + name="tuichu" + className={classes.userinfo_top_right_wallet_disconnect} + color={"#fff"} + /> +
+
+
+ + {t("普通非活跃")} +
+
{ + navigate("/levelup"); + }} + > + {t("升级")} + +
+
+
+ ) : ( + <> +
{ + open(); + }} + > + {t("链接钱包")} +
+ + )} +
+
    +
  • + 20 + {t("邀请铸造")} +
  • +
  • + 20 + {t("团队社长")} +
  • +
  • + 3 + {t("邀请空投")} +
  • +
+
+ +
+
    +
  • setTabIndex(0)} + > + NFT +
  • +
  • setTabIndex(1)} + > + {t("代币")} +
  • +
+ +
+ {tabIndex == 0 && ( + <> + {address ? ( + <> + {true ? ( +
+
+ # 737389 + { + navigate("/mint"); + }} + > + {t("铸造 NFT")} + + +
+ + + {t("Min结束后按照规则进行空投。")} + +
+ ) : ( +
+
{ + navigate("/mint"); + }} + > + {t("铸造 NFT")} + +
+ {t("铸造 NFT 获得代币空投")} +
+ )} + + ) : ( + <> +
+ {t("钱包未链接,无法向您显示 NFT")} +
+ + )} + + )} + {tabIndex == 1 && ( +
+
+ {t("资产金额 = 已领取 + 待处理")} +
+ +
    + { + navigate("/assetrecord"); + }} + /> + { + navigate("/airdroprecord"); + }} + /> +
+
+ )} +
+
+ +
+
+ {t("邀请")} + { + navigate("/invitationlist"); + }} + > + {t("邀请列表")}{" "} + + +
+ +
+ {t("邀请链接")} + + https://www.rmob_nft.com/regster=id?1{" "} + { + copyText("https://www.rmob_nft.com/regster=id?1"); + }} + className={classes.invite_content_icon} + name="fuzhi" + color={"#fff"} + />{" "} + + + + {t( + "普通会员每邀请铸造一个NFT可获得一份空投福利;推荐铸造20个NFT的可升级为会长;团队中拥有20位会长可升级为基金会社长;邀请越多级别越高福利越多。" + )} + +
+
+ +
+ {t("数据披露")} +
    +
  • + {t("资金池")} + 10000 +
  • +
  • + {t("社长席位")} + 499 +
  • +
  • + {t("基金会社长席位")} + 19 +
  • +
+
); } + +function ReceiveCom({ + tokenName, + tokenNum, + toReceive, + onAssetRec, +}: { + tokenName: string; + tokenNum: number; + toReceive: number; + onAssetRec: () => void; +}) { + const { t } = useTranslation(); + return ( +
  • + +
    + + {tokenName} + + + {tokenNum} + + { + onAssetRec(); + }} + > + {t("资产记录")}{" "} + + +
    + +
    +
    + {t("待领取")} + {toReceive} +
    +
    { + Toast.show({ + content: t("领取成功,前往钱包查看"), + icon: "success", + }); + }} + > + {t("领取")} +
    +
    +
  • + ); +} diff --git a/src/pages/InvitationList.tsx b/src/pages/InvitationList.tsx new file mode 100644 index 0000000..cf86e5c --- /dev/null +++ b/src/pages/InvitationList.tsx @@ -0,0 +1,77 @@ +/* + * @LastEditors: John + * @Date: 2024-06-19 11:03:01 + * @LastEditTime: 2024-06-19 17:33:25 + * @Author: John + */ +import { shortenString } from "@/utils"; +import Ellipsis from "antd-mobile/es/components/ellipsis"; +import DataTable, { TableColumn } from "react-data-table-component"; +import { useTranslation } from "react-i18next"; +import { useAccount } from "wagmi"; + +interface DataRow { + id: number; + address: string; + level: string; + nft: number; +} +export default function () { + const { address } = useAccount(); + const { t } = useTranslation(); + const columns: TableColumn[] = [ + { + name: t("地址"), + selector: (row) => row.address, + grow: 4, + // cell(row, rowIndex, column, id) { + // return ; + // }, + }, + { + name: t("级别"), + selector: (row) => row.level, + grow: 4, + }, + { + name: t("直推NFT"), + selector: (row) => row.nft, + // @ts-ignore + right: "true", + grow: 2, + }, + ]; + + const data: DataRow[] = [ + { + id: 1, + address: "0x1000.....2223", + level: t("非活跃普通"), + nft: 0, + }, + { + id: 2, + address: "0x1000.....2223", + level: t("活跃普通"), + nft: 2, + }, + { + id: 3, + address: "0x1000.....2223", + level: t("社长"), + nft: 23, + }, + { + id: 4, + address: "0x1000.....2223", + level: t("基金会社长"), + nft: 50, + }, + ]; + + return ( + <> + + + ); +} diff --git a/src/pages/LevelUp.module.css b/src/pages/LevelUp.module.css new file mode 100644 index 0000000..db828a5 --- /dev/null +++ b/src/pages/LevelUp.module.css @@ -0,0 +1,302 @@ +.container { + padding: 0 14px; +} + +.LevelUp { + padding-bottom: 32px; + .content { + margin-top: 16px; + .content_box { + display: flex; + justify-content: space-between; + align-items: center; + + .box_item { + /* 自动布局子元素 */ + width: 153px; + height: 90px; + border-radius: 12px; + opacity: 1; + + /* 自动布局 */ + display: flex; + flex-direction: column; + align-items: center; + gap: 7px; + padding: 26px 23px; + + background: #171719; + + box-shadow: 0px 4px 10px 0px rgba(138, 29, 19, 0.3), + inset 0px 0px 6px 0px #8a1d13; + + z-index: 0; + + box-sizing: border-box; + span { + &:nth-of-type(1) { + /* 自动布局子元素 */ + opacity: 1; + + font-family: DM Sans; + font-size: 10px; + font-weight: 500; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #4d4d4d; + + z-index: 0; + } + &:nth-of-type(2) { + /* 自动布局子元素 */ + opacity: 1; + + font-family: DM Sans; + font-size: 14px; + font-weight: bold; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + + z-index: 1; + } + } + } + + .box_arrow { + width: 24px; + height: 24px; + } + } + + .content_price { + display: flex; + align-items: center; + gap: 4px; + margin-top: 16px; + padding: 0 10px; + span { + &:nth-of-type(1) { + /* 自动布局子元素 */ + opacity: 1; + + font-family: DM Sans; + font-size: 10px; + font-weight: 500; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + + z-index: 0; + } + &:nth-of-type(2) { + /* 自动布局子元素 */ + opacity: 1; + + font-family: DM Sans; + font-size: 10px; + font-weight: bold; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #fc872b; + + z-index: 1; + } + } + } + + .content_price_des { + display: flex; + flex-direction: column; + gap: 4px; + margin-top: 10px; + padding: 0 10px; + span { + /* 自动布局子元素 */ + opacity: 1; + + font-family: DM Sans; + font-size: 10px; + font-weight: 500; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #4d4d4d; + + z-index: 1; + } + } + + .content_btn { + /* 自动布局子元素 */ + width: 331px; + height: 40px; + border-radius: 10px; + opacity: 1; + + /* 自动布局 */ + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + padding: 11px 40px; + gap: 10px; + + background: #fc872b; + + z-index: 3; + + box-sizing: border-box; + + margin: 0 auto; + + margin-top: 14px; + + span { + /* 自动布局子元素 */ + opacity: 1; + + font-family: DM Sans; + font-size: 14px; + font-weight: 500; + line-height: normal; + text-align: center; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + + z-index: 0; + } + + .icon { + width: 16px; + height: 16px; + } + + &[disabled] { + /* 自动布局子元素 */ + background: #666666; + } + } + } + + .upgrade_conditions { + margin-top: 26px; + > span { + /* 自动布局子元素 */ + opacity: 1; + + font-family: DM Sans; + font-size: 14px; + font-weight: bold; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + + z-index: 0; + } + > ul { + display: flex; + flex-direction: column; + gap: 14px; + + margin-top: 16px; + > li { + /* 自动布局子元素 */ + width: 344px; + border-radius: 16px; + opacity: 1; + + /* 自动布局 */ + display: flex; + flex-direction: column; + padding: 15px 10px; + + background: #171719; + + z-index: 0; + + gap: 10px; + box-sizing: border-box; + div { + display: flex; + align-items: center; + gap: 6px; + span { + &:nth-of-type(1) { + /* 自动布局子元素 */ + opacity: 1; + + font-family: DM Sans; + font-size: 12px; + font-weight: bold; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + color: #fc872b; + + z-index: 0; + } + &:nth-of-type(2) { + /* 自动布局子元素 */ + opacity: 1; + + font-family: DM Sans; + font-size: 12px; + font-weight: 500; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + color: #ffffff; + + z-index: 1; + } + } + } + + > ul { + display: flex; + flex-direction: column; + gap: 4px; + li { + /* 自动布局子元素 */ + opacity: 1; + + font-family: DM Sans; + font-size: 12px; + font-weight: 500; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #eaeaea; + + z-index: 0; + } + } + } + } + } +} diff --git a/src/pages/LevelUp.tsx b/src/pages/LevelUp.tsx new file mode 100644 index 0000000..3d2558b --- /dev/null +++ b/src/pages/LevelUp.tsx @@ -0,0 +1,117 @@ +import IconFont from "@/components/iconfont"; +import classes from "./LevelUp.module.css"; +import { cn } from "@/utils"; +import Button from "antd-mobile/es/components/button"; +import Space from "antd-mobile/es/components/space"; +import { PropsWithChildren } from "react"; +import { useTranslation } from "react-i18next"; +export default function () { + const { t } = useTranslation(); + return ( + <> +
    +
    +
    +
    + {t("当前级别")} + {t("普通活跃")} +
    + +
    + {t("提升级别")} + {t("社长")} +
    +
    + +
    + {t("当前升级价格:")} + 110 USDT +
    + +
    + {t("价格说明:")} + + {t( + "升级费用100USDT起,其中gas费2USDT,剩余部分50%进入资金池,另外50%平均分给所有升级成功的社长和基金会社长。自第二个社长升级开始,每升级一名社长所需铸造费用增加10%,既第二位社长升级铸造费用为100u+100*10%=110USDT,以此类推。" + )} + +
    + + +
    + +
    + {t("升级条件")} +
      + + + + + +
    +
    +
    + + ); +} + +function ConItem({ + memberName, + limitText, + conList, +}: PropsWithChildren<{ + memberName: string; + limitText: string; + conList: string[]; +}>) { + return ( +
  • +
    + {memberName} + {limitText} +
    +
      + {conList.map((v, i) => ( +
    • {v}
    • + ))} +
    +
  • + ); +} diff --git a/src/pages/Mint.module.css b/src/pages/Mint.module.css new file mode 100644 index 0000000..55660bb --- /dev/null +++ b/src/pages/Mint.module.css @@ -0,0 +1,172 @@ +.container { + padding: 0 14px; +} +.Mint { + display: flex; + flex-direction: column; + gap: 18px; + .nftImg { + width: 345px; + height: 190px; + border-radius: 10px; + opacity: 1; + background: #171719; + box-shadow: 0px 3px 6px 0px rgba(0, 0, 0, 0.16), + 0px 3px 6px 0px rgba(0, 0, 0, 0.23); + padding: 8px; + box-sizing: border-box; + + margin-top: 17px; + img { + width: 100%; + height: 100%; + border-radius: 10px; + opacity: 1; + object-fit: cover; + } + } + + > ul { + display: flex; + flex-direction: column; + gap: 10px; + + padding: 0 7px; + + li { + display: flex; + align-items: center; + justify-content: space-between; + span { + &:nth-of-type(1) { + /* 自动布局子元素 */ + opacity: 1; + + font-family: DM Sans; + font-size: 14px; + font-weight: 500; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + + z-index: 0; + } + + &:nth-of-type(2) { + /* 自动布局子元素 */ + opacity: 1; + + font-family: DM Sans; + font-size: 16px; + font-weight: bold; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + + z-index: 1; + } + } + } + } + + .des { + display: flex; + flex-direction: column; + gap: 6px; + + padding: 0 7px; + span { + &:nth-of-type(1) { + /* 自动布局子元素 */ + opacity: 1; + + font-family: DM Sans; + font-size: 14px; + font-weight: 500; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + + z-index: 0; + } + + &:nth-of-type(2) { + /* 自动布局子元素 */ + opacity: 1; + + font-family: DM Sans; + font-size: 14px; + font-weight: 500; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #eaeaea; + + z-index: 1; + } + } + } + + .btn { + /* 自动布局子元素 */ + width: 331px; + height: 40px; + border-radius: 10px; + opacity: 1; + + /* 自动布局 */ + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + padding: 11px 40px; + gap: 10px; + + background: #fc872b; + + z-index: 3; + + box-sizing: border-box; + + margin: 0 auto; + + span { + /* 自动布局子元素 */ + opacity: 1; + + font-family: DM Sans; + font-size: 14px; + font-weight: 500; + line-height: normal; + text-align: center; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + + z-index: 0; + } + + .icon { + width: 16px; + height: 16px; + } + + &[disabled] { + /* 自动布局子元素 */ + background: #666666; + } + } +} diff --git a/src/pages/Mint.tsx b/src/pages/Mint.tsx new file mode 100644 index 0000000..f7e735d --- /dev/null +++ b/src/pages/Mint.tsx @@ -0,0 +1,58 @@ +/* + * @LastEditors: John + * @Date: 2024-06-18 15:28:03 + * @LastEditTime: 2024-06-19 14:06:59 + * @Author: John + */ +import { cn } from "@/utils"; +import classes from "./Mint.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"; +export default function () { + const { t } = useTranslation(); + return ( + <> +
    +
    + +
    + +
      +
    • + {t("NFT总量:")} + 20000 +
    • + +
    • + {t("MINT余量:")} + 15000 +
    • + +
    • + {t("当前MINT价格:")} + 110 USDT +
    • +
    + +
    + {t("价格说明:")} + + {t( + "100USDT起,每增加100名普通会员,NFT价格上涨1%,既:前100名价格为100USDT/枚,101-200名价格为100u+100u*1%=101USDT/枚,以此类推。" + )} + +
    + + +
    + + ); +} diff --git a/src/store/User.ts b/src/store/User.ts index 6556e92..66031db 100644 --- a/src/store/User.ts +++ b/src/store/User.ts @@ -1,16 +1,19 @@ /* * @LastEditors: John * @Date: 2024-06-17 17:45:43 - * @LastEditTime: 2024-06-17 17:57:42 + * @LastEditTime: 2024-06-19 16:26:24 * @Author: John */ -import { ASYNC_STORAGE_KEY } from "@/constants"; +import { ASYNC_STORAGE_KEY, Lang } from "@/constants"; import { create } from "zustand"; import { createJSONStorage, persist } from "zustand/middleware"; interface UserState { Token: string; UpdateToken: (t: string) => void; + + Lang: Lang; + UpdateLang: (l: Lang) => void; } export const useUserStore = create()( @@ -18,9 +21,12 @@ export const useUserStore = create()( (set, _get) => ({ Token: "", UpdateToken: (t) => set({ Token: t }), + + Lang: Lang.en, + UpdateLang: (l) => set({ Lang: l }), }), { - name: ASYNC_STORAGE_KEY.Token, // name of item in the storage (must be unique) + name: ASYNC_STORAGE_KEY.Store, // name of item in the storage (must be unique) storage: createJSONStorage(() => localStorage), // (optional) by default the 'localStorage' is used } ) diff --git a/src/style/ant-cover-m.css b/src/style/ant-cover-m.css new file mode 100644 index 0000000..03be39d --- /dev/null +++ b/src/style/ant-cover-m.css @@ -0,0 +1,258 @@ +.adm-tabs { + .adm-tabs-header { + border-bottom: 0.25px solid #333333; + + .adm-tabs-tab-line { + background-color: #fc872b; + } + + .adm-tabs-tab { + opacity: 1; + + font-family: DM Sans; + font-size: 14px; + font-weight: 500; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #666666; + padding-bottom: 4px; + &.adm-tabs-tab-active { + color: #ffffff; + } + } + } + .adm-tabs-content { + padding: 0; + } +} + +.adm-capsule-tabs { + .adm-capsule-tabs-header { + padding: 0px 15px; + border-bottom: none; + margin-top: 20px; + + .adm-scroll-mask { + opacity: 0 !important; + } + + .adm-capsule-tabs-tab-list { + gap: 8px; + .adm-capsule-tabs-tab-wrapper { + padding: 0; + + .adm-capsule-tabs-tab { + /* 自动布局子元素 */ + height: 25px; + border-radius: 8px; + opacity: 1; + + box-sizing: border-box; + border: 1px solid #fc872b; + + z-index: 1; + background-color: transparent; + + /* 自动布局子元素 */ + opacity: 1; + + font-family: DM Sans; + font-size: 10px; + font-weight: 500; + line-height: 25px; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + + z-index: 0; + + padding: 0 14px; + } + + .adm-capsule-tabs-tab-active { + /* 自动布局子元素 */ + height: 25px; + border-radius: 8px; + opacity: 1; + + background: #fc872b; + + z-index: 0; + + /* 自动布局子元素 */ + opacity: 1; + + font-family: DM Sans; + font-size: 10px; + font-weight: 500; + line-height: 25px; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + + z-index: 0; + } + } + } + } +} + +/* picker */ +.adm-picker-popup { + .adm-picker-header { + border-bottom: 1px solid #404040; + .adm-picker-header-title { + opacity: 1; + + font-family: DM Sans; + font-size: 17px; + font-weight: bold; + line-height: 24px; + letter-spacing: 0px; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + } + .adm-picker-header-button { + opacity: 1; + + font-family: DM Sans; + font-size: 17px; + font-weight: 500; + line-height: 24px; + letter-spacing: 0px; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #1890ff; + } + } + .adm-popup-body { + background-color: #000000; + .adm-picker { + /* height: 280px; */ + .adm-picker-body { + .adm-picker-view { + background-color: #000000; + .adm-picker-view-column { + .adm-picker-view-column-wheel { + .adm-picker-view-column-item { + /* height: 34px; */ + .adm-picker-view-column-item-label { + /* font-family: DM Sans; + font-size: 16px; + font-weight: 500; + line-height: 34px; + text-align: center; + letter-spacing: 0px; + + font-variation-settings: "opsz" auto; */ + color: #ffffff; + } + } + } + } + .adm-picker-view-mask { + .adm-picker-view-mask-top, + .adm-picker-view-mask-bottom { + background-color: #000000; + } + .adm-picker-view-mask-middle { + /* height: 34px; */ + border-top: 1px solid #404040; + border-bottom: 1px solid #404040; + } + } + } + } + } + } +} + +/* toast */ +.adm-toast-main { + min-width: 170px !important; + min-height: 40px !important; + max-width: 320px !important; + max-height: max-content !important; + border-radius: 10px !important; + opacity: 1; + + /* 自动布局 */ + padding: 11px 20px !important; + + /* background: rgba(252, 135, 43, 0.5) !important; */ + + box-sizing: border-box !important; + border: 1px solid #fc872b !important; + + /* backdrop-filter: blur(10px); */ + + .adm-auto-center-content { + /* 自动布局子元素 */ + opacity: 1; + + font-family: DM Sans; + font-size: 14px; + font-weight: 500; + line-height: normal; + letter-spacing: 0px; + + font-variation-settings: "opsz" auto; + color: #ffffff; + + z-index: 0; + } +} + +.adm-popover-menu { + .adm-popover-arrow { + color: rgba(42, 42, 42, 0.6) !important; + } + .adm-popover-inner { + background: rgba(42, 42, 42, 0.6); + + box-sizing: border-box; + border-image: radial-gradient( + 103% 103% at 50% 50%, + #a41914 0%, + rgba(164, 25, 20, 0) 100% + ); + + backdrop-filter: blur(10px); + + .adm-popover-menu-item { + padding: 0 10px; + background-color: transparent !important; + &::after { + display: none !important; + } + + .adm-popover-menu-item-text { + /* 自动布局子元素 */ + opacity: 1; + + font-family: DM Sans; + font-size: 14px; + font-weight: normal; + line-height: normal; + text-transform: capitalize; + letter-spacing: 0em; + + color: #ffffff; + + z-index: 0; + padding: 10px 0; + border-top: 1px solid #3d3d3d; + } + } + } +} diff --git a/src/style/react-data-table-component-cover-m.css b/src/style/react-data-table-component-cover-m.css new file mode 100644 index 0000000..12f3c9f --- /dev/null +++ b/src/style/react-data-table-component-cover-m.css @@ -0,0 +1,54 @@ +.rdt_Table { + width: 100vw !important; + background-color: transparent !important; + padding: 0 14px; + + .rdt_TableHead { + .rdt_TableHeadRow { + height: 16px !important; + min-height: 16px !important; + background-color: transparent !important; + + .rdt_TableCol { + div { + opacity: 1; + + font-family: DM Sans; + font-size: 12px; + font-weight: 500; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #eaeaea; + } + } + } + } + + .rdt_TableBody { + gap: 10px; + margin-top: 14px; + .rdt_TableRow { + height: 18px !important; + min-height: 18px !important; + background-color: transparent !important; + .rdt_TableCell { + div { + opacity: 1; + + font-family: DM Sans; + font-size: 14px; + font-weight: bold; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + } + } + } + } +} diff --git a/src/utils/index.ts b/src/utils/index.ts index 78b2b27..c08f2dc 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,11 +1,13 @@ /* * @LastEditors: John * @Date: 2024-06-17 18:19:27 - * @LastEditTime: 2024-06-18 10:48:05 + * @LastEditTime: 2024-06-19 17:07:43 * @Author: John */ - +import { type ClassValue, clsx } from "clsx"; +import { twMerge } from "tailwind-merge"; import Toast from "antd-mobile/es/components/toast"; +import i18next from "i18next"; export const ua = navigator.userAgent; export const isIOS = /iphone|ipad|ipod|ios/i.test(ua); @@ -72,8 +74,12 @@ export function copyText(text: string) { isCopySuccess && Toast.show({ icon: "success", - content: "Copy successful", + content: i18next.t("复制成功"), }); // 8、 销毁DOM document.body.removeChild(input); } + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)); +} diff --git a/src/utils/wallet.ts b/src/utils/wallet.ts new file mode 100644 index 0000000..e3c3774 --- /dev/null +++ b/src/utils/wallet.ts @@ -0,0 +1,57 @@ +/* + * @LastEditors: John + * @Date: 2024-06-19 15:55:07 + * @LastEditTime: 2024-06-19 15:56:45 + * @Author: John + */ +import { config } from "@/components/WalletProvider"; +import { + writeContract, + readContract, + estimateGas, + waitForTransactionReceipt, + getConnectorClient, + getChains, + switchChain, + getChainId, +} from "@wagmi/core"; + +/** + * @description: 检测网络并切换 + * @return {*} + */ +export function checkNetWork(): Promise { + return new Promise(async (reslove, reject) => { + // TODO 切换网络✔ + const chains = getChains(config); + let chainId = getChainId(config); + // console.log("all chains:", chains); + console.log("current chain id:", chainId); + let netWork = chains.find( + (v) => v.id == import.meta.env.VITE_PARTICIPATE_CHAIN_ID + ); + console.log("participate network:", netWork); + if (chainId != netWork?.id && netWork) { + try { + await switchChain(config, { + chainId: netWork.id, + }); + + const timer = setInterval(() => { + chainId = getChainId(config); + console.log("current chain id:", chainId); + if (chainId == netWork?.id) { + console.log("switch chain success!"); + reslove(); + clearInterval(timer); + } + }, 1000); + } catch (error) { + // TODO 切换网络失败,自动添加网络✔ + console.error("switch chain error:", error); + } + } else { + reslove(); + } + }); +} diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts index e4a2a41..171ee5d 100644 --- a/src/vite-env.d.ts +++ b/src/vite-env.d.ts @@ -2,6 +2,9 @@ interface ImportMetaEnv { readonly VITE_BASE_API_URL: string; + readonly VITE_PARTICIPATE_CHAIN_ID: number; + readonly VITE_NETWORK_USDT_ADDRESS: `0x${string}`; + readonly VITE_CHECK_TRANSACTION_DETAILS_URL: string; // 更多环境变量... readonly MODE: "development" | "production" | "test"; } diff --git a/vite.config.ts b/vite.config.ts index 85f39b3..c3f9fea 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,3 +1,9 @@ +/* + * @LastEditors: John + * @Date: 2024-06-17 17:20:03 + * @LastEditTime: 2024-06-19 17:41:43 + * @Author: John + */ import { defineConfig } from "vite"; import react from "@vitejs/plugin-react"; import path from "path"; @@ -6,6 +12,9 @@ import { nodePolyfills } from "vite-plugin-node-polyfills"; // https://vitejs.dev/config/ export default defineConfig({ + server: { + host: "192.168.10.167", + }, plugins: [ react(), viteCompression({ deleteOriginFile: false }), diff --git a/yarn.lock b/yarn.lock index 673e775..744bc21 100644 --- a/yarn.lock +++ b/yarn.lock @@ -240,7 +240,7 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.18.0, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.19.4, @babel/runtime@npm:^7.20.6, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.23.9": +"@babel/runtime@npm:^7.17.2, @babel/runtime@npm:^7.18.0, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.19.4, @babel/runtime@npm:^7.20.6, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.23.9, @babel/runtime@npm:^7.24.1": version: 7.24.7 resolution: "@babel/runtime@npm:7.24.7" dependencies: @@ -321,6 +321,29 @@ __metadata: languageName: node linkType: hard +"@emotion/is-prop-valid@npm:1.2.2": + version: 1.2.2 + resolution: "@emotion/is-prop-valid@npm:1.2.2" + dependencies: + "@emotion/memoize": "npm:^0.8.1" + checksum: 10c0/bb1530dcb4e0e5a4fabb219279f2d0bc35796baf66f6241f98b0d03db1985c890a8cafbea268e0edefd5eeda143dbd5c09a54b5fba74cee8c69b98b13194af50 + languageName: node + linkType: hard + +"@emotion/memoize@npm:^0.8.1": + version: 0.8.1 + resolution: "@emotion/memoize@npm:0.8.1" + checksum: 10c0/dffed372fc3b9fa2ba411e76af22b6bb686fb0cb07694fdfaa6dd2baeb0d5e4968c1a7caa472bfcf06a5997d5e7c7d16b90e993f9a6ffae79a2c3dbdc76dfe78 + languageName: node + linkType: hard + +"@emotion/unitless@npm:0.8.1": + version: 0.8.1 + resolution: "@emotion/unitless@npm:0.8.1" + checksum: 10c0/a1ed508628288f40bfe6dd17d431ed899c067a899fa293a13afe3aed1d70fac0412b8a215fafab0b42829360db687fecd763e5f01a64ddc4a4b58ec3112ff548 + languageName: node + linkType: hard + "@esbuild/aix-ppc64@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/aix-ppc64@npm:0.21.5" @@ -1884,6 +1907,13 @@ __metadata: languageName: node linkType: hard +"@types/stylis@npm:4.2.5": + version: 4.2.5 + resolution: "@types/stylis@npm:4.2.5" + checksum: 10c0/23f5b35a3a04f6bb31a29d404fa1bc8e0035fcaff2356b4047743a057e0c37b2eba7efe14d57dd2b95b398cea3bac294d9c6cd93ed307d8c0b7f5d282224b469 + languageName: node + linkType: hard + "@types/trusted-types@npm:^2.0.2": version: 2.0.7 resolution: "@types/trusted-types@npm:2.0.7" @@ -3190,6 +3220,13 @@ __metadata: languageName: node linkType: hard +"camelize@npm:^1.0.0": + version: 1.0.1 + resolution: "camelize@npm:1.0.1" + checksum: 10c0/4c9ac55efd356d37ac483bad3093758236ab686192751d1c9daa43188cc5a07b09bd431eb7458a4efd9ca22424bba23253e7b353feb35d7c749ba040de2385fb + languageName: node + linkType: hard + "caniuse-lite@npm:^1.0.30001599, caniuse-lite@npm:^1.0.30001629": version: 1.0.30001636 resolution: "caniuse-lite@npm:1.0.30001636" @@ -3334,6 +3371,13 @@ __metadata: languageName: node linkType: hard +"clsx@npm:^2.1.1": + version: 2.1.1 + resolution: "clsx@npm:2.1.1" + checksum: 10c0/c4c8eb865f8c82baab07e71bfa8897c73454881c4f99d6bc81585aecd7c441746c1399d08363dc096c550cceaf97bd4ce1e8854e1771e9998d9f94c4fe075839 + languageName: node + linkType: hard + "color-convert@npm:^1.9.0": version: 1.9.3 resolution: "color-convert@npm:1.9.3" @@ -3422,6 +3466,20 @@ __metadata: languageName: node linkType: hard +"copy-text-to-clipboard@npm:^3.0.1": + version: 3.2.0 + resolution: "copy-text-to-clipboard@npm:3.2.0" + checksum: 10c0/d60fdadc59d526e19d56ad23cec2b292d33c771a5091621bd322d138804edd3c10eb2367d46ec71b39f5f7f7116a2910b332281aeb36a5b679199d746a8a5381 + languageName: node + linkType: hard + +"core-js@npm:^3.11.0": + version: 3.37.1 + resolution: "core-js@npm:3.37.1" + checksum: 10c0/440eb51a7a39128a320225fe349f870a3641b96c9ecd26470227db730ef8c161ea298eaea621db66ec0ff622a85299efb4e23afebf889c0a1748616102307675 + languageName: node + linkType: hard + "core-util-is@npm:~1.0.0": version: 1.0.3 resolution: "core-util-is@npm:1.0.3" @@ -3542,7 +3600,25 @@ __metadata: languageName: node linkType: hard -"csstype@npm:^3.0.2": +"css-color-keywords@npm:^1.0.0": + version: 1.0.0 + resolution: "css-color-keywords@npm:1.0.0" + checksum: 10c0/af205a86c68e0051846ed91eb3e30b4517e1904aac040013ff1d742019b3f9369ba5658ba40901dbbc121186fc4bf0e75a814321cc3e3182fbb2feb81c6d9cb7 + languageName: node + linkType: hard + +"css-to-react-native@npm:3.2.0": + version: 3.2.0 + resolution: "css-to-react-native@npm:3.2.0" + dependencies: + camelize: "npm:^1.0.0" + css-color-keywords: "npm:^1.0.0" + postcss-value-parser: "npm:^4.0.2" + checksum: 10c0/fde850a511d5d3d7c55a1e9b8ed26b69a8ad4868b3487e36ebfbfc0b96fc34bc977d9cd1d61a289d0c74d3f9a662d8cee297da53d4433bf2e27d6acdff8e1003 + languageName: node + linkType: hard + +"csstype@npm:3.1.3, csstype@npm:^3.0.2": version: 3.1.3 resolution: "csstype@npm:3.1.3" checksum: 10c0/80c089d6f7e0c5b2bd83cf0539ab41474198579584fa10d86d0cafe0642202343cbc119e076a0b1aece191989477081415d66c9fefbf3c957fc2fc4b7009f248 @@ -5793,6 +5869,13 @@ __metadata: languageName: node linkType: hard +"mutation-observer@npm:^1.0.3": + version: 1.0.3 + resolution: "mutation-observer@npm:1.0.3" + checksum: 10c0/2f010fdec4b860a6576558013bcaa691c4912e287ea1dc99ea3b9360b52586267b291e7a2a88c0f2a9b399b4ef1e116ce8c0f839f88d2d7c9b4323fb0badc321 + languageName: node + linkType: hard + "nano-memoize@npm:^3.0.16": version: 3.0.16 resolution: "nano-memoize@npm:3.0.16" @@ -6405,13 +6488,24 @@ __metadata: languageName: node linkType: hard -"postcss-value-parser@npm:^4.2.0": +"postcss-value-parser@npm:^4.0.2, postcss-value-parser@npm:^4.2.0": version: 4.2.0 resolution: "postcss-value-parser@npm:4.2.0" checksum: 10c0/f4142a4f56565f77c1831168e04e3effd9ffcc5aebaf0f538eee4b2d465adfd4b85a44257bb48418202a63806a7da7fe9f56c330aebb3cac898e46b4cbf49161 languageName: node linkType: hard +"postcss@npm:8.4.38, postcss@npm:^8.2.6, postcss@npm:^8.4.38": + version: 8.4.38 + resolution: "postcss@npm:8.4.38" + dependencies: + nanoid: "npm:^3.3.7" + picocolors: "npm:^1.0.0" + source-map-js: "npm:^1.2.0" + checksum: 10c0/955407b8f70cf0c14acf35dab3615899a2a60a26718a63c848cf3c29f2467b0533991b985a2b994430d890bd7ec2b1963e36352b0774a19143b5f591540f7c06 + languageName: node + linkType: hard + "postcss@npm:^7.0.27": version: 7.0.39 resolution: "postcss@npm:7.0.39" @@ -6422,17 +6516,6 @@ __metadata: languageName: node linkType: hard -"postcss@npm:^8.2.6, postcss@npm:^8.4.38": - version: 8.4.38 - resolution: "postcss@npm:8.4.38" - dependencies: - nanoid: "npm:^3.3.7" - picocolors: "npm:^1.0.0" - source-map-js: "npm:^1.2.0" - checksum: 10c0/955407b8f70cf0c14acf35dab3615899a2a60a26718a63c848cf3c29f2467b0533991b985a2b994430d890bd7ec2b1963e36352b0774a19143b5f591540f7c06 - languageName: node - linkType: hard - "preact@npm:^10.16.0": version: 10.22.0 resolution: "preact@npm:10.22.0" @@ -6671,6 +6754,21 @@ __metadata: languageName: node linkType: hard +"react-data-table-component@npm:^7.6.2": + version: 7.6.2 + resolution: "react-data-table-component@npm:7.6.2" + dependencies: + deepmerge: "npm:^4.3.1" + peerDependencies: + react: ">= 16.8.3" + styled-components: ">= 5.0.0" + peerDependenciesMeta: + styled-components: + optional: false + checksum: 10c0/870ac972362c8144efea9e1841f01276a5a5af59334a7bc955fc4a07a244ba2933fd67026ec253e2ece29bb57f69edcfdab573d524b89cb56aa780a6a4e4540f + languageName: node + linkType: hard + "react-dom@npm:^18.2.0": version: 18.3.1 resolution: "react-dom@npm:18.3.1" @@ -6861,6 +6959,7 @@ __metadata: "@web3modal/wagmi": "npm:^5.0.2" antd-mobile: "npm:^5.36.1" autoprefixer: "npm:^10.4.19" + clsx: "npm:^2.1.1" eslint: "npm:^8.57.0" eslint-plugin-react-hooks: "npm:^4.6.0" eslint-plugin-react-refresh: "npm:^0.4.6" @@ -6869,11 +6968,15 @@ __metadata: postcss: "npm:^8.4.38" postcss-pxtorem: "npm:5.1.1" react: "npm:^18.2.0" + react-data-table-component: "npm:^7.6.2" react-dom: "npm:^18.2.0" react-i18next: "npm:^14.1.2" react-iconfont-cli: "npm:^2.0.2" react-router-dom: "npm:^6.23.1" + styled-components: "npm:^6.1.11" + tailwind-merge: "npm:^2.3.0" typescript: "npm:^5.2.2" + vconsole: "npm:^3.15.1" viem: "npm:^2.14.2" vite: "npm:^5.2.0" vite-plugin-compression: "npm:^0.5.1" @@ -7198,6 +7301,13 @@ __metadata: languageName: node linkType: hard +"shallowequal@npm:1.1.0": + version: 1.1.0 + resolution: "shallowequal@npm:1.1.0" + checksum: 10c0/b926efb51cd0f47aa9bc061add788a4a650550bbe50647962113a4579b60af2abe7b62f9b02314acc6f97151d4cf87033a2b15fc20852fae306d1a095215396c + languageName: node + linkType: hard + "shebang-command@npm:^2.0.0": version: 2.0.0 resolution: "shebang-command@npm:2.0.0" @@ -7474,6 +7584,33 @@ __metadata: languageName: node linkType: hard +"styled-components@npm:^6.1.11": + version: 6.1.11 + resolution: "styled-components@npm:6.1.11" + dependencies: + "@emotion/is-prop-valid": "npm:1.2.2" + "@emotion/unitless": "npm:0.8.1" + "@types/stylis": "npm:4.2.5" + css-to-react-native: "npm:3.2.0" + csstype: "npm:3.1.3" + postcss: "npm:8.4.38" + shallowequal: "npm:1.1.0" + stylis: "npm:4.3.2" + tslib: "npm:2.6.2" + peerDependencies: + react: ">= 16.8.0" + react-dom: ">= 16.8.0" + checksum: 10c0/1d149a51d24f779bba700c8c23ec0538b2d2b57745ccd49d1cfdc2dfce8bcea21e8ff81fed1143d1b35d127cc591717a398da72ea6671abbf705432b13e59e56 + languageName: node + linkType: hard + +"stylis@npm:4.3.2": + version: 4.3.2 + resolution: "stylis@npm:4.3.2" + checksum: 10c0/0410e1404cbeee3388a9e17587875211ce2f014c8379af0d1e24ca55878867c9f1ccc7b0ce9a156ca53f5d6e301391a82b0645522a604674a378b3189a4a1994 + languageName: node + linkType: hard + "superstruct@npm:^1.0.3": version: 1.0.4 resolution: "superstruct@npm:1.0.4" @@ -7513,6 +7650,15 @@ __metadata: languageName: node linkType: hard +"tailwind-merge@npm:^2.3.0": + version: 2.3.0 + resolution: "tailwind-merge@npm:2.3.0" + dependencies: + "@babel/runtime": "npm:^7.24.1" + checksum: 10c0/5ea308e23c3ab1cf4c3f35f0a471753f4d3ed232d63dd7c09151a74428737321902203d90e9f0cb76ea5c3978e71b0adbc503dc455e56cda967a7674ae4b94b5 + languageName: node + linkType: hard + "tar@npm:^6.1.11, tar@npm:^6.1.2": version: 6.2.1 resolution: "tar@npm:6.2.1" @@ -7591,6 +7737,13 @@ __metadata: languageName: node linkType: hard +"tslib@npm:2.6.2": + version: 2.6.2 + resolution: "tslib@npm:2.6.2" + checksum: 10c0/e03a8a4271152c8b26604ed45535954c0a45296e32445b4b87f8a5abdb2421f40b59b4ca437c4346af0f28179780d604094eb64546bee2019d903d01c6c19bdb + languageName: node + linkType: hard + "tslib@npm:^2.0.0, tslib@npm:^2.3.1, tslib@npm:^2.4.1, tslib@npm:^2.5.0": version: 2.6.3 resolution: "tslib@npm:2.6.3" @@ -7921,6 +8074,18 @@ __metadata: languageName: node linkType: hard +"vconsole@npm:^3.15.1": + version: 3.15.1 + resolution: "vconsole@npm:3.15.1" + dependencies: + "@babel/runtime": "npm:^7.17.2" + copy-text-to-clipboard: "npm:^3.0.1" + core-js: "npm:^3.11.0" + mutation-observer: "npm:^1.0.3" + checksum: 10c0/1e62132b719e324eb7d533c94f38e9db288a9d0c9e85c8752ba742adee4e5925df10d4b43d05ba0cd264d99c32817f9f9c8f24fe391a7d8837469bd318d1b2ac + languageName: node + linkType: hard + "viem@npm:^1.0.0, viem@npm:^1.1.4": version: 1.21.4 resolution: "viem@npm:1.21.4"