Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Election Countdown and Voter Status #193

Merged
merged 4 commits into from
Aug 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"ethers": "^6.6.7",
"jsonp": "^0.2.1",
"moment": "^2.29.4",
"moment-timezone": "^0.5.43",
"near-api-js": "^2.1.4",
"react": "^18.2.0",
"react-confetti": "^6.1.0",
Expand Down
58 changes: 58 additions & 0 deletions src/components/common/ProgressTracker.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import { formatNumberWithComma } from '../../utils/utilityFunctions';
import { useSelector } from 'react-redux';
import { Links, ReducerNames } from '../../utils/constants';
import moment from 'moment-timezone';

const ProgressTracker = () => {
const ProgressMeterMax = process.env.REACT_APP_PROGRESS_METER_MAX ?? 3000;
Expand Down Expand Up @@ -36,7 +37,7 @@

const getRegisteredPercentage = useCallback(
() => (humansRegistered / ProgressMeterMax) * 100,
[humansRegistered]

Check warning on line 40 in src/components/common/ProgressTracker.jsx

View workflow job for this annotation

GitHub Actions / Lint and Format code

React Hook useCallback has a missing dependency: 'ProgressMeterMax'. Either include it or remove the dependency array
);

// to make sure the the right corner is not clipped much with increasing width
Expand All @@ -56,6 +57,51 @@

const ReadableNumber = formatNumberWithComma(ProgressMeterMax);

const futureDateUtc = moment.unix(1693612799); // September 1 @ 23:59:59

// Get the user's local timezone
const userTimezone = moment.tz.guess();
const [countdown, setCountdown] = useState({
days: 0,
hours: 0,
minutes: 0,
seconds: 0,
});

function updateCountdown() {
const nowLocal = moment(); // Get the current local time
const futureDateLocal = futureDateUtc.clone().tz(userTimezone);

// Calculate the time remaining
const countdownDuration = moment.duration(futureDateLocal.diff(nowLocal));

setCountdown({
days: countdownDuration.days(),
hours: countdownDuration.hours(),
minutes: countdownDuration.minutes(),
seconds: countdownDuration.seconds(),
});
}

useEffect(() => {
updateCountdown();

const interval = setInterval(updateCountdown, 1000);

return () => clearInterval(interval);
}, []);

Check warning on line 92 in src/components/common/ProgressTracker.jsx

View workflow job for this annotation

GitHub Actions / Lint and Format code

React Hook useEffect has a missing dependency: 'updateCountdown'. Either include it or remove the dependency array

const NumberContainer = ({ number, text }) => {
return (
<span className="flex gap-x-0.5 items-end">
<p style={{ color: '#FDE047' }} className="text-3xl">
{number}
</p>
<p className="text-xl font-normal">{text}</p>
</span>
);
};

if (showTracker) {
return (
<div className="text-center text-md">
Expand Down Expand Up @@ -110,6 +156,18 @@
)}
</div>
</>
<div
style={{ backgroundColor: '#F29BC0' }}
className="p-2 text-white font-semibold flex gap-x-8 justify-center items-center"
>
<p>VOTER REGISTRATION ENDS</p>
<p className="text-lg flex gap-x-3 items-end">
<NumberContainer number={countdown.days} text="D" />
<NumberContainer number={countdown.hours} text="H" />
<NumberContainer number={countdown.minutes} text="M" />
<NumberContainer number={countdown.seconds} text="S" />
</p>
</div>
</div>
);
} else return null;
Expand Down
12 changes: 12 additions & 0 deletions src/images/InfoIcon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export const InfoIcon = ({ styles = '' }) => (
<svg
xmlns="http://www.w3.org/2000/svg"
x="0px"
y="0px"
width="20"
height="20"
viewBox="0 0 50 50"
>
<path d="M 25 2 C 12.309295 2 2 12.309295 2 25 C 2 37.690705 12.309295 48 25 48 C 37.690705 48 48 37.690705 48 25 C 48 12.309295 37.690705 2 25 2 z M 25 4 C 36.609824 4 46 13.390176 46 25 C 46 36.609824 36.609824 46 25 46 C 13.390176 46 4 36.609824 4 25 C 4 13.390176 13.390176 4 25 4 z M 25 11 A 3 3 0 0 0 22 14 A 3 3 0 0 0 25 17 A 3 3 0 0 0 28 14 A 3 3 0 0 0 25 11 z M 21 21 L 21 23 L 22 23 L 23 23 L 23 36 L 22 36 L 21 36 L 21 38 L 22 38 L 23 38 L 27 38 L 28 38 L 29 38 L 29 36 L 28 36 L 27 36 L 27 21 L 26 21 L 22 21 L 21 21 z"></path>
</svg>
);
152 changes: 151 additions & 1 deletion src/pages/auth/Home.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import React, { useEffect } from 'react';
import React, { useEffect, useState } from 'react';
import { wallet } from '../../index';
import { getConfig } from '../../utils/config';
import { toast } from 'react-toastify';
import { isNumber } from '../../utils/utilityFunctions';
import {
AccountFlag,
ImageSrc,
LSKeys,
ReducerNames,
Expand All @@ -13,6 +14,8 @@ import { useDispatch, useSelector } from 'react-redux';
import { updateTokens } from '../../redux/reducer/sbtsReducer';
import TokensGrid from '../../components/common/TokensGrid';
import { setActivePageIndex } from '../../redux/reducer/commonReducer';
import { InfoIcon } from '../../images/InfoIcon';
import { PrimaryButton } from '../../components/common/Buttons';

const Home = () => {
const { isUserHuman } = useSelector((state) => state[ReducerNames.SBT]);
Expand All @@ -39,6 +42,9 @@ const Home = () => {
}
}, [activePageIndex]);

const [showTooltip, setShowtooltip] = useState(false);
const [voterStatus, setVoterStatus] = useState(null);

const fetchOGSBTTokens = async () => {
try {
const data = await wallet.viewMethod({
Expand Down Expand Up @@ -182,8 +188,152 @@ const Home = () => {
}
};

// useEffect(() => {
// if (isUserHuman) {
// fetchVoterStatus();
// }
// }, [isUserHuman]);

const fetchVoterStatus = async () => {
const data = await wallet.viewMethod({
contractId: app_contract,
method: 'account_flagged',
args: {
account: wallet.accountId,
},
});
setVoterStatus(data);
};

const tagClasses = 'rounded-2xl md:rounded-full p-2 px-4';

const ToolTip = ({ heading, description }) => {
return (
<div class="w-60 bg-black text-white text-xs rounded-lg py-3 absolute z-10 bottom-full -left-28 px-4 mb-1">
<div className="flex flex-col gap-2">
<h2>{heading}</h2>
<p className="text-gray-500">{description}</p>
</div>
<svg
class="absolute text-black h-2 w-full left-0 top-full"
x="0px"
y="0px"
viewBox="0 0 255 255"
xmlSpace="preserve"
>
<polygon class="fill-current" points="0,0 127.5,127.5 255,0" />
</svg>
</div>
);
};

const VerifiedTag = () => {
return (
<div
className={tagClasses + ' text-white'}
style={{ backgroundColor: '#16C784' }}
>
Verified Voter
</div>
);
};

const BlacklistTag = () => {
return (
<div className="flex gap-3 items-center">
<div
className={
tagClasses + ' flex gap-2 items-center bg-black text-white'
}
>
<p>Blacklist</p>
<div
onMouseOver={() => setShowtooltip(true)}
onMouseLeave={() => setShowtooltip(false)}
className="bg-icon-white pointer group relative"
>
<InfoIcon />
{showTooltip && (
<ToolTip
heading="Blacklist"
description="The community has voted to block backlisted accounts from voting
in the NDC general election. You have been blacklisted due
previously violating the Fair Voting Policy."
/>
)}
</div>
</div>
<PrimaryButton
onClick={() =>
window.open(
'https://docs.google.com/forms/d/e/1FAIpQLSdQYxiUcxpiCDVKnN55Q7T2fnUPt0VjRdzo46qEkV7ub5mWFw/viewform',
'_blank'
)
}
>
Complete Appeal
</PrimaryButton>
</div>
);
};

const VerificationTag = () => {
return (
<div className="flex gap-3 items-center">
<div
style={{ backgroundColor: '#FDE047' }}
className={tagClasses + ' flex gap-2 items-center'}
>
<p className="font-semibold"> More Verification Need</p>
<div
onMouseOver={() => setShowtooltip(true)}
onMouseLeave={() => setShowtooltip(false)}
className="pointer group relative"
>
<InfoIcon />
{showTooltip && (
<ToolTip
heading="More Verification Need"
description=" Voters without reputation need to be verified by the Election
Integrity Council or place a substantial bond to vote."
/>
)}
</div>
</div>
<PrimaryButton
onClick={() =>
window.open(
'https://docs.google.com/forms/d/e/1FAIpQLSfa3S6Qz1MdiJEXINMICv9O9oVD7LOdwiPmHI_4_gCLAhN0CA/viewform',
'_blank'
)
}
>
Apply to Verify
</PrimaryButton>
</div>
);
};

const VoterStatusTags = () => {
switch (voterStatus) {
case AccountFlag.Blacklisted:
return <BlacklistTag />;
case AccountFlag.Verified:
return <VerifiedTag />;
default:
return <VerificationTag />;
}
};

return (
<div className="mb-20">
{/* voter status */}
{/* {isUserHuman && (
<div className="bg-gray-100 p-6 flex justify-between items-center rounded-lg mb-8 flex-wrap">
<h1 className="font-semibold text-xl">Voter Status</h1>
<VoterStatusTags />
</div>
)} */}
<h1 className="text-center text-2xl font-semibold mb-10">
My I-AM-HUMAN Soul Bound Tokens
</h1>
Expand Down
4 changes: 4 additions & 0 deletions src/styles/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -157,3 +157,7 @@ html {
width: 5rem !important;
height: 5rem !important;
}

.bg-icon-white svg {
fill: white !important;
}
5 changes: 5 additions & 0 deletions src/utils/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,8 @@ export const Links = {
FAIR_VOTING_POLICY:
'https://bafkreidwdxocdkfsv6srynw7ipnogfuw76fzncmxd5jv7furbsn5cp4bz4.ipfs.nftstorage.link/',
};

export const AccountFlag = {
Blacklisted: 'Blacklisted',
Verified: 'Verified',
};
7 changes: 7 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -11738,6 +11738,13 @@ mkdirp@^0.5.1, mkdirp@~0.5.1:
dependencies:
minimist "^1.2.6"

moment-timezone@^0.5.43:
version "0.5.43"
resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.43.tgz#3dd7f3d0c67f78c23cd1906b9b2137a09b3c4790"
integrity sha512-72j3aNyuIsDxdF1i7CEgV2FfxM1r6aaqJyLB2vwb33mXYyoyLly+F1zbWqhA3/bVIoJ4szlUoMbUnVdid32NUQ==
dependencies:
moment "^2.29.4"

moment@^2.29.4:
version "2.29.4"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108"
Expand Down
Loading