diff --git a/src/app/context/web3.tsx b/src/app/context/web3.tsx index 9a355d2c..8f2fb945 100644 --- a/src/app/context/web3.tsx +++ b/src/app/context/web3.tsx @@ -3,7 +3,7 @@ import { Contract, ethers } from "ethers"; import abi from './abi'; import abiNFT from './abiNFT' import chains from './config'; -import { CreateBountyFunction,withdrawFromOpenBountyFunction ,SubmitClaimForVoteFunction, GetParticipants, CreateClaimFunction, AcceptClaimFunction, CancelBountyFunction, FetchBountiesFunction, FetchBountyByIdFunction, GetBountiesByUserFunction, Bounty , GetClaimsByUserFunction, GetClaimsByBountyIdFunction, GetURIFunction, Claim, GetAllBountiesFunction, JoinOpenBountyFunction, BountyCurrentVotingClaimFunction, BountyVotingTrackerFunction, VoteClaimFunction, ResolveVoteFunction } from '../../types/web3'; +import { CreateBountyFunction,withdrawFromOpenBountyFunction ,SubmitClaimForVoteFunction, GetParticipants, CreateClaimFunction, AcceptClaimFunction, CancelBountyFunction, FetchBountiesFunction, FetchBountyByIdFunction, GetBountiesByUserFunction, Bounty , GetClaimsByUserFunction, GetClaimsByBountyIdFunction, GetURIFunction, Claim, GetAllBountiesFunction, JoinOpenBountyFunction, BountyCurrentVotingClaimFunction, BountyVotingTrackerFunction, VoteClaimFunction, ResolveVoteFunction, GetClaimByIdFunction } from '../../types/web3'; const currentChain = chains.sepolia; @@ -33,6 +33,35 @@ export const getNFTContractRead = async () => { }; +export const getNftsOfOwner = async () => { + const contract = getNFTContractRead() + + // console.log(contract) + // console.log(balance) + return contract +} + +// async function getNFTsOfOwner() { +// const contract = new ethers.Contract(contractAddress, erc721ABI, provider); +// const balance = await contract.balanceOf(ownerAddress); //Returns the number of tokens owned by the address + +// let tokenIds = []; + +// for(let i = 0; i < balance.toNumber(); i++) { +// const tokenId = await contract.tokenOfOwnerByIndex(ownerAddress, i); //Get the token ID based on the index from the balanceOf call +// tokenIds.push(tokenId.toString()); +// } + +// console.log(`Token IDs owned by ${ownerAddress}: ${tokenIds}`); +// } + + + + + + + + // WRITE Functions @@ -119,7 +148,6 @@ export const submitClaimForVote: SubmitClaimForVoteFunction = async ( } }; - export const cancelOpenBounty: CancelBountyFunction = async ( primaryWallet, id ) => { @@ -283,10 +311,13 @@ export const getBountiesByUser: GetBountiesByUserFunction = async ( export const fetchAllBounties: GetAllBountiesFunction = async () => { + const contractRead = await getContractRead(); const bountyCounter = await contractRead.bountyCounter(); let allBounties: Bounty[] = []; + + const totalBounties = Number(bountyCounter.toString()); for (let offset = Math.floor(totalBounties / 10) * 10; offset >= 0; offset -= 10) { @@ -308,7 +339,6 @@ export const fetchAllBounties: GetAllBountiesFunction = async () => { allBounties.sort((a, b) => Number(b.createdAt) - Number(a.createdAt)); - console.log(allBounties) return allBounties; }; @@ -405,6 +435,45 @@ export const getClaimsByBountyId: GetClaimsByBountyIdFunction = async (id) => { return formattedClaims; }; + +export const getClaimById: GetClaimByIdFunction = async (claimId) => { + const contractRead = await getContractRead(); + const claimById = await contractRead.claims(claimId); + + const formattedClaim: Claim[] = [{ + id: claimById[0].toString(), + issuer: claimById[1], + bountyId: claimById[2].toString(), + bountyIssuer: claimById[3], + name: claimById[4], + description: claimById[5], + createdAt: claimById[6].toString(), + accepted: claimById[7] + }]; + + return formattedClaim; +}; + + + + + +// export const getClaimById: GetClaimByIdFunction = async (claimId) => { +// const contractRead = await getContractRead(); +// const claimById = await contractRead.claims(claimId); + +// const names = claimById['#names']; +// const data = claimById.filter((_, index) => index !== '#names'); + +// const formattedClaim = {}; +// names.forEach((name, index) => { +// formattedClaim[name] = data[index]; +// }); + +// return formattedClaim; +// }; + + export const getURI: GetURIFunction = async (claimId) => { const contractNFT = await getNFTContractRead(); const uri = await contractNFT.tokenURI(claimId); diff --git a/src/components/account/AccountInfo.tsx b/src/components/account/AccountInfo.tsx index a8fe61c4..65f656e7 100644 --- a/src/components/account/AccountInfo.tsx +++ b/src/components/account/AccountInfo.tsx @@ -4,10 +4,13 @@ import { ethers } from "ethers"; import { useDynamicContext, } from '@dynamic-labs/sdk-react-core' -import { getSigner, getContract, getBountiesByUser, getProvider, getClaimsByUser } from '@/app/context/web3'; +import { getSigner, getContract, getBountiesByUser, getProvider, getClaimsByUser, getNftsOfOwner , getClaimById, getURI} from '@/app/context/web3'; import Button from '@/components/ui/Button'; import BountyList from '@/components/ui/BountyList'; import { BountiesData, ClaimsData } from '@/types/web3'; +import FilterButton from '@/components/ui/FilterButton'; +import ProofList from '@/components/bounty/ProofList'; +import ProofListAccount from '@/components/bounty/ProofListAccount'; @@ -19,10 +22,13 @@ const AccountInfo = () => { const [bountiesData, setBountiesData] = useState([]); const [claimsData, setClaimsData] = useState([]); - const [completedBounties, setCompletedBounties] = useState(""); + const [completedBounties, setCompletedBounties] = useState([]); const [inProgressBounties, setInProgressBounties] = useState(""); const [ETHinContract, setETHinContract] = useState(""); const [completedClaims, setCompletedClaims] = useState(""); + const [submitedClaims, setSubmitedClaims] = useState([]); + const [currentSection, setCurrentSection] = useState('a'); + @@ -41,23 +47,48 @@ const AccountInfo = () => { const contractBalance = await provider.getBalance(contract.getAddress()) const balanceETH = ethers.formatEther(contractBalance) setETHinContract(balanceETH) + + + // console.log("getting nft...") + + // const getNfts = await getNftsOfOwner() + + // console.log(getNfts) + + // const balance = await getNfts.balanceOf(primaryWallet?.address); + + + // const tid = await getNfts.tokenOfOwnerByIndex(primaryWallet?.address, 0) + + // console.log(tid) + + // console.log("got nft...") getBountiesByUser(address, 0, []) .then((data: any) => { setBountiesData(data) - const completedBounties = data.filter((bounty:any) => bounty.claimer !== '0x0000000000000000000000000000000000000000' && bounty.claimer.toLowerCase() !== address.toLowerCase()).length; - const inProgressBounties = data.filter((bounty:any) => bounty.claimer === '0x0000000000000000000000000000000000000000').length; + const completedBounties = data.filter((bounty:any) => bounty.claimer !== '0x0000000000000000000000000000000000000000' && bounty.claimer.toLowerCase() !== address.toLowerCase()); + const inProgressBounties = data.filter((bounty:any) => bounty.claimer === '0x0000000000000000000000000000000000000000'); setInProgressBounties(inProgressBounties); setCompletedBounties(completedBounties); + + }) + + + + getClaimsByUser(address) .then((data: any) => { setClaimsData(data); - const completedClaims = data.filter((claim: any) => claim.accepted !== true).length; + const completedClaims = data.filter((claim: any) => claim.accepted === true); + const submitedClaims = data.filter((claim: any) => claim.accepted === false); + setCompletedClaims(completedClaims); - console.log(claimsData); + setSubmitedClaims(submitedClaims); + }); @@ -68,6 +99,29 @@ const AccountInfo = () => { userInformation().catch(console.error); } }, [primaryWallet]); + + useEffect(() => { + const fetchClaimInformation = async () => { + const claimIds = completedBounties.map(bounty => bounty.claimId); + const claimInformationPromises = claimIds.map(async (claimId) => { + const uri = await getURI(claimId); + return { + claimId: claimId, + claimURI: uri + }; + }); + const claimInformation = await Promise.all(claimInformationPromises); + console.log("Claim Information:", claimInformation); + }; + + fetchClaimInformation(); + }, [completedBounties]); + + const handleFilterButtonClick = (section: string) => { + setCurrentSection(section); + }; + + return ( @@ -82,11 +136,11 @@ const AccountInfo = () => {
-
completed bounties: {completedBounties}
+
completed bounties: {completedBounties.length}
total eth paid: 0.0144
-
in progress bounties: {inProgressBounties}
+
in progress bounties: {inProgressBounties.length}
total eth in contract: {ETHinContract}
-
completed claims: {completedClaims}
+
completed claims: {completedClaims.length}
total eth earned: 0.0109
@@ -100,9 +154,33 @@ const AccountInfo = () => {
-
- -
+ +
+ handleFilterButtonClick('a')} >nft's (3) + handleFilterButtonClick('b')} >your bounties ({inProgressBounties.length}) + handleFilterButtonClick('c')} >submitted claims ({submitedClaims.length}) + collab bounties (0) +
+ +
+ {currentSection === 'a' && ( +
+ +
+ )} + {currentSection === 'b' && ( +
+ +
+ )} + {currentSection === 'c' && ( +
+ +
+ )} +
+ + ) : (
diff --git a/src/components/bounty/BountyInfo.tsx b/src/components/bounty/BountyInfo.tsx index 4a026cbf..fb857fdf 100644 --- a/src/components/bounty/BountyInfo.tsx +++ b/src/components/bounty/BountyInfo.tsx @@ -17,7 +17,7 @@ function weiToEther(weiValue: string | number): string { const BountyInfo = ({ bountyId }: { bountyId: string }) => { - const { isMultiplayer, isOwner, bountyData, isBountyClaimed} = useBountyContext()!; + const { isMultiplayer, isOwner, bountyData, isBountyClaimed, isBountyCanceled} = useBountyContext()!; console.log("Is multiplayer:", isMultiplayer) @@ -29,20 +29,33 @@ const BountyInfo = ({ bountyId }: { bountyId: string }) => { return ( <> -
-
-

{bountyData?.name}

+
+
+

{bountyData?.name}

{bountyData?.description}

+

Bounty issuer: {bountyData?.issuer}

+
+

Debug:

+ +

is Owner: {isOwner ? "true" : "false"}

+

isBountyClaimed: {isBountyClaimed ? "true" : "false"}

+

isMultiplayer: {isMultiplayer ? "true" : "false"}

+

isBountyCanceled: {isBountyCanceled ? "true" : "false"}

+ + +
+ +
-
+
{bountyData ? weiToEther(bountyData.amount) : "Loading..."} eth
-
{isMultiplayer? "this is multiplayer" : "no this is solo"}
-
{!isBountyClaimed && !isOwner ? : ""}
+ {/*
{isMultiplayer? "this is multiplayer" : "no this is solo"}
*/} +
{!isBountyClaimed && !isOwner ? : ""}
diff --git a/src/components/bounty/BountyMultiplayer.tsx b/src/components/bounty/BountyMultiplayer.tsx index 13e3f128..9b6909ce 100644 --- a/src/components/bounty/BountyMultiplayer.tsx +++ b/src/components/bounty/BountyMultiplayer.tsx @@ -6,6 +6,7 @@ import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; import { useDynamicContext } from '@dynamic-labs/sdk-react-core'; import Withdraw from '@/components/ui/Withdraw'; import CancelOpenBounty from '@/components/ui/CancelOpenBounty'; +import { useBountyContext } from '@/components/bounty/BountyProvider'; function weiToEther(weiValue: string | number): string { const etherValue = Number(weiValue) / 1e18; @@ -43,6 +44,7 @@ const BountyMultiplayer = ({ bountyId }: { bountyId: string }) => { const isCurrentUserAParticipant = currentUser ? participants?.addresses.includes(currentUser) : false; + const { isMultiplayer, isOwner, bountyData, isBountyClaimed} = useBountyContext()!; return ( @@ -53,19 +55,19 @@ const BountyMultiplayer = ({ bountyId }: { bountyId: string }) => {
{showParticipants && ( -
+
{participants ? ( participants.addresses.map((address, index) => ( -
- {address} - {weiToEther(participants.amounts[index])} ETH +
+ {address.substring(0, 6)}...{address.substring(address.length - 3)} - {weiToEther(participants.amounts[index])} ETH
)) ) : ( @@ -77,11 +79,18 @@ const BountyMultiplayer = ({ bountyId }: { bountyId: string }) => {
- + +{isOwner ? +: null +}
- {isCurrentUserAParticipant ? : } + {isCurrentUserAParticipant && !isBountyClaimed ? : null} +
+ +
+ {!isCurrentUserAParticipant && !isBountyClaimed ? : null }
diff --git a/src/components/bounty/BountyProofs.tsx b/src/components/bounty/BountyProofs.tsx index c7e5ee62..00897053 100644 --- a/src/components/bounty/BountyProofs.tsx +++ b/src/components/bounty/BountyProofs.tsx @@ -41,16 +41,16 @@ const BountyProofs = ({ bountyId }: { bountyId: string }) => { return (
-
Currently voting on: {currentVotingClaim === 0 ? "no claim for vote selected" : currentVotingClaim}
+ {/*
Currently voting on: {currentVotingClaim === 0 ? "no claim for vote selected" : currentVotingClaim}
*/}
({claimsData ? claimsData.length : 0}) - proofs
+ claims
{claimsData && claimsData.length > 0 ? : } -
+
{currentVotingClaim !== 0 ? : null}
diff --git a/src/components/bounty/BountyProvider.tsx b/src/components/bounty/BountyProvider.tsx index 3c687150..a5dd1792 100644 --- a/src/components/bounty/BountyProvider.tsx +++ b/src/components/bounty/BountyProvider.tsx @@ -9,6 +9,7 @@ interface BountyContextType { isOwner: boolean; isMultiplayer: boolean | null; isBountyClaimed: boolean | null; + isBountyCanceled: boolean | null; } @@ -22,6 +23,8 @@ export const BountyProvider = ({ bountyId, children }: { bountyId: string, child const [isOwner, setIsOwner] = useState(false); const [isMultiplayer, setIsMultiplayer] = useState(false); const [isBountyClaimed, setIsBountyClaimed] = useState(null); + const [isBountyCanceled, setIsBountyCanceled] = useState(null); + const { user } = useDynamicContext(); const currentUser = user?.verifiedCredentials[0].address; @@ -32,6 +35,7 @@ export const BountyProvider = ({ bountyId, children }: { bountyId: string, child setBountyData(data); setIsOwner(currentUser === data.issuer); setIsBountyClaimed(data.claimer !== "0x0000000000000000000000000000000000000000"); + setIsBountyCanceled(data.claimer === data.issuer); }).catch(console.error); getParticipants(bountyId).then((openBounty) => { @@ -41,7 +45,7 @@ export const BountyProvider = ({ bountyId, children }: { bountyId: string, child }, [bountyId, currentUser]); return ( - + {children} ); diff --git a/src/components/bounty/NoProof.tsx b/src/components/bounty/NoProof.tsx index 5c928798..74de7f0e 100644 --- a/src/components/bounty/NoProof.tsx +++ b/src/components/bounty/NoProof.tsx @@ -60,7 +60,7 @@ const NoProof = ({ bountyId }: { bountyId: string }) => { return (
- { !bountyCanceled ? "this bounty has not yet received any proof." : "bounty canceled"} + { !bountyCanceled ? "this bounty has not yet received any claim." : "bounty canceled"} {walletConnected && youOwner && !bountyCanceled ? ( ) : walletConnected && !youOwner && !bountyCanceled ? ( ) : null} diff --git a/src/components/bounty/ProofItem.tsx b/src/components/bounty/ProofItem.tsx index db75ed72..f258f389 100644 --- a/src/components/bounty/ProofItem.tsx +++ b/src/components/bounty/ProofItem.tsx @@ -2,6 +2,7 @@ import React, { useEffect, useState } from 'react'; import { getURI, acceptClaim, submitClaimForVote} from '@/app/context/web3'; import { useDynamicContext } from "@dynamic-labs/sdk-react-core"; +import { useBountyContext } from '@/components/bounty/BountyProvider'; interface ProofItemProps { @@ -20,9 +21,13 @@ const ProofItem: React.FC = ({ openBounty, id, title, descriptio const { user, primaryWallet } = useDynamicContext(); const [claimsURI, setClaimsURI] = useState("") - const currentUser = user?.verifiedCredentials[0].address; + const { isMultiplayer, isOwner, bountyData, isBountyClaimed} = useBountyContext()!; - const notOwner = currentUser === issuer ; + + + // const currentUser = user?.verifiedCredentials[0].address; + + // const notOwner = currentUser === issuer ; useEffect(() => { @@ -69,8 +74,8 @@ const ProofItem: React.FC = ({ openBounty, id, title, descriptio return (
-
{openBounty && !notOwner ? - +
{isMultiplayer && isOwner ? + : null}
{ accepted ?
@@ -80,28 +85,30 @@ const ProofItem: React.FC = ({ openBounty, id, title, descriptio null } - { !accepted && !notOwner && !isAccepted && primaryWallet ? + { isOwner && !isBountyClaimed && primaryWallet ?
accept
: null } -
- - { claimsURI ? - claim image - : null - } +
+ {claimsURI && ( + claim image + )} +
-

{title}

{description}

+
-
claim id: {id}
issuer @@ -109,6 +116,8 @@ const ProofItem: React.FC = ({ openBounty, id, title, descriptio ${issuer.slice(0, 5)}...{issuer.slice(-6)}
+
claim id: {id}
+
); diff --git a/src/components/bounty/ProofItemAccount.tsx b/src/components/bounty/ProofItemAccount.tsx new file mode 100644 index 00000000..641d9218 --- /dev/null +++ b/src/components/bounty/ProofItemAccount.tsx @@ -0,0 +1,129 @@ + +import React, { useEffect, useState } from 'react'; +import { getURI, acceptClaim, submitClaimForVote} from '@/app/context/web3'; +import { useDynamicContext } from "@dynamic-labs/sdk-react-core"; +import { useBountyContext } from '@/components/bounty/BountyProvider'; +import Link from 'next/link'; + + +interface ProofItemProps { + id: string; + title: string; + description: string; + issuer: string; + bountyId:string; + youOwner:boolean; + accepted:boolean; + isAccepted:boolean + // openBounty: boolean | null; +} + +const ProofItem: React.FC = ({ id, title, description, issuer , bountyId, accepted, isAccepted}) => { + + const { user, primaryWallet } = useDynamicContext(); + const [claimsURI, setClaimsURI] = useState("") + // const { isMultiplayer, isOwner, bountyData, isBountyClaimed} = useBountyContext()!; + + + + // const currentUser = user?.verifiedCredentials[0].address; + + // const notOwner = currentUser === issuer ; + + + useEffect(() => { + if (id) { + getURI(id) + .then(data => setClaimsURI(data)) + .catch(console.error); + } + + }, [id]); + + const handleAcceptClaim = async () => { + if (!id || !bountyId || !primaryWallet ) { + alert("Please check connection"); + return; + } + + try { + await acceptClaim(primaryWallet, bountyId, id) + + } catch (error) { + console.error('Error accepting claim:', error); + alert("Failed to accept claim."); + } + }; + + const handleSubmitClaimForVote = async () => { + if (!id || !bountyId || !primaryWallet ) { + alert("Please check connection"); + return; + } + + try { + await submitClaimForVote(primaryWallet, bountyId, id) + + } catch (error) { + console.error('Error accepting claim:', error); + alert("Failed to accept claim."); + } + }; + + + + + return ( +
+ + {/*
{isMultiplayer && isOwner ? + + : null}
*/} + { accepted ? +
+ accepted +
+ : + null + } +{/* + { isOwner && !isBountyClaimed && primaryWallet ? +
+ accept +
: + null + } */} + +
+ {claimsURI && ( + claim image + )} +
+ +
+
+

{title}

+

{description}

+
+ +
+ + issuer + + + ${issuer.slice(0, 5)}...{issuer.slice(-6)} + +
+
claim id: {id}
+ +
+ +
+ ); +}; + +export default ProofItem; diff --git a/src/components/bounty/ProofList.tsx b/src/components/bounty/ProofList.tsx index b58d82d7..00c4626d 100644 --- a/src/components/bounty/ProofList.tsx +++ b/src/components/bounty/ProofList.tsx @@ -33,7 +33,7 @@ const ProofList: React.FC = ({ data, youOwner, openBounty, curre return ( -
+
{data.map((claim) => (
= ({ data, }) => { + const [isAccepted, setIsAccepted] = useState(true); + + useEffect(() => { + const checkAccepted = data.some(claim => claim.accepted === true); + setIsAccepted(checkAccepted); + }, [data]); + + + + return ( +
+ {data.map((claim) => ( +
+ +
+ ))} +
+ ); +}; + +export default ProofList; diff --git a/src/components/bounty/Voting.tsx b/src/components/bounty/Voting.tsx index 42330146..ac6c41c9 100644 --- a/src/components/bounty/Voting.tsx +++ b/src/components/bounty/Voting.tsx @@ -84,10 +84,12 @@ const Voting: React.FC = ({ bountyId }) => { return ( -
+
{votingData ? ( <> - + + = ({ bountyId }) => { width={400} height={200} /> + + +
+
Yes votes: {votingData.yes} ETH
No votes: {votingData.no} ETH
@@ -120,7 +126,7 @@ const Voting: React.FC = ({ bountyId }) => {
-
Deadline: {votingData.deadline}
+
Deadline: {votingData.deadline}
) : (
Loading voting data...
diff --git a/src/components/global/FormProof.tsx b/src/components/global/FormProof.tsx index f4c1715b..f3d1d2ec 100644 --- a/src/components/global/FormProof.tsx +++ b/src/components/global/FormProof.tsx @@ -55,7 +55,11 @@ const FormProof: React.FC = ({ bountyId }) => { setCid(resData.IpfsHash); setUploading(false); console.log(resData) - setUri(`${process.env.NEXT_PUBLIC_GATEWAY_URL}/ipfs/${resData.IpfsHash}`); + setUri(JSON.stringify({ + name: name, + description: description, + uri: `${process.env.NEXT_PUBLIC_GATEWAY_URL}/ipfs/${cid}` + })); } catch (e) { console.log(e); @@ -76,7 +80,11 @@ const FormProof: React.FC = ({ bountyId }) => { } try { - setUri(`${process.env.NEXT_PUBLIC_GATEWAY_URL}/ipfs/${cid}`); + setUri(JSON.stringify({ + name: name, + description: description, + uri: `${process.env.NEXT_PUBLIC_GATEWAY_URL}/ipfs/${cid}` + })); console.log("setting uri") console.log(name) console.log(uri) diff --git a/src/components/global/Menu.tsx b/src/components/global/Menu.tsx index 1b2ed4d2..2d6381e0 100644 --- a/src/components/global/Menu.tsx +++ b/src/components/global/Menu.tsx @@ -13,7 +13,7 @@ const Menu: React.FC = ({ menuPoints }) => { return ( -
+
{menuPoints.map((point, index) => (
diff --git a/src/components/layout/ContentHome.tsx b/src/components/layout/ContentHome.tsx index 0d49917f..68483c6d 100644 --- a/src/components/layout/ContentHome.tsx +++ b/src/components/layout/ContentHome.tsx @@ -1,39 +1,74 @@ -import { fetchBounties, fetchAllBounties } from "@/app/context/web3"; +import { fetchAllBounties } from "@/app/context/web3"; import BountyList from "@/components/ui/BountyList"; import { useDynamicContext } from "@dynamic-labs/sdk-react-core"; import { useEffect, useState } from "react"; -import { BountiesData } from '../../types/web3'; - - - - - +import { BountiesData } from '../../types/web3'; +import ToggleButton from "@/components/ui/ToggleButton"; const ContentHome = () => { const { primaryWallet } = useDynamicContext(); const [bountiesData, setBountiesData] = useState([]); - + const [openBounties, setOpenBounties] = useState([]); + const [pastBounties, setPastBounties] = useState([]); + const [loadedBountiesCount, setLoadedBountiesCount] = useState(20); + const [hasMoreBounties, setHasMoreBounties] = useState(false); + const [displayOpenBounties, setDisplayOpenBounties] = useState(false); useEffect(() => { - const data = async () => { + const fetchData = async () => { try { - fetchAllBounties() - .then(data => { - setBountiesData(data) - }) + const data = await fetchAllBounties(); + setBountiesData(data); } catch (error) { - console.log("this is error:" , error) + console.log("Error fetching bounties:", error); } - } - data() + }; + + fetchData(); }, [primaryWallet]); + useEffect(() => { + // Filter bountiesData into openBounties and pastBounties + const open = bountiesData.filter(bounty => bounty.claimer !== "0x0000000000000000000000000000000000000000"); + const past = bountiesData.filter(bounty => bounty.claimer === "0x0000000000000000000000000000000000000000"); + + setOpenBounties(open); + setPastBounties(past); + + // Update hasMoreBounties based on the total number of bounties + setHasMoreBounties(bountiesData.length > loadedBountiesCount); + }, [bountiesData, loadedBountiesCount]); + + const handleLoadMore = () => { + // Increase the number of loaded bounties by 20 + setLoadedBountiesCount(prevCount => prevCount + 20); + }; + + const handleToggle = (option: string) => { + // Toggle between displaying open and past bounties + if (option === "Open Bounties") { + setDisplayOpenBounties(true); + } else if (option === "Past Bounties") { + setDisplayOpenBounties(false); + } + }; return ( -
- -
+ <> +
+ +
+
+ {/* Render either openBounties or pastBounties based on displayOpenBounties state */} + +
+ {hasMoreBounties && ( +
+ +
+ )} + ); }; -export default ContentHome; \ No newline at end of file +export default ContentHome; diff --git a/src/components/layout/Footer.tsx b/src/components/layout/Footer.tsx index ce1e0f41..42c64a42 100644 --- a/src/components/layout/Footer.tsx +++ b/src/components/layout/Footer.tsx @@ -2,9 +2,9 @@ import Link from 'next/link'; const Footer = () => { return ( -
+
Socials
-
+
terms | security diff --git a/src/components/layout/Header.tsx b/src/components/layout/Header.tsx index ddaf5925..061c0342 100644 --- a/src/components/layout/Header.tsx +++ b/src/components/layout/Header.tsx @@ -6,11 +6,16 @@ import ConnectWallet from '@/components/web3/ConnectWallet'; import Logo from '@/components/ui/Logo'; import Menu from '@/components/global/Menu'; import { WalletContext } from '@/app/context/WalletProvider'; +import Footer from '@/components/layout/Footer'; const Header = () => { const { isAuthenticated } = useDynamicContext(); const [isClient, setIsClient] = useState(false); + const [isOpen, setIsOpen] = useState(false); + const handleOpenMenu = () => { + setIsOpen(!isOpen); + }; const walletContext = useContext(WalletContext); useEffect(() => { @@ -20,6 +25,7 @@ const Header = () => { const walletAddress = walletContext?.walletAddress; return ( + <>
@@ -30,9 +36,13 @@ const Header = () => {
-
- {isClient && isAuthenticated ? my bounties : null} +
+ {isClient && isAuthenticated ? my bounties : null} {isClient ? : null} + + + +
@@ -45,13 +55,38 @@ const Header = () => { {walletAddress ? walletAddress : "connect your wallet" } + - {/* {walletAddress ? - {walletAddress} - : - } */} - +
+ +
+
+ + + + +
+ +
+
+
+ +
+
@@ -60,6 +95,14 @@ const Header = () => {
+
+ + {isClient && isAuthenticated ? my bounties : null} + + + +
+ ); }; diff --git a/src/components/ui/BountyList.tsx b/src/components/ui/BountyList.tsx index fbe5b709..ef090359 100644 --- a/src/components/ui/BountyList.tsx +++ b/src/components/ui/BountyList.tsx @@ -28,28 +28,21 @@ const item = { const BountyList: React.FC = ({ bountiesData }) => { -const [showFilters, setShowFilters] = useState(false); +// const [showFilters, setShowFilters] = useState(false); - useEffect(() => { - if (window.location.pathname === '/account') { - setShowFilters(true); - } else { - setShowFilters(false); - } - }, []); + // useEffect(() => { + // if (window.location.pathname === '/account') { + // setShowFilters(true); + // } else { + // setShowFilters(false); + // } + // }, []); return ( <> - {showFilters && ( -
- nft's (3) - your bounties (0) - submitted claims (0) - collab bounties (0) -
- )} + { null } {showForm && ( -
+
); diff --git a/src/components/web3/ConnectWallet.tsx b/src/components/web3/ConnectWallet.tsx index 0c6d753e..42520cbd 100644 --- a/src/components/web3/ConnectWallet.tsx +++ b/src/components/web3/ConnectWallet.tsx @@ -31,7 +31,7 @@ const ConnectWallet = () => {
+ className=' bg-gradient-to-t text-[10px] lg:text-base from-[#D8393A] to-[#D8393A] flex items-center gap-x-2 border-[#F15E5F] border rounded-md px-2 py-2 '> connect @@ -45,7 +45,7 @@ const ConnectWallet = () => { :
handleLogOut()} > disconnect diff --git a/src/styles/globals.css b/src/styles/globals.css index 8656f605..5fb5d4cb 100644 --- a/src/styles/globals.css +++ b/src/styles/globals.css @@ -146,3 +146,12 @@ body { opacity: 1; transition: opacity 300ms ease-in-out; } + +.aspect-w-1 { + width: 100%; +} + +.aspect-h-1 { + height: 0; + padding-bottom: 100%; +} diff --git a/src/types/web3.ts b/src/types/web3.ts index f2cabc88..d733d9c4 100644 --- a/src/types/web3.ts +++ b/src/types/web3.ts @@ -12,7 +12,7 @@ interface Wallet { // Contract Data Types export type MainContractType = Contract; -export type NFTContractType = Contract; +// export type NFTContractType = Contract; // Bounties and Claims export interface Bounty { @@ -37,6 +37,27 @@ export interface BountiesData { } +export interface BountiesDataClosed { + id: string; + issuer: string; + name: string; + description: string; + claimer: string; + createdAt: bigint; + claimId: string; +} + +export interface BountiesDataOpen { + id: string; + issuer: string; + name: string; + description: string; + claimer: string; + createdAt: bigint; + claimId: string; +} + + export interface ClaimsData { accepted: boolean; @@ -64,6 +85,9 @@ export interface OpenBounty { + + + export interface Claim { id: string; issuer: string; @@ -118,4 +142,9 @@ export type ResolveVoteFunction = (primaryWallet: Wallet, bountyId: string, ) = export type GetClaimsByUserFunction = (user: string) => Promise; export type GetClaimsByBountyIdFunction = (id: string) => Promise; +export type GetClaimByIdFunction = (claimId: string) => Promise; + + + + export type GetURIFunction = (claimId: string) => Promise;