Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: update "react-query" in page explore #366

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/assets/styles/mobile/component-style/user/challengeItem.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@
border-width: .0625rem;
border-radius: .625rem;
transition: none;
.edit{
width: 1.75rem;
height: 1.75rem;
border-radius: .3125rem;
right: .3125rem;
top: .3125rem;
font-size: .625rem;
z-index: 1;
background-color: #fff;
}
.item-claimed, .item-claimable{
width: 2.8125rem;
height: 1.125rem;
Expand Down
2 changes: 1 addition & 1 deletion src/assets/styles/mobile/view-style/explore.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
}
// title
h3 {
margin-bottom: 1.25rem;
font-size: 1.125rem;
font-weight: 600;
line-height: 1.5625rem;
Expand All @@ -34,6 +33,7 @@
// challenges
.challenges {
padding: 0;
padding-top: 1.25rem;
padding-bottom: 9.375rem;
gap: .625rem;
}
Expand Down
2 changes: 1 addition & 1 deletion src/assets/styles/view-style/explore.scss
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
}
// title
h3 {
margin-bottom: 80px;
font-size: 32px;
font-weight: 600;
line-height: 38px;
Expand All @@ -35,6 +34,7 @@
// challenges
.challenges {
padding: 0;
padding-top: 80px;
padding-bottom: 150px;
display: flex;
flex-wrap: wrap;
Expand Down
101 changes: 101 additions & 0 deletions src/components/ChallengeItem/ChallengeItemIcons.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { Tooltip } from "antd";
import {
CONTRACT_ADDR_1155,
CONTRACT_ADDR_1155_TESTNET,
CONTRACT_ADDR_721,
CONTRACT_ADDR_721_TESTNET,
} from "@/config";
import { useAddress } from "@/hooks/useAddress";
import { constans } from "@/utils/constans";

/*
hasNft: Boolean
hasVc: Boolean
info: {
nft_address,
badge_chain_id,
badge_token_id,
tokenId
}
*/

export default function ChallengeItemIcons({ hasNft, hasVc, info }) {
const isDev = process.env.REACT_APP_IS_DEV;
const contract721 = isDev ? CONTRACT_ADDR_721_TESTNET : CONTRACT_ADDR_721;
const contract1155 = isDev
? CONTRACT_ADDR_1155_TESTNET
: CONTRACT_ADDR_1155;
const { openseaLink, openseaSolanaLink } = constans();
const { walletType } = useAddress();

function toOpensea(event) {
event.stopPropagation();
const { nft_address, badge_chain_id, badge_token_id, tokenId } = info;
let evmLink = openseaLink;
const solanaLink = `${openseaSolanaLink}/${nft_address}`;
if (!badge_token_id) {
evmLink = `${evmLink}/${isDev ? "mumbai" : "matic"}/${contract1155.Badge}/${tokenId}`;
} else {
const chainAddr = contract721[badge_chain_id];
evmLink = `${evmLink}/${chainAddr.opensea}/${chainAddr.Badge}/${badge_token_id}`;
}
window.open(walletType === "evm" ? evmLink : solanaLink, "_blank");
}

return (
<div
style={{
position: "absolute",
right: "5px",
top: "5px",
display: "flex",
gap: "5px",
}}
>
{hasNft && (
<>
{/* 链 */}
<div
className={`opensea img ${isMobile ? "show" : ""}`}
onClick={(event) => event.stopPropagation()}
>
<img
src={contract721[info.badge_chain_id]?.img}
alt=""
/>
</div>
{/* opensea */}
<div
className={`opensea img ${isMobile ? "show" : ""}`}
onClick={toOpensea}
>
<img
src={require("@/assets/images/icon/user-opensea.png")}
alt=""
/>
</div>
</>
)}
{hasVc && (
// zk
<Tooltip
trigger={isMobile ? "focus" : "hover"}
title={t("zkTool")}
>
<div
className={`opensea img ${isMobile ? "show" : ""}`}
onClick={(event) => {
event.stopPropagation();
// showZk({address: profile.address, token_id: info.tokenId})
}}
>
<img
src={require("@/assets/images/icon/user-zk.png")}
alt=""
/>
</div>
</Tooltip>
)}
</div>
);
}
43 changes: 43 additions & 0 deletions src/components/ChallengeItem/ChallengeItemImg.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { LazyLoadImage } from "react-lazy-load-image-component";
import ChallengeItemIcons from "./ChallengeItemIcons";



export default function ChallengeItemImg({img, claimedInfo, questNum}) {

return (
<div className="right-sbt challenge-img">
<div className="img">
<LazyLoadImage src={img} />
</div>
{/* 阴影文本: ERC-721展示 */}
{
claimedInfo?.info.version === "2" && !claimedInfo?.hasNft &&
<div className="img-mask">
<p className="newline-omitted">{claimedInfo?.info.title}</p>
</div>
}
{/* 挑战集合信息 */}
{
questNum &&
<div className="sbt-bottom">
<div>
<img src={require("@/assets/images/icon/icon-collection.png")} alt="" />
</div>
<div>
<img src={require("@/assets/images/icon/icon-challenge.png")} alt="" />
<p>{questNum}</p>
</div>
</div>
}
{
claimedInfo &&
<ChallengeItemIcons
hasNft={claimedInfo?.hasNft}
hasVc={claimedInfo?.hasVc}
info={claimedInfo?.info}
/>
}
</div>
)
}
32 changes: 32 additions & 0 deletions src/components/ChallengeItem/ChallengeItemStatus.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { useTranslation } from "react-i18next";

/**
*
* @param {Boolean} claimable - 可领取状态
* @param {Boolean} claimed - 已领取状态
* @param {Boolean} review - 待打分状态
* @returns
*/

export default function ChallengeItemStatus({
claimable,
claimed,
review,
}) {
const { t } = useTranslation(["profile"]);

return (
<>
{claimable && <div className="item-claimable">{t("claimble")}</div>}
{claimed && <div className="item-claimed">{t("explore:pass")}</div>}
{review && (
<div
className="item-claimed"
style={{ borderColor: "#007DFA", color: "#007DFA" }}
>
{t("explore:review")}
</div>
)}
</>
);
}
117 changes: 117 additions & 0 deletions src/components/ChallengeItem/ChallengeItems.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { useState } from "react";
import { useTranslation } from "react-i18next";
import { useUpdateEffect } from "ahooks";
import { useQuery } from "@tanstack/react-query";
import { getCollection } from "@/state/explore/challenge";
import { constans } from "@/utils/constans";
import ChallengeItemStatus from "./ChallengeItemStatus";
import ChallengeItemImg from "./ChallengeItemImg";
import { convertTime } from "@/utils/convert";

export default function ChallengeItems({ info, goCollection }) {
const { data } = useQuery({
queryKey: ["collection"],
queryFn: () => getCollection(Number(info.id)),
});

const { ipfsPath, imgPath } = constans();
const { t } = useTranslation(["profile", "explore"]);
let [timestamp, setTimeStamp] = useState();
let [collectionInfo, setCollectionInfo] = useState({
questNum: 0,
claimable: false,
claimed: false,
});

function getTimeDiff(time) {
const { type, time: num } = convertTime(time, "all")
return t(`translation:${type}`, {time: Math.round(num)})
}

async function init() {
try {
let tokenId = data.collection.tokenId;
collectionInfo.questNum = data.list.length;
timestamp = info.quest_data?.estimateTime
? getTimeDiff(info?.estimateTime)
: null;
setTimeStamp(timestamp);
if (tokenId && tokenId !== "0") {
collectionInfo.claimable = !list.some((e) => !e.claimed);
collectionInfo.claimed = data.status;
}
setCollectionInfo({ ...collectionInfo });
} catch (error) {
console.log(error);
}
}

useUpdateEffect(() => {
data && init();
}, [data]);

return (
<div className="ChallengeItem" onClick={() => goCollection(info.id)}>
{/* 挑战状态 */}
<ChallengeItemStatus
claimable={
collectionInfo.claimable && collectionInfo.questNum !== 0
}
claimed={
collectionInfo.claimed && collectionInfo.questNum !== 0
}
/>
<ChallengeItemImg
img={`${ipfsPath}/${info.cover}`}
questNum={collectionInfo.questNum}
/>
<div className="left-info">
<div>
<p className="title newline-omitted">{info.title}</p>
<p className="desc newline-omitted">{info.description}</p>
</div>
<div className="collection-author">
{info.author_info.avatar && (
<div className="img">
<img
src={imgPath + info.author_info.avatar}
alt=""
/>
</div>
)}
<p>{info.author_info.nickname}</p>
</div>
<div className="sbt-detail">
<div className="flex">
{info?.difficulty !== null && (
<>
<span>{t("translation:diff")}</span>
<div className="imgs">
{new Array(3).fill(0).map((e, i) => (
<img
key={i}
alt=""
src={require(`@/assets/images/icon/star-${
i >= info?.difficulty + 1
? "line"
: "full"
}.png`)}
/>
))}
</div>
</>
)}
</div>
<div className="time">
{info?.estimate_time !== null && (
<>
<ClockCircleFilled />
{timestamp}
</>
)}
</div>
</div>
</div>
</div>
);
}
Loading