2023-07-11 17:22:54 -06:00
|
|
|
|
import { type GetServerSideProps, type NextPage } from "next";
|
2023-04-20 04:20:00 -06:00
|
|
|
|
import Head from "next/head";
|
2023-07-11 17:22:54 -06:00
|
|
|
|
import Image from "next/image";
|
2023-04-20 04:20:00 -06:00
|
|
|
|
import { useEffect, useState } from "react";
|
|
|
|
|
|
|
|
|
|
import { useSession } from "next-auth/react";
|
2023-07-11 17:22:54 -06:00
|
|
|
|
import { useRouter } from "next/router";
|
2023-04-20 04:20:00 -06:00
|
|
|
|
import {
|
2023-07-11 18:19:45 -06:00
|
|
|
|
IoCheckmarkCircleOutline,
|
|
|
|
|
IoCopyOutline,
|
|
|
|
|
IoDownloadOutline,
|
|
|
|
|
IoEyeOffOutline,
|
|
|
|
|
IoEyeOutline,
|
|
|
|
|
IoHourglassOutline,
|
|
|
|
|
IoReloadOutline,
|
|
|
|
|
IoSaveOutline,
|
2023-04-20 04:20:00 -06:00
|
|
|
|
} from "react-icons/io5";
|
2023-07-11 17:22:54 -06:00
|
|
|
|
import { z } from "zod";
|
|
|
|
|
import { api } from "~/utils/api";
|
|
|
|
|
import { getServerAuthSession } from "../../server/auth";
|
2023-04-20 04:20:00 -06:00
|
|
|
|
|
|
|
|
|
import { configureAbly, useChannel, usePresence } from "@ably-labs/react-hooks";
|
2023-07-11 17:22:54 -06:00
|
|
|
|
import Link from "next/link";
|
2023-04-20 04:20:00 -06:00
|
|
|
|
import { FaShieldAlt } from "react-icons/fa";
|
|
|
|
|
import { RiVipCrownFill } from "react-icons/ri";
|
2023-07-11 17:22:54 -06:00
|
|
|
|
import { env } from "~/env.mjs";
|
2023-04-20 04:20:00 -06:00
|
|
|
|
import { downloadCSV } from "~/utils/helpers";
|
2023-07-11 17:22:54 -06:00
|
|
|
|
import type { PresenceItem } from "~/utils/types";
|
2023-04-20 04:20:00 -06:00
|
|
|
|
|
|
|
|
|
export const getServerSideProps: GetServerSideProps = async (ctx) => {
|
|
|
|
|
const session = await getServerAuthSession(ctx);
|
|
|
|
|
|
2023-05-31 16:49:11 -06:00
|
|
|
|
// Redirect to login if not signed in
|
2023-04-20 04:20:00 -06:00
|
|
|
|
if (!session) {
|
|
|
|
|
return {
|
|
|
|
|
redirect: {
|
2023-05-30 22:16:33 -06:00
|
|
|
|
destination: `/api/auth/signin?callbackUrl=${ctx.resolvedUrl}`,
|
2023-04-20 04:20:00 -06:00
|
|
|
|
permanent: false,
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Return session if logged in
|
|
|
|
|
return {
|
|
|
|
|
props: { session },
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const Room: NextPage = () => {
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
<Head>
|
|
|
|
|
<title>Sprint Padawan</title>
|
|
|
|
|
<meta name="description" content="Plan. Sprint. Repeat." />
|
2023-06-28 17:04:11 -06:00
|
|
|
|
<meta http-equiv="Cache-control" content="no-cache" />
|
2023-04-20 04:20:00 -06:00
|
|
|
|
</Head>
|
|
|
|
|
<div className="flex flex-col items-center justify-center text-center gap-2">
|
|
|
|
|
<RoomBody />
|
|
|
|
|
</div>
|
|
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default Room;
|
|
|
|
|
|
2023-06-14 12:59:20 -06:00
|
|
|
|
const RoomBody: React.FC = () => {
|
2023-04-20 04:20:00 -06:00
|
|
|
|
const { data: sessionData } = useSession();
|
|
|
|
|
const { query } = useRouter();
|
|
|
|
|
const roomId = z.string().parse(query.id);
|
|
|
|
|
|
|
|
|
|
const [storyNameText, setStoryNameText] = useState<string>("");
|
|
|
|
|
const [roomScale, setRoomScale] = useState<string>("");
|
2023-07-10 00:30:57 -06:00
|
|
|
|
const [copied, setCopied] = useState<boolean>(false);
|
2023-04-20 04:20:00 -06:00
|
|
|
|
|
|
|
|
|
const { data: roomFromDb, refetch: refetchRoomFromDb } =
|
|
|
|
|
api.room.get.useQuery({ id: roomId });
|
|
|
|
|
|
2023-06-04 15:43:46 -06:00
|
|
|
|
const { data: votesFromDb, refetch: refetchVotesFromDb } =
|
|
|
|
|
api.vote.getAllByRoomId.useQuery({ roomId });
|
|
|
|
|
|
2023-04-20 04:20:00 -06:00
|
|
|
|
const setVoteInDb = api.vote.set.useMutation({});
|
|
|
|
|
const setRoomInDb = api.room.set.useMutation({});
|
|
|
|
|
|
|
|
|
|
configureAbly({
|
|
|
|
|
key: env.NEXT_PUBLIC_ABLY_PUBLIC_KEY,
|
|
|
|
|
clientId: sessionData?.user.id,
|
|
|
|
|
recover: (_, cb) => {
|
|
|
|
|
cb(true);
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const [channel] = useChannel(
|
|
|
|
|
{
|
|
|
|
|
channelName: `${env.NEXT_PUBLIC_APP_ENV}-${roomId}`,
|
|
|
|
|
},
|
2023-06-04 15:43:46 -06:00
|
|
|
|
({ name }) => {
|
|
|
|
|
if (name === "ROOM_UPDATE") {
|
|
|
|
|
void refetchVotesFromDb();
|
|
|
|
|
void refetchRoomFromDb();
|
|
|
|
|
} else if (name === "VOTE_UPDATE") {
|
|
|
|
|
void refetchVotesFromDb();
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-04-20 04:20:00 -06:00
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const [presenceData] = usePresence<PresenceItem>(
|
|
|
|
|
`${env.NEXT_PUBLIC_APP_ENV}-${roomId}`,
|
|
|
|
|
{
|
|
|
|
|
name: sessionData?.user.name || "",
|
|
|
|
|
image: sessionData?.user.image || "",
|
|
|
|
|
client_id: sessionData?.user.id || "",
|
|
|
|
|
role: sessionData?.user.role || "USER",
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Subscribe on mount and unsubscribe on unmount
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
window.addEventListener("beforeunload", () => channel.presence.leave());
|
|
|
|
|
return () => {
|
|
|
|
|
window.removeEventListener("beforeunload", () =>
|
|
|
|
|
channel.presence.leave()
|
|
|
|
|
);
|
|
|
|
|
channel.presence.leave();
|
|
|
|
|
};
|
2023-05-31 16:40:03 -06:00
|
|
|
|
}, [channel.presence, roomId]);
|
2023-04-20 04:20:00 -06:00
|
|
|
|
|
|
|
|
|
// Init story name
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (sessionData && roomFromDb) {
|
2023-06-28 16:35:12 -06:00
|
|
|
|
setStoryNameText(roomFromDb.storyName || "");
|
|
|
|
|
setRoomScale(roomFromDb.scale || "ERROR");
|
2023-04-20 04:20:00 -06:00
|
|
|
|
}
|
2023-05-31 16:40:03 -06:00
|
|
|
|
}, [roomFromDb, roomId, sessionData]);
|
2023-04-20 04:20:00 -06:00
|
|
|
|
|
|
|
|
|
// Helper functions
|
|
|
|
|
const getVoteForCurrentUser = () => {
|
|
|
|
|
if (roomFromDb && sessionData) {
|
|
|
|
|
return (
|
2023-06-04 15:43:46 -06:00
|
|
|
|
votesFromDb &&
|
|
|
|
|
votesFromDb.find((vote) => vote.userId === sessionData.user.id)
|
2023-04-20 04:20:00 -06:00
|
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const setVote = (value: string) => {
|
|
|
|
|
if (roomFromDb) {
|
|
|
|
|
setVoteInDb.mutate({
|
|
|
|
|
roomId: roomFromDb.id,
|
|
|
|
|
value: value,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const saveRoom = (visible: boolean, reset = false, log = false) => {
|
|
|
|
|
if (roomFromDb) {
|
|
|
|
|
setRoomInDb.mutate({
|
|
|
|
|
name: storyNameText,
|
|
|
|
|
roomId: roomFromDb.id,
|
|
|
|
|
scale: roomScale,
|
|
|
|
|
visible: visible,
|
|
|
|
|
reset: reset,
|
|
|
|
|
log: log,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const downloadLogs = () => {
|
2023-06-04 15:43:46 -06:00
|
|
|
|
if (roomFromDb && votesFromDb) {
|
2023-04-20 04:20:00 -06:00
|
|
|
|
const jsonObject = roomFromDb?.logs
|
|
|
|
|
.map((item) => {
|
|
|
|
|
return {
|
|
|
|
|
...item,
|
|
|
|
|
scale: item.scale,
|
|
|
|
|
votes: item.votes,
|
|
|
|
|
roomName: item.roomName,
|
|
|
|
|
storyName: item.storyName,
|
|
|
|
|
};
|
|
|
|
|
})
|
|
|
|
|
.concat({
|
|
|
|
|
id: "LATEST",
|
|
|
|
|
createdAt: new Date(),
|
|
|
|
|
userId: roomFromDb.owner.id,
|
|
|
|
|
roomId: roomFromDb.id,
|
|
|
|
|
scale: roomScale,
|
2023-06-04 15:43:46 -06:00
|
|
|
|
votes: votesFromDb.map((vote) => {
|
2023-04-20 04:20:00 -06:00
|
|
|
|
return {
|
|
|
|
|
name: vote.owner.name,
|
|
|
|
|
value: vote.value,
|
|
|
|
|
};
|
|
|
|
|
}),
|
|
|
|
|
roomName: roomFromDb.roomName,
|
|
|
|
|
storyName: storyNameText,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
downloadCSV(jsonObject, `sprint-padawan-room-${roomId}.csv`);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const copyRoomURLHandler = () => {
|
|
|
|
|
navigator.clipboard
|
|
|
|
|
.writeText(window.location.href)
|
2023-07-10 00:34:01 -06:00
|
|
|
|
.then(() => {
|
2023-04-20 04:20:00 -06:00
|
|
|
|
console.log(`Copied Room Link to Clipboard!`);
|
2023-07-10 00:30:57 -06:00
|
|
|
|
setCopied(true);
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
setCopied(false);
|
|
|
|
|
}, 2000);
|
2023-04-20 04:20:00 -06:00
|
|
|
|
})
|
|
|
|
|
.catch(() => {
|
|
|
|
|
console.log(`Error Copying Room Link to Clipboard!`);
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const voteString = (
|
|
|
|
|
visible: boolean,
|
2023-06-04 15:43:46 -06:00
|
|
|
|
votes: typeof votesFromDb,
|
2023-04-20 04:20:00 -06:00
|
|
|
|
presenceItem: PresenceItem
|
|
|
|
|
) => {
|
2023-06-04 15:43:46 -06:00
|
|
|
|
const matchedVote = votes?.find(
|
2023-04-20 04:20:00 -06:00
|
|
|
|
(vote) => vote.userId === presenceItem.client_id
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (visible) {
|
|
|
|
|
if (!!matchedVote) {
|
2023-07-11 18:19:45 -06:00
|
|
|
|
return <p>{ matchedVote.value }</p>;
|
2023-04-20 04:20:00 -06:00
|
|
|
|
} else {
|
|
|
|
|
return <IoHourglassOutline className="text-xl mx-auto text-red-400" />;
|
|
|
|
|
}
|
|
|
|
|
} else if (!!matchedVote) {
|
|
|
|
|
return (
|
|
|
|
|
<IoCheckmarkCircleOutline className="text-xl mx-auto text-green-400" />
|
|
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
return (
|
|
|
|
|
<IoHourglassOutline className="text-xl animate-spin mx-auto text-yellow-400" />
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Room is loading
|
|
|
|
|
if (roomFromDb === undefined) {
|
|
|
|
|
return (
|
|
|
|
|
<div className="flex flex-col items-center justify-center text-center">
|
2023-07-11 18:19:45 -06:00
|
|
|
|
<span className="loading loading-dots loading-lg"></span>{ " " }
|
2023-04-20 04:20:00 -06:00
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
// Room has been loaded
|
|
|
|
|
} else if (roomFromDb) {
|
|
|
|
|
return (
|
|
|
|
|
<span className="text-center">
|
2023-07-11 18:19:45 -06:00
|
|
|
|
<div className="text-2xl">{ roomFromDb.roomName }</div>
|
2023-04-20 04:20:00 -06:00
|
|
|
|
<div className="flex flex-row flex-wrap text-center justify-center items-center gap-1 text-md mx-auto">
|
|
|
|
|
<div>ID:</div>
|
2023-07-11 18:19:45 -06:00
|
|
|
|
<div>{ roomFromDb.id }</div>
|
2023-04-20 04:20:00 -06:00
|
|
|
|
|
|
|
|
|
<button>
|
2023-07-11 18:19:45 -06:00
|
|
|
|
{ copied ? (
|
2023-07-10 00:30:57 -06:00
|
|
|
|
<IoCheckmarkCircleOutline className="mx-1 text-green-400 animate-bounce" />
|
|
|
|
|
) : (
|
|
|
|
|
<IoCopyOutline
|
|
|
|
|
className="mx-1 hover:text-primary"
|
2023-07-11 18:19:45 -06:00
|
|
|
|
onClick={ copyRoomURLHandler }
|
2023-07-10 00:30:57 -06:00
|
|
|
|
></IoCopyOutline>
|
2023-07-11 18:19:45 -06:00
|
|
|
|
) }
|
2023-04-20 04:20:00 -06:00
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
|
2023-07-11 18:19:45 -06:00
|
|
|
|
{ roomFromDb && (
|
2023-04-20 04:20:00 -06:00
|
|
|
|
<div className="card card-compact bg-neutral shadow-xl mx-auto m-4">
|
|
|
|
|
<div className="card-body">
|
|
|
|
|
<h2 className="card-title mx-auto">
|
2023-07-11 18:19:45 -06:00
|
|
|
|
Story: { roomFromDb.storyName }
|
2023-04-20 04:20:00 -06:00
|
|
|
|
</h2>
|
|
|
|
|
|
|
|
|
|
<ul className="p-0 mx-auto flex flex-row flex-wrap justify-center items-center text-ceter gap-4">
|
2023-07-11 18:19:45 -06:00
|
|
|
|
{ presenceData &&
|
2023-04-20 04:20:00 -06:00
|
|
|
|
presenceData
|
|
|
|
|
.filter(
|
|
|
|
|
(value, index, self) =>
|
|
|
|
|
index ===
|
|
|
|
|
self.findIndex(
|
|
|
|
|
(presenceItem) =>
|
|
|
|
|
presenceItem.clientId === value.clientId
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
.map((presenceItem) => {
|
|
|
|
|
return (
|
|
|
|
|
<li
|
2023-07-11 18:19:45 -06:00
|
|
|
|
key={ presenceItem.clientId }
|
2023-04-20 04:20:00 -06:00
|
|
|
|
className="flex flex-row items-center justify-center gap-2"
|
|
|
|
|
>
|
|
|
|
|
<div className="w-10 rounded-full avatar mx-auto">
|
|
|
|
|
<Image
|
2023-07-11 18:19:45 -06:00
|
|
|
|
src={ presenceItem.data.image }
|
|
|
|
|
alt={ `${presenceItem.data.name}'s Profile Picture` }
|
|
|
|
|
height={ 32 }
|
|
|
|
|
width={ 32 }
|
2023-04-20 04:20:00 -06:00
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<p className="flex flex-row flex-wrap text-center justify-center items-center gap-1 text-md mx-auto">
|
2023-07-11 18:19:45 -06:00
|
|
|
|
{ presenceItem.data.name }{ " " }
|
|
|
|
|
{ presenceItem.data.role === "ADMIN" && (
|
2023-04-20 04:20:00 -06:00
|
|
|
|
<div
|
|
|
|
|
className="tooltip tooltip-primary"
|
|
|
|
|
data-tip="Admin"
|
|
|
|
|
>
|
|
|
|
|
<FaShieldAlt className="inline-block text-primary" />
|
|
|
|
|
</div>
|
2023-07-11 18:19:45 -06:00
|
|
|
|
) }{ " " }
|
|
|
|
|
{ presenceItem.clientId === roomFromDb.userId && (
|
2023-04-20 04:20:00 -06:00
|
|
|
|
<div
|
|
|
|
|
className="tooltip tooltip-warning"
|
|
|
|
|
data-tip="Room Owner"
|
|
|
|
|
>
|
|
|
|
|
<RiVipCrownFill className="inline-block text-yellow-500" />
|
|
|
|
|
</div>
|
2023-07-11 18:19:45 -06:00
|
|
|
|
) }
|
|
|
|
|
{ " : " }
|
2023-04-20 04:20:00 -06:00
|
|
|
|
</p>
|
|
|
|
|
|
2023-07-11 18:19:45 -06:00
|
|
|
|
{ roomFromDb &&
|
2023-06-04 15:43:46 -06:00
|
|
|
|
votesFromDb &&
|
2023-04-20 04:20:00 -06:00
|
|
|
|
voteString(
|
|
|
|
|
roomFromDb.visible,
|
2023-06-04 15:43:46 -06:00
|
|
|
|
votesFromDb,
|
2023-04-20 04:20:00 -06:00
|
|
|
|
presenceItem.data
|
2023-07-11 18:19:45 -06:00
|
|
|
|
) }
|
2023-04-20 04:20:00 -06:00
|
|
|
|
</li>
|
|
|
|
|
);
|
2023-07-11 18:19:45 -06:00
|
|
|
|
}) }
|
2023-04-20 04:20:00 -06:00
|
|
|
|
</ul>
|
|
|
|
|
|
2023-06-02 23:10:36 -06:00
|
|
|
|
<div className="join md:btn-group-horizontal mx-auto">
|
2023-07-11 18:19:45 -06:00
|
|
|
|
{ roomFromDb.scale.split(",").map((scaleItem, index) => {
|
2023-04-20 04:20:00 -06:00
|
|
|
|
return (
|
|
|
|
|
<button
|
2023-07-11 18:19:45 -06:00
|
|
|
|
key={ index }
|
|
|
|
|
className={ `join-item ${getVoteForCurrentUser()?.value === scaleItem
|
2023-06-02 23:10:36 -06:00
|
|
|
|
? "btn btn-active btn-primary"
|
2023-04-20 04:20:00 -06:00
|
|
|
|
: "btn"
|
2023-07-11 18:19:45 -06:00
|
|
|
|
}` }
|
|
|
|
|
onClick={ () => setVote(scaleItem) }
|
2023-04-20 04:20:00 -06:00
|
|
|
|
>
|
2023-07-11 18:19:45 -06:00
|
|
|
|
{ scaleItem }
|
2023-04-20 04:20:00 -06:00
|
|
|
|
</button>
|
|
|
|
|
);
|
2023-07-11 18:19:45 -06:00
|
|
|
|
}) }
|
2023-04-20 04:20:00 -06:00
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2023-07-11 18:19:45 -06:00
|
|
|
|
) }
|
2023-04-20 04:20:00 -06:00
|
|
|
|
|
2023-07-11 18:19:45 -06:00
|
|
|
|
{ sessionData &&
|
2023-04-20 04:20:00 -06:00
|
|
|
|
!!roomFromDb &&
|
|
|
|
|
roomFromDb.userId === sessionData.user.id && (
|
|
|
|
|
<>
|
|
|
|
|
<div className="card card-compact bg-neutral shadow-xl mx-auto m-4">
|
|
|
|
|
<div className="card-body flex flex-col flex-wrap">
|
|
|
|
|
<h2 className="card-title mx-auto">Room Settings</h2>
|
|
|
|
|
|
|
|
|
|
<label className="label mx-auto">
|
2023-07-11 18:19:45 -06:00
|
|
|
|
{ "Vote Scale (Comma Separated):" }{ " " }
|
2023-04-20 04:20:00 -06:00
|
|
|
|
</label>
|
|
|
|
|
|
|
|
|
|
<input
|
|
|
|
|
type="text"
|
|
|
|
|
placeholder="Scale (Comma Separated)"
|
|
|
|
|
className="input input-bordered m-auto"
|
2023-07-11 18:19:45 -06:00
|
|
|
|
value={ roomScale }
|
|
|
|
|
onChange={ (event) => {
|
2023-05-30 16:44:01 -06:00
|
|
|
|
setRoomScale(event.target.value);
|
2023-07-11 18:19:45 -06:00
|
|
|
|
} }
|
2023-04-20 04:20:00 -06:00
|
|
|
|
/>
|
|
|
|
|
|
2023-07-11 18:19:45 -06:00
|
|
|
|
<label className="label mx-auto">{ "Story Name:" } </label>
|
2023-04-20 04:20:00 -06:00
|
|
|
|
|
|
|
|
|
<input
|
|
|
|
|
type="text"
|
|
|
|
|
placeholder="Story Name"
|
|
|
|
|
className="input input-bordered m-auto"
|
2023-07-11 18:19:45 -06:00
|
|
|
|
value={ storyNameText }
|
|
|
|
|
onChange={ (event) => {
|
2023-05-30 16:44:01 -06:00
|
|
|
|
setStoryNameText(event.target.value);
|
2023-07-11 18:19:45 -06:00
|
|
|
|
} }
|
2023-04-20 04:20:00 -06:00
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<div className="flex flex-row flex-wrap text-center items-center justify-center gap-2">
|
|
|
|
|
<div>
|
|
|
|
|
<button
|
2023-07-11 18:19:45 -06:00
|
|
|
|
onClick={ () => saveRoom(!roomFromDb.visible, false) }
|
2023-04-20 04:20:00 -06:00
|
|
|
|
className="btn btn-primary inline-flex"
|
|
|
|
|
>
|
2023-07-11 18:19:45 -06:00
|
|
|
|
{ roomFromDb.visible ? (
|
2023-04-20 04:20:00 -06:00
|
|
|
|
<>
|
|
|
|
|
<IoEyeOffOutline className="text-xl mr-1" />
|
|
|
|
|
Hide
|
|
|
|
|
</>
|
|
|
|
|
) : (
|
|
|
|
|
<>
|
|
|
|
|
<IoEyeOutline className="text-xl mr-1" />
|
|
|
|
|
Show
|
|
|
|
|
</>
|
2023-07-11 18:19:45 -06:00
|
|
|
|
) }
|
2023-04-20 04:20:00 -06:00
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
<button
|
2023-07-11 18:19:45 -06:00
|
|
|
|
onClick={ () =>
|
2023-04-20 04:20:00 -06:00
|
|
|
|
saveRoom(
|
|
|
|
|
false,
|
|
|
|
|
true,
|
|
|
|
|
roomFromDb.storyName === storyNameText ||
|
2023-06-04 15:43:46 -06:00
|
|
|
|
votesFromDb?.length === 0
|
2023-04-20 04:20:00 -06:00
|
|
|
|
? false
|
|
|
|
|
: true
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
className="btn btn-primary inline-flex"
|
|
|
|
|
disabled={
|
|
|
|
|
[...new Set(roomScale.split(","))].filter(
|
|
|
|
|
(item) => item !== ""
|
|
|
|
|
).length <= 1
|
|
|
|
|
}
|
|
|
|
|
>
|
2023-07-11 18:19:45 -06:00
|
|
|
|
{ roomFromDb.storyName === storyNameText ||
|
|
|
|
|
votesFromDb?.length === 0 ? (
|
2023-04-20 04:20:00 -06:00
|
|
|
|
<>
|
2023-06-02 23:10:36 -06:00
|
|
|
|
<IoReloadOutline className="text-xl mr-1" /> Reset
|
2023-04-20 04:20:00 -06:00
|
|
|
|
</>
|
|
|
|
|
) : (
|
|
|
|
|
<>
|
|
|
|
|
<IoSaveOutline className="text-xl mr-1" /> Save
|
|
|
|
|
</>
|
2023-07-11 18:19:45 -06:00
|
|
|
|
) }
|
2023-04-20 04:20:00 -06:00
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
|
2023-07-11 18:19:45 -06:00
|
|
|
|
{ votesFromDb &&
|
2023-06-04 15:43:46 -06:00
|
|
|
|
(roomFromDb.logs.length > 0 ||
|
|
|
|
|
votesFromDb.length > 0) && (
|
|
|
|
|
<div>
|
|
|
|
|
<button
|
2023-07-11 18:19:45 -06:00
|
|
|
|
onClick={ () => downloadLogs() }
|
2023-06-04 15:43:46 -06:00
|
|
|
|
className="btn btn-primary inline-flex hover:animate-pulse"
|
|
|
|
|
>
|
|
|
|
|
<>
|
|
|
|
|
<IoDownloadOutline className="text-xl" />
|
|
|
|
|
</>
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
2023-07-11 18:19:45 -06:00
|
|
|
|
) }
|
2023-04-20 04:20:00 -06:00
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</>
|
2023-07-11 18:19:45 -06:00
|
|
|
|
) }
|
2023-04-20 04:20:00 -06:00
|
|
|
|
</span>
|
|
|
|
|
);
|
|
|
|
|
// Room does not exist
|
|
|
|
|
} else {
|
|
|
|
|
return (
|
2023-06-05 16:56:28 -06:00
|
|
|
|
<span className="text-center">
|
|
|
|
|
<h1 className="text-5xl font-bold m-2">4️⃣0️⃣4️⃣</h1>
|
|
|
|
|
<h1 className="text-5xl font-bold m-2">
|
2023-04-20 04:20:00 -06:00
|
|
|
|
Oops! This room does not appear to exist, or may have been deleted! 😢
|
|
|
|
|
</h1>
|
|
|
|
|
<Link
|
|
|
|
|
about="Back to home."
|
|
|
|
|
href="/"
|
2023-06-05 16:56:28 -06:00
|
|
|
|
className="btn btn-secondary normal-case text-xl m-2"
|
2023-04-20 04:20:00 -06:00
|
|
|
|
>
|
|
|
|
|
Back to Home
|
|
|
|
|
</Link>
|
|
|
|
|
</span>
|
|
|
|
|
);
|
|
|
|
|
}
|
2023-06-14 12:59:20 -06:00
|
|
|
|
};
|