diff --git a/src/pages/reputation-score/index.tsx b/src/pages/reputation-score/index.tsx index 847212c6..a7473d10 100644 --- a/src/pages/reputation-score/index.tsx +++ b/src/pages/reputation-score/index.tsx @@ -7,6 +7,7 @@ import { useAccount, useReadContract } from 'wagmi'; import { engagementContracts } from '@/lib/contracts/engagement/contracts'; +import SimpleBackdrop from '@/components/global/LoadingBackdrop'; import SEO from '@/components/global/SEO'; import TcBoxContainer from '@/components/shared/TcBox/TcBoxContainer'; @@ -25,13 +26,17 @@ function ReputationScore() { (contract) => contract.chainId === chainId ); - const { data: hasMinted } = useReadContract({ + const { data: hasMinted, isLoading } = useReadContract({ address: engagementContract?.address as `0x${string}`, abi: engagementContract?.abi as Abi, functionName: 'balanceOf', args: [address, dynamicNFTModuleInfo?.metadata[0]?.tokenId], }); + if(isConnected && isLoading) { + return + } + return ( <> @@ -86,7 +91,7 @@ function ReputationScore() { color='primary' onClick={() => router.push( - `/reputation-score/${dynamicNFTModuleInfo?.metadata[0]?.tokenId}/${address}/score` + `/reputation-score/score?tokenId=${dynamicNFTModuleInfo?.metadata[0]?.tokenId}&address=${address}` ) } disabled={!isConnected} diff --git a/src/pages/reputation-score/[...score].tsx b/src/pages/reputation-score/score.tsx similarity index 73% rename from src/pages/reputation-score/[...score].tsx rename to src/pages/reputation-score/score.tsx index 27f8b945..71e8904f 100644 --- a/src/pages/reputation-score/[...score].tsx +++ b/src/pages/reputation-score/score.tsx @@ -1,5 +1,6 @@ +'use client'; + import React, { useEffect, useState } from 'react'; -import { useRouter } from 'next/router'; import { FiShare2 } from 'react-icons/fi'; import GaugeChart from '@/components/global/GaugeChart'; @@ -15,50 +16,42 @@ import { withRoles } from '@/utils/withRoles'; const ScorePage = () => { const { showMessage } = useSnackbar(); const { retrieveReputationScore } = useAppStore(); - const router = useRouter(); const [communityName, setCommunityName] = useState(null); const [reputationScore, setReputationScore] = useState(null); const [loading, setLoading] = useState(true); - const [tokenId, setTokenId] = useState(null); - const [address, setAddress] = useState(null); + const [error, setError] = useState(null); useEffect(() => { - const parseUrl = () => { - const pathSegments = router.asPath.split('/'); - const tokenIndex = pathSegments.indexOf('reputation-score') + 1; - - if (tokenIndex > 0 && tokenIndex + 1 < pathSegments.length) { - setTokenId(pathSegments[tokenIndex]); - setAddress(pathSegments[tokenIndex + 1]); + const fetchReputationScore = async (tokenId: string, address: string) => { + setLoading(true); + setError(null); + + try { + const score = await retrieveReputationScore({ tokenId, address }); + + setReputationScore(score.reputationScore ?? 0); + setCommunityName(score.communityName); + } catch (err) { + console.error('Error fetching reputation score:', err); + setError('Failed to fetch reputation score.'); + } finally { + setLoading(false); } }; - parseUrl(); - }, [router.asPath]); + const params = new URLSearchParams(window.location.search); + const tokenId = params.get('tokenId'); + const address = params.get('address'); - useEffect(() => { - if (tokenId && address) { - const fetchReputationScore = async () => { - setLoading(true); - try { - const score = await retrieveReputationScore({ - tokenId, - address, - }); - - setReputationScore(score.reputationScore ?? 0); - setCommunityName(score.communityName); - } catch (error) { - console.error('Error fetching reputation score:', error); - } finally { - setLoading(false); - } - }; - - fetchReputationScore(); + if (!tokenId || !address) { + setError('Invalid URL format. Missing tokenId or address.'); + setLoading(false); + return; } - }, [tokenId, address]); + + fetchReputationScore(tokenId, address); + }, [retrieveReputationScore]); const gaugeOptions = { chart: { @@ -102,7 +95,7 @@ const ScorePage = () => { series: [ { name: 'Score', - data: [reputationScore ?? 0], + data: [reputationScore ? parseFloat(reputationScore.toFixed(1)) : 0], tooltip: { valueSuffix: ' /100', }, @@ -126,6 +119,17 @@ const ScorePage = () => { return ; } + if (error) { + return ( +
+
+

Error

+

{error}

+
+
+ ); + } + return ( <> @@ -173,4 +177,4 @@ const ScorePage = () => { ); }; -export default withRoles(ScorePage, []); +export default ScorePage; diff --git a/src/utils/withRoles.tsx b/src/utils/withRoles.tsx index 84c1b6e8..87eb12d3 100644 --- a/src/utils/withRoles.tsx +++ b/src/utils/withRoles.tsx @@ -1,3 +1,5 @@ +'use client'; + import React, { ComponentType, FunctionComponent, @@ -6,6 +8,8 @@ import React, { } from 'react'; import { useRouter } from 'next/router'; +import SimpleBackdrop from '@/components/global/LoadingBackdrop'; + import useAppStore from '../store/useStore'; interface WithRolesProps { @@ -21,7 +25,7 @@ interface ComponentWithLayout

extends FunctionComponent

{ export function withRoles

( Component: ComponentWithLayout

, - requiredPermissions: string[] + requiredPermissions: string[] = [] ): ComponentWithLayout

{ const WithRolesWrapper: ComponentWithLayout

= (props) => { const userPermissions = useAppStore( @@ -31,6 +35,11 @@ export function withRoles

( const router = useRouter(); useEffect(() => { + if (requiredPermissions.length === 0) { + setIsPermissionLoaded(true); + return; + } + const hasPermission = requiredPermissions.some((permission) => userPermissions.includes(permission) );