2023-09-01 19:43:15 -06:00
|
|
|
"use client";
|
|
|
|
|
2023-09-27 12:46:15 -06:00
|
|
|
import { EventTypes } from "@/_utils/types";
|
2023-09-01 19:43:15 -06:00
|
|
|
import Image from "next/image";
|
|
|
|
import { useEffect, useState } from "react";
|
|
|
|
|
2023-10-08 13:21:30 -06:00
|
|
|
import { experimental_useOptimistic } from "react";
|
|
|
|
|
2023-09-27 12:46:15 -06:00
|
|
|
import LoadingIndicator from "@/_components/LoadingIndicator";
|
|
|
|
import type { PresenceItem, RoomResponse, VoteResponse } from "@/_utils/types";
|
|
|
|
import { useUser } from "@clerk/nextjs";
|
|
|
|
import { useChannel, usePresence } from "ably/react";
|
|
|
|
import { isAdmin, isVIP, jsonToCsv } from "app/_utils/helpers";
|
|
|
|
import { env } from "env.mjs";
|
2023-09-01 19:43:15 -06:00
|
|
|
import { useParams } from "next/navigation";
|
2023-09-27 12:46:15 -06:00
|
|
|
import { FaShieldAlt } from "react-icons/fa";
|
|
|
|
import { GiStarFormation } from "react-icons/gi";
|
2023-09-01 19:43:15 -06:00
|
|
|
import {
|
2023-10-04 14:45:35 -06:00
|
|
|
IoCheckmarkCircleOutline,
|
|
|
|
IoCopyOutline,
|
|
|
|
IoDownloadOutline,
|
|
|
|
IoEyeOffOutline,
|
|
|
|
IoEyeOutline,
|
|
|
|
IoHourglassOutline,
|
|
|
|
IoReloadOutline,
|
|
|
|
IoSaveOutline,
|
2023-09-01 19:43:15 -06:00
|
|
|
} from "react-icons/io5";
|
|
|
|
import { RiVipCrownFill } from "react-icons/ri";
|
2023-09-24 23:49:24 -06:00
|
|
|
import NoRoomUI from "./NoRoomUI";
|
2023-09-06 12:57:13 -06:00
|
|
|
|
2023-09-06 12:53:48 -06:00
|
|
|
const VoteUI = () => {
|
2023-09-01 19:43:15 -06:00
|
|
|
const params = useParams();
|
|
|
|
const roomId = params?.id as string;
|
2023-09-06 13:00:01 -06:00
|
|
|
const { user } = useUser();
|
2023-09-01 19:43:15 -06:00
|
|
|
|
|
|
|
const [storyNameText, setStoryNameText] = useState<string>("");
|
|
|
|
const [roomScale, setRoomScale] = useState<string>("");
|
|
|
|
const [copied, setCopied] = useState<boolean>(false);
|
|
|
|
|
2023-09-24 23:49:24 -06:00
|
|
|
const [roomFromDb, setRoomFromDb] = useState<RoomResponse>();
|
|
|
|
const [votesFromDb, setVotesFromDb] = useState<VoteResponse>(undefined);
|
2023-09-09 19:25:23 -06:00
|
|
|
|
2023-10-08 13:21:30 -06:00
|
|
|
const [optimisticVotes, setOptimisticVotes] =
|
|
|
|
experimental_useOptimistic(votesFromDb);
|
|
|
|
|
2023-09-27 12:52:48 -06:00
|
|
|
const getRoomHandler = () => {
|
2023-09-27 12:46:15 -06:00
|
|
|
fetch(`/api/internal/room/${roomId}`, {
|
2023-09-24 23:49:24 -06:00
|
|
|
cache: "no-cache",
|
|
|
|
method: "GET",
|
2023-10-04 14:45:35 -06:00
|
|
|
})
|
|
|
|
.then(async (response) => {
|
|
|
|
const dbRoom = (await response.json()) as RoomResponse;
|
|
|
|
setRoomFromDb(dbRoom);
|
|
|
|
})
|
|
|
|
.catch(() => {
|
|
|
|
setRoomFromDb(null);
|
|
|
|
});
|
2023-09-09 19:25:23 -06:00
|
|
|
};
|
2023-09-01 19:43:15 -06:00
|
|
|
|
2023-09-09 19:25:23 -06:00
|
|
|
const getVotesHandler = async () => {
|
2023-09-24 23:49:24 -06:00
|
|
|
const dbVotesResponse = await fetch(`/api/internal/room/${roomId}/votes`, {
|
|
|
|
cache: "no-cache",
|
|
|
|
method: "GET",
|
|
|
|
});
|
|
|
|
const dbVotes = (await dbVotesResponse.json()) as VoteResponse;
|
2023-09-09 19:25:23 -06:00
|
|
|
setVotesFromDb(dbVotes);
|
|
|
|
};
|
2023-09-01 19:43:15 -06:00
|
|
|
|
2023-09-24 23:49:24 -06:00
|
|
|
useChannel(
|
2023-09-01 19:43:15 -06:00
|
|
|
{
|
|
|
|
channelName: `${env.NEXT_PUBLIC_APP_ENV}-${roomId}`,
|
|
|
|
},
|
2023-09-24 23:49:24 -06:00
|
|
|
({ name }: { name: string }) => {
|
2023-09-01 19:43:15 -06:00
|
|
|
if (name === EventTypes.ROOM_UPDATE) {
|
2023-09-09 19:25:23 -06:00
|
|
|
void getVotesHandler();
|
|
|
|
void getRoomHandler();
|
2023-09-01 19:43:15 -06:00
|
|
|
} else if (name === EventTypes.VOTE_UPDATE) {
|
2023-09-09 19:25:23 -06:00
|
|
|
void getVotesHandler();
|
2023-09-01 19:43:15 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2023-09-24 23:49:24 -06:00
|
|
|
const { presenceData } = usePresence<PresenceItem>(
|
2023-09-01 19:43:15 -06:00
|
|
|
`${env.NEXT_PUBLIC_APP_ENV}-${roomId}`,
|
|
|
|
{
|
2023-09-06 13:00:00 -06:00
|
|
|
name: (user?.fullName ?? user?.username) || "",
|
2023-09-01 19:43:15 -06:00
|
|
|
image: user?.imageUrl || "",
|
|
|
|
client_id: user?.id || "unknown",
|
|
|
|
isAdmin: isAdmin(user?.publicMetadata),
|
|
|
|
isVIP: isVIP(user?.publicMetadata),
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2023-09-24 23:49:24 -06:00
|
|
|
// Init Story name
|
2023-09-01 19:43:15 -06:00
|
|
|
useEffect(() => {
|
|
|
|
if (roomFromDb) {
|
|
|
|
setStoryNameText(roomFromDb.storyName || "");
|
|
|
|
setRoomScale(roomFromDb.scale || "ERROR");
|
2023-09-09 19:25:23 -06:00
|
|
|
} else {
|
|
|
|
void getRoomHandler();
|
2023-09-10 23:00:00 -06:00
|
|
|
void getVotesHandler();
|
2023-09-01 19:43:15 -06:00
|
|
|
}
|
|
|
|
}, [roomFromDb, roomId, user]);
|
|
|
|
|
|
|
|
// Helper functions
|
|
|
|
const getVoteForCurrentUser = () => {
|
|
|
|
if (roomFromDb) {
|
2023-09-06 12:53:48 -06:00
|
|
|
return (
|
2023-10-08 13:21:30 -06:00
|
|
|
optimisticVotes &&
|
|
|
|
optimisticVotes.find((vote) => vote.userId === user?.id)
|
2023-09-06 12:53:48 -06:00
|
|
|
);
|
2023-09-01 19:43:15 -06:00
|
|
|
} else {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2023-09-09 19:25:23 -06:00
|
|
|
const setVoteHandler = async (value: string) => {
|
2023-10-08 13:21:30 -06:00
|
|
|
const newVotes = optimisticVotes?.map((vote) => {
|
|
|
|
if (vote.userId === user?.id) {
|
|
|
|
return {
|
|
|
|
...vote,
|
|
|
|
value,
|
|
|
|
};
|
|
|
|
} else {
|
|
|
|
return vote;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
setOptimisticVotes(newVotes);
|
|
|
|
|
2023-09-01 19:43:15 -06:00
|
|
|
if (roomFromDb) {
|
2023-09-24 23:49:24 -06:00
|
|
|
await fetch(`/api/internal/room/${roomId}/vote`, {
|
|
|
|
cache: "no-cache",
|
|
|
|
method: "PUT",
|
|
|
|
body: JSON.stringify({
|
|
|
|
value,
|
|
|
|
}),
|
|
|
|
});
|
2023-09-01 19:43:15 -06:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2023-09-09 19:25:23 -06:00
|
|
|
const setRoomHandler = async (
|
|
|
|
visible: boolean,
|
|
|
|
reset = false,
|
|
|
|
log = false
|
|
|
|
) => {
|
2023-09-01 19:43:15 -06:00
|
|
|
if (roomFromDb) {
|
2023-09-24 23:49:24 -06:00
|
|
|
await fetch(`/api/internal/room/${roomId}`, {
|
|
|
|
cache: "no-cache",
|
|
|
|
method: "PUT",
|
|
|
|
body: JSON.stringify({
|
|
|
|
name: storyNameText,
|
|
|
|
visible,
|
|
|
|
scale: roomScale,
|
|
|
|
reset,
|
|
|
|
log,
|
|
|
|
}),
|
|
|
|
});
|
2023-09-01 19:43:15 -06:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const downloadLogs = () => {
|
2023-10-08 13:21:30 -06:00
|
|
|
if (roomFromDb && optimisticVotes) {
|
2023-09-01 19:43:15 -06:00
|
|
|
const jsonObject = roomFromDb?.logs
|
|
|
|
.map((item) => {
|
|
|
|
return {
|
|
|
|
id: item.id,
|
|
|
|
created_at: item.created_at,
|
|
|
|
userId: item.userId,
|
|
|
|
roomId: item.roomId,
|
|
|
|
roomName: item.roomName,
|
|
|
|
storyName: item.storyName,
|
|
|
|
scale: item.scale,
|
|
|
|
votes: item.votes,
|
|
|
|
};
|
|
|
|
})
|
|
|
|
.concat({
|
|
|
|
id: "LATEST",
|
|
|
|
created_at: new Date(),
|
|
|
|
userId: roomFromDb.userId,
|
|
|
|
roomId: roomFromDb.id,
|
|
|
|
roomName: roomFromDb.roomName,
|
|
|
|
storyName: storyNameText,
|
|
|
|
scale: roomScale,
|
2023-10-08 13:21:30 -06:00
|
|
|
votes: optimisticVotes.map((vote) => {
|
2023-09-01 19:43:15 -06:00
|
|
|
return {
|
|
|
|
value: vote.value,
|
|
|
|
};
|
|
|
|
}),
|
|
|
|
});
|
|
|
|
|
2023-09-03 16:04:35 -06:00
|
|
|
jsonToCsv(jsonObject, `sp_${roomId}.csv`);
|
2023-09-01 19:43:15 -06:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const copyRoomURLHandler = () => {
|
|
|
|
navigator.clipboard
|
|
|
|
.writeText(window.location.href)
|
|
|
|
.then(() => {
|
|
|
|
console.log(`Copied Room Link to Clipboard!`);
|
|
|
|
setCopied(true);
|
|
|
|
setTimeout(() => {
|
|
|
|
setCopied(false);
|
|
|
|
}, 2000);
|
|
|
|
})
|
|
|
|
.catch(() => {
|
|
|
|
console.log(`Error Copying Room Link to Clipboard!`);
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
const voteString = (
|
|
|
|
visible: boolean,
|
|
|
|
votes: typeof votesFromDb,
|
|
|
|
presenceItem: PresenceItem
|
|
|
|
) => {
|
|
|
|
const matchedVote = votes?.find(
|
|
|
|
(vote) => vote.userId === presenceItem.client_id
|
|
|
|
);
|
|
|
|
|
|
|
|
if (visible) {
|
|
|
|
if (!!matchedVote) {
|
2023-10-04 14:45:35 -06:00
|
|
|
return <div>{matchedVote.value}</div>;
|
2023-09-01 19:43:15 -06:00
|
|
|
} else {
|
2023-09-24 23:49:24 -06:00
|
|
|
return <IoHourglassOutline className="text-xl text-error" />;
|
2023-09-01 19:43:15 -06:00
|
|
|
}
|
|
|
|
} else if (!!matchedVote) {
|
2023-09-24 23:49:24 -06:00
|
|
|
return <IoCheckmarkCircleOutline className="text-xl text-success" />;
|
2023-09-01 19:43:15 -06:00
|
|
|
} else {
|
|
|
|
return (
|
2023-09-24 23:49:24 -06:00
|
|
|
<IoHourglassOutline className="text-xl animate-spin text-warning" />
|
2023-09-01 19:43:15 -06:00
|
|
|
);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Room is loading
|
|
|
|
if (roomFromDb === undefined) {
|
2023-09-06 13:00:00 -06:00
|
|
|
return <LoadingIndicator />;
|
2023-09-01 19:43:15 -06:00
|
|
|
// Room has been loaded
|
|
|
|
} else if (roomFromDb) {
|
|
|
|
return (
|
2023-09-24 23:49:24 -06:00
|
|
|
<div className="flex flex-col gap-4 text-center justify-center items-center">
|
2023-10-04 14:45:35 -06:00
|
|
|
<div className="text-2xl">{roomFromDb.roomName}</div>
|
2023-09-24 23:49:24 -06:00
|
|
|
<div className="flex flex-row flex-wrap text-center justify-center items-center gap-1 text-md">
|
2023-09-01 19:43:15 -06:00
|
|
|
<div>ID:</div>
|
2023-10-04 14:45:35 -06:00
|
|
|
<div>{roomFromDb.id}</div>
|
2023-09-01 19:43:15 -06:00
|
|
|
|
|
|
|
<button>
|
2023-10-04 14:45:35 -06:00
|
|
|
{copied ? (
|
2023-09-01 19:43:15 -06:00
|
|
|
<IoCheckmarkCircleOutline className="mx-1 text-success animate-bounce" />
|
|
|
|
) : (
|
|
|
|
<IoCopyOutline
|
|
|
|
className="mx-1 hover:text-primary"
|
2023-10-04 14:45:35 -06:00
|
|
|
onClick={copyRoomURLHandler}
|
2023-09-01 19:43:15 -06:00
|
|
|
></IoCopyOutline>
|
2023-10-04 14:45:35 -06:00
|
|
|
)}
|
2023-09-01 19:43:15 -06:00
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
|
2023-10-04 14:45:35 -06:00
|
|
|
{roomFromDb && (
|
2023-09-24 23:49:24 -06:00
|
|
|
<div className="card card-compact bg-base-100 shadow-xl">
|
2023-09-01 19:43:15 -06:00
|
|
|
<div className="card-body">
|
2023-10-04 14:45:35 -06:00
|
|
|
<h2 className="card-title mx-auto">
|
|
|
|
Story: {roomFromDb.storyName}
|
|
|
|
</h2>
|
2023-09-01 19:43:15 -06:00
|
|
|
|
2023-09-24 23:49:24 -06:00
|
|
|
<ul className="p-0 flex flex-row flex-wrap justify-center items-center text-ceter gap-4">
|
2023-10-04 14:45:35 -06:00
|
|
|
{presenceData &&
|
2023-09-01 19:43:15 -06:00
|
|
|
presenceData
|
|
|
|
.filter(
|
|
|
|
(value, index, self) =>
|
|
|
|
index ===
|
|
|
|
self.findIndex(
|
|
|
|
(presenceItem) =>
|
|
|
|
presenceItem.clientId === value.clientId
|
|
|
|
)
|
|
|
|
)
|
|
|
|
.map((presenceItem) => {
|
|
|
|
return (
|
|
|
|
<li
|
2023-10-04 14:45:35 -06:00
|
|
|
key={presenceItem.clientId}
|
2023-09-01 19:43:15 -06:00
|
|
|
className="flex flex-row items-center justify-center gap-2"
|
|
|
|
>
|
2023-09-24 23:49:24 -06:00
|
|
|
<div className="w-10 rounded-full avatar">
|
2023-09-01 19:43:15 -06:00
|
|
|
<Image
|
2023-10-04 14:45:35 -06:00
|
|
|
src={presenceItem.data.image}
|
|
|
|
alt={`${presenceItem.data.name}'s Profile Picture`}
|
|
|
|
height={32}
|
|
|
|
width={32}
|
2023-09-01 19:43:15 -06:00
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
|
2023-09-24 23:49:24 -06:00
|
|
|
<p className="flex flex-row flex-wrap text-center justify-center items-center gap-1 text-md">
|
2023-10-04 14:45:35 -06:00
|
|
|
{presenceItem.data.name}{" "}
|
|
|
|
{presenceItem.data.isAdmin && (
|
2023-09-01 19:43:15 -06:00
|
|
|
<span
|
|
|
|
className="tooltip tooltip-primary"
|
|
|
|
data-tip="Admin"
|
|
|
|
>
|
|
|
|
<FaShieldAlt className="inline-block text-primary" />
|
|
|
|
</span>
|
2023-10-04 14:45:35 -06:00
|
|
|
)}{" "}
|
|
|
|
{presenceItem.data.isVIP && (
|
2023-09-01 19:43:15 -06:00
|
|
|
<span
|
|
|
|
className="tooltip tooltip-secondary"
|
|
|
|
data-tip="VIP"
|
|
|
|
>
|
|
|
|
<GiStarFormation className="inline-block text-secondary" />
|
|
|
|
</span>
|
2023-10-04 14:45:35 -06:00
|
|
|
)}{" "}
|
|
|
|
{presenceItem.clientId === roomFromDb.userId && (
|
2023-09-01 19:43:15 -06:00
|
|
|
<span
|
|
|
|
className="tooltip tooltip-warning"
|
|
|
|
data-tip="Room Owner"
|
|
|
|
>
|
|
|
|
<RiVipCrownFill className="inline-block text-yellow-500" />
|
|
|
|
</span>
|
2023-10-04 14:45:35 -06:00
|
|
|
)}
|
|
|
|
{" : "}
|
2023-09-01 19:43:15 -06:00
|
|
|
</p>
|
|
|
|
|
2023-10-04 14:45:35 -06:00
|
|
|
{roomFromDb &&
|
2023-10-08 13:21:30 -06:00
|
|
|
optimisticVotes &&
|
2023-09-01 19:43:15 -06:00
|
|
|
voteString(
|
|
|
|
roomFromDb.visible,
|
2023-10-08 13:21:30 -06:00
|
|
|
optimisticVotes,
|
2023-09-01 19:43:15 -06:00
|
|
|
presenceItem.data
|
2023-10-04 14:45:35 -06:00
|
|
|
)}
|
2023-09-01 19:43:15 -06:00
|
|
|
</li>
|
|
|
|
);
|
2023-10-04 14:45:35 -06:00
|
|
|
})}
|
2023-09-01 19:43:15 -06:00
|
|
|
</ul>
|
|
|
|
|
2023-10-04 14:45:35 -06:00
|
|
|
<div className="join md:btn-group-horizontal mx-auto">
|
|
|
|
{roomFromDb.scale?.split(",").map((scaleItem, index) => {
|
2023-09-01 19:43:15 -06:00
|
|
|
return (
|
|
|
|
<button
|
2023-10-04 14:45:35 -06:00
|
|
|
key={index}
|
|
|
|
className={`join-item ${
|
|
|
|
getVoteForCurrentUser()?.value === scaleItem
|
|
|
|
? "btn btn-active btn-primary"
|
|
|
|
: "btn"
|
|
|
|
}`}
|
|
|
|
onClick={() => void setVoteHandler(scaleItem)}
|
2023-09-01 19:43:15 -06:00
|
|
|
>
|
2023-10-04 14:45:35 -06:00
|
|
|
{scaleItem}
|
2023-09-01 19:43:15 -06:00
|
|
|
</button>
|
|
|
|
);
|
2023-10-04 14:45:35 -06:00
|
|
|
})}
|
2023-09-01 19:43:15 -06:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
2023-10-04 14:45:35 -06:00
|
|
|
)}
|
2023-09-01 19:43:15 -06:00
|
|
|
|
2023-10-04 14:45:35 -06:00
|
|
|
{!!roomFromDb &&
|
2023-09-06 12:53:48 -06:00
|
|
|
(roomFromDb.userId === user?.id || isAdmin(user?.publicMetadata)) && (
|
2023-09-01 19:43:15 -06:00
|
|
|
<>
|
2023-09-24 23:49:24 -06:00
|
|
|
<div className="card card-compact bg-base-100 shadow-xl">
|
2023-09-01 19:43:15 -06:00
|
|
|
<div className="card-body flex flex-col flex-wrap">
|
2023-09-24 23:49:24 -06:00
|
|
|
<h2 className="card-title">Room Settings</h2>
|
2023-09-01 19:43:15 -06:00
|
|
|
|
2023-09-24 23:49:24 -06:00
|
|
|
<label className="label">
|
2023-10-04 14:45:35 -06:00
|
|
|
{"Vote Scale (Comma Separated):"}{" "}
|
2023-09-01 19:43:15 -06:00
|
|
|
</label>
|
|
|
|
|
|
|
|
<input
|
|
|
|
type="text"
|
|
|
|
placeholder="Scale (Comma Separated)"
|
2023-09-24 23:49:24 -06:00
|
|
|
className="input input-bordered"
|
2023-10-04 14:45:35 -06:00
|
|
|
value={roomScale}
|
|
|
|
onChange={(event) => {
|
2023-09-01 19:43:15 -06:00
|
|
|
setRoomScale(event.target.value);
|
2023-10-04 14:45:35 -06:00
|
|
|
}}
|
2023-09-01 19:43:15 -06:00
|
|
|
/>
|
|
|
|
|
2023-10-04 14:45:35 -06:00
|
|
|
<label className="label">{"Story Name:"} </label>
|
2023-09-01 19:43:15 -06:00
|
|
|
|
|
|
|
<input
|
|
|
|
type="text"
|
|
|
|
placeholder="Story Name"
|
2023-09-24 23:49:24 -06:00
|
|
|
className="input input-bordered"
|
2023-10-04 14:45:35 -06:00
|
|
|
value={storyNameText}
|
|
|
|
onChange={(event) => {
|
2023-09-01 19:43:15 -06:00
|
|
|
setStoryNameText(event.target.value);
|
2023-10-04 14:45:35 -06:00
|
|
|
}}
|
2023-09-01 19:43:15 -06:00
|
|
|
/>
|
|
|
|
|
|
|
|
<div className="flex flex-row flex-wrap text-center items-center justify-center gap-2">
|
|
|
|
<div>
|
|
|
|
<button
|
2023-10-04 14:45:35 -06:00
|
|
|
onClick={() =>
|
2023-09-09 19:25:23 -06:00
|
|
|
void setRoomHandler(!roomFromDb.visible, false)
|
|
|
|
}
|
2023-09-01 19:43:15 -06:00
|
|
|
className="btn btn-primary inline-flex"
|
|
|
|
>
|
2023-10-04 14:45:35 -06:00
|
|
|
{roomFromDb.visible ? (
|
2023-09-01 19:43:15 -06:00
|
|
|
<>
|
|
|
|
<IoEyeOffOutline className="text-xl mr-1" />
|
|
|
|
Hide
|
|
|
|
</>
|
|
|
|
) : (
|
|
|
|
<>
|
|
|
|
<IoEyeOutline className="text-xl mr-1" />
|
|
|
|
Show
|
|
|
|
</>
|
2023-10-04 14:45:35 -06:00
|
|
|
)}
|
2023-09-01 19:43:15 -06:00
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div>
|
|
|
|
<button
|
2023-10-04 14:45:35 -06:00
|
|
|
onClick={() =>
|
2023-09-09 19:25:23 -06:00
|
|
|
void setRoomHandler(
|
2023-09-01 19:43:15 -06:00
|
|
|
false,
|
|
|
|
true,
|
|
|
|
roomFromDb.storyName === storyNameText ||
|
2023-10-08 13:21:30 -06:00
|
|
|
optimisticVotes?.length === 0
|
2023-09-01 19:43:15 -06:00
|
|
|
? false
|
|
|
|
: true
|
|
|
|
)
|
|
|
|
}
|
|
|
|
className="btn btn-primary inline-flex"
|
|
|
|
disabled={
|
|
|
|
[...new Set(roomScale.split(","))].filter(
|
|
|
|
(item) => item !== ""
|
|
|
|
).length <= 1
|
|
|
|
}
|
|
|
|
>
|
2023-10-04 14:45:35 -06:00
|
|
|
{roomFromDb.storyName === storyNameText ||
|
2023-10-08 13:21:30 -06:00
|
|
|
optimisticVotes?.length === 0 ? (
|
2023-09-01 19:43:15 -06:00
|
|
|
<>
|
|
|
|
<IoReloadOutline className="text-xl mr-1" /> Reset
|
|
|
|
</>
|
|
|
|
) : (
|
|
|
|
<>
|
|
|
|
<IoSaveOutline className="text-xl mr-1" /> Save
|
|
|
|
</>
|
2023-10-04 14:45:35 -06:00
|
|
|
)}
|
2023-09-01 19:43:15 -06:00
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
|
2023-10-08 13:21:30 -06:00
|
|
|
{optimisticVotes &&
|
2023-09-01 19:43:15 -06:00
|
|
|
(roomFromDb.logs.length > 0 ||
|
2023-10-08 13:21:30 -06:00
|
|
|
optimisticVotes.length > 0) && (
|
2023-09-01 19:43:15 -06:00
|
|
|
<div>
|
|
|
|
<button
|
2023-10-04 14:45:35 -06:00
|
|
|
onClick={() => downloadLogs()}
|
2023-09-01 19:43:15 -06:00
|
|
|
className="btn btn-primary inline-flex hover:animate-pulse"
|
|
|
|
>
|
|
|
|
<>
|
|
|
|
<IoDownloadOutline className="text-xl" />
|
|
|
|
</>
|
|
|
|
</button>
|
|
|
|
</div>
|
2023-10-04 14:45:35 -06:00
|
|
|
)}
|
2023-09-01 19:43:15 -06:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</>
|
2023-10-04 14:45:35 -06:00
|
|
|
)}
|
2023-09-24 23:49:24 -06:00
|
|
|
</div>
|
2023-09-01 19:43:15 -06:00
|
|
|
);
|
|
|
|
// Room does not exist
|
|
|
|
} else {
|
2023-09-24 23:49:24 -06:00
|
|
|
return <NoRoomUI />;
|
2023-09-01 19:43:15 -06:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
export default VoteUI;
|