Skip to content

Commit 22c21e6

Browse files
tractorssjaybuidl
authored andcommitted
feat(web): add-multiple-voting-options-support
1 parent 269d772 commit 22c21e6

File tree

6 files changed

+71
-49
lines changed

6 files changed

+71
-49
lines changed

web/src/context/NewDisputeContext.tsx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ export interface IDisputeTemplate {
3434
interface IDisputeData extends IDisputeTemplate {
3535
courtId: string;
3636
numberOfJurors: number;
37-
numberOfRulingOptions: number;
3837
arbitrationCost?: string;
3938
}
4039

@@ -53,7 +52,6 @@ interface INewDisputeContext {
5352
const initialDisputeData: IDisputeData = {
5453
courtId: "1",
5554
numberOfJurors: 3,
56-
numberOfRulingOptions: 2,
5755
title: "",
5856
description: "",
5957
question: "",
@@ -85,7 +83,6 @@ export const NewDisputeProvider: React.FC<{ children: React.ReactNode }> = ({ ch
8583
const [isSubmittingCase, setIsSubmittingCase] = useState<boolean>(false);
8684
const [isPolicyUploading, setIsPolicyUploading] = useState<boolean>(false);
8785

88-
//TODO: reset data on submit or maybe page leave?
8986
useEffect(() => {
9087
localStorage.setItem("disputeData", JSON.stringify(disputeData));
9188
}, [disputeData]);

web/src/pages/Resolver/NavigationButtons/NextButton.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,7 @@ const NextButton: React.FC<INextButton> = ({ nextRoute }) => {
1414

1515
//checks if each answer is filled in
1616
const areVotingOptionsFilled =
17-
disputeData.question !== "" &&
18-
disputeData.answers.every((answer) => answer.title !== "") &&
19-
disputeData.answers.length === disputeData.numberOfRulingOptions;
17+
disputeData.question !== "" && disputeData.answers.every((answer) => answer.title !== "");
2018

2119
const isButtonDisabled =
2220
(location.pathname.includes("/resolver/title") && !disputeData.title) ||

web/src/pages/Resolver/NavigationButtons/SubmitDisputeButton.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ const SubmitDisputeButton: React.FC = () => {
2828
prepareArbitratorExtradata(disputeData.courtId, disputeData.numberOfJurors, 1), //TODO: decide which dispute kit to use
2929
JSON.stringify(disputeTemplate),
3030
"TODO: mappings",
31-
BigInt(disputeData.numberOfRulingOptions),
31+
BigInt(disputeTemplate.answers.length),
3232
],
3333
value: BigInt(disputeData.arbitrationCost ?? 0),
3434
});
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import React from "react";
2+
import styled, { css } from "styled-components";
3+
import { landscapeStyle } from "styles/landscapeStyle";
4+
import { responsiveSize } from "styles/responsiveSize";
5+
import PlusMinusField from "components/PlusMinusField";
6+
import LabeledInput from "components/LabeledInput";
7+
import { Answer, useNewDisputeContext } from "context/NewDisputeContext";
8+
9+
const OptionsContainer = styled.div`
10+
display: flex;
11+
flex-direction: column;
12+
gap: 30px;
13+
width: 84vw;
14+
15+
${landscapeStyle(
16+
() => css`
17+
width: ${responsiveSize(442, 700, 900)};
18+
`
19+
)}
20+
`;
21+
22+
const StyledPlusMinusField = styled(PlusMinusField)`
23+
align-self: start;
24+
margin: 24px 0px;
25+
`;
26+
27+
const OptionsFields: React.FC = () => {
28+
const { disputeData, setDisputeData } = useNewDisputeContext();
29+
30+
const updateOptions = (value: number) => {
31+
let defaultAnswer: Answer = { title: "" };
32+
let answers = disputeData.answers;
33+
34+
if (value < answers?.length) return setDisputeData({ ...disputeData, answers: answers.splice(0, value) });
35+
if (value > answers?.length) return setDisputeData({ ...disputeData, answers: [...answers, defaultAnswer] });
36+
};
37+
38+
const handleOptionWrite = (event: React.ChangeEvent<HTMLInputElement>, key: number) => {
39+
let answers = disputeData.answers;
40+
answers[key] = { ...answers[key], [event.target.name]: event.target.value };
41+
setDisputeData({ ...disputeData, answers });
42+
};
43+
return (
44+
<>
45+
<OptionsContainer>
46+
{disputeData.answers.map((answer, index) => (
47+
<LabeledInput
48+
name="title"
49+
label={`Voting Option ${index + 1}`}
50+
placeholder="eg. Pay 150 DAI"
51+
key={index}
52+
value={answer.title ?? ""}
53+
onChange={(event) => handleOptionWrite(event, index)}
54+
/>
55+
))}
56+
</OptionsContainer>
57+
<StyledPlusMinusField currentValue={disputeData.answers?.length ?? 2} updateValue={updateOptions} minValue={2} />
58+
</>
59+
);
60+
};
61+
62+
export default OptionsFields;

web/src/pages/Resolver/Parameters/VotingOptions.tsx renamed to web/src/pages/Resolver/Parameters/VotingOptions/index.tsx

Lines changed: 6 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import React from "react";
22
import Header from "pages/Resolver/Header";
33
import styled, { css } from "styled-components";
4-
import NavigationButtons from "../NavigationButtons";
54
import { landscapeStyle } from "styles/landscapeStyle";
65
import { responsiveSize } from "styles/responsiveSize";
76
import { AlertMessage } from "@kleros/ui-components-library";
87
import LabeledInput from "components/LabeledInput";
9-
import { Answer, useNewDisputeContext } from "context/NewDisputeContext";
8+
import { useNewDisputeContext } from "context/NewDisputeContext";
9+
import NavigationButtons from "../../NavigationButtons";
10+
import OptionsFields from "./OptionsFields";
1011

1112
const Container = styled.div`
1213
display: flex;
@@ -18,45 +19,26 @@ const QuestionField = styled(LabeledInput)`
1819
margin-bottom: 58px;
1920
`;
2021

21-
const OptionsContainer = styled.div`
22-
display: flex;
23-
flex-direction: column;
24-
gap: 30px;
25-
width: 84vw;
26-
27-
${landscapeStyle(
28-
() => css`
29-
width: ${responsiveSize(442, 700, 900)};
30-
`
31-
)}
32-
`;
33-
3422
const AlertMessageContainer = styled.div`
3523
width: 84vw;
3624
${landscapeStyle(
3725
() => css`
3826
width: ${responsiveSize(442, 700, 900)};
3927
`
4028
)}
41-
margin-top: 24px;
29+
margin-top: 16px;
4230
> div {
4331
width: 100%;
4432
}
4533
`;
34+
4635
const VotingOptions: React.FC = () => {
4736
const { disputeData, setDisputeData } = useNewDisputeContext();
4837

4938
const handleQuestionWrite = (event: React.ChangeEvent<HTMLInputElement>) => {
5039
setDisputeData({ ...disputeData, question: event.target.value });
5140
};
5241

53-
//TODO: add description too and implement multiple options
54-
const handleOptionWrite = (event: React.ChangeEvent<HTMLInputElement>, key: number) => {
55-
let answers: Answer[] = disputeData.answers;
56-
answers[key].title = event.target.value;
57-
setDisputeData({ ...disputeData, answers });
58-
};
59-
6042
return (
6143
<Container>
6244
<Header text="Voting options" />
@@ -68,24 +50,7 @@ const VotingOptions: React.FC = () => {
6850
value={disputeData.question}
6951
onChange={handleQuestionWrite}
7052
/>
71-
{/* TODO: Add multi-vote support */}
72-
<OptionsContainer>
73-
<LabeledInput
74-
label="Voting Option 1"
75-
placeholder="eg. Pay 250 DAI"
76-
key={0}
77-
value={disputeData.answers[0]?.title ?? ""}
78-
onChange={(event) => handleOptionWrite(event, 0)}
79-
/>
80-
<LabeledInput
81-
label="Voting Option 2"
82-
placeholder="eg. Pay 150 DAI"
83-
key={1}
84-
value={disputeData.answers[1]?.title ?? ""}
85-
onChange={(event) => handleOptionWrite(event, 1)}
86-
/>
87-
</OptionsContainer>
88-
53+
<OptionsFields />
8954
<AlertMessageContainer>
9055
<AlertMessage
9156
title="Add the question and options jurors will see when voting"

web/src/pages/Resolver/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import ConnectWallet from "components/ConnectWallet";
77
import Timeline from "./Timeline";
88
import HeroImage from "components/HeroImage";
99
import Title from "./Briefing/Title";
10-
import { landscapeStyle } from "~src/styles/landscapeStyle";
10+
import { landscapeStyle } from "styles/landscapeStyle";
1111
import Description from "./Briefing/Description";
1212
import Court from "./Parameters/Court";
1313
import Category from "./Parameters/Category";

0 commit comments

Comments
 (0)