diff --git a/src/components/pages/campaigns/questItem/freeQuest.tsx b/src/components/pages/campaigns/questItem/freeQuest.tsx index 034e4b69..3d69546a 100644 --- a/src/components/pages/campaigns/questItem/freeQuest.tsx +++ b/src/components/pages/campaigns/questItem/freeQuest.tsx @@ -1,48 +1,27 @@ import Button from 'components/core/Button/Button' import moment from 'moment' import { useRouter } from 'next/router' -import { useContext, useState } from 'react' import Countdown, { zeroPad } from 'react-countdown' import { useTranslation } from 'react-i18next' -import { toast } from 'react-toastify' -import { Context } from 'src/context' import { Quest } from 'src/models/campaign' -import { checkQuestStatus } from 'src/services' -import { mutate } from 'swr' export default function FreeQuest({ quest, loading, claimQuestHandler, + checkQuestHandler, + checking, + status }: { quest: Quest loading: boolean + checking: boolean + status: any + checkQuestHandler: () => void claimQuestHandler: () => void }) { const { t } = useTranslation() - const { locale, query } = useRouter() - const [status, setStatus] = useState(quest.reward_status) - const [checking, setChecking] = useState(false) - const { account } = useContext(Context) - const slug = query.campaignSlug as string - const checkQuestHandler = async () => { - try { - if (checking) return - setChecking(true) - const res = await checkQuestStatus(quest.id) - if (res.data) { - setStatus(res.data.reward_status) - mutate({ key: 'fetch_campaign_auth_data', slug, account: account?.id }) - } - setChecking(false) - console.log(res) - } catch (error) { - setChecking(false) - toast(error?.message || 'Claim failed. Please try again later.', { - type: 'error', - }) - console.error(error) - } - } + const { locale} = useRouter() + return (
{status == 'CAN_CLAIM' ? ( diff --git a/src/components/pages/campaigns/questItem/index.tsx b/src/components/pages/campaigns/questItem/index.tsx index 1c1d7fef..09cdae7d 100644 --- a/src/components/pages/campaigns/questItem/index.tsx +++ b/src/components/pages/campaigns/questItem/index.tsx @@ -7,7 +7,7 @@ import NoImage from 'images/no_img.png' import moment from 'moment' import Image from 'next/image' import { useRouter } from 'next/router' -import { useCallback, useContext, useEffect, useState } from 'react' +import { useContext, useEffect, useState } from 'react' import Countdown, { zeroPad } from 'react-countdown' import { useTranslation } from 'react-i18next' import { toast } from 'react-toastify' @@ -17,7 +17,6 @@ import { claimQuest, getRequestLog } from 'src/services' import Decor from '../assets/decor.svg' import ClamQuestSuccessModal from './claimQuestSuccessModal' import QuestDetailModal from './questDetailModal' -import { useGoogleReCaptcha } from 'react-google-recaptcha-v3' export default function QuestItem({ quest, refreshCallback }: { quest: Quest; refreshCallback?: () => void }) { const { getProfile } = useContext(Context) const [open, setOpen] = useState(false) @@ -26,7 +25,6 @@ export default function QuestItem({ quest, refreshCallback }: { quest: Quest; re const [loading, setLoading] = useState(false) const { t } = useTranslation() const { locale } = useRouter() - const { executeRecaptcha } = useGoogleReCaptcha() const revealResult = async (id: string) => { const data = await getRequestLog(id) if (data?.status == 'SUCCEEDED') { @@ -53,22 +51,11 @@ export default function QuestItem({ quest, refreshCallback }: { quest: Quest; re setTimeout(() => revealResult(id), 4000) } - const claimQuestHandler = useCallback(async () => { + const claimQuestHandler = async () => { try { - if (!executeRecaptcha) { - console.log('Execute recaptcha not yet available') - return - } - const token = await executeRecaptcha('claim-quest') - if (!token) { - toast('Recapcat failed.', { - type: 'error', - }) - return - } if (loading) return setLoading(true) - const res = await claimQuest(quest.id, token) + const res = await claimQuest(quest.id) if (res?.requestId) { revealResult(res?.requestId) } else { @@ -85,7 +72,7 @@ export default function QuestItem({ quest, refreshCallback }: { quest: Quest; re } catch (error) { console.error(error) } - }, [executeRecaptcha]) + } useEffect(() => { if (open) setSeeMore(undefined) diff --git a/src/components/pages/campaigns/questItem/mintQuest.tsx b/src/components/pages/campaigns/questItem/mintQuest.tsx index 9e34d06e..d58e0710 100644 --- a/src/components/pages/campaigns/questItem/mintQuest.tsx +++ b/src/components/pages/campaigns/questItem/mintQuest.tsx @@ -1,6 +1,5 @@ import Button from 'components/core/Button/Button' import moment from 'moment' -import getConfig from 'next/config' import { useRouter } from 'next/router' import { useContext, useState } from 'react' @@ -10,10 +9,9 @@ import { toast } from 'react-toastify' import { Context } from 'src/context' import { ModalContext } from 'src/context/modals' import { Quest } from 'src/models/campaign' -import { checkQuestStatus, getMintNftSignature } from 'src/services' +import { getMintNftSignature } from 'src/services' import { storyBadgeAbi } from 'src/services/abi/storyBadgeAbi' import { storyChain } from 'src/services/wagmi/config' -import { mutate } from 'swr' import { useAccount, useChainId, useSwitchChain, useWriteContract } from 'wagmi' export default function MintQuest({ quest, @@ -21,45 +19,29 @@ export default function MintQuest({ claimQuestHandler, setOpen, setHash, + checkQuestHandler, + checking, + status, }: { quest: Quest loading: boolean claimQuestHandler: () => void setOpen: (v: boolean) => void setHash: (v: string) => void + checking: boolean + status: any + checkQuestHandler: () => void }) { const { t } = useTranslation() - const { locale, query } = useRouter() + const { locale } = useRouter() const { account } = useContext(Context) const { setMigrateWalletOpen, setWalletConnectOpen } = useContext(ModalContext) - const config = getConfig() - const [status, setStatus] = useState(quest.reward_status) - const [checking, setChecking] = useState(false) const [minting, setMinting] = useState(false) const chainId = useChainId() const { writeContractAsync } = useWriteContract() const { switchChainAsync } = useSwitchChain() const { isConnected } = useAccount() - const slug = query.campaignSlug as string - const checkQuestHandler = async () => { - try { - if (checking) return - setChecking(true) - const res = await checkQuestStatus(quest.id) - if (res.data) { - setStatus(res.data.reward_status) - mutate({ key: 'fetch_campaign_auth_data', slug, account: account?.id }) - } - setChecking(false) - console.log(res) - } catch (error) { - setChecking(false) - toast(error?.message || 'Claim failed. Please try again later.', { - type: 'error', - }) - console.error(error) - } - } + const mintHandler = async () => { try { if (minting) return diff --git a/src/components/pages/campaigns/questItem/questDetailModal.tsx b/src/components/pages/campaigns/questItem/questDetailModal.tsx index dc0e4912..515d36d4 100644 --- a/src/components/pages/campaigns/questItem/questDetailModal.tsx +++ b/src/components/pages/campaigns/questItem/questDetailModal.tsx @@ -6,7 +6,7 @@ import SFImage from 'components/pages/campaigns/assets/sf.png' import NoImage from 'images/no_img.png' import Image from 'next/image' import { useRouter } from 'next/router' -import { useState } from 'react' +import { useCallback, useContext, useState } from 'react' import ReactHtmlParser from 'react-html-parser' import { useTranslation } from 'react-i18next' import { Quest } from 'src/models/campaign' @@ -15,6 +15,11 @@ import MintBadgeSuccessModal from './mintBadgeSuccessModal' import MintQuest from './mintQuest' import QuizQuest from './quizQuest' import RefQuest from './refQuest' +import { useGoogleReCaptcha } from 'react-google-recaptcha-v3' +import { toast } from 'react-toastify' +import { checkQuestStatus } from 'src/services' +import { mutate } from 'swr' +import { Context } from 'src/context' export default function QuestDetailModal({ quest, open, @@ -30,10 +35,44 @@ export default function QuestDetailModal({ }) { const [openNFTPreview, setOpenNFTPreview] = useState(false) const { t } = useTranslation() - const { locale } = useRouter() + const { account } = useContext(Context) const [hash, setHash] = useState('') const xpImageSrc = quest.pointText == 'KP' ? KPImage : quest.pointText == 'SF' ? SFImage : XPImage const xpText = quest.pointText + const { executeRecaptcha } = useGoogleReCaptcha() + const [status, setStatus] = useState(quest.status) + const [checking, setChecking] = useState(false) + const { query, locale } = useRouter() + const slug = query.campaignSlug as string + const checkQuestHandler = useCallback(async () => { + try { + if (!executeRecaptcha) { + console.log('Execute recaptcha not yet available') + return + } + const token = await executeRecaptcha('check-status') + if (!token) { + toast('Verify failed by reCAPCHA. Please reload and try again!', { + type: 'error', + }) + return + } + if (checking) return + setChecking(true) + const res = await checkQuestStatus(quest.id, token) + if (res.data) { + setStatus(res.data.reward_status) + mutate({ key: 'fetch_campaign_auth_data', slug, account: account?.id }) + } + setChecking(false) + } catch (error) { + setChecking(false) + toast(error?.message || 'Claim failed. Please try again later.', { + type: 'error', + }) + console.error(error) + } + }, [executeRecaptcha]) return ( <> @@ -167,8 +206,27 @@ export default function QuestDetailModal({ 'LikeEventArtwork', 'CollectIP', 'StakeIP', - ].includes(quest.type) && } - {quest.type == 'Empty' && } + ].includes(quest.type) && ( + + )} + {quest.type == 'Empty' && ( + + )} {quest.type == 'MintBadge' && ( )} {quest.type == 'Quiz' && ( diff --git a/src/components/pages/campaigns/questItem/refQuest.tsx b/src/components/pages/campaigns/questItem/refQuest.tsx index e087f5c9..188994e5 100644 --- a/src/components/pages/campaigns/questItem/refQuest.tsx +++ b/src/components/pages/campaigns/questItem/refQuest.tsx @@ -6,51 +6,35 @@ import { useRouter } from 'next/router' import { useContext, useState } from 'react' import Countdown, { zeroPad } from 'react-countdown' import { useTranslation } from 'react-i18next' -import { toast } from 'react-toastify' import { Context } from 'src/context' import { ModalContext } from 'src/context/modals' import { Quest } from 'src/models/campaign' -import { checkQuestStatus } from 'src/services' -import { mutate } from 'swr' import { useAccount } from 'wagmi' export default function BasicQuest({ quest, loading, claimQuestHandler, setOpen, + checkQuestHandler, + checking, + status, }: { quest: Quest loading: boolean claimQuestHandler: () => void setOpen: (v: boolean) => void + + checking: boolean + status: any + checkQuestHandler: () => void }) { const { t } = useTranslation() - const { locale, query } = useRouter() + const { locale } = useRouter() const { account } = useContext(Context) const { setMigrateWalletOpen, setWalletConnectOpen } = useContext(ModalContext) const config = getConfig() - const [status, setStatus] = useState(quest.reward_status) - const [checking, setChecking] = useState(false) const { isConnected } = useAccount() - const slug = query.campaignSlug as string - const checkQuestHandler = async () => { - try { - if (checking) return - setChecking(true) - const res = await checkQuestStatus(quest.id) - if (res.data) { - setStatus(res.data.reward_status) - mutate({ key: 'fetch_campaign_auth_data', slug, account: account?.id }) - } - setChecking(false) - } catch (error) { - setChecking(false) - toast(error?.message || 'Claim failed. Please try again later.', { - type: 'error', - }) - console.error(error) - } - } + const RefButton = () => { switch (quest.type) { case 'EngagesEventManga': diff --git a/src/services/index.ts b/src/services/index.ts index 2bd586dc..76a843e3 100644 --- a/src/services/index.ts +++ b/src/services/index.ts @@ -355,10 +355,8 @@ export const getQuestDetail = async (questId: string, accountId?: string) => { }) return data } -export const claimQuest = async (questId: string, token: string) => { - const { data } = await privateAxios.post(`${getConfig().REST_API_URL}/quest/${questId}/claim`, { - token - }) +export const claimQuest = async (questId: string) => { + const { data } = await privateAxios.post(`${getConfig().REST_API_URL}/quest/${questId}/claim`) return data } export const readChapter = async (chapterId: string) => { @@ -783,9 +781,11 @@ export const updateProfile = async (data) => { throw error // Re-throw the error so it can be caught in the component } } -export const checkQuestStatus = async (id: string) => { +export const checkQuestStatus = async (id: string, token: string) => { try { - return await privateAxios.post(`${getConfig().REST_API_URL}/quest/${id}/check-status`) + return await privateAxios.post(`${getConfig().REST_API_URL}/quest/${id}/check-status`, { + token, + }) } catch (error) { throw error }