{title}
-
+
{
!hiddenCloseIcon && (
- setVisible(false)} />
+ setVisible(false)} />
)
}
{children}
-
buttonClick()}>{buttonText}
+ {
+ !showConfirmButton && (
+
buttonClick && buttonClick()}>{buttonText}
+ )
+ }
{
showCancelButton &&
showCancelButtonClick && showCancelButtonClick()}>{showCancelButtonText || '關閉'}
diff --git a/src/components/ProductInfo.tsx b/src/components/ProductInfo.tsx
index e5126d8..53d6cdc 100644
--- a/src/components/ProductInfo.tsx
+++ b/src/components/ProductInfo.tsx
@@ -1,39 +1,72 @@
+import { observer } from 'mobx-react'
+import { useState } from 'react'
+import useLike from '~/hooks/useLike'
+import store from '~/store'
import '~/styles/components.scss'
+import { MarketNFTData } from '~/types/store'
+import { toThousands } from '~/utils'
+import { copy } from '~/utils/copy'
+import Modal from './Modal'
+
+interface ProductInfoProps {
+ data: MarketNFTData
+}
+
+const ProductInfo = (props: ProductInfoProps) => {
+
+ const { data } = props
+ const { likeNft } = store.state
+ const { setLike, isLike } = useLike()
+ const [visible, setVisible] = useState(false)
+
+ const share = () => {
+ const pathname = `${process.env.REACT_APP_SHARE_LINK}detail?id=${data.id}&type=${data.type}`
+ copy(pathname)
+ setVisible(true)
+ }
-const ProductInfo = () => {
return (
-
+
-
-
-
-
-
-
生肖唐彩-龙
-
USDT 21,100.15
+ {data.type !== 0 &&
+ setLike(data.id)} />
+
+
}
+
{data.name}
+
{data.symbol} {toThousands(data.price)}
铸造者
-
-
Filefast
+
+
{data.cast_name}
售卖者
-
-
Filefast
+
+
{data.sell_name}
-
+
+
+ 已複製鏈接
+
+
)
}
-export default ProductInfo
\ No newline at end of file
+export default observer(ProductInfo)
\ No newline at end of file
diff --git a/src/hooks/useLike.ts b/src/hooks/useLike.ts
new file mode 100644
index 0000000..76f0ecc
--- /dev/null
+++ b/src/hooks/useLike.ts
@@ -0,0 +1,41 @@
+import { useRef } from "react";
+import { set_like } from "~/api";
+import store from "~/store";
+import { MarketNFTData } from "~/types/store";
+
+const useLike = () => {
+ const throttle = useRef(false)
+ /**
+ * @description 設置喜歡的NFT
+ * @param id nftid
+ * 1.喜歡 2.取消喜歡
+ */
+ const setLike = async (id: number) => {
+ if (!store.state.token) return store.setVisibleUnLogin(true);
+ if(throttle.current)return
+ throttle.current = true
+ let item = store.state.likeNft.find((v) => v.id === id);
+ let status = item ? 2 : 1;
+ let res: any = await set_like(id, status);
+ throttle.current = false
+ if (res && res.code === 0) {
+ store.getMyNft("likeNft", 2);
+ }
+ };
+
+ /**
+ * 判斷喜歡的NFt
+ */
+ const isLike = (id: number, likeNft: MarketNFTData[]) => {
+ const item = likeNft.find((v) => v.id === id);
+ if (item) return true;
+ return false;
+ };
+
+ return {
+ setLike,
+ isLike,
+ };
+};
+
+export default useLike;
diff --git a/src/pages/detail/BuyNft.tsx b/src/pages/detail/BuyNft.tsx
new file mode 100644
index 0000000..a698553
--- /dev/null
+++ b/src/pages/detail/BuyNft.tsx
@@ -0,0 +1,95 @@
+import '~/styles/detail.scss'
+import { Button, Toast } from 'react-vant'
+import { MarketNFTData } from '~/types/store'
+import Modal from '~/components/Modal'
+import { useState } from 'react'
+import { observer } from 'mobx-react'
+import store from '~/store'
+import { toThousands } from '~/utils'
+import { buy_nft } from '~/api'
+
+interface BuyNftProps {
+ data: MarketNFTData
+}
+
+const BuyNft = (props: BuyNftProps) => {
+
+ const { data } = props
+ const { userInfo, token } = store.state
+ const [buyVisible, setBuyVisible] = useState(false)
+ const [successVisible, setSuccessVisible] = useState(false)
+
+ const openBuyModal = () => {
+ if (!token) return store.setVisibleUnLogin(true)
+ let symbol = data.symbol
+ if (symbol === 'USDT' && Number(userInfo.balance_Usdt) < Number(data.price)) {
+ Toast.fail('餘額不足')
+ return
+ }
+ if (symbol === 'FIL' && Number(userInfo.balance_fil) < Number(data.price)) {
+ Toast.fail('餘額不足')
+ return
+ }
+ setBuyVisible(true)
+ }
+
+ const buyNft = async () => {
+ setBuyVisible(false)
+ const params = {
+ id: data.id,
+ type: data.type
+ }
+ const res: any = await buy_nft(params)
+ if (res && res.code === 0) {
+ setSuccessVisible(true)
+ store.getMyNft("myNft", 1)
+ store.getMarketNft("issueNft")
+ store.getMarketNft("sellNft")
+ }
+ }
+
+ return (
+
+
+ {/* Buy Modal */}
+ 確定購買
}
+ buttonClick={buyNft}
+ >
+
+
您將以 {toThousands(data.price)} {data.symbol}
+
購買一張 "{data.name}" NFT
+
+
+ {/* success */}
+
+
+
+
+
+
恭喜購買成功
+
{data.name}
+
+
+
+ )
+}
+
+export default observer(BuyNft)
\ No newline at end of file
diff --git a/src/pages/detail/NFTProperties.tsx b/src/pages/detail/NFTProperties.tsx
new file mode 100644
index 0000000..0a505e7
--- /dev/null
+++ b/src/pages/detail/NFTProperties.tsx
@@ -0,0 +1,35 @@
+import { MarketNFTData } from "~/types/store"
+import { getTime } from "~/utils"
+
+interface NFTPropertiesProps {
+ data: MarketNFTData
+}
+
+const NFTProperties = (props: NFTPropertiesProps) => {
+
+ const { data } = props
+
+ return (
+
+
NFT屬性:
+
+
鑄造日期:{getTime(data.time * 1000, 'day')}
+
NFT名稱:{data.name}
+
+
+
NFT編號:{data.number}
+
NFT發行數:{data.total_stock}
+
+
+
NFT功能:{data.function}
+
歸屬平臺:{data.platform}
+
+
+
獎勵分配:{data.award}
+
分配天數:{data.day}
+
+
+ )
+}
+
+export default NFTProperties
\ No newline at end of file
diff --git a/src/pages/detail/OnShelvesNFT.tsx b/src/pages/detail/OnShelvesNFT.tsx
new file mode 100644
index 0000000..9fcf5e3
--- /dev/null
+++ b/src/pages/detail/OnShelvesNFT.tsx
@@ -0,0 +1,18 @@
+import { MarketNFTData } from "~/types/store"
+
+interface OnShelvesNFTProps {
+ data: MarketNFTData
+}
+
+const OnShelvesNFT = (props: OnShelvesNFTProps) => {
+
+ const { data } = props
+
+ return (
+
+ 售賣 拍賣
+
+ )
+}
+
+export default OnShelvesNFT
\ No newline at end of file
diff --git a/src/pages/detail/index.tsx b/src/pages/detail/index.tsx
index bb57c0d..8b4d706 100644
--- a/src/pages/detail/index.tsx
+++ b/src/pages/detail/index.tsx
@@ -1,22 +1,104 @@
-import { Button } from "react-vant"
+import { useEffect, useMemo, useState } from "react"
+import { Button, Empty, Loading } from "react-vant"
+import { nft_detail } from "~/api"
+import BackBar from "~/components/BackBar"
import ProductInfo from "~/components/ProductInfo"
+import { useRouter } from "~/hooks/useRouter"
import '~/styles/detail.scss'
+import { MarketNFTData } from "~/types/store"
+import BuyNft from "./BuyNft"
+import NFTProperties from "./NFTProperties"
+import OnShelvesNFT from "./OnShelvesNFT"
const Detail = () => {
+
+ const { location } = useRouter()
+ const query = useMemo(() => {
+ let obj = {} as { [key: string]: number }
+ if (location.state) {
+ obj.id = Number(location.state.id)
+ obj.type = Number(location.state.type)
+ }
+ if (location.search) {
+ let val = location.search.substring(1).split('&')
+ val.forEach(item => {
+ let value = item.split('=')
+ obj[value[0]] = Number(value[1])
+ })
+ }
+ return obj
+ }, [location])
+
+ const [product, setProduct] = useState({} as MarketNFTData)
+ const [loading, setLoading] = useState(false)
+ console.log(product);
+
+ const titles = useMemo(() => ({
+ "0": "上架",
+ "1": "拍賣",
+ "2": "售賣",
+ "3": "發行"
+ } as any), [])
+
+ useEffect(() => {
+ const getData = async () => {
+ setLoading(true)
+ const res: any = await nft_detail(query)
+ setLoading(false)
+ res && res.code === 0 && setProduct(res.data)
+ }
+
+ Object.keys(query).length === 2 && getData()
+ }, [])
+
+ if (Object.keys(query).length < 2) return (
+
+ )
+
+ if (loading) return (
+
+ )
+
return (
-
-
-
+
+
+ {/* type 0.表示上架NFT 2.購買NFT 3.搶購 */}
+ {
+ product.type === 0 && (
+
+
+
+ )
+ }
+
+ {
+ product.type === 0 && (
+
+ )
+ }
+
+ {
+ product.type === 2 && (
+
+ )
+ }
)
}
diff --git a/src/pages/home/index.tsx b/src/pages/home/index.tsx
index 22961c8..d20692b 100644
--- a/src/pages/home/index.tsx
+++ b/src/pages/home/index.tsx
@@ -1,44 +1,81 @@
import '~/styles/home.scss'
import ProductItem from '~/components/ProductItem'
import { useRouter } from '~/hooks/useRouter'
-import { Button } from 'react-vant'
-import { useEffect, useState } from 'react'
-import { market_list } from '~/api'
-import { MarketNFTData } from '~/types/store'
+import { Button, Swiper, SwiperInstance } from 'react-vant'
+import { useEffect, useRef } from 'react'
import { splitAddress } from '~/utils'
import { observer } from 'mobx-react'
+import store from '~/store'
+import useLike from '~/hooks/useLike'
const Home = () => {
const { push } = useRouter()
- const [marketData, setMarketData] = useState([] as MarketNFTData[])
- const [auctionData, setAuctionData] = useState([] as MarketNFTData[])
-
+ const { sellNft, auctionNft, likeNft } = store.state
+ const like = useLike()
+ const swiperRef = useRef
(null)
useEffect(() => {
- const getMarketData = async () => {
- const res: any = await market_list(2)
- res && res.code === 0 && res.data && setMarketData(res.data)
- }
- const getAuctionData = async () => {
- const res: any = await market_list(1)
- res && res.code === 0 && res.data && setAuctionData(res.data)
- }
- getMarketData()
- getAuctionData()
+ store.getMarketNft("sellNft")
+ store.getMarketNft("auctionNft")
+ store.getMarketNft("issueNft")
}, [])
return (
-
拍卖趋势
+
發行搶購
+
+
+ {
+ swiperRef.current && swiperRef.current.swipePrev()
+ }}>
+
+
+
+
+
+
+
+
+
回購型NFT
+
生肖唐彩-猴
+
+
+
USDT 10000
+
+
+
+
+
+
+
Filefaasdasdasdfdsfsdf
+
+
+
+
+
+
+
+
+
+
+ {
+ swiperRef.current && swiperRef.current.swipeNext()
+ }}>
+
+
+
拍卖趋势
{
- auctionData.map((item, index) => (
+ auctionNft.map((item, index) => (
-
push('/detail', { id: item.id })} />
+
push('/detail', { id: item.id, type: item.type })} />
@@ -64,7 +101,9 @@ const Home = () => {
-
+
like.setLike(item.id)} />
@@ -72,12 +111,12 @@ const Home = () => {
))
}
-
售卖市场
-
+
售卖市场
+
{
- marketData.map((item, index) => (
-
push('/detail', { id: item.id })}>
+ sellNft.map((item, index) => (
+
push('/detail', { id: item.id, type: item.type })}>
))
@@ -89,4 +128,4 @@ const Home = () => {
)
}
-export default Home
\ No newline at end of file
+export default observer(Home)
\ No newline at end of file
diff --git a/src/pages/product/index.tsx b/src/pages/product/index.tsx
index 757cadd..252ad21 100644
--- a/src/pages/product/index.tsx
+++ b/src/pages/product/index.tsx
@@ -1,25 +1,72 @@
-import { Divider } from 'react-vant'
+import { debounce } from 'lodash'
+import { observer } from 'mobx-react'
+import { useEffect, useState } from 'react'
+import { Divider, Loading } from 'react-vant'
+import { search_nft } from '~/api'
+import { useRouter } from '~/hooks/useRouter'
+import store from '~/store'
import '~/styles/product.scss'
import { MarketNFTData } from '~/types/store'
import ProductItem from '../../components/ProductItem'
const Product = () => {
+ const { rmdNft } = store.state
+ const { push } = useRouter()
+ const [nftList, setNftList] = useState([] as MarketNFTData[])
+ const [loading, setLoading] = useState(false)
+
+ const onChange = (e: any) => {
+ searchNft(e.target.value)
+ }
+
+ const searchNft = debounce(async (value: string) => {
+ if (!value) return setNftList([])
+ setLoading(true)
+ const res: any = await search_nft(value)
+ setLoading(false)
+ if (res && res.code === 0 && res.data) {
+ setNftList(res.data)
+ }
+ }, 700)
+
+ useEffect(() => {
+ store.getMarketNft("rmdNft")
+ }, [])
return (
-
+
+
{nftList.length}個結果
+
+
+ {
+ nftList.map((item, index) => (
+
push("/detail", { id: item.id, type: item.type })}>
+
+
+ ))
+ }
+
-
0个结构
-
推荐
{
- Array.from({ length: 6 }).map((_, index) => (
-
+ rmdNft.map((item, index) => (
+
push("/detail", { id: item.id, type: item.type })}>
+
+
))
}
@@ -28,4 +75,4 @@ const Product = () => {
)
}
-export default Product
\ No newline at end of file
+export default observer(Product)
\ No newline at end of file
diff --git a/src/pages/share/index.tsx b/src/pages/share/index.tsx
index 77bd4d2..aa4dd26 100644
--- a/src/pages/share/index.tsx
+++ b/src/pages/share/index.tsx
@@ -1,16 +1,17 @@
import '~/styles/share.scss'
import { Popup, Tabs, Toast } from 'react-vant'
import ProductItem from '~/components/ProductItem'
-import { MarketNFTData } from '~/types/store'
import store from '~/store'
import { observer } from 'mobx-react'
import { toFixed2 } from '~/utils'
-import { useEffect, useMemo, useRef, useState } from 'react'
-import { open_page, personal_nft, reset_name, upload_image } from '~/api'
+import { useMemo, useRef, useState } from 'react'
+import { open_page, reset_name, upload_image } from '~/api'
+import { useRouter } from '~/hooks/useRouter'
const Share = () => {
- const { userInfo, token } = store.state
+ const { userInfo, token, likeNft, myNft } = store.state
+ const { push } = useRouter()
const [visible, setVisible] = useState(false)
const inputRef = useRef
(null)
const nameRef = useRef(null)
@@ -18,10 +19,6 @@ const Share = () => {
const prevent = useRef(false) //阻止重複點擊
const fileRef = useRef(null as any)
const [tempUrl, setTempUrl] = useState(null as any)
- const [nftList, setNftList] = useState([
- [], //我的
- [],//我喜歡的
- ] as MarketNFTData[][])
const tabs = useMemo(() => ['我的NFT', '我喜歡的NFT'], [])
const avatarmenuClick = (event: any) => {
@@ -90,18 +87,6 @@ const Share = () => {
inputRef.current!.value = ''
}
- useEffect(() => {
- const getData = async () => {
- const res: any = await personal_nft(1)
- if (res && res.code === 0) {
- nftList[0] = res.data
- setNftList([...nftList])
- }
- }
-
- token && getData()
- }, [token])
-
return (
@@ -180,12 +165,18 @@ const Share = () => {
key={index}
title={
{item}
- {nftList[index].length}
+ {
+ index === 0 ? myNft.length : likeNft.length
+ }
}
titleClass='fz-wb-550'
>
- {nftList[index].map((item, index) =>
)}
+ {(index === 0 ? myNft : likeNft).map((item, index) => (
+
push('/detail', { id: item.id, type: item.type })}>
+
+
+ ))}
))
diff --git a/src/router/layout/index.tsx b/src/router/layout/index.tsx
index 2a08142..1d81137 100644
--- a/src/router/layout/index.tsx
+++ b/src/router/layout/index.tsx
@@ -41,10 +41,20 @@ const LayoutRouter = () => {
}
useEffect(() => {
- token && store.getUserInfo()
- token && store.getCoinList()
- !token && store.resetCoinList()
- !token && store.resetUserInfo()
+ if (token) {
+ store.getUserInfo()
+ store.getCoinList()
+ store.getMyNft('myNft', 1)
+ store.getMyNft('likeNft', 2)
+ }
+
+ if (!token) {
+ store.resetCoinList()
+ store.resetUserInfo()
+ store.resetNft("likeNft")
+ store.resetNft("myNft")
+ }
+
// token && messageWs.connect(token)
// !token && messageWs.disconnect()
}, [token])
@@ -55,7 +65,6 @@ const LayoutRouter = () => {
let isRouter = routes.find(v => v.path === location.pathname)
const address = location.pathname.substring(1, location.pathname.length)
- if (user.is_bound) return
if (isRouter) return
if (Object.keys(user).length <= 0) {
@@ -79,7 +88,7 @@ const LayoutRouter = () => {
return
}
// 已有推荐人
- if (user.is_bound) {
+ if (user.is_bound && ethers.utils.isAddress(address)) {
setVisibleAlreadyBind(true)
}
}
@@ -120,7 +129,7 @@ const LayoutRouter = () => {
onClick={() => {
push('/', null, true)
setVisibleAlreadyBind(false)
- push('/share')
+ push('/team')
}}
visible={visibleAlreadyBind}
setVisible={setVisibleAlreadyBind}
diff --git a/src/router/layout/ui.tsx b/src/router/layout/ui.tsx
index 0f1204b..3230fac 100644
--- a/src/router/layout/ui.tsx
+++ b/src/router/layout/ui.tsx
@@ -1,6 +1,7 @@
import { ethers } from "ethers";
import { useRef } from "react";
import { Toast } from "react-vant";
+import { useRouter } from "~/hooks/useRouter";
import Modal from "../../components/Modal";
interface UIProps {
visible: boolean,
@@ -88,22 +89,32 @@ export const BindRmd = ({ visible, setVisible, address, onClick }: UIProps) => (
)
-export const BindSuccess = ({ visible, setVisible, address }: UIProps) => (
-
-
-
-)
+export const BindSuccess = ({ visible, setVisible, address }: UIProps) => {
+ const { push } = useRouter()
+ return (
+
{
+ push('/', null, true)
+ setVisible()
+ push('/team')
+ }}
+ buttonText="查看綁定"
+ hiddenCloseIcon
+ showCancelButton
+ showCancelButtonText="關閉"
+ showCancelButtonClick={setVisible}
+ >
+
+
+ )
+}
export const AlreadyBind = ({ visible, setVisible, onClick }: UIProps) => (
{
* @param value
* @returns
*/
-const getTime = (value: number) => {
+const getTime = (value: number, type?: string) => {
let date = new Date(value);
let yy: number | string = date.getFullYear();
let mm: number | string = date.getMonth() + 1;
@@ -76,6 +76,7 @@ const getTime = (value: number) => {
xs = xs >= 10 ? xs : "0" + xs;
ff = ff >= 10 ? ff : "0" + ff;
ss = ss >= 10 ? ss : "0" + ss;
+ if(type === 'day') return `${yy}-${mm}-${dd}`
return `${yy}-${mm}-${dd} ${xs}:${ff}`;
};