Skip to content

Commit

Permalink
chore: [#3] added Claim Period countdown
Browse files Browse the repository at this point in the history
  • Loading branch information
mdnorman committed May 13, 2022
1 parent abb35f6 commit 668114c
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 21 deletions.
63 changes: 63 additions & 0 deletions components/ClaimPeriodCountdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import React from 'react';
import Countdown from 'react-countdown';

export interface ClaimPeriodCountdownProps {
claimPeriodStart: number;
claimPeriodEnd: number;
}

interface RendererProps {
days: number;
hours: number;
minutes: number;
seconds: number;
completed: boolean;
}

const ClaimPeriodCountdown = ({ claimPeriodStart, claimPeriodEnd }: ClaimPeriodCountdownProps) => {
const ClaimPeriodEnded = () => <span>Claim Period has ended</span>;

const buildRenderer =
(beforeStart: boolean) =>
// eslint-disable-next-line react/display-name
({ days, hours, minutes, seconds, completed }: RendererProps) => {
if (completed) {
if (beforeStart) {
return <span>Claim Period has started</span>;
}

return <ClaimPeriodEnded />;
}

const numberText = (number: number, singular: string, plural: string = singular + 's') =>
number > 0 ? number + ' ' + (number === 1 ? singular : plural) : '';

const daysText = numberText(days, 'day');
const hoursText = numberText(hours, 'hour');
const minutesText = numberText(minutes, 'minute');
const secondsText = numberText(seconds, 'second');

const allText = [daysText, hoursText, minutesText, secondsText].filter((text) => text).join(', ');

return <span className="remaining-time">{allText}</span>;
};

if (claimPeriodStart > Date.now()) {
return (
<span>
Claim Period starts in <Countdown date={claimPeriodStart} renderer={buildRenderer(true)} />
</span>
);
}

if (claimPeriodEnd > Date.now()) {
return (
<span>
Claim Period ends in <Countdown date={claimPeriodEnd} renderer={buildRenderer(false)} />
</span>
);
}

return <ClaimPeriodEnded />;
};
export default ClaimPeriodCountdown;
37 changes: 27 additions & 10 deletions hooks/parcelNFT.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ParcelNFT__factory } from '@citydao/parcel-contracts/dist/types/contracts/factories/ParcelNFT__factory';
import { ParcelNFT } from '@citydao/parcel-contracts/dist/types/contracts/ParcelNFT';
import { ContractAddress } from '@citydao/parcel-contracts/src/constants/accounts';
import { BigNumber } from 'ethers';
import { useEffect, useState } from 'react';
import { addresses } from '../data/whiteListedAddresses';
import { useContractLoader } from './contractHooks';
Expand All @@ -16,6 +17,8 @@ export interface ParcelNFTDetails {
totalSupply: number;
walletAlreadyClaimed: number;
allowance: number;
claimPeriodStart: number;
claimPeriodEnd: number;
}

export const useParcelNFT = (contractAddress: ContractAddress): ParcelNFTHook => {
Expand All @@ -24,22 +27,36 @@ export const useParcelNFT = (contractAddress: ContractAddress): ParcelNFTHook =>
contract: parcelNFT,
values,
refetch: refetchValues,
} = useContractLoader(new ParcelNFT__factory(), contractAddress, ['totalSupply']);
} = useContractLoader(new ParcelNFT__factory(), contractAddress, ['totalSupply', 'claimPeriod']);
const [walletAlreadyClaimed, setWalletAlreadyClaimed] = useState<number>(0);

const parcelNFTDetails: ParcelNFTDetails | null =
parcelNFT && values && account
? {
parcelNFT: parcelNFT,
walletAlreadyClaimed,
totalSupply: values.totalSupply.toNumber(),
allowance: addresses[account.toLowerCase()],
}
: null;
const buildParcelNFTDetails = (): ParcelNFTDetails | null => {
if (!(parcelNFT && values && account)) {
return null;
}

const { totalSupply, claimPeriod } = values;

const totalSupplyNumber = 'toNumber' in totalSupply ? totalSupply.toNumber() : 0;
const [claimPeriodStart, claimPeriodEnd] =
claimPeriod instanceof Array ? claimPeriod : [BigNumber.from(0), BigNumber.from(0)];

return {
parcelNFT: parcelNFT,
walletAlreadyClaimed,
totalSupply: totalSupplyNumber,
claimPeriodStart: claimPeriodStart.toNumber() * 1000,
claimPeriodEnd: claimPeriodEnd.toNumber() * 1000,
allowance: addresses[account.toLowerCase()],
};
};

const parcelNFTDetails: ParcelNFTDetails | null = buildParcelNFTDetails();

useEffect(() => {
// noinspection JSIgnoredPromiseFromCall
loadFields();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [account, parcelNFT]);

const loadFields = async () => {
Expand Down
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"merkletreejs": "^0.2.31",
"next": "12.0.4",
"react": "17.0.2",
"react-countdown": "^2.3.2",
"react-dom": "17.0.2",
"react-modal": "^3.15.1",
"react-tooltip": "^4.2.21",
Expand All @@ -44,5 +45,8 @@
"pretty-quick": "^3.1.3",
"styled-components": "^5.3.5",
"typescript": "4.5.2"
},
"resolutions": {
"eth-sig-util/**/ethereumjs-abi": "^0.6.8"
}
}
16 changes: 6 additions & 10 deletions pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { useEffect, useMemo, useState } from 'react';
import ReactTooltip from 'react-tooltip';
import ClaimButton from '../components/ClaimButton';
import { ClaimModal } from '../components/ClaimModal';
import ClaimPeriodCountdown from '../components/ClaimPeriodCountdown';
import { ClaimSuccessModal } from '../components/ClaimSuccessModal';
import { ConnectButton } from '../components/ConnectButton';
import { MintedNftsView } from '../components/MintedNftsView';
Expand All @@ -28,18 +29,15 @@ const Home: NextPage = () => {
const { handleOpenClaimModal, handleCloseClaimModal, handleOpenClaimSuccessModal } = useModal();
const [currentView, setCurrentView] = useState<VIEWS>(VIEWS.INITIAL_VIEW);

const {
account: address,
connect,
disconnect,
chainId,
} = useWallet();
const { account: address, connect, disconnect, chainId } = useWallet();

const { parcelNFTDetails, refetch } = useParcelNFT(PARCEL0_NFT_CONTRACT_ADDRESSES[chainId ?? 0]);

const allowance = parcelNFTDetails?.allowance || 0;
const walletAlreadyClaimed = parcelNFTDetails?.walletAlreadyClaimed || 0;
const totalSupply = parcelNFTDetails?.totalSupply || 0;
const claimPeriodStart = parcelNFTDetails?.claimPeriodStart || 0;
const claimPeriodEnd = parcelNFTDetails?.claimPeriodEnd || 0;

const onWalletDisconnect = async () => {
await disconnect();
Expand Down Expand Up @@ -84,11 +82,10 @@ const Home: NextPage = () => {
}
};

//TODO trkaplan check what happens when you visit with a browser that does not have metamask

useEffect(() => {
// noinspection JSIgnoredPromiseFromCall
checkEligibility();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [address, parcelNFTDetails]);

const checkEligibility = async () => {
Expand Down Expand Up @@ -127,8 +124,7 @@ const Home: NextPage = () => {
<div className="address">70 HAIL BASIN RD, POWELL, WYOMING</div>
</div>
<div className="message-box">
Claim ends in <span className="remaining-time">45 Days 00 Hours</span>{' '}
{/* TODO trkaplan use countdown component */}
<ClaimPeriodCountdown claimPeriodStart={claimPeriodStart} claimPeriodEnd={claimPeriodEnd} />
<br />
{address && (
<>
Expand Down
9 changes: 8 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2794,7 +2794,7 @@ ethereum-cryptography@^0.1.3:
secp256k1 "^4.0.1"
setimmediate "^1.0.5"

ethereumjs-abi@0.6.8:
ethereumjs-abi@^0.6.8, "ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git":
version "0.6.8"
resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz#71bc152db099f70e62f108b7cdfca1b362c6fcae"
integrity sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==
Expand Down Expand Up @@ -4793,6 +4793,13 @@ raw-body@2.4.1:
iconv-lite "0.4.24"
unpipe "1.0.0"

react-countdown@^2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/react-countdown/-/react-countdown-2.3.2.tgz#4cc27f28f2dcd47237ee66e4b9f6d2a21fc0b0ad"
integrity sha512-Q4SADotHtgOxNWhDdvgupmKVL0pMB9DvoFcxv5AzjsxVhzOVxnttMbAywgqeOdruwEAmnPhOhNv/awAgkwru2w==
dependencies:
prop-types "^15.7.2"

react-dom@17.0.2:
version "17.0.2"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23"
Expand Down

0 comments on commit 668114c

Please sign in to comment.