Skip to content

Commit

Permalink
feat: possible to duplicate a votation (#192)
Browse files Browse the repository at this point in the history
* feat: possible to duplicate an ended votation

* test: add new method

* feat: add duplicate button to not started votation
  • Loading branch information
edalholt authored Sep 24, 2023
1 parent 85bd3ba commit ed4a52d
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 19 deletions.
39 changes: 29 additions & 10 deletions frontend/src/components/EditAssembly.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,14 @@ import {
import { getVotations } from "../services/votation";
import { AssemblyType } from "../types/assembly";
import VotationPanel from "./VotationPanel";
import { VoteType } from "../types/votes";
import { OptionType, VoteType } from "../types/votes";
import { Results } from "./Results";
import { useMediaQuery } from "@mantine/hooks";
import useWebSocket from "react-use-websocket";
import { showNotification } from "@mantine/notifications";

export function EditAssembly(state: { group: UserDataGroupType }) {
const breakpoint = useMediaQuery("(min-width: 800px)");
const breakpoint = useMediaQuery("(min-width: 1010px)");
const [group, setGroup] = useState<UserDataGroupType>(state.group);
const [votations, setVotations] = useState<VoteType[]>([]);
const [assembly, setAssembly] = useState<AssemblyType | undefined>();
Expand Down Expand Up @@ -108,7 +109,7 @@ export function EditAssembly(state: { group: UserDataGroupType }) {
navigate("/admin");
}

async function addCase() {
async function addCase(votationTemplate?: VoteType) {
// Creates a temporary case to the votation list, this is not saved as a votation in the database before the required values are provided.
// Only one element can exist at the same time, the user therefore has to finish editing the current temporary element before creating another one.
if (!votations.some((votation) => votation._id == "temp")) {
Expand All @@ -117,17 +118,22 @@ export function EditAssembly(state: { group: UserDataGroupType }) {
...votations,
{
_id: "temp",
title: "Placeholder",
title: votationTemplate ? votationTemplate.title : "Placeholder",
caseNumber: 0.1,
voteText: "",
voteText: votationTemplate ? votationTemplate.voteText : "",
voted: [],
options: [],
options: votationTemplate ? votationTemplate.options : [],
isFinished: false,
isActive: false,
numberParticipants: 0,
editable: true,
},
]);
} else {
showNotification({
title: "Error",
message: "You can only create one new votation at a time",
});
}
}

Expand Down Expand Up @@ -288,15 +294,19 @@ export function EditAssembly(state: { group: UserDataGroupType }) {
</>
)}

<Button onClick={addCase} m={10} data-testid="add-case-button">
Add case
<Button
onClick={() => addCase()}
m={10}
data-testid="add-case-button"
>
Add votation
</Button>
</Container>
</Container>
<Container p={0} pt={"xs"} w={breakpoint ? "45%" : "95%"}>
{votations.length < 1 ? (
<Text data-testid="no-cases-warning">
There are currently no cases
There are currently no votations in this assembly.
</Text>
) : (
<Accordion
Expand All @@ -318,7 +328,13 @@ export function EditAssembly(state: { group: UserDataGroupType }) {
.sort((a, b) => a.caseNumber - b.caseNumber)
.map((vote: VoteType) => {
return vote.isFinished ? (
<Results key={vote._id} votation={vote} />
<Results
key={vote._id}
votation={vote}
addCase={(votationTemplate: VoteType) =>
addCase(votationTemplate)
}
/>
) : (
<VotationPanel
// Passing accordionActiveTabs to VotationPanel so it can provide it's ID to remain open when vote is submitted.
Expand All @@ -333,6 +349,9 @@ export function EditAssembly(state: { group: UserDataGroupType }) {
setIsChanged={setIsChanged}
assemblyStatus={assembly.isActive}
initEditable={vote.editable || false}
addCase={(votationTemplate: VoteType) =>
addCase(votationTemplate)
}
/>
);
})}
Expand Down
20 changes: 18 additions & 2 deletions frontend/src/components/Results.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
import { Accordion, Container, Card, Progress, Text } from "@mantine/core";
import {
Accordion,
Container,
Card,
Progress,
Text,
Button,
} from "@mantine/core";
import { useMediaQuery } from "@mantine/hooks";
import { VoteType } from "../types/votes";
import { useEffect, useState } from "react";

export function Results({ votation }: { votation: VoteType }) {
export function Results({
votation,
addCase,
}: {
votation: VoteType;
addCase: (votation: VoteType) => void;
}) {
const matches = useMediaQuery("(min-width: 400px)");
const [isOpen, setIsOpen] = useState(false);

Expand Down Expand Up @@ -99,6 +112,9 @@ export function Results({ votation }: { votation: VoteType }) {
votation.voted.length} of {votation.numberParticipants || 0}{" "}
participants did not vote
</Text>
<Button mt={15} onClick={() => addCase(votation)}>
Duplicate votation
</Button>
</Card>
</Accordion.Panel>
</Accordion.Item>
Expand Down
21 changes: 15 additions & 6 deletions frontend/src/components/VotationPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ function VotationPanel({
setIsChanged,
assemblyStatus,
initEditable,
addCase,
}: {
accordionActiveTabs: string[];
setAccordionActiveTabs: (tabs: string[]) => void;
Expand All @@ -50,6 +51,7 @@ function VotationPanel({
setIsChanged: React.Dispatch<React.SetStateAction<boolean>>;
assemblyStatus: boolean;
initEditable: boolean;
addCase: (votation: VoteType) => void;
}) {
const [editable, setEditable] = useState(initEditable);
const [isFinishChecked, setIsFinishChecked] = useState<boolean>(false);
Expand All @@ -69,7 +71,6 @@ function VotationPanel({
});
const { classes } = useStyles();
const matches = useMediaQuery("(min-width: 400px)");
const participantMatch = useMediaQuery("(min-width: 500px)");
const [defaultOptions] = useState<string[]>(["Yes", "No", "Blank"]);
const [options, setOptions] = useState<string[]>(
votation.options.map((option) => {
Expand Down Expand Up @@ -282,7 +283,8 @@ function VotationPanel({
<Button
color={"green"}
disabled={votation.isFinished}
m={matches ? 10 : 5}
m={5}
ml={10}
onClick={() => {
activateVote(votation);
setIsEndChecked(false);
Expand All @@ -297,18 +299,25 @@ function VotationPanel({
onClick={() => {
setEditable(true);
}}
w={matches ? "auto" : "30%"}
m={5}
color={"gray"}
disabled={votation.isFinished || votation.isActive}
data-testid="edit-case-button"
>
Edit
</Button>
<Button
w={matches ? "auto" : "60%"}
onClick={() => {
addCase(votation);
}}
m={5}
disabled={votation.isFinished || votation.isActive}
data-testid="edit-case-button"
>
Duplicate
</Button>
<Button
color={"red"}
m={matches ? 10 : 5}
m={5}
disabled={votation.isFinished || votation.isActive}
onClick={
!isEndChecked
Expand Down
6 changes: 5 additions & 1 deletion frontend/src/tests/Results.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,11 @@ describe("Result component test", () => {
}}
>
<Accordion>
<Results key={votation._id} votation={votation} />
<Results
key={votation._id}
votation={votation}
addCase={() => {}}
/>
</Accordion>
</MantineProvider>
</BrowserRouter>
Expand Down

0 comments on commit ed4a52d

Please sign in to comment.