From 4486f317b3254d009dcefd5b8993e52ab512f326 Mon Sep 17 00:00:00 2001
From: "Kalle (Sendou)" <38327916+Sendouc@users.noreply.github.com>
Date: Fri, 19 Mar 2021 09:40:10 +0200
Subject: [PATCH] can submit votes
---
app/plus/api.ts | 6 ++
app/plus/components/PlusVotingPage.tsx | 142 ++++++++++++++++---------
app/plus/hooks/usePlusVoting.ts | 41 ++++---
app/plus/service.ts | 17 ++-
4 files changed, 142 insertions(+), 64 deletions(-)
diff --git a/app/plus/api.ts b/app/plus/api.ts
index 1b5ecdf1f..7f0791a4f 100644
--- a/app/plus/api.ts
+++ b/app/plus/api.ts
@@ -22,6 +22,12 @@ const plusApi = createRouter()
return service.getUsersForVoting(user.id);
},
})
+ .query("hasVoted", {
+ resolve({ ctx }) {
+ const user = throwIfNotLoggedIn(ctx.user);
+ return service.hasVoted(user.id);
+ },
+ })
.mutation("suggestion", {
input: suggestionFullSchema,
resolve({ input, ctx }) {
diff --git a/app/plus/components/PlusVotingPage.tsx b/app/plus/components/PlusVotingPage.tsx
index 90cffc322..c98bf81f0 100644
--- a/app/plus/components/PlusVotingPage.tsx
+++ b/app/plus/components/PlusVotingPage.tsx
@@ -1,3 +1,4 @@
+import { Alert, AlertIcon } from "@chakra-ui/alert";
import { Button } from "@chakra-ui/button";
import { Box, HStack } from "@chakra-ui/layout";
import { Progress } from "@chakra-ui/progress";
@@ -5,6 +6,7 @@ import Markdown from "components/common/Markdown";
import SubText from "components/common/SubText";
import UserAvatar from "components/common/UserAvatar";
import { useEffect } from "react";
+import { getVotingRange } from "utils/plus";
import { getFullUsername } from "utils/strings";
import usePlusVoting from "../hooks/usePlusVoting";
import { PlusVotingButton } from "./PlusVotingButton";
@@ -19,17 +21,29 @@ export default function PlusVotingPage() {
progress,
previousUser,
goBack,
+ submit,
+ status,
+ hasVoted,
} = usePlusVoting();
useEffect(() => {
//redirect!!
}, [shouldRedirect]);
- if (isLoading || !plusStatus || !currentUser) return null;
+ if (isLoading || !plusStatus) return null;
+
+ if (hasVoted)
+ return (
+
+
+ Votes succesfully recorded. Voting ends{" "}
+ {getVotingRange().endDate.toLocaleString()}.
+
+ );
return (
- {previousUser && (
+ {previousUser ? (
@@ -47,55 +61,87 @@ export default function PlusVotingPage() {
{previousUser.score}
+ ) : (
+
+
+ asd
+
+
+
)}
-
-
-
- {getFullUsername(currentUser)}
-
-
-
- {currentUser.region === plusStatus.region && (
-
- handleVote({ userId: currentUser.userId, score: -2 })
- }
- />
- )}
- handleVote({ userId: currentUser.userId, score: -1 })}
- />
- handleVote({ userId: currentUser.userId, score: 1 })}
- />
- {currentUser.region === plusStatus.region && (
- handleVote({ userId: currentUser.userId, score: 2 })}
- />
- )}
-
- {currentUser.suggestions && (
-
- Suggestions
- {currentUser.suggestions.map((suggestion) => {
- return (
-
- "{suggestion.description}" -{" "}
- {getFullUsername(suggestion.suggesterUser)}
-
- );
- })}
-
+ {currentUser && (
+ <>
+
+
+
+ {getFullUsername(currentUser)}
+
+
+
+ {currentUser.region === plusStatus.region && (
+
+ handleVote({ userId: currentUser.userId, score: -2 })
+ }
+ />
+ )}
+
+ handleVote({ userId: currentUser.userId, score: -1 })
+ }
+ />
+
+ handleVote({ userId: currentUser.userId, score: 1 })
+ }
+ />
+ {currentUser.region === plusStatus.region && (
+
+ handleVote({ userId: currentUser.userId, score: 2 })
+ }
+ />
+ )}
+
+ {currentUser.suggestions && (
+
+ Suggestions
+ {currentUser.suggestions.map((suggestion) => {
+ return (
+
+ "{suggestion.description}" -{" "}
+ {getFullUsername(suggestion.suggesterUser)}
+
+ );
+ })}
+
+ )}
+ {currentUser.bio && (
+
+ Bio
+
+
+ )}
+ >
)}
- {currentUser.bio && (
-
- Bio
-
+ {previousUser && !currentUser && (
+
+ {" "}
+
)}
diff --git a/app/plus/hooks/usePlusVoting.ts b/app/plus/hooks/usePlusVoting.ts
index c5b7e4c98..1a1e87d7d 100644
--- a/app/plus/hooks/usePlusVoting.ts
+++ b/app/plus/hooks/usePlusVoting.ts
@@ -1,5 +1,7 @@
+import { useToast } from "@chakra-ui/toast";
import { useUser } from "hooks/common";
import { useState } from "react";
+import { getToastOptions } from "utils/getToastOptions";
import { trpc } from "utils/trpc";
import { Unpacked } from "utils/types";
import { votesSchema } from "utils/validators/votes";
@@ -9,29 +11,41 @@ export default function usePlusVoting() {
const [currentIndex, setCurrentIndex] = useState(0);
const [votes, setVotes] = useState>([]);
+ const toast = useToast();
const [user] = useUser();
- const { data: ballotsData, isLoading: isLoadingBallots } = trpc.useQuery([
+
+ const { data: hasVoted, isLoading: hasVotedIsLoading } = trpc.useQuery([
+ "plus.hasVoted",
+ ]);
+ const { data: usersForVoting, isLoading: isLoadingBallots } = trpc.useQuery([
"plus.usersForVoting",
]);
- const { data: statusesData, isLoading: isLoadingStatuses } = trpc.useQuery([
+ const { data: statuses, isLoading: isLoadingStatuses } = trpc.useQuery([
"plus.statuses",
]);
+ const { mutate, status } = trpc.useMutation("plus.vote", {
+ onSuccess() {
+ toast(getToastOptions("Successfully voted", "success"));
+ trpc.invalidateQuery(["plus.hasVoted"]);
+ },
+ onError(error) {
+ toast(getToastOptions(error.message, "error"));
+ },
+ });
- const ownPlusStatus = statusesData?.find(
- (status) => status.user.id === user?.id
- );
+ const ownPlusStatus = statuses?.find((status) => status.user.id === user?.id);
return {
- isLoading: isLoadingBallots || isLoadingStatuses,
- shouldRedirect: !isLoadingBallots && !ballotsData,
+ isLoading: isLoadingBallots || isLoadingStatuses || hasVotedIsLoading,
+ shouldRedirect: !isLoadingBallots && !usersForVoting,
plusStatus: ownPlusStatus,
- currentUser: ballotsData?.[currentIndex],
+ currentUser: usersForVoting?.[currentIndex],
previousUser:
- currentIndex > 0 && ballotsData
- ? { ...ballotsData[currentIndex - 1], ...votes[votes.length - 1] }
+ currentIndex > 0 && usersForVoting
+ ? { ...usersForVoting[currentIndex - 1], ...votes[votes.length - 1] }
: undefined,
- progress: ballotsData
- ? ((currentIndex + 1) / ballotsData.length) * 100
+ progress: usersForVoting
+ ? (currentIndex / usersForVoting.length) * 100
: undefined,
handleVote: (vote: Unpacked>) => {
setVotes([...votes, vote]);
@@ -42,5 +56,8 @@ export default function usePlusVoting() {
setVotes(votes.slice(0, votes.length - 1));
setCurrentIndex(currentIndex - 1);
},
+ submit: () => mutate(votes),
+ status,
+ hasVoted,
};
}
diff --git a/app/plus/service.ts b/app/plus/service.ts
index 03236a221..34207b48d 100644
--- a/app/plus/service.ts
+++ b/app/plus/service.ts
@@ -261,6 +261,14 @@ const getUsersForVoting = async (userId: number) => {
return shuffleArray(result).sort((a, b) => a.region.localeCompare(b.region));
};
+const hasVoted = async (userId: number) => {
+ return Boolean(
+ await prisma.plusBallot.count({
+ where: { voterId: userId, isStale: false },
+ })
+ );
+};
+
const addSuggestion = async ({
input,
userId,
@@ -443,15 +451,15 @@ const addVotes = async ({
if (
input.some((vote) => {
const region = allowedUsers.get(vote.userId);
- if (!region) return false;
+ if (!region) return true;
if (region === usersPlusStatus.region) {
- if (![-2, -1, 1, 2].includes(vote.score)) return false;
+ if (![-2, -1, 1, 2].includes(vote.score)) return true;
} else {
- if (![-1, 1].includes(vote.score)) return false;
+ if (![-1, 1].includes(vote.score)) return true;
}
- return true;
+ return false;
})
) {
throw httpError.badRequest("invalid vote provided");
@@ -479,4 +487,5 @@ export default {
addSuggestion,
addVouch,
addVotes,
+ hasVoted,
};