From a49cecc2db04ebab3839f260b90e08be48d88531 Mon Sep 17 00:00:00 2001
From: Caoqizhi <2391580279@qq.com>
Date: Tue, 23 Jan 2024 15:32:24 +0800
Subject: [PATCH 1/7] en: explore query
---
src/router/index.js | 3 +-
src/state/explore/challenge.js | 11 +++++++
src/views/Explore/index.jsx | 56 ++++++++++++++++++++++++++++++++++
3 files changed, 69 insertions(+), 1 deletion(-)
create mode 100644 src/state/explore/challenge.js
create mode 100644 src/views/Explore/index.jsx
diff --git a/src/router/index.js b/src/router/index.js
index 4a01a932..ab236bf1 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -1,5 +1,6 @@
import Index from "@/views/Index"
import Explore from "@/views/Explore"
+import ExploreNew from "@/views/Explore/index"
import NewPublish from "@/views/Publish/index"
import Question from "@/views/Question/index";
import Challenge from "@/views/Challenge/index";
@@ -21,7 +22,7 @@ const routes = [
},
{
path: "/challenges",
- element: ,
+ element: ,
},
{
path: "/collection/:id",
diff --git a/src/state/explore/challenge.js b/src/state/explore/challenge.js
new file mode 100644
index 00000000..5598b796
--- /dev/null
+++ b/src/state/explore/challenge.js
@@ -0,0 +1,11 @@
+import { getQuests } from "@/request/api/public";
+
+export const getChallengeList = async (pageParam) => {
+ try {
+ const res = await getQuests({pageSize: 10, page: pageParam});
+ return res.data?.list || []
+ } catch (error) {
+ console.log(error);
+ return null;
+ }
+};
diff --git a/src/views/Explore/index.jsx b/src/views/Explore/index.jsx
new file mode 100644
index 00000000..263f62f6
--- /dev/null
+++ b/src/views/Explore/index.jsx
@@ -0,0 +1,56 @@
+import { Spin } from "antd";
+import { useNavigate } from "react-router-dom";
+import { useTranslation } from "react-i18next";
+import { useInfiniteQuery } from "@tanstack/react-query";
+import InfiniteScroll from "react-infinite-scroll-component";
+import PageLoader from "@/components/Loader/PageLoader";
+import ChallengeItem from "@/components/User/ChallengeItem";
+import ChallengeItems from "@/components/User/ChallengeItems";
+import { getChallengeList } from "@/state/explore/challenge";
+
+export default function Explore(params) {
+ const navigateTo = useNavigate();
+ const { t } = useTranslation(["explore", "translation"]);
+ const { data, fetchNextPage, hasNextPage, status } = useInfiniteQuery({
+ queryKey: ["challenges"],
+ queryFn: ({ pageParam }) => getChallengeList(pageParam),
+ initialPageParam: 1,
+ getNextPageParam: (lastPage, allPages) => {
+ return lastPage.length > 0 ? allPages.length + 1 : undefined;
+ },
+ });
+
+ return (
+
+
+
{t("title")}
+
}
+ >
+ {status === "pending" ? (
+
+ ) : (
+ data.pages
+ .flat()
+ .map((item) =>
+ item.style === 1 ? (
+
+ ) : (
+
+ navigateTo(`/collection/${id}`)
+ }
+ />
+ )
+ )
+ )}
+
+
+ );
+}
From 00af15bf3a76289c0b49d325967fa7295bf13003 Mon Sep 17 00:00:00 2001
From: Caoqizhi <2391580279@qq.com>
Date: Fri, 26 Jan 2024 10:31:37 +0800
Subject: [PATCH 2/7] en: stash
---
.../styles/mobile/view-style/explore.scss | 2 +-
src/assets/styles/view-style/explore.scss | 2 +-
.../ChallengeItem/ChallengeItemIcons.jsx | 57 +++++++++++++++
src/components/ChallengeItem/index.jsx | 69 +++++++++++++++++++
.../Explore/components/ChallengeList.jsx | 9 +++
src/views/Explore/index.jsx | 3 +
src/views/Explore/style/index.scss | 44 ++++++++++++
src/views/Explore/style/mobile.scss | 41 +++++++++++
8 files changed, 225 insertions(+), 2 deletions(-)
create mode 100644 src/components/ChallengeItem/ChallengeItemIcons.jsx
create mode 100644 src/components/ChallengeItem/index.jsx
create mode 100644 src/views/Explore/components/ChallengeList.jsx
create mode 100644 src/views/Explore/style/index.scss
create mode 100644 src/views/Explore/style/mobile.scss
diff --git a/src/assets/styles/mobile/view-style/explore.scss b/src/assets/styles/mobile/view-style/explore.scss
index d0096d88..0018ba24 100644
--- a/src/assets/styles/mobile/view-style/explore.scss
+++ b/src/assets/styles/mobile/view-style/explore.scss
@@ -17,7 +17,6 @@
}
// title
h3 {
- margin-bottom: 1.25rem;
font-size: 1.125rem;
font-weight: 600;
line-height: 1.5625rem;
@@ -34,6 +33,7 @@
// challenges
.challenges {
padding: 0;
+ padding-top: 1.25rem;
padding-bottom: 9.375rem;
gap: .625rem;
}
diff --git a/src/assets/styles/view-style/explore.scss b/src/assets/styles/view-style/explore.scss
index 9b202538..70163248 100644
--- a/src/assets/styles/view-style/explore.scss
+++ b/src/assets/styles/view-style/explore.scss
@@ -18,7 +18,6 @@
}
// title
h3 {
- margin-bottom: 80px;
font-size: 32px;
font-weight: 600;
line-height: 38px;
@@ -35,6 +34,7 @@
// challenges
.challenges {
padding: 0;
+ padding-top: 80px;
padding-bottom: 150px;
display: flex;
flex-wrap: wrap;
diff --git a/src/components/ChallengeItem/ChallengeItemIcons.jsx b/src/components/ChallengeItem/ChallengeItemIcons.jsx
new file mode 100644
index 00000000..a02d230a
--- /dev/null
+++ b/src/components/ChallengeItem/ChallengeItemIcons.jsx
@@ -0,0 +1,57 @@
+import { Tooltip } from "antd";
+
+
+/*
+hasNft: Boolean
+hasVc: Boolean
+*/
+export default function ChallengeItemIcons({
+ hasNft,
+ hasVc
+}) {
+
+ function name(params) {
+
+ }
+
+ return (
+
+ {
+ hasNft &&
+ <>
+ {/* 链 */}
+
event.stopPropagation()}>
+
+
+ {/* opensea */}
+
+
+
+ >
+ }
+ {
+ hasVc &&
+ // zk
+
+ {
+ event.stopPropagation();
+ showZk({address: profile.address, token_id: info.tokenId})
+ }}>
+
+
+
+ }
+
+ )
+}
\ No newline at end of file
diff --git a/src/components/ChallengeItem/index.jsx b/src/components/ChallengeItem/index.jsx
new file mode 100644
index 00000000..b21c99e0
--- /dev/null
+++ b/src/components/ChallengeItem/index.jsx
@@ -0,0 +1,69 @@
+import { LazyLoadImage } from "react-lazy-load-image-component";
+import ChallengeItemIcons from "./ChallengeItemIcons";
+
+/*
+info: {
+ img,
+ title,
+ description,
+ difficulty,
+ time
+}
+hasNft: Boolean
+hasVc: Boolean
+*/
+
+export default function ChallengeItem({
+ info,
+ hasNft,
+ hasVc
+}) {
+
+
+
+ return (
+
+
+
+
+
+ {info.title}
+
+
+ {info.description}
+
+
+
+
+ {
+ info.metadata?.attributes?.difficulty !== null &&
+ <>
+
{t("translation:diff")}
+
+ {
+ arr.map((e,i) => {
+ if (i >= info.metadata?.attributes?.difficulty+1) {
+ return
+ }else{
+ return
+ }
+ })
+ }
+
+ >
+ }
+
+
+
+ {info?.time}
+
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/src/views/Explore/components/ChallengeList.jsx b/src/views/Explore/components/ChallengeList.jsx
new file mode 100644
index 00000000..d724fe63
--- /dev/null
+++ b/src/views/Explore/components/ChallengeList.jsx
@@ -0,0 +1,9 @@
+
+
+
+export default function ChallengeList(params) {
+
+
+
+
+}
\ No newline at end of file
diff --git a/src/views/Explore/index.jsx b/src/views/Explore/index.jsx
index 263f62f6..5a2c0750 100644
--- a/src/views/Explore/index.jsx
+++ b/src/views/Explore/index.jsx
@@ -7,6 +7,9 @@ import PageLoader from "@/components/Loader/PageLoader";
import ChallengeItem from "@/components/User/ChallengeItem";
import ChallengeItems from "@/components/User/ChallengeItems";
import { getChallengeList } from "@/state/explore/challenge";
+import "./style/index.scss";
+import "./mobile.scss";
+
export default function Explore(params) {
const navigateTo = useNavigate();
diff --git a/src/views/Explore/style/index.scss b/src/views/Explore/style/index.scss
new file mode 100644
index 00000000..70163248
--- /dev/null
+++ b/src/views/Explore/style/index.scss
@@ -0,0 +1,44 @@
+.Explore {
+ width: 1440px;
+ padding-top: 170px;
+ margin: 0 auto;
+ font-family: Source;
+ position: relative;
+ .back{
+ position: absolute;
+ display: flex;
+ align-items: center;
+ top: 95px;
+ font-size: 20px;
+ cursor: pointer;
+ .anticon{
+ margin-right: 11px;
+ font-size: 30px;
+ }
+ }
+ // title
+ h3 {
+ font-size: 32px;
+ font-weight: 600;
+ line-height: 38px;
+ }
+ // depass
+ .depass {
+ margin-top: 63px;
+ h4 {
+ font-size: 20px;
+ font-weight: 800;
+ color: #3d3d3d;
+ }
+ }
+ // challenges
+ .challenges {
+ padding: 0;
+ padding-top: 80px;
+ padding-bottom: 150px;
+ display: flex;
+ flex-wrap: wrap;
+ gap: 36px 40px;
+ }
+}
+
\ No newline at end of file
diff --git a/src/views/Explore/style/mobile.scss b/src/views/Explore/style/mobile.scss
new file mode 100644
index 00000000..0018ba24
--- /dev/null
+++ b/src/views/Explore/style/mobile.scss
@@ -0,0 +1,41 @@
+.Mobile{
+ .Explore {
+ width: 21.875rem;
+ min-height: 100vh;
+ padding-top: 5.625rem;
+ .back{
+ position: absolute;
+ display: flex;
+ align-items: center;
+ top: 4.3375rem;
+ font-size: .75rem;
+ cursor: pointer;
+ .anticon{
+ margin-right: .3125rem;
+ font-size: 1rem;
+ }
+ }
+ // title
+ h3 {
+ font-size: 1.125rem;
+ font-weight: 600;
+ line-height: 1.5625rem;
+ }
+ // depass
+ .depass {
+ margin-top: 3.9375rem;
+ h4 {
+ font-size: 1.25rem;
+ font-weight: 800;
+ color: #3d3d3d;
+ }
+ }
+ // challenges
+ .challenges {
+ padding: 0;
+ padding-top: 1.25rem;
+ padding-bottom: 9.375rem;
+ gap: .625rem;
+ }
+ }
+}
\ No newline at end of file
From cf89e13558bc5cc9d728fbe03d3d7c6634c1ffce Mon Sep 17 00:00:00 2001
From: Caoqizhi <2391580279@qq.com>
Date: Fri, 26 Jan 2024 16:32:40 +0800
Subject: [PATCH 3/7] =?UTF-8?q?en:=20=E8=B0=83=E6=95=B4challengeItem?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../ChallengeItem/ChallengeItemIcons.jsx | 112 ++++++++----
.../ChallengeItem/ChallengeItemImg.jsx | 23 +++
.../ChallengeItem/ChallengeItemStatus.jsx | 32 ++++
src/components/ChallengeItem/index.jsx | 171 +++++++++++++-----
src/views/Explore/index.jsx | 6 +-
5 files changed, 262 insertions(+), 82 deletions(-)
create mode 100644 src/components/ChallengeItem/ChallengeItemImg.jsx
create mode 100644 src/components/ChallengeItem/ChallengeItemStatus.jsx
diff --git a/src/components/ChallengeItem/ChallengeItemIcons.jsx b/src/components/ChallengeItem/ChallengeItemIcons.jsx
index a02d230a..dd900147 100644
--- a/src/components/ChallengeItem/ChallengeItemIcons.jsx
+++ b/src/components/ChallengeItem/ChallengeItemIcons.jsx
@@ -1,57 +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
-}) {
- function name(params) {
-
+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 (
-
- {
- hasNft &&
+
+ {hasNft && (
<>
{/* 链 */}
-
event.stopPropagation()}>
-
+
event.stopPropagation()}
+ >
+
{/* opensea */}
-
-
+
+
>
- }
- {
- hasVc &&
+ )}
+ {hasVc && (
// zk
- {
- event.stopPropagation();
- showZk({address: profile.address, token_id: info.tokenId})
- }}>
-
+
{
+ event.stopPropagation();
+ // showZk({address: profile.address, token_id: info.tokenId})
+ }}
+ >
+
- }
+ )}
- )
-}
\ No newline at end of file
+ );
+}
diff --git a/src/components/ChallengeItem/ChallengeItemImg.jsx b/src/components/ChallengeItem/ChallengeItemImg.jsx
new file mode 100644
index 00000000..459d2216
--- /dev/null
+++ b/src/components/ChallengeItem/ChallengeItemImg.jsx
@@ -0,0 +1,23 @@
+import { LazyLoadImage } from "react-lazy-load-image-component";
+import ChallengeItemIcons from "./ChallengeItemIcons";
+
+
+
+export default function ChallengeItemImg({img, claimedInfo}) {
+
+ return (
+
+
+
+
+ {
+ claimedInfo &&
+
+ }
+
+ )
+}
\ No newline at end of file
diff --git a/src/components/ChallengeItem/ChallengeItemStatus.jsx b/src/components/ChallengeItem/ChallengeItemStatus.jsx
new file mode 100644
index 00000000..13f9240d
--- /dev/null
+++ b/src/components/ChallengeItem/ChallengeItemStatus.jsx
@@ -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 && {t("claimble")}
}
+ {claimed && {t("explore:pass")}
}
+ {review && (
+
+ {t("explore:review")}
+
+ )}
+ >
+ );
+}
diff --git a/src/components/ChallengeItem/index.jsx b/src/components/ChallengeItem/index.jsx
index b21c99e0..1cf8b890 100644
--- a/src/components/ChallengeItem/index.jsx
+++ b/src/components/ChallengeItem/index.jsx
@@ -1,69 +1,150 @@
+import { useTranslation } from "react-i18next";
+import { ClockCircleFilled, EditOutlined } from "@ant-design/icons";
import { LazyLoadImage } from "react-lazy-load-image-component";
import ChallengeItemIcons from "./ChallengeItemIcons";
+import ChallengeItemStatus from "./ChallengeItemStatus";
+import { message } from "antd";
+import { useEffect, useState } from "react";
+import { convertTime } from "@/utils/convert";
+import { constans } from "@/utils/constans";
+import { useNavigate } from "react-router-dom";
+import ChallengeItemImg from "./ChallengeItemImg";
/*
+isMe: Boolean,
info: {
- img,
- title,
- description,
- difficulty,
- time
+ tokenId: String,
+ img: String,
+ title: String,
+ description: String,
+ difficulty: Number,
+ time: timestamp,
+ claimable: Boolean,
+ claimed: Boolean,
+ editable: Boolean,
+ has_claim: Boolean,
+ review: Boolean,
+}
+claimedInfo: {
+ hasNft: Boolean,
+ hasVc: Boolean,
+ info: {
+ nft_address,
+ badge_chain_id,
+ badge_token_id,
+ }
}
-hasNft: Boolean
-hasVc: Boolean
*/
-export default function ChallengeItem({
- info,
- hasNft,
- hasVc
-}) {
-
+export default function ChallengeItem({ info, claimedInfo }) {
+ const navigateTo = useNavigate();
+ const { t } = useTranslation(["profile", "explore"]);
+ const { ipfsPath, defaultImg, openseaLink, openseaSolanaLink } = constans();
+ let [itemInfo, setItemInfo] = useState();
+
+ function toQuest() {
+ if (itemInfo?.claimable || itemInfo?.claimed || itemInfo?.review) {
+ // 个人查看完成的挑战
+ navigateTo(`/claim/${info.uuid}`);
+ } else {
+ navigateTo(`/quests/${info.uuid}`);
+ }
+ }
+
+ function editChallenge(event) {
+ event.stopPropagation();
+ // 已有人claim,终止
+ if (itemInfo?.has_claim) {
+ message.warning(t("edit.error"));
+ return;
+ }
+ window.open(`/publish?${itemInfo.tokenId}`, "_blank");
+ }
+
+ function getTimeDiff(time) {
+ const { type, time: num } = convertTime(time, "all");
+ return t(`translation:${type}`, { time: Math.round(num) });
+ }
+
+ function init() {
+ const img =
+ info.metadata.image.indexOf("https://") !== -1
+ ? info.metadata.image
+ : info.metadata.image.split("//")[1]
+ ? `${ipfsPath}/${info.metadata.image.split("//")[1]}`
+ : info.metadata?.properties?.media.split("//")[1]
+ ? `${ipfsPath}/${
+ info.metadata?.properties?.media.split("//")[1]
+ }`
+ : defaultImg;
+ itemInfo = {
+ ...info,
+ difficulty: info.metadata?.attributes?.difficulty,
+ time: info.quest_data?.estimateTime
+ ? getTimeDiff(info.quest_data?.estimateTime)
+ : null,
+ review: info?.open_quest_review_status === 1,
+ img,
+ };
+ setItemInfo({ ...itemInfo });
+ }
+
+ useEffect(() => {
+ init();
+ }, []);
return (
-
-
-
-
+
+ {/* 挑战状态 */}
+
+ {/* 编辑挑战 */}
+ {itemInfo?.editable && (
+
+
-
-
+ )}
+ {/* 挑战Img */}
+
+ {/* 挑战详情 */}
-
- {info.title}
-
+
{itemInfo?.title}
- {info.description}
+ {itemInfo?.description}
-
- {
- info.metadata?.attributes?.difficulty !== null &&
- <>
+ {itemInfo?.difficulty !== null && (
+
{t("translation:diff")}
- {
- arr.map((e,i) => {
- if (i >= info.metadata?.attributes?.difficulty+1) {
- return
- }else{
- return
- }
- })
- }
+ {new Array(3).fill(0).map((e, i) => (
+
= itemInfo?.difficulty + 1
+ ? "line"
+ : "full"
+ }.png`)}
+ />
+ ))}
- >
- }
-
-
-
- {info?.time}
-
+
+ )}
+ {itemInfo?.time && (
+
+
+ {itemInfo?.time}
+
+ )}
- )
-}
\ No newline at end of file
+ );
+}
diff --git a/src/views/Explore/index.jsx b/src/views/Explore/index.jsx
index 5a2c0750..c01c7acb 100644
--- a/src/views/Explore/index.jsx
+++ b/src/views/Explore/index.jsx
@@ -4,11 +4,11 @@ import { useTranslation } from "react-i18next";
import { useInfiniteQuery } from "@tanstack/react-query";
import InfiniteScroll from "react-infinite-scroll-component";
import PageLoader from "@/components/Loader/PageLoader";
-import ChallengeItem from "@/components/User/ChallengeItem";
+import ChallengeItem from "@/components/ChallengeItem";
import ChallengeItems from "@/components/User/ChallengeItems";
import { getChallengeList } from "@/state/explore/challenge";
import "./style/index.scss";
-import "./mobile.scss";
+import "./style/mobile.scss";
export default function Explore(params) {
@@ -41,7 +41,7 @@ export default function Explore(params) {
.flat()
.map((item) =>
item.style === 1 ? (
-
+
) : (
Date: Tue, 30 Jan 2024 09:51:35 +0800
Subject: [PATCH 4/7] =?UTF-8?q?en:=20=E6=8C=91=E6=88=98=E5=88=97=E8=A1=A8?=
=?UTF-8?q?=E6=95=B0=E6=8D=AE=E7=BC=93=E5=AD=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../ChallengeItem/ChallengeItemImg.jsx | 22 +++-
.../ChallengeItem/ChallengeItems.jsx | 117 ++++++++++++++++++
src/components/ChallengeItem/index.jsx | 18 +--
src/components/User/ChallengeItem.js | 10 +-
src/state/explore/challenge.js | 28 ++++-
src/views/Explore/index.jsx | 22 +++-
6 files changed, 191 insertions(+), 26 deletions(-)
create mode 100644 src/components/ChallengeItem/ChallengeItems.jsx
diff --git a/src/components/ChallengeItem/ChallengeItemImg.jsx b/src/components/ChallengeItem/ChallengeItemImg.jsx
index 459d2216..572da0e1 100644
--- a/src/components/ChallengeItem/ChallengeItemImg.jsx
+++ b/src/components/ChallengeItem/ChallengeItemImg.jsx
@@ -3,13 +3,33 @@ import ChallengeItemIcons from "./ChallengeItemIcons";
-export default function ChallengeItemImg({img, claimedInfo}) {
+export default function ChallengeItemImg({img, claimedInfo, questNum}) {
return (
+ {/* 阴影文本: ERC-721展示 */}
+ {
+ claimedInfo?.info.version === "2" && !claimedInfo?.hasNft &&
+
+
{claimedInfo?.info.title}
+
+ }
+ {/* 挑战集合信息 */}
+ {
+ questNum &&
+
+
+
+
+
+
+
{questNum}
+
+
+ }
{
claimedInfo &&
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 (
+ goCollection(info.id)}>
+ {/* 挑战状态 */}
+
+
+
+
+
{info.title}
+
{info.description}
+
+
+ {info.author_info.avatar && (
+
+
+
+ )}
+
{info.author_info.nickname}
+
+
+
+ {info?.difficulty !== null && (
+ <>
+
{t("translation:diff")}
+
+ {new Array(3).fill(0).map((e, i) => (
+
= info?.difficulty + 1
+ ? "line"
+ : "full"
+ }.png`)}
+ />
+ ))}
+
+ >
+ )}
+
+
+ {info?.estimate_time !== null && (
+ <>
+
+ {timestamp}
+ >
+ )}
+
+
+
+
+ );
+}
diff --git a/src/components/ChallengeItem/index.jsx b/src/components/ChallengeItem/index.jsx
index 1cf8b890..62fa0bc9 100644
--- a/src/components/ChallengeItem/index.jsx
+++ b/src/components/ChallengeItem/index.jsx
@@ -1,13 +1,11 @@
+import { useEffect, useState } from "react";
+import { useNavigate } from "react-router-dom";
import { useTranslation } from "react-i18next";
-import { ClockCircleFilled, EditOutlined } from "@ant-design/icons";
-import { LazyLoadImage } from "react-lazy-load-image-component";
-import ChallengeItemIcons from "./ChallengeItemIcons";
-import ChallengeItemStatus from "./ChallengeItemStatus";
import { message } from "antd";
-import { useEffect, useState } from "react";
-import { convertTime } from "@/utils/convert";
+import { ClockCircleFilled, EditOutlined } from "@ant-design/icons";
import { constans } from "@/utils/constans";
-import { useNavigate } from "react-router-dom";
+import { convertTime } from "@/utils/convert";
+import ChallengeItemStatus from "./ChallengeItemStatus";
import ChallengeItemImg from "./ChallengeItemImg";
/*
@@ -29,6 +27,8 @@ claimedInfo: {
hasNft: Boolean,
hasVc: Boolean,
info: {
+ version,
+ title,
nft_address,
badge_chain_id,
badge_token_id,
@@ -66,7 +66,7 @@ export default function ChallengeItem({ info, claimedInfo }) {
return t(`translation:${type}`, { time: Math.round(num) });
}
- function init() {
+ function initInfo() {
const img =
info.metadata.image.indexOf("https://") !== -1
? info.metadata.image
@@ -91,7 +91,7 @@ export default function ChallengeItem({ info, claimedInfo }) {
}
useEffect(() => {
- init();
+ initInfo();
}, []);
return (
diff --git a/src/components/User/ChallengeItem.js b/src/components/User/ChallengeItem.js
index a72198c2..8afbabd9 100644
--- a/src/components/User/ChallengeItem.js
+++ b/src/components/User/ChallengeItem.js
@@ -20,7 +20,6 @@ export default function ChallengeItem(props) {
const navigateTo = useNavigate();
const [messageApi, contextHolder] = message.useMessage();
const { ipfsPath, defaultImg, openseaLink, openseaSolanaLink } = constans(profile?.checkType);
- const arr = [0, 1, 2];
const toQuest = () => {
@@ -95,12 +94,7 @@ export default function ChallengeItem(props) {
function getTimeDiff(time) {
const { type, time: num } = convertTime(time, "all")
-
- return (
- <>
- {t(`translation:${type}`, {time: Math.round(num)})}
- >
- )
+ return t(`translation:${type}`, {time: Math.round(num)})
}
return (
@@ -221,7 +215,7 @@ export default function ChallengeItem(props) {
{t("translation:diff")}
{
- arr.map((e,i) => {
+ new Array(3).map((e,i) => {
if (i >= info.metadata?.attributes?.difficulty+1) {
return
}else{
diff --git a/src/state/explore/challenge.js b/src/state/explore/challenge.js
index 5598b796..7ab65a61 100644
--- a/src/state/explore/challenge.js
+++ b/src/state/explore/challenge.js
@@ -1,9 +1,31 @@
-import { getQuests } from "@/request/api/public";
+import { getQuests, hasClaimed } from "@/request/api/public";
+import { getCollectionQuest } from "@/request/api/quests";
export const getChallengeList = async (pageParam) => {
try {
- const res = await getQuests({pageSize: 10, page: pageParam});
- return res.data?.list || []
+ const res = await getQuests({ pageSize: 10, page: pageParam });
+ return res.data?.list || [];
+ } catch (error) {
+ console.log(error);
+ return null;
+ }
+};
+
+export const getCollection = async (pageParam) => {
+ try {
+ const res = await getCollectionQuest({ id: pageParam });
+ const tokenId = res.data.collection.tokenId;
+ let status = false;
+ if (tokenId && tokenId !== "0") {
+ await hasClaimed({ id: tokenId }).then((res) => {
+ status = res.data?.status === 2;
+ });
+ }
+ return {
+ list: res.data.list || [],
+ collection: res.data.collection,
+ status,
+ };
} catch (error) {
console.log(error);
return null;
diff --git a/src/views/Explore/index.jsx b/src/views/Explore/index.jsx
index c01c7acb..902f8323 100644
--- a/src/views/Explore/index.jsx
+++ b/src/views/Explore/index.jsx
@@ -5,7 +5,7 @@ import { useInfiniteQuery } from "@tanstack/react-query";
import InfiniteScroll from "react-infinite-scroll-component";
import PageLoader from "@/components/Loader/PageLoader";
import ChallengeItem from "@/components/ChallengeItem";
-import ChallengeItems from "@/components/User/ChallengeItems";
+import ChallengeItems from "@/components/ChallengeItem/ChallengeItems";
import { getChallengeList } from "@/state/explore/challenge";
import "./style/index.scss";
import "./style/mobile.scss";
@@ -41,14 +41,26 @@ export default function Explore(params) {
.flat()
.map((item) =>
item.style === 1 ? (
-
+
) : (
- navigateTo(`/collection/${id}`)
- }
+ goCollection={(id) => navigateTo(`/collection/${id}`)}
/>
)
)
From dfbe3cd49b3ed9056dc699ffdc70e90f98522642 Mon Sep 17 00:00:00 2001
From: Caoqizhi <2391580279@qq.com>
Date: Sun, 18 Feb 2024 15:32:12 +0800
Subject: [PATCH 5/7] en: update style
---
.../mobile/component-style/user/challengeItem.scss | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/src/assets/styles/mobile/component-style/user/challengeItem.scss b/src/assets/styles/mobile/component-style/user/challengeItem.scss
index b36aaf2f..db43202c 100644
--- a/src/assets/styles/mobile/component-style/user/challengeItem.scss
+++ b/src/assets/styles/mobile/component-style/user/challengeItem.scss
@@ -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;
From 8426b4b32663bcd86123c7c96c78ec1b99950d17 Mon Sep 17 00:00:00 2001
From: Caoqizhi <2391580279@qq.com>
Date: Thu, 22 Feb 2024 10:02:06 +0800
Subject: [PATCH 6/7] en: update router config
---
src/router/index.js | 9 ++-
src/views/Explore.js | 129 -------------------------------------------
2 files changed, 4 insertions(+), 134 deletions(-)
delete mode 100644 src/views/Explore.js
diff --git a/src/router/index.js b/src/router/index.js
index ab236bf1..84fea61a 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -1,7 +1,6 @@
import Index from "@/views/Index"
-import Explore from "@/views/Explore"
-import ExploreNew from "@/views/Explore/index"
-import NewPublish from "@/views/Publish/index"
+import Explore from "@/views/Explore/index"
+import Publish from "@/views/Publish/index"
import Question from "@/views/Question/index";
import Challenge from "@/views/Challenge/index";
import Claim from "@/views/Claim/index";
@@ -22,7 +21,7 @@ const routes = [
},
{
path: "/challenges",
- element: ,
+ element: ,
},
{
path: "/collection/:id",
@@ -30,7 +29,7 @@ const routes = [
},
{
path: "/publish",
- element: ,
+ element: ,
},
{
path: "/quests/:questId",
diff --git a/src/views/Explore.js b/src/views/Explore.js
deleted file mode 100644
index 61a1da73..00000000
--- a/src/views/Explore.js
+++ /dev/null
@@ -1,129 +0,0 @@
-import { useEffect, useState } from "react"
-import { getQuests } from "../request/api/public"
-import "@/assets/styles/view-style/explore.scss"
-import "@/assets/styles/mobile/view-style/explore.scss"
-import { useTranslation } from "react-i18next";
-import store from "@/redux/store";
-import ChallengeItem from "@/components/User/ChallengeItem";
-import ChallengeItems from "@/components/User/ChallengeItems";
-import { useLocation, useNavigate, useParams } from "react-router-dom";
-import { getCollectionQuest } from "@/request/api/quests";
-import {
- ArrowLeftOutlined,
- } from '@ant-design/icons';
-import InfiniteScroll from "react-infinite-scroll-component";
-import { Spin } from "antd";
-
-export default function Explore(params) {
-
- const { t } = useTranslation(["explore", "translation"]);
- const { id } = useParams();
- const location = useLocation();
- const navigateTo = useNavigate();
-
- let [page, setPage] = useState(0);
-
- let [isOver, setIsOver] = useState();
- let [challenges, setChallenges] = useState([]);
- let [isMobile, setIsMobile] = useState(store.getState().isMobile);
- let [loading, setLoading] = useState(false);
-
- function handleMobileChange() {
- isMobile = store.getState().isMobile;
- setIsMobile(isMobile);
- }
-
- store.subscribe(handleMobileChange);
-
- const goCollection = (id) => {
- navigateTo(`/collection/${id}`)
- }
-
- const getChallenge = async() => {
- if (loading) {
- return
- }
- setLoading(true);
- const cache = localStorage.getItem("decert.cache");
-
- page += 1;
- setPage(page);
- let res
- if (id) {
- res = await getCollectionQuest({id: Number(id)});
- }else{
- res = await getQuests({pageSize: 10, page: page});
- }
- challenges = challenges.concat(res.data.list);
- if (challenges.length === res.data.total || id) {
- setIsOver(true);
- }
- if (cache) {
- const claimable = JSON.parse(cache)?.claimable;
- if (claimable && claimable.length > 0) {
- challenges.map(e => {
- claimable.map((ele,index) => {
- if (e.uuid == ele.uuid && e.claimed) {
- const newCache = JSON.parse(cache);
- newCache.claimable.splice(index,1);
- localStorage.setItem("decert.cache", JSON.stringify(newCache));
- }else if (e.uuid == ele.uuid) {
- e.claimable = true;
- }
- })
- })
- }
- }
- setChallenges([...challenges]);
- setLoading(false);
- }
-
- useEffect(() => {
- challenges = [];
- setChallenges([...challenges]);
- page = 0;
- setPage(page);
- isOver = false;
- setIsOver(isOver);
- getChallenge()
- },[location])
-
- return (
-
-
- {
- id &&
-
navigateTo("/challenges")}>
-
-
返回
-
- }
- {/* title */}
-
{t("title")}
- {/* Challenge */}
-
}
- >
- {
- challenges.map(item => (
- item.style === 1 ?
-
- :
-
- ))
- }
-
-
- )
-}
\ No newline at end of file
From 17ddb44f37a70d9212751843204c276a5cca945c Mon Sep 17 00:00:00 2001
From: Caoqizhi <2391580279@qq.com>
Date: Thu, 22 Feb 2024 10:03:13 +0800
Subject: [PATCH 7/7] del: test code
---
src/views/Explore/components/ChallengeList.jsx | 9 ---------
1 file changed, 9 deletions(-)
delete mode 100644 src/views/Explore/components/ChallengeList.jsx
diff --git a/src/views/Explore/components/ChallengeList.jsx b/src/views/Explore/components/ChallengeList.jsx
deleted file mode 100644
index d724fe63..00000000
--- a/src/views/Explore/components/ChallengeList.jsx
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-export default function ChallengeList(params) {
-
-
-
-
-}
\ No newline at end of file