Skip to content

Commit f7f5936

Browse files
committed
feat(web): add toast notifications for user actions
1 parent 60004e5 commit f7f5936

File tree

10 files changed

+104
-57
lines changed

10 files changed

+104
-57
lines changed

web/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181
"react-markdown": "^8.0.3",
8282
"react-modal": "^3.16.1",
8383
"react-router-dom": "^6.4.2",
84+
"react-toastify": "^9.1.1",
8485
"react-use": "^17.4.0",
8586
"styled-components": "^5.3.6",
8687
"swr": "^1.3.0"

web/src/app.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import Cases from "./pages/Cases";
1212
import Dashboard from "./pages/Dashboard";
1313
import Courts from "./pages/Courts";
1414

15+
import "react-toastify/dist/ReactToastify.css";
16+
1517
const fetcherBuilder =
1618
(url: string) =>
1719
({ query, variables }: { query: string; variables?: any }) => {

web/src/layout/index.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React from "react";
22
import styled from "styled-components";
33
import { Outlet } from "react-router-dom";
4+
import { ToastContainer } from "react-toastify";
45
import Header from "./Header";
56
import Footer from "./Footer";
67

@@ -9,9 +10,15 @@ const Container = styled.div`
910
width: 100%;
1011
`;
1112

13+
const StyledToastContainer = styled(ToastContainer)`
14+
padding: 16px;
15+
padding-top: 70px;
16+
`;
17+
1218
const Layout: React.FC = () => (
1319
<Container>
1420
<Header />
21+
<StyledToastContainer />
1522
<Outlet />
1623
<Footer />
1724
</Container>

web/src/pages/Cases/CaseDetails/Appeal/Classic/Fund.tsx

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { useParams } from "react-router-dom";
44
import { Field, Button } from "@kleros/ui-components-library";
55
import { DisputeKitClassic } from "@kleros/kleros-v2-contracts/typechain-types/src/arbitration/dispute-kits/DisputeKitClassic";
66
import { useConnectedContract } from "hooks/useConnectedContract";
7+
import { wrapWithToast } from "utils/wrapWithToast";
78
import { useParsedAmount } from "hooks/useParsedAmount";
89
import { useETHBalance } from "hooks/queries/useETHBalance";
910

@@ -16,8 +17,6 @@ const Fund: React.FC<IFund> = ({ selectedOption }) => {
1617
const { data: balance } = useETHBalance();
1718
const [amount, setAmount] = useState("");
1819
const parsedAmount = useParsedAmount(amount);
19-
console.log("parsedAmount: ", parsedAmount);
20-
console.log("balance: ", balance);
2120
const [isSending, setIsSending] = useState(false);
2221
const disputeKitClassic = useConnectedContract(
2322
"DisputeKitClassic"
@@ -43,16 +42,15 @@ const Fund: React.FC<IFund> = ({ selectedOption }) => {
4342
typeof id !== "undefined"
4443
) {
4544
setIsSending(true);
46-
disputeKitClassic
47-
.fundAppeal(id, selectedOption, { value: parsedAmount })
48-
.then(
49-
async (tx) =>
50-
await tx.wait().then(() => {
51-
setAmount("");
52-
close();
53-
})
54-
)
55-
.catch()
45+
wrapWithToast(
46+
disputeKitClassic.fundAppeal(id, selectedOption, {
47+
value: parsedAmount,
48+
})
49+
)
50+
.then(() => {
51+
setAmount("");
52+
close();
53+
})
5654
.finally(() => setIsSending(false));
5755
}
5856
}}

web/src/pages/Cases/CaseDetails/Evidence/SubmitEvidenceModal.tsx

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import styled from "styled-components";
33
import Modal from "react-modal";
44
import { Textarea, Button } from "@kleros/ui-components-library";
55
import { DisputeKitClassic } from "@kleros/kleros-v2-contracts/typechain-types/src/arbitration/dispute-kits/DisputeKitClassic";
6+
import { wrapWithToast } from "utils/wrapWithToast";
67
import { useConnectedContract } from "hooks/useConnectedContract";
78

89
const SubmitEvidenceModal: React.FC<{
@@ -36,16 +37,11 @@ const SubmitEvidenceModal: React.FC<{
3637
disabled={isSending}
3738
onClick={() => {
3839
setIsSending(true);
39-
disputeKit
40-
.submitEvidence(evidenceGroup, message)
41-
.then(
42-
async (tx) =>
43-
await tx.wait().then(() => {
44-
setMessage("");
45-
close();
46-
})
47-
)
48-
.catch()
40+
wrapWithToast(disputeKit.submitEvidence(evidenceGroup, message))
41+
.then(() => {
42+
setMessage("");
43+
close();
44+
})
4945
.finally(() => setIsSending(false));
5046
}}
5147
/>

web/src/pages/Cases/CaseDetails/Voting/Binary.tsx

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { DisputeKitClassic } from "@kleros/kleros-v2-contracts/typechain-types/s
55
import { Button, Textarea } from "@kleros/ui-components-library";
66
import { useConnectedContract } from "hooks/useConnectedContract";
77
import { useGetMetaEvidence } from "queries/useGetMetaEvidence";
8+
import { wrapWithToast } from "utils/wrapWithToast";
89

910
const Binary: React.FC<{ arbitrable?: string; voteIDs: string[] }> = ({
1011
arbitrable,
@@ -40,16 +41,15 @@ const Binary: React.FC<{ arbitrable?: string; voteIDs: string[] }> = ({
4041
text={answer}
4142
disabled={isSending}
4243
isLoading={chosenOption === i + 1}
43-
onClick={async () => {
44+
onClick={() => {
4445
setIsSending(true);
4546
setChosenOption(i + 1);
46-
await disputeKit
47-
.castVote(id, voteIDs, i + 1, 0, justification)
48-
.then(async (tx) => await tx.wait(2))
49-
.finally(() => {
50-
setChosenOption(-1);
51-
setIsSending(false);
52-
});
47+
wrapWithToast(
48+
disputeKit.castVote(id, voteIDs, i + 1, 0, justification)
49+
).finally(() => {
50+
setChosenOption(-1);
51+
setIsSending(false);
52+
});
5353
}}
5454
/>
5555
)
@@ -62,16 +62,15 @@ const Binary: React.FC<{ arbitrable?: string; voteIDs: string[] }> = ({
6262
text="Refuse to Arbitrate"
6363
disabled={isSending}
6464
isLoading={chosenOption === 0}
65-
onClick={async () => {
65+
onClick={() => {
6666
setIsSending(true);
6767
setChosenOption(0);
68-
await disputeKit
69-
.castVote(id, voteIDs, 0, 0, justification)
70-
.then(async (tx) => await tx.wait(2))
71-
.finally(() => {
72-
setChosenOption(-1);
73-
setIsSending(false);
74-
});
68+
wrapWithToast(
69+
disputeKit.castVote(id, voteIDs, 0, 0, justification)
70+
).finally(() => {
71+
setChosenOption(-1);
72+
setIsSending(false);
73+
});
7574
}}
7675
/>
7776
</RefuseToArbitrateContainer>

web/src/pages/Courts/CourtDetails/StakeModal.tsx

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { PNK } from "@kleros/kleros-v2-contracts/typechain-types/src/arbitration
88
import { KlerosCore } from "@kleros/kleros-v2-contracts/typechain-types/src/arbitration/KlerosCore";
99
import { useWeb3 } from "hooks/useWeb3";
1010
import { useConnectedContract } from "hooks/useConnectedContract";
11+
import { wrapWithToast } from "utils/wrapWithToast";
1112
import { useParsedAmount } from "hooks/useParsedAmount";
1213
import { usePNKBalance } from "queries/usePNKBalance";
1314
import { usePNKAllowance } from "queries/usePNKAllowance";
@@ -80,16 +81,12 @@ const AllowanceButton: React.FC<IAllowanceButton> = ({
8081
}
8182
onClick={() => {
8283
setIsSending(true);
83-
pnk
84-
.increaseAllowance(klerosCore.address, parsedAmount.sub(allowance!))
85-
.then(
86-
async (tx) =>
87-
await tx.wait().then(() => {
88-
console.log("nice!");
89-
})
84+
wrapWithToast(
85+
pnk.increaseAllowance(
86+
klerosCore.address,
87+
parsedAmount.sub(allowance!)
9088
)
91-
.catch()
92-
.finally(() => setIsSending(false));
89+
).finally(() => setIsSending(false));
9390
}}
9491
/>
9592
);
@@ -117,16 +114,11 @@ const StakeButton: React.FC<IStakeButton> = ({
117114
onClick={() => {
118115
if (typeof id !== "undefined") {
119116
setIsSending(true);
120-
klerosCore
121-
.setStake(id, parsedAmount)
122-
.then(
123-
async (tx) =>
124-
await tx.wait().then(() => {
125-
setAmount("");
126-
close();
127-
})
128-
)
129-
.catch()
117+
wrapWithToast(klerosCore.setStake(id, parsedAmount))
118+
.then(() => {
119+
setAmount("");
120+
close();
121+
})
130122
.finally(() => setIsSending(false));
131123
}
132124
}}

web/src/styles/global-style.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
import { createGlobalStyle } from "styled-components";
22

33
export const GlobalStyle = createGlobalStyle`
4+
:root {
5+
--toastify-color-info: ${({ theme }) => theme.primaryBlue};
6+
--toastify-color-success: ${({ theme }) => theme.success};
7+
--toastify-color-warning: ${({ theme }) => theme.warning};
8+
--toastify-color-error: ${({ theme }) => theme.error};
9+
}
10+
411
body {
512
font-family: "Open Sans", sans-serif;
613
margin: 0px;

web/src/utils/wrapWithToast.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { toast, ToastPosition, Theme } from "react-toastify";
2+
import { ContractTransaction } from "ethers";
3+
4+
const OPTIONS = {
5+
position: "top-center" as ToastPosition,
6+
autoClose: 5000,
7+
hideProgressBar: false,
8+
closeOnClick: true,
9+
pauseOnHover: true,
10+
draggable: true,
11+
progress: undefined,
12+
theme: "colored" as Theme,
13+
};
14+
15+
export async function wrapWithToast(tx: Promise<ContractTransaction>) {
16+
toast.info("Transaction initiated", OPTIONS);
17+
await tx
18+
.then((tx) => {
19+
tx.wait(2);
20+
toast.success("Transaction mined!", OPTIONS);
21+
})
22+
.catch((error) => {
23+
toast.error(error.message, OPTIONS);
24+
});
25+
}

yarn.lock

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2353,6 +2353,7 @@ __metadata:
23532353
react-markdown: ^8.0.3
23542354
react-modal: ^3.16.1
23552355
react-router-dom: ^6.4.2
2356+
react-toastify: ^9.1.1
23562357
react-use: ^17.4.0
23572358
styled-components: ^5.3.6
23582359
swr: ^1.3.0
@@ -8141,6 +8142,13 @@ __metadata:
81418142
languageName: node
81428143
linkType: hard
81438144

8145+
"clsx@npm:^1.1.1":
8146+
version: 1.2.1
8147+
resolution: "clsx@npm:1.2.1"
8148+
checksum: 30befca8019b2eb7dbad38cff6266cf543091dae2825c856a62a8ccf2c3ab9c2907c4d12b288b73101196767f66812365400a227581484a05f968b0307cfaf12
8149+
languageName: node
8150+
linkType: hard
8151+
81448152
"code-point-at@npm:^1.0.0":
81458153
version: 1.1.0
81468154
resolution: "code-point-at@npm:1.1.0"
@@ -19830,6 +19838,18 @@ __metadata:
1983019838
languageName: node
1983119839
linkType: hard
1983219840

19841+
"react-toastify@npm:^9.1.1":
19842+
version: 9.1.1
19843+
resolution: "react-toastify@npm:9.1.1"
19844+
dependencies:
19845+
clsx: ^1.1.1
19846+
peerDependencies:
19847+
react: ">=16"
19848+
react-dom: ">=16"
19849+
checksum: 2039255539961a9b4d77b2656f120b20abe46cb0c699a7f3c0af23b4ef669d9c4d24dae6b8f4954b5efd83edf6d6e23614a29e94e9ee0d2647741fba9ba2db85
19850+
languageName: node
19851+
linkType: hard
19852+
1983319853
"react-universal-interface@npm:^0.6.2":
1983419854
version: 0.6.2
1983519855
resolution: "react-universal-interface@npm:0.6.2"

0 commit comments

Comments
 (0)