From d4479b41e7d76ef929140a0b36b27a92199bb809 Mon Sep 17 00:00:00 2001 From: Lulox Date: Thu, 21 Sep 2023 01:52:14 -0300 Subject: [PATCH 1/3] Added a countdown component --- .../components/op/projects/YourBallot.tsx | 9 +- .../op/projects/YourBallotCountdown.tsx | 58 +++++++ .../nextjs/generated/deployedContracts.ts | 155 +++++++++++++++++- 3 files changed, 218 insertions(+), 4 deletions(-) create mode 100644 packages/nextjs/components/op/projects/YourBallotCountdown.tsx diff --git a/packages/nextjs/components/op/projects/YourBallot.tsx b/packages/nextjs/components/op/projects/YourBallot.tsx index da8390e..eaf130a 100644 --- a/packages/nextjs/components/op/projects/YourBallot.tsx +++ b/packages/nextjs/components/op/projects/YourBallot.tsx @@ -1,4 +1,5 @@ import React from "react"; +import CountdownTimer from "./YourBallotCountdown"; import { ArrowTopRightOnSquareIcon } from "@heroicons/react/20/solid"; import { useBallot } from "~~/context/BallotContext"; import { useProjects } from "~~/context/ProjectsContext"; @@ -6,12 +7,16 @@ import { useProjects } from "~~/context/ProjectsContext"; const YourBallot = () => { const { state } = useBallot(); const { projects } = useProjects(); + + const fakeTimestamp = 1700453260; + const votingDeadline = fakeTimestamp; + return (

YOUR BALLOT

-

Voting ends in

- 3d:12h:30m:24s + {/*

Voting ends in

*/} +

Projects added

diff --git a/packages/nextjs/components/op/projects/YourBallotCountdown.tsx b/packages/nextjs/components/op/projects/YourBallotCountdown.tsx new file mode 100644 index 0000000..9d9f5d9 --- /dev/null +++ b/packages/nextjs/components/op/projects/YourBallotCountdown.tsx @@ -0,0 +1,58 @@ +import { useEffect, useState } from "react"; + +interface CountdownTimerProps { + deadline: number; // Specify the type for the deadline prop +} + +const CountdownTimer: React.FC = ({ deadline }) => { + const [timeRemaining, setTimeRemaining] = useState(null); + + useEffect(() => { + const timer = setInterval(() => { + const now = Math.floor(new Date().getTime() / 1000); + + if (now >= deadline) { + setTimeRemaining(null); + clearInterval(timer); + } else { + const timeRemainingSeconds = deadline - now; + const days = Math.floor(timeRemainingSeconds / 86400); + const hours = Math.floor((timeRemainingSeconds % 86400) / 3600); + const minutes = Math.floor((timeRemainingSeconds % 3600) / 60); + const seconds = Math.floor(timeRemainingSeconds % 60); + + if (days > 0) { + setTimeRemaining(`${days}d:${hours}h:${minutes}m:${seconds}s`); + } else { + setTimeRemaining(`${hours}h:${minutes}m:${seconds}s`); + } + } + }, 1000); + + return () => clearInterval(timer); + }, [deadline]); + + const deadlineMessage = () => { + const now = Math.floor(new Date().getTime() / 1000); + if (now >= deadline) { + return { + message: "Ended on", + }; + } else { + return { + message: "Voting ends in", + }; + } + }; + + return ( + <> +

{deadlineMessage().message}

+ + {timeRemaining ? timeRemaining : new Date(deadline * 1000).toLocaleString()} + + + ); +}; + +export default CountdownTimer; diff --git a/packages/nextjs/generated/deployedContracts.ts b/packages/nextjs/generated/deployedContracts.ts index 54e60f9..98a5061 100644 --- a/packages/nextjs/generated/deployedContracts.ts +++ b/packages/nextjs/generated/deployedContracts.ts @@ -1,3 +1,154 @@ -const deployedContracts = null; +const contracts = { + 31337: [ + { + chainId: "31337", + name: "localhost", + contracts: { + YourContract: { + address: "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512", + abi: [ + { + inputs: [ + { + internalType: "address", + name: "_owner", + type: "address", + }, + ], + stateMutability: "nonpayable", + type: "constructor", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "greetingSetter", + type: "address", + }, + { + indexed: false, + internalType: "string", + name: "newGreeting", + type: "string", + }, + { + indexed: false, + internalType: "bool", + name: "premium", + type: "bool", + }, + { + indexed: false, + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "GreetingChange", + type: "event", + }, + { + inputs: [], + name: "greeting", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "owner", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "premium", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "string", + name: "_newGreeting", + type: "string", + }, + ], + name: "setGreeting", + outputs: [], + stateMutability: "payable", + type: "function", + }, + { + inputs: [], + name: "totalCounter", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + name: "userGreetingCounter", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "withdraw", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + stateMutability: "payable", + type: "receive", + }, + ], + }, + }, + }, + ], +} as const; -export default deployedContracts; \ No newline at end of file +export default contracts; From 6713ae7bff6228f012acc7e9912d633b44ce714e Mon Sep 17 00:00:00 2001 From: Lulox Date: Thu, 21 Sep 2023 02:01:42 -0300 Subject: [PATCH 2/3] Revert deployedContracts.ts to default (oops) --- .../nextjs/generated/deployedContracts.ts | 155 +----------------- 1 file changed, 2 insertions(+), 153 deletions(-) diff --git a/packages/nextjs/generated/deployedContracts.ts b/packages/nextjs/generated/deployedContracts.ts index 98a5061..04fae51 100644 --- a/packages/nextjs/generated/deployedContracts.ts +++ b/packages/nextjs/generated/deployedContracts.ts @@ -1,154 +1,3 @@ -const contracts = { - 31337: [ - { - chainId: "31337", - name: "localhost", - contracts: { - YourContract: { - address: "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512", - abi: [ - { - inputs: [ - { - internalType: "address", - name: "_owner", - type: "address", - }, - ], - stateMutability: "nonpayable", - type: "constructor", - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: "address", - name: "greetingSetter", - type: "address", - }, - { - indexed: false, - internalType: "string", - name: "newGreeting", - type: "string", - }, - { - indexed: false, - internalType: "bool", - name: "premium", - type: "bool", - }, - { - indexed: false, - internalType: "uint256", - name: "value", - type: "uint256", - }, - ], - name: "GreetingChange", - type: "event", - }, - { - inputs: [], - name: "greeting", - outputs: [ - { - internalType: "string", - name: "", - type: "string", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [], - name: "owner", - outputs: [ - { - internalType: "address", - name: "", - type: "address", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [], - name: "premium", - outputs: [ - { - internalType: "bool", - name: "", - type: "bool", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [ - { - internalType: "string", - name: "_newGreeting", - type: "string", - }, - ], - name: "setGreeting", - outputs: [], - stateMutability: "payable", - type: "function", - }, - { - inputs: [], - name: "totalCounter", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [ - { - internalType: "address", - name: "", - type: "address", - }, - ], - name: "userGreetingCounter", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [], - name: "withdraw", - outputs: [], - stateMutability: "nonpayable", - type: "function", - }, - { - stateMutability: "payable", - type: "receive", - }, - ], - }, - }, - }, - ], -} as const; +const deployedContracts = null; -export default contracts; +export default deployedContracts; From 9665226bac31f71974388340f621be321c977552 Mon Sep 17 00:00:00 2001 From: Lulox Date: Thu, 21 Sep 2023 20:09:20 -0300 Subject: [PATCH 3/3] Refactored countdown to display instantly --- .../nextjs/components/lists/ListHeader.tsx | 4 +- .../op/projects/YourBallotCountdown.tsx | 39 +++++++++++++++---- packages/nextjs/tailwind.config.js | 2 +- 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/packages/nextjs/components/lists/ListHeader.tsx b/packages/nextjs/components/lists/ListHeader.tsx index f6cc8bc..22e9fb2 100644 --- a/packages/nextjs/components/lists/ListHeader.tsx +++ b/packages/nextjs/components/lists/ListHeader.tsx @@ -119,8 +119,8 @@ function ListHeader({ displayList, titleHeader, display, onCategoryChange, onShu onClick={() => handleButtonClick(`${category.category}`)} className={`px-4 py-2 rounded-md font-normal text-base leading-6 font-inter ${ active == `${category.category}` - ? "bg-secondary-content text-white dark:bg-black" - : "bg-customWhite text-customGrayBtn" + ? "bg-[#FF0520] text-white" + : "bg-customWhite dark:bg-slate-700 text-customGrayBtn" }`} > {category.category} diff --git a/packages/nextjs/components/op/projects/YourBallotCountdown.tsx b/packages/nextjs/components/op/projects/YourBallotCountdown.tsx index 9d9f5d9..54a6f42 100644 --- a/packages/nextjs/components/op/projects/YourBallotCountdown.tsx +++ b/packages/nextjs/components/op/projects/YourBallotCountdown.tsx @@ -1,11 +1,14 @@ import { useEffect, useState } from "react"; interface CountdownTimerProps { - deadline: number; // Specify the type for the deadline prop + deadline: number; } const CountdownTimer: React.FC = ({ deadline }) => { - const [timeRemaining, setTimeRemaining] = useState(null); + const [timeRemaining, setTimeRemaining] = useState( + calculateTimeRemaining(deadline), // Initialize with the initial value + ); + const [isEnded, setIsEnded] = useState(false); useEffect(() => { const timer = setInterval(() => { @@ -13,6 +16,7 @@ const CountdownTimer: React.FC = ({ deadline }) => { if (now >= deadline) { setTimeRemaining(null); + setIsEnded(true); clearInterval(timer); } else { const timeRemainingSeconds = deadline - now; @@ -27,16 +31,16 @@ const CountdownTimer: React.FC = ({ deadline }) => { setTimeRemaining(`${hours}h:${minutes}m:${seconds}s`); } } - }, 1000); + }, 1000); // Update every 1 second return () => clearInterval(timer); }, [deadline]); const deadlineMessage = () => { - const now = Math.floor(new Date().getTime() / 1000); - if (now >= deadline) { + if (isEnded) { return { message: "Ended on", + formattedDate: new Date(deadline * 1000).toLocaleString(), }; } else { return { @@ -48,11 +52,30 @@ const CountdownTimer: React.FC = ({ deadline }) => { return ( <>

{deadlineMessage().message}

- - {timeRemaining ? timeRemaining : new Date(deadline * 1000).toLocaleString()} - + {isEnded ? deadlineMessage().formattedDate : timeRemaining || ""} ); }; export default CountdownTimer; + +// Helper function to calculate initial time remaining +const calculateTimeRemaining = (deadline: number): string => { + const now = Math.floor(new Date().getTime() / 1000); + + if (now >= deadline) { + return ""; // Timer has already ended + } + + const timeRemainingSeconds = deadline - now; + const days = Math.floor(timeRemainingSeconds / 86400); + const hours = Math.floor((timeRemainingSeconds % 86400) / 3600); + const minutes = Math.floor((timeRemainingSeconds % 3600) / 60); + const seconds = Math.floor(timeRemainingSeconds % 60); + + if (days > 0) { + return `${days}d:${hours}h:${minutes}m:${seconds}s`; + } else { + return `${hours}h:${minutes}m:${seconds}s`; + } +}; diff --git a/packages/nextjs/tailwind.config.js b/packages/nextjs/tailwind.config.js index dd174e6..1ace34f 100644 --- a/packages/nextjs/tailwind.config.js +++ b/packages/nextjs/tailwind.config.js @@ -41,7 +41,7 @@ module.exports = { scaffoldEthDark: { primary: "#212638", "primary-content": "#F9FBFF", - secondary: "#323f61", + secondary: "#991b1b", "secondary-content": "#F9FBFF", accent: "#4969A6", "accent-content": "#F9FBFF",