♻️ Update how we store poll status (#957)

This commit is contained in:
Luke Vella 2023-12-05 14:43:48 +07:00 committed by GitHub
parent 7670db6778
commit 04211ac168
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 108 additions and 186 deletions

View file

@ -75,12 +75,7 @@ export function PollsPage() {
data.length > 0 ? (
<div className="mx-auto grid max-w-3xl gap-3 sm:gap-4">
{data.map((poll) => {
const { title, id: pollId, createdAt, closed: paused } = poll;
const status = poll.event
? "closed"
: paused
? "paused"
: "live";
const { title, id: pollId, createdAt, status } = poll;
return (
<div
key={poll.id}

View file

@ -34,8 +34,6 @@ export const EventCard = () => {
),
);
const status = poll?.event ? "closed" : poll?.closed ? "paused" : "live";
if (!poll) {
return null;
}
@ -49,7 +47,7 @@ export const EventCard = () => {
/>
<div className="bg-pattern p-4 sm:flex sm:flex-row-reverse sm:justify-between sm:px-6">
<div className="mb-2">
<PollStatusBadge status={status} />
<PollStatusBadge status={poll.status} />
</div>
<div className="flex items-start justify-between">
<div className="flex items-start gap-4 sm:gap-6">

View file

@ -42,7 +42,7 @@ import {
import ManagePoll from "@/components/poll/manage-poll";
import NotificationsToggle from "@/components/poll/notifications-toggle";
import { LegacyPollContextProvider } from "@/components/poll/poll-context-provider";
import { PollStatus } from "@/components/poll-status";
import { PollStatusLabel } from "@/components/poll-status";
import { Skeleton } from "@/components/skeleton";
import { Trans } from "@/components/trans";
import { useUser } from "@/components/user-provider";
@ -53,7 +53,6 @@ import { NextPageWithLayout } from "../../types";
const StatusControl = () => {
const poll = usePoll();
const state = poll.event ? "closed" : poll.closed ? "paused" : "live";
const queryClient = trpc.useUtils();
const reopen = trpc.polls.reopen.useMutation({
onMutate: () => {
@ -110,7 +109,7 @@ const StatusControl = () => {
<DropdownMenu modal={false}>
<DropdownMenuTrigger asChild>
<Button>
<PollStatus status={state} />
<PollStatusLabel status={poll.status} />
<ChevronDownIcon className="h-4 w-4" />
</Button>
</DropdownMenuTrigger>

View file

@ -1,11 +1,10 @@
import { PollStatus } from "@rallly/database";
import { cn } from "@rallly/ui";
import { CheckCircleIcon, PauseCircleIcon, RadioIcon } from "lucide-react";
import { Trans } from "@/components/trans";
import { IconComponent } from "@/types";
export type PollState = "live" | "paused" | "closed";
const LabelWithIcon = ({
icon: Icon,
children,
@ -23,11 +22,11 @@ const LabelWithIcon = ({
);
};
export const PollStatus = ({
export const PollStatusLabel = ({
status,
className,
}: {
status: PollState;
status: PollStatus;
className?: string;
}) => {
switch (status) {
@ -43,7 +42,7 @@ export const PollStatus = ({
<Trans i18nKey="pollStatusPaused" defaults="Paused" />
</LabelWithIcon>
);
case "closed":
case "finalized":
return (
<LabelWithIcon icon={CheckCircleIcon} className={className}>
<Trans i18nKey="pollStatusClosed" defaults="Finalized" />
@ -52,13 +51,13 @@ export const PollStatus = ({
}
};
export const PollStatusBadge = ({ status }: { status: PollState }) => {
export const PollStatusBadge = ({ status }: { status: PollStatus }) => {
return (
<PollStatus
<PollStatusLabel
className={cn("rounded-full border py-0.5 pl-1.5 pr-3 text-sm", {
"border-blue-500 text-blue-500": status === "live",
"border-gray-500 text-gray-500": status === "paused",
"border-green-500 text-green-500": status === "closed",
"border-green-500 text-green-500": status === "finalized",
})}
status={status}
/>

View file

@ -65,7 +65,7 @@ const NotificationsToggle: React.FunctionComponent = () => {
loading={watch.isLoading || unwatch.isLoading}
icon={isWatching ? BellRingIcon : BellOffIcon}
data-testid="notifications-toggle"
disabled={poll.demo || user.isGuest}
disabled={user.isGuest}
className="flex items-center gap-2 px-2.5"
onClick={async () => {
if (user.isGuest) {

View file

@ -1,4 +1,4 @@
import { User, VoteType } from "@rallly/database";
import { PollStatus, User, VoteType } from "@rallly/database";
export type GetPollApiResponse = {
id: string;
@ -9,10 +9,9 @@ export type GetPollApiResponse = {
user: User | null;
timeZone: string | null;
adminUrlId: string;
status: PollStatus;
participantUrlId: string;
closed: boolean;
legacy: boolean;
demo: boolean;
createdAt: Date;
deleted: boolean;
};

View file

@ -1,130 +0,0 @@
import { prisma, VoteType } from "@rallly/database";
import dayjs from "dayjs";
import { nanoid } from "nanoid";
const participantData: Array<{ name: string; votes: VoteType[] }> = [
{
name: "Reed",
votes: ["yes", "no", "yes", "no"],
},
{
name: "Susan",
votes: ["yes", "yes", "yes", "no"],
},
{
name: "Johnny",
votes: ["no", "no", "yes", "yes"],
},
{
name: "Ben",
votes: ["yes", "yes", "yes", "yes"],
},
];
const optionValues = ["2022-12-14", "2022-12-15", "2022-12-16", "2022-12-17"];
export const createPoll = async () => {
const pollId = nanoid();
const adminUrlId = nanoid();
const options: Array<{ start: Date; id: string }> = [];
for (let i = 0; i < optionValues.length; i++) {
options.push({ id: nanoid(), start: new Date(optionValues[i]) });
}
const participants: Array<{
name: string;
id: string;
userId: string;
createdAt: Date;
}> = [];
const votes: Array<{
optionId: string;
participantId: string;
type: VoteType;
}> = [];
for (let i = 0; i < participantData.length; i++) {
const { name, votes: participantVotes } = participantData[i];
const participantId = nanoid();
participants.push({
id: participantId,
name,
userId: "user-demo",
createdAt: dayjs()
.add(i * -1, "minutes")
.toDate(),
});
options.forEach((option, index) => {
votes.push({
optionId: option.id,
participantId,
type: participantVotes[index],
});
});
}
await prisma.poll.create({
data: {
id: pollId,
title: "Lunch Meeting",
location: "Starbucks, 901 New York Avenue",
description: `Hey everyone, please choose the dates when you are available to meet for our monthly get together. Looking forward to see you all!`,
demo: true,
adminUrlId,
participantUrlId: nanoid(),
userId: "guest-user",
options: {
createMany: {
data: options,
},
},
participants: {
createMany: {
data: participants,
},
},
votes: {
createMany: {
data: votes,
},
},
},
});
return pollId;
};
export const deletePoll = async (pollId: string) => {
await prisma.$transaction([
prisma.vote.deleteMany({
where: {
pollId,
},
}),
prisma.option.deleteMany({
where: {
pollId,
},
}),
prisma.participant.deleteMany({
where: {
pollId,
},
}),
prisma.comment.deleteMany({
where: {
pollId,
},
}),
prisma.poll.deleteMany({
where: {
id: pollId,
},
}),
]);
};