Skip to content

Commit 5394494

Browse files
committed
feat(finalize): fix small ui bugs
1 parent 024ca5f commit 5394494

File tree

13 files changed

+134
-137
lines changed

13 files changed

+134
-137
lines changed

bun.lock

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"dompurify": "^3.2.5",
2222
"ethers": "^6.14.4",
2323
"ipfs-http-client": "^60.0.1",
24+
"lucide-react": "^0.525.0",
2425
"multiformats": "^13.3.3",
2526
"next": "14.2.4",
2627
"react": "^18.2.0",
@@ -2018,6 +2019,8 @@
20182019

20192020
"lru_map": ["lru_map@0.3.3", "", {}, "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ=="],
20202021

2022+
"lucide-react": ["lucide-react@0.525.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Tm1txJ2OkymCGkvwoHt33Y2JpN5xucVq1slHcgE6Lk0WjDfjgKWor5CdVER8U6DvcfMwh4M8XxmpTiyzfmfDYQ=="],
2023+
20212024
"make-error": ["make-error@1.3.6", "", {}, "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw=="],
20222025

20232026
"makeerror": ["makeerror@1.0.12", "", { "dependencies": { "tmpl": "1.0.5" } }, "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg=="],

context/Alerts.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ export const AlertProvider: React.FC<{ children: React.ReactNode }> = ({ childre
3636
// Update the existing one
3737
setAlerts((curAlerts) => {
3838
const [prevAlert] = curAlerts.splice(idx, 1);
39+
if (!prevAlert) return curAlerts;
40+
3941
clearTimeout(prevAlert.dismissTimeout);
4042
const timeout = alertOptions?.timeout ?? DEFAULT_ALERT_TIMEOUT;
4143
prevAlert.dismissTimeout = setTimeout(() => removeAlert(prevAlert.id), timeout);

plugins/maciVoting/components/PollCard.tsx

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,20 @@
11
import { Button, Card, Heading } from "@aragon/ods";
2-
import { useCallback, useEffect, useMemo, useState, useRef } from "react";
2+
import { useCallback, useEffect, useMemo, useState } from "react";
33
import { useMaci } from "../hooks/useMaci";
44
import { VoteOption } from "../utils/types";
55
import { PleaseWaitSpinner } from "@/components/please-wait";
6-
import { useEthersSigner } from "../hooks/useEthersSigner";
76
import { unixTimestampToDate } from "../utils/formatPollDate";
87
import { useGetPollData } from "../hooks/useGetPollData";
98
import { VoteResultCard } from "./VoteResultCard";
109

1110
const PollCard = ({ pollId }: { pollId: bigint }) => {
1211
// check if the user joined the poll
1312
const { setPollId, onJoinPoll, onVote, isRegistered, hasJoinedPoll, isLoading, error: maciError } = useMaci();
14-
const signer = useEthersSigner();
13+
1514
const [error, setError] = useState<string | undefined>(undefined);
1615
const [voteOption, setVoteOption] = useState<VoteOption | undefined>(undefined);
1716

18-
const { data: { voteStartDate, tallied, voteEnded, disabled, results } = {}, isLoading: isLoadingPollData } =
19-
useGetPollData(pollId);
17+
const { data: { voteStartDate, tallied, voteEnded, disabled, results } = {} } = useGetPollData(pollId);
2018

2119
useEffect(() => {
2220
setError(maciError);
@@ -92,13 +90,7 @@ const PollCard = ({ pollId }: { pollId: bigint }) => {
9290
</div>
9391
)}
9492
<p>The voting period has ended. Here are the results:</p>
95-
<VoteResultCard
96-
results={{
97-
yes: Number(results[0].value),
98-
no: Number(results[1].value),
99-
abstain: Number(results[2].value),
100-
}}
101-
/>
93+
<VoteResultCard pollId={pollId} />
10294
</Card>
10395
</div>
10496
);

plugins/maciVoting/components/VoteResultCard.tsx

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,36 @@
11
"use client";
22

3-
import { CheckCircle, XCircle, MinusCircle, Trophy, Sparkles, AlertTriangle } from "lucide-react";
4-
import { useEffect, useState } from "react";
3+
import { CheckCircle, XCircle, MinusCircle } from "lucide-react";
4+
import { useEffect, useMemo, useState } from "react";
55
import classNames from "classnames";
6+
import { useGetPollData } from "../hooks/useGetPollData";
67

78
type WinnerType = "yes" | "no" | "abstain" | "tie";
89

910
interface VoteResultCardProps {
10-
results: {
11-
yes: number;
12-
no: number;
13-
abstain: number;
14-
};
11+
pollId: bigint;
1512
}
1613

17-
export const VoteResultCard = ({ results }: VoteResultCardProps) => {
14+
export const VoteResultCard = ({ pollId }: VoteResultCardProps) => {
15+
const { data: { results } = {} } = useGetPollData(pollId);
1816
const [isVisible, setIsVisible] = useState(false);
1917

20-
const total = results.yes + results.no + results.abstain;
21-
const yesPercentage = total > 0 ? (results.yes / total) * 100 : 0;
22-
const noPercentage = total > 0 ? (results.no / total) * 100 : 0;
18+
const yes = results ? Number(results[0].value) : 0;
19+
const no = results ? Number(results[1].value) : 0;
20+
const abstain = results ? Number(results[2].value) : 0;
2321

24-
const getWinner = () => {
25-
if (results.yes > results.no) return "yes";
26-
if (results.no > results.yes) return "no";
27-
return "tie";
28-
};
22+
const total = yes + no + abstain;
2923

30-
const winner: WinnerType = getWinner();
24+
const yesPercentage = total > 0 ? (yes / total) * 100 : 0;
25+
const noPercentage = total > 0 ? (no / total) * 100 : 0;
3126

32-
const getWinnerConfig = () => {
27+
const winner = useMemo<WinnerType>(() => {
28+
if (yes > no) return "yes";
29+
if (no > yes) return "no";
30+
return "tie";
31+
}, [yes, no]);
32+
33+
const config = useMemo(() => {
3334
switch (winner) {
3435
case "yes":
3536
return {
@@ -44,9 +45,7 @@ export const VoteResultCard = ({ results }: VoteResultCardProps) => {
4445
percentage: 50,
4546
};
4647
}
47-
};
48-
49-
const config = getWinnerConfig();
48+
}, [noPercentage, winner, yesPercentage]);
5049

5150
useEffect(() => {
5251
setIsVisible(true);
@@ -109,7 +108,7 @@ export const VoteResultCard = ({ results }: VoteResultCardProps) => {
109108
fontWeight: winner === "yes" ? 700 : winner === "no" ? 700 : 400,
110109
}}
111110
>
112-
{results.yes}
111+
{yes}
113112
</div>
114113
<div className={`text-sm ${textClass("yes")}`}>Yes</div>
115114
</div>
@@ -122,7 +121,7 @@ export const VoteResultCard = ({ results }: VoteResultCardProps) => {
122121
fontWeight: winner === "no" ? 700 : winner === "yes" ? 700 : 400,
123122
}}
124123
>
125-
{results.no}
124+
{no}
126125
</div>
127126
<div className={`text-sm ${textClass("no")}`}>No</div>
128127
</div>
@@ -135,7 +134,7 @@ export const VoteResultCard = ({ results }: VoteResultCardProps) => {
135134
fontWeight: 400,
136135
}}
137136
>
138-
{results.abstain}
137+
{abstain}
139138
</div>
140139
<div className={`text-sm ${textClass("abstain")}`}>Abstain</div>
141140
</div>

plugins/maciVoting/components/finalize/finalizeAction.tsx

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
11
import { useCallback, useMemo } from "react";
2-
import { useCoordinator } from "../../hooks/useCoordinator";
32
import { Button } from "@aragon/ods";
43
import { PleaseWaitSpinner } from "@/components/please-wait";
54
import { If } from "@/components/if";
6-
import { useRouter } from "next/router";
5+
import { useCoordinatorFinalize } from "../../hooks/useCoordinatorFinalize";
76

87
interface IFinalizeActionProps {
98
pollId: number;
109
}
1110

1211
export const FinalizeAction: React.FC<IFinalizeActionProps> = ({ pollId }) => {
13-
const router = useRouter();
14-
const { finalizeStatus, finalizeProposal } = useCoordinator();
12+
const { finalizeStatus, finalizeProposal } = useCoordinatorFinalize(pollId);
1513

1614
const finalizationMessage = useMemo(() => {
1715
switch (finalizeStatus) {
@@ -31,9 +29,8 @@ export const FinalizeAction: React.FC<IFinalizeActionProps> = ({ pollId }) => {
3129
}, [finalizeStatus]);
3230

3331
const onClickFinalize = useCallback(async () => {
34-
await finalizeProposal(pollId);
35-
router.reload();
36-
}, [finalizeProposal, pollId, router]);
32+
await finalizeProposal();
33+
}, [finalizeProposal]);
3734

3835
return (
3936
<div className="overflow-hidden rounded-xl bg-neutral-0 pb-2 shadow-neutral">

plugins/maciVoting/contexts/CoordinatorContext.tsx

Lines changed: 8 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
import { EMode } from "@maci-protocol/core";
2-
import { getPoll, isTallied, type ITallyData, Poll__factory as PollFactory } from "@maci-protocol/sdk/browser";
2+
import { type ITallyData } from "@maci-protocol/sdk/browser";
33
import { PUBLIC_CHAIN_NAME, PUBLIC_COORDINATOR_SERVICE_URL, PUBLIC_MACI_ADDRESS } from "@/constants";
4-
import { createContext, type ReactNode, useCallback, useMemo, useState } from "react";
4+
import { createContext, type ReactNode, useCallback, useMemo } from "react";
55
import {
66
type TCoordinatorServiceResult,
77
type IGenerateData,
88
type ICoordinatorContextType,
9-
type FinalizeStatus,
9+
type IFinalizeProposalArgs,
1010
} from "./types";
1111
import { useEthersSigner } from "../hooks/useEthersSigner";
1212
import { toBackendChainFormat } from "../utils/chains";
1313
import { useAlerts } from "@/context/Alerts";
14+
import { useMaci } from "../hooks/useMaci";
1415

1516
export const CoordinatorContext = createContext<ICoordinatorContextType | undefined>(undefined);
1617

@@ -44,8 +45,7 @@ async function makeCoordinatorServicePostRequest<T>(url: string, body: string):
4445
}
4546

4647
export const CoordinatorProvider = ({ children }: { children: ReactNode }) => {
47-
const [finalizeStatus, setFinalizeStatus] = useState<FinalizeStatus>("notStarted");
48-
48+
const { checkMergeStatus, checkIsTallied } = useMaci();
4949
const signer = useEthersSigner();
5050
const { addAlert } = useAlerts();
5151

@@ -84,42 +84,12 @@ export const CoordinatorProvider = ({ children }: { children: ReactNode }) => {
8484
);
8585
}, []);
8686

87-
const checkMergeStatus = useCallback(
88-
async (pollId: number) => {
89-
const { address: pollAddress } = await getPoll({
90-
maciAddress: PUBLIC_MACI_ADDRESS,
91-
pollId,
92-
signer,
93-
});
94-
const poll = PollFactory.connect(pollAddress, signer);
95-
return await poll.stateMerged();
96-
},
97-
[signer]
98-
);
99-
100-
const checkIsTallied = useCallback(
101-
async (pollId: number) => {
102-
if (!signer) {
103-
// eslint-disable-next-line no-console
104-
console.log("No signer");
105-
return false;
106-
}
107-
108-
const isPollTallied = await isTallied({
109-
maciAddress: PUBLIC_MACI_ADDRESS,
110-
pollId: pollId.toString(),
111-
signer,
112-
});
113-
return isPollTallied;
114-
},
115-
[signer]
116-
);
117-
11887
const finalizeProposal = useCallback(
119-
async (pollId: number) => {
88+
async ({ pollId, setFinalizeStatus }: IFinalizeProposalArgs) => {
12089
if (!signer) {
12190
// eslint-disable-next-line no-console
12291
console.log("No signer");
92+
return;
12393
}
12494

12595
const isTallied = await checkIsTallied(pollId);
@@ -185,11 +155,9 @@ export const CoordinatorProvider = ({ children }: { children: ReactNode }) => {
185155

186156
const value = useMemo<ICoordinatorContextType>(
187157
() => ({
188-
finalizeStatus,
189-
checkIsTallied,
190158
finalizeProposal,
191159
}),
192-
[finalizeStatus, checkIsTallied, finalizeProposal]
160+
[finalizeProposal]
193161
);
194162

195163
return <CoordinatorContext.Provider value={value as ICoordinatorContextType}>{children}</CoordinatorContext.Provider>;

plugins/maciVoting/contexts/MaciContext.tsx

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import {
1111
getPoll,
1212
publish,
1313
getSignedupUserData,
14+
Poll__factory as PollFactory,
15+
isTallied,
1416
} from "@maci-protocol/sdk/browser";
1517
import { PUBLIC_MACI_ADDRESS, PUBLIC_MACI_DEPLOYMENT_BLOCK } from "@/constants";
1618
import { useAccount, usePublicClient, useSignMessage } from "wagmi";
@@ -330,6 +332,37 @@ export const MaciProvider = ({ children }: { children: ReactNode }) => {
330332
[signer, maciKeypair, pollId, pollStateIndex, hasJoinedPoll, addAlert, initialVoiceCredits]
331333
);
332334

335+
const checkIsTallied = useCallback(
336+
async (pollId: number) => {
337+
if (!signer) {
338+
// eslint-disable-next-line no-console
339+
console.log("No signer");
340+
return false;
341+
}
342+
343+
const isPollTallied = await isTallied({
344+
maciAddress: PUBLIC_MACI_ADDRESS,
345+
pollId: pollId.toString(),
346+
signer,
347+
});
348+
return isPollTallied;
349+
},
350+
[signer]
351+
);
352+
353+
const checkMergeStatus = useCallback(
354+
async (pollId: number) => {
355+
const { address: pollAddress } = await getPoll({
356+
maciAddress: PUBLIC_MACI_ADDRESS,
357+
pollId,
358+
signer,
359+
});
360+
const poll = PollFactory.connect(pollAddress, signer);
361+
return await poll.stateMerged();
362+
},
363+
[signer]
364+
);
365+
333366
// check if user is connected
334367
useEffect(() => {
335368
setError(undefined);
@@ -529,6 +562,8 @@ export const MaciProvider = ({ children }: { children: ReactNode }) => {
529562
onSignup,
530563
onJoinPoll,
531564
onVote,
565+
checkIsTallied,
566+
checkMergeStatus,
532567
}),
533568
[
534569
isLoading,
@@ -544,6 +579,8 @@ export const MaciProvider = ({ children }: { children: ReactNode }) => {
544579
onSignup,
545580
onJoinPoll,
546581
onVote,
582+
checkIsTallied,
583+
checkMergeStatus,
547584
]
548585
);
549586

plugins/maciVoting/contexts/types.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,13 @@ export type TCoordinatorServiceResult<T, E = Error> = { success: true; data: T }
1616

1717
export type FinalizeStatus = "notStarted" | "merging" | "proving" | "submitting" | "submitted";
1818

19+
export interface IFinalizeProposalArgs {
20+
pollId: number;
21+
setFinalizeStatus: (status: FinalizeStatus) => void;
22+
}
23+
1924
export interface ICoordinatorContextType {
20-
finalizeStatus: FinalizeStatus;
21-
checkIsTallied: (pollId: number) => Promise<boolean>;
22-
finalizeProposal: (pollId: number) => Promise<void>;
25+
finalizeProposal: (args: IFinalizeProposalArgs) => Promise<void>;
2326
}
2427

2528
export interface IMaciContextType {
@@ -37,4 +40,6 @@ export interface IMaciContextType {
3740
onSignup: () => Promise<void>;
3841
onJoinPoll: (pollId: bigint) => Promise<void>;
3942
onVote: (option: VoteOption) => Promise<void>;
43+
checkIsTallied: (pollId: number) => Promise<boolean>;
44+
checkMergeStatus: (pollId: number) => Promise<boolean>;
4045
}

0 commit comments

Comments
 (0)