Small UI adjustments

This commit is contained in:
Atridad Lahiji 2023-07-11 18:19:45 -06:00
parent 79b189bdc9
commit f2e4ac2575
No known key found for this signature in database
13 changed files with 229 additions and 228 deletions

View file

@ -6,9 +6,9 @@ const Footer: React.FC = () => {
<footer className="footer footer-center h-12 p-2 bg-base-100 text-base-content"> <footer className="footer footer-center h-12 p-2 bg-base-100 text-base-content">
<div> <div>
<p> <p>
Made with{" "} Made with{ " " }
<GiTechnoHeart className="inline-block text-primary text-lg animate-pulse" />{" "} <GiTechnoHeart className="inline-block text-primary text-lg animate-pulse" />{ " " }
by{" "} by{ " " }
<a <a
className="link link-primary link-hover" className="link link-primary link-hover"
href="https://atri.dad" href="https://atri.dad"
@ -16,15 +16,15 @@ const Footer: React.FC = () => {
target="_blank" target="_blank"
> >
Atridad Lahiji Atridad Lahiji
</a>{" "} </a>{ " " }
-{" "} -{ " " }
<a <a
className="link link-primary link-hover" className="link link-primary link-hover"
href={`https://github.com/atridadl/sprintpadawan/releases/tag/${packagejson.version}`} href={ `https://github.com/atridadl/sprintpadawan/releases/tag/${packagejson.version}` }
rel="noreferrer" rel="noreferrer"
target="_blank" target="_blank"
> >
v{packagejson.version} v{ packagejson.version }
</a> </a>
</p> </p>
</div> </div>

View file

@ -21,7 +21,7 @@ const Navbar: React.FC<NavbarProps> = ({ title }) => {
); );
} else if (sessionStatus === "unauthenticated") { } else if (sessionStatus === "unauthenticated") {
return ( return (
<button className="btn btn-secondary" onClick={() => void signIn()}> <button className="btn btn-secondary" onClick={ () => void signIn() }>
Sign In Sign In
</button> </button>
); );
@ -40,40 +40,40 @@ const Navbar: React.FC<NavbarProps> = ({ title }) => {
className="md:mr-2" className="md:mr-2"
src="/logo.webp" src="/logo.webp"
alt="Nav Logo" alt="Nav Logo"
width={32} width={ 32 }
height={32} height={ 32 }
priority priority
/> />
<span className="hidden md:inline-flex"> <span className="hidden md:inline-flex">
{title} { title }
{env.NEXT_PUBLIC_APP_ENV === "development" && " >> Staging"} { env.NEXT_PUBLIC_APP_ENV === "development" && " >> Staging" }
</span> </span>
</Link> </Link>
</div> </div>
{sessionStatus === "loading" ? ( { sessionStatus === "loading" ? (
<div className="flex items-center justify-center"> <div className="flex items-center justify-center">
<span className="loading loading-dots loading-lg"></span> <span className="loading loading-dots loading-lg"></span>
</div> </div>
) : ( ) : (
navigationMenu() navigationMenu()
)} ) }
{sessionData?.user.image && ( { sessionData?.user.image && (
<div className="flex-none gap-2"> <div className="flex-none gap-2">
<div className="dropdown dropdown-end"> <div className="dropdown dropdown-end">
<label tabIndex={0} className="btn btn-ghost btn-circle avatar"> <label tabIndex={ 0 } className="btn btn-ghost btn-circle avatar">
<div className="w-10 rounded-full"> <div className="w-10 rounded-full">
<Image <Image
src={sessionData.user.image} src={ sessionData.user.image }
alt="Profile picture." alt="Profile picture."
height={32} height={ 32 }
width={32} width={ 32 }
/> />
</div> </div>
</label> </label>
<ul <ul
tabIndex={0} tabIndex={ 0 }
className="mt-3 p-2 shadow menu menu-compact dropdown-content bg-base-100 rounded-box z-50" className="mt-3 p-2 shadow menu menu-compact dropdown-content bg-base-100 rounded-box z-50"
> >
<li> <li>
@ -85,7 +85,7 @@ const Navbar: React.FC<NavbarProps> = ({ title }) => {
Profile Profile
</Link> </Link>
</li> </li>
{sessionData.user.role === "ADMIN" && ( { sessionData.user.role === "ADMIN" && (
<li> <li>
<Link <Link
about="Admin Page" about="Admin Page"
@ -95,16 +95,16 @@ const Navbar: React.FC<NavbarProps> = ({ title }) => {
Admin Admin
</Link> </Link>
</li> </li>
)} ) }
<li> <li>
<a onClick={() => void signOut({ callbackUrl: "/" })}> <a onClick={ () => void signOut({ callbackUrl: "/" }) }>
Sign Out Sign Out
</a> </a>
</li> </li>
</ul> </ul>
</div> </div>
</div> </div>
)} ) }
</nav> </nav>
); );
}; };

View file

@ -50,7 +50,7 @@ const RoomList: React.FC = () => {
return ( return (
<div className="flex flex-col items-center justify-center gap-8"> <div className="flex flex-col items-center justify-center gap-8">
{/* Modal for Adding Rooms */} {/* Modal for Adding Rooms */ }
<input type="checkbox" id="new-room-modal" className="modal-toggle" /> <input type="checkbox" id="new-room-modal" className="modal-toggle" />
<div className="modal modal-bottom sm:modal-middle"> <div className="modal modal-bottom sm:modal-middle">
<div className="modal-box flex-col flex text-center justify-center items-center"> <div className="modal-box flex-col flex text-center justify-center items-center">
@ -72,30 +72,30 @@ const RoomList: React.FC = () => {
type="text" type="text"
placeholder="Type here" placeholder="Type here"
className="input input-bordered w-full max-w-xs" className="input input-bordered w-full max-w-xs"
onChange={(event) => { onChange={ (event) => {
setRoomName(event.target.value); setRoomName(event.target.value);
}} } }
/> />
</div> </div>
<div className="modal-action"> <div className="modal-action">
{roomName.length > 0 && ( { roomName.length > 0 && (
<label <label
htmlFor="new-room-modal" htmlFor="new-room-modal"
className="btn btn-primary" className="btn btn-primary"
onClick={() => createRoomHandler()} onClick={ () => createRoomHandler() }
> >
Submit Submit
</label> </label>
)} ) }
</div> </div>
</div> </div>
</div> </div>
{roomsFromDb && roomsFromDb.length > 0 && ( { roomsFromDb && roomsFromDb.length > 0 && (
<div className="overflow-x-auto"> <div className="overflow-x-auto">
<table className="table text-center"> <table className="table text-center">
{/* head */} {/* head */ }
<thead> <thead>
<tr className="border-white"> <tr className="border-white">
<th>Room Name</th> <th>Room Name</th>
@ -103,43 +103,43 @@ const RoomList: React.FC = () => {
</tr> </tr>
</thead> </thead>
<tbody className=""> <tbody className="">
{roomsFromDb?.map((room) => { { roomsFromDb?.map((room) => {
return ( return (
<tr key={room.id} className="hover border-white"> <tr key={ room.id } className="hover border-white">
<td className="break-all max-w-[200px] md:max-w-[400px]"> <td className="break-all max-w-[200px] md:max-w-[400px]">
{room.roomName} { room.roomName }
</td> </td>
<td> <td>
<Link <Link
className="m-2 no-underline" className="m-2 no-underline"
href={`/room/${room.id}`} href={ `/room/${room.id}` }
> >
<IoEnterOutline className="text-xl inline-block hover:text-secondary" /> <IoEnterOutline className="text-xl inline-block hover:text-secondary" />
</Link> </Link>
<button <button
className="m-2" className="m-2"
onClick={() => deleteRoomHandler(room.id)} onClick={ () => deleteRoomHandler(room.id) }
> >
<IoTrashBinOutline className="text-xl inline-block hover:text-error" /> <IoTrashBinOutline className="text-xl inline-block hover:text-error" />
</button> </button>
</td> </td>
</tr> </tr>
); );
})} }) }
</tbody> </tbody>
</table> </table>
</div> </div>
)} ) }
<label htmlFor="new-room-modal" className="btn btn-secondary"> <label htmlFor="new-room-modal" className="btn btn-secondary">
New Room New Room
</label> </label>
{roomsFromDb === undefined && ( { roomsFromDb === undefined && (
<div className="flex items-center justify-center"> <div className="flex items-center justify-center">
<span className="loading loading-dots loading-lg"></span> <span className="loading loading-dots loading-lg"></span>
</div> </div>
)} ) }
</div> </div>
); );
}; };

View file

@ -1,17 +1,17 @@
import * as React from "react";
import { import {
Body, Body,
Container, Container,
Head, Head,
Heading, Heading,
Html,
Preview,
Text,
Hr, Hr,
Tailwind, Html,
Section,
Img, Img,
Preview,
Section,
Tailwind,
Text,
} from "@react-email/components"; } from "@react-email/components";
import * as React from "react";
interface GoodbyeTemplateProps { interface GoodbyeTemplateProps {
name: string; name: string;
@ -30,15 +30,15 @@ export const Goodbye: React.FC<Readonly<GoodbyeTemplateProps>> = ({ name }) => (
<Container className="border border-solid border-[#eaeaea] rounded my-[40px] mx-auto p-[20px] w-[465px]"> <Container className="border border-solid border-[#eaeaea] rounded my-[40px] mx-auto p-[20px] w-[465px]">
<Section className="mt-[32px]"> <Section className="mt-[32px]">
<Img <Img
src={`${baseUrl}/logo.webp`} src={ `${baseUrl}/logo.webp` }
width="40" width="40"
height="37" height="37"
alt={`Sprint Padawan Logo`} alt={ `Sprint Padawan Logo` }
className="my-0 mx-auto" className="my-0 mx-auto"
/> />
</Section> </Section>
<Heading className="text-4xl">Farewell, {name}...</Heading> <Heading className="text-4xl">Farewell, { name }...</Heading>
<Text>{"Were sorry to see you go."}</Text> <Text>{ "Were sorry to see you go." }</Text>
<Text> <Text>
Your data has been deleted, including all room history, user data, Your data has been deleted, including all room history, user data,
votes, etc. votes, etc.

View file

@ -1,15 +1,15 @@
import { import {
Body, Body,
Container, Container,
Head, Head,
Heading, Heading,
Hr, Hr,
Html, Html,
Img, Img,
Preview, Preview,
Section, Section,
Tailwind, Tailwind,
Text, Text,
} from "@react-email/components"; } from "@react-email/components";
import * as React from "react"; import * as React from "react";
@ -30,18 +30,18 @@ export const Welcome: React.FC<Readonly<WelcomeTemplateProps>> = ({ name }) => (
<Container className="border border-solid border-[#eaeaea] rounded my-[40px] mx-auto p-[20px] w-[465px]"> <Container className="border border-solid border-[#eaeaea] rounded my-[40px] mx-auto p-[20px] w-[465px]">
<Section className="mt-[32px]"> <Section className="mt-[32px]">
<Img <Img
src={`${baseUrl}/logo.webp`} src={ `${baseUrl}/logo.webp` }
width="40" width="40"
height="37" height="37"
alt={`Sprint Padawan Logo`} alt={ `Sprint Padawan Logo` }
className="my-0 mx-auto" className="my-0 mx-auto"
/> />
</Section> </Section>
<Heading className="text-black text-[24px] font-normal text-center p-0 my-[30px] mx-0"> <Heading className="text-black text-[24px] font-normal text-center p-0 my-[30px] mx-0">
🎉 Welcome to Sprint Padawan, <strong>{name}</strong>! 🎉 🎉 Welcome to Sprint Padawan, <strong>{ name }</strong>! 🎉
</Heading> </Heading>
<Text className="text-black text-[14px] leading-[24px]"> <Text className="text-black text-[14px] leading-[24px]">
Hello {name}, Hello { name },
</Text> </Text>
<Text>Thank you for signing up for Sprint Padawan!</Text> <Text>Thank you for signing up for Sprint Padawan!</Text>
<Text> <Text>

View file

@ -38,15 +38,15 @@ const MyApp: AppType<{ session: Session | null }> = ({
}, [router.events]); }, [router.events]);
return ( return (
<SessionProvider session={session}> <SessionProvider session={ session }>
<div className="block h-[100%]"> <div className="block h-[100%]">
<Navbar title="Sprint Padawan" /> <Navbar title="Sprint Padawan" />
<div className="flex flex-row items-center justify-center min-h-[calc(100%-114px)]"> <div className="flex flex-row items-center justify-center min-h-[calc(100%-114px)]">
{pageLoading ? ( { pageLoading ? (
<span className="loading loading-dots loading-lg"></span> <span className="loading loading-dots loading-lg"></span>
) : ( ) : (
<Component {...pageProps} /> <Component { ...pageProps } />
)} ) }
</div> </div>
<Footer /> <Footer />
</div> </div>

View file

@ -158,70 +158,70 @@ const AdminBody: React.FC = () => {
<div className="stat"> <div className="stat">
<div className="stat-title">Users</div> <div className="stat-title">Users</div>
<div className="stat-value"> <div className="stat-value">
{usersCountLoading || usersCountFetching ? ( { usersCountLoading || usersCountFetching ? (
<span className="loading loading-dots loading-lg"></span> <span className="loading loading-dots loading-lg"></span>
) : ( ) : (
<>{usersCount ? usersCount : "0"}</> <>{ usersCount ? usersCount : "0" }</>
)} ) }
</div> </div>
</div> </div>
<div className="stat"> <div className="stat">
<div className="stat-title">Rooms</div> <div className="stat-title">Rooms</div>
<div className="stat-value"> <div className="stat-value">
{roomsCountLoading || roomsCountFetching ? ( { roomsCountLoading || roomsCountFetching ? (
<span className="loading loading-dots loading-lg"></span> <span className="loading loading-dots loading-lg"></span>
) : ( ) : (
<>{roomsCount ? roomsCount : "0"}</> <>{ roomsCount ? roomsCount : "0" }</>
)} ) }
</div> </div>
</div> </div>
<div className="stat"> <div className="stat">
<div className="stat-title">Votes</div> <div className="stat-title">Votes</div>
<div className="stat-value"> <div className="stat-value">
{votesCountLoading || votesCountFetching ? ( { votesCountLoading || votesCountFetching ? (
<span className="loading loading-dots loading-lg"></span> <span className="loading loading-dots loading-lg"></span>
) : ( ) : (
<>{votesCount ? votesCount : "0"}</> <>{ votesCount ? votesCount : "0" }</>
)} ) }
</div> </div>
</div> </div>
</div> </div>
{usersCountFetching || { usersCountFetching ||
usersFetching || usersFetching ||
roomsCountFetching || roomsCountFetching ||
votesCountFetching ? ( votesCountFetching ? (
<span className="loading loading-dots loading-lg"></span> <span className="loading loading-dots loading-lg"></span>
) : ( ) : (
<div className="flex flex-row flex-wrap text-center items-center justify-center gap-2"> <div className="flex flex-row flex-wrap text-center items-center justify-center gap-2">
<button <button
className="btn btn-primary m-2" className="btn btn-primary m-2"
onClick={() => void clearSessionsHandler()} onClick={ () => void clearSessionsHandler() }
> >
Delete All Sessions Delete All Sessions
</button> </button>
<button <button
className="btn btn-primary" className="btn btn-primary"
onClick={() => void refetchData()} onClick={ () => void refetchData() }
> >
Re-fetch Re-fetch
</button> </button>
</div> </div>
)} ) }
<div className="card max-w-[80vw] bg-neutral shadow-xl m-4"> <div className="card max-w-[80vw] bg-neutral shadow-xl m-4">
<div className="card-body"> <div className="card-body">
<h2 className="card-title">Users:</h2> <h2 className="card-title">Users:</h2>
{usersLoading || usersFetching ? ( { usersLoading || usersFetching ? (
<span className="loading loading-dots loading-lg"></span> <span className="loading loading-dots loading-lg"></span>
) : ( ) : (
<div className="overflow-x-scroll"> <div className="overflow-x-scroll">
<table className="table text-center"> <table className="table text-center">
{/* head */} {/* head */ }
<thead> <thead>
<tr className="border-white"> <tr className="border-white">
<th>ID</th> <th>ID</th>
@ -233,55 +233,55 @@ const AdminBody: React.FC = () => {
</tr> </tr>
</thead> </thead>
<tbody className=""> <tbody className="">
{users { users
?.sort((user1, user2) => ?.sort((user1, user2) =>
user2.createdAt > user1.createdAt ? 1 : -1 user2.createdAt > user1.createdAt ? 1 : -1
) )
.map((user) => { .map((user) => {
return ( return (
<tr key={user.id} className="hover"> <tr key={ user.id } className="hover">
<td className="max-w-[100px] break-words"> <td className="max-w-[100px] break-words">
{user.id} { user.id }
</td> </td>
<td className="max-w-[100px] break-normal"> <td className="max-w-[100px] break-normal">
{user.name} { user.name }
</td> </td>
<td className="max-w-[100px] break-normal"> <td className="max-w-[100px] break-normal">
{user.createdAt.toLocaleDateString()} { user.createdAt.toLocaleDateString() }
</td> </td>
<td className="max-w-[100px] break-normal"> <td className="max-w-[100px] break-normal">
{user.sessions.length} { user.sessions.length }
</td> </td>
<td className="max-w-[100px] break-normal"> <td className="max-w-[100px] break-normal">
{getProviders(user).includes("google") && ( { getProviders(user).includes("google") && (
<SiGoogle className="text-xl m-1 inline-block hover:text-secondary" /> <SiGoogle className="text-xl m-1 inline-block hover:text-secondary" />
)} ) }
{getProviders(user).includes("github") && ( { getProviders(user).includes("github") && (
<SiGithub className="text-xl m-1 inline-block hover:text-secondary" /> <SiGithub className="text-xl m-1 inline-block hover:text-secondary" />
)} ) }
</td> </td>
<td> <td>
<button className="m-2"> <button className="m-2">
{user.role === "ADMIN" ? ( { user.role === "ADMIN" ? (
<FaShieldAlt <FaShieldAlt
className="text-xl inline-block text-primary" className="text-xl inline-block text-primary"
onClick={() => onClick={ () =>
void setUserRoleHandler(user.id, "USER") void setUserRoleHandler(user.id, "USER")
} }
/> />
) : ( ) : (
<FaShieldAlt <FaShieldAlt
className="text-xl inline-block" className="text-xl inline-block"
onClick={() => onClick={ () =>
void setUserRoleHandler(user.id, "ADMIN") void setUserRoleHandler(user.id, "ADMIN")
} }
/> />
)} ) }
</button> </button>
<button <button
className="m-2" className="m-2"
onClick={() => onClick={ () =>
void clearSessionsByUserHandler(user.id) void clearSessionsByUserHandler(user.id)
} }
> >
@ -289,18 +289,18 @@ const AdminBody: React.FC = () => {
</button> </button>
<button <button
className="m-2" className="m-2"
onClick={() => void deleteUserHandler(user.id)} onClick={ () => void deleteUserHandler(user.id) }
> >
<IoTrashBinOutline className="text-xl inline-block hover:text-error" /> <IoTrashBinOutline className="text-xl inline-block hover:text-error" />
</button> </button>
</td> </td>
</tr> </tr>
); );
})} }) }
</tbody> </tbody>
</table> </table>
</div> </div>
)} ) }
</div> </div>
</div> </div>
</> </>

View file

@ -1,6 +1,6 @@
import type { NextApiRequest, NextApiResponse } from "next"; import type { NextApiRequest, NextApiResponse } from "next";
export default function handler(req: NextApiRequest, res: NextApiResponse) { export default function handler(req: NextApiRequest, res: NextApiResponse) {
res.status(200).json({ result: "Pong!" }); res.status(200).json({ result: "Pong!" });
} }

View file

@ -11,9 +11,9 @@ export default createNextApiHandler({
onError: onError:
env.NODE_ENV === "development" env.NODE_ENV === "development"
? ({ path, error }) => { ? ({ path, error }) => {
console.error( console.error(
`❌ tRPC failed on ${path ?? "<no-path>"}: ${error.message}`, `❌ tRPC failed on ${path ?? "<no-path>"}: ${error.message}`,
); );
} }
: undefined, : undefined,
}); });

View file

@ -57,20 +57,20 @@ const HomePageBody: React.FC = () => {
return ( return (
<> <>
<h1 className="flex flex-row flex-wrap text-center justify-center items-center gap-1 text-4xl font-bold mx-auto"> <h1 className="flex flex-row flex-wrap text-center justify-center items-center gap-1 text-4xl font-bold mx-auto">
Hi, {sessionData?.user.name}!{" "} Hi, { sessionData?.user.name }!{ " " }
{sessionData?.user.role === "ADMIN" && ( { sessionData?.user.role === "ADMIN" && (
<FaShieldAlt className="inline-block text-primary" /> <FaShieldAlt className="inline-block text-primary" />
)} ) }
</h1> </h1>
<div className="tabs tabs-boxed border-2 border-cyan-500 mb-4"> <div className="tabs tabs-boxed border-2 border-cyan-500 mb-4">
<a <a
className={ className={
tabIndex === 0 ? "tab no-underline tab-active" : "tab no-underline" tabIndex === 0 ? "tab no-underline tab-active" : "tab no-underline"
} }
onClick={() => { onClick={ () => {
setTabIndex(0); setTabIndex(0);
localStorage.setItem("dashboardTabIndex", "0"); localStorage.setItem("dashboardTabIndex", "0");
}} } }
> >
Join a Room Join a Room
</a> </a>
@ -78,36 +78,36 @@ const HomePageBody: React.FC = () => {
className={ className={
tabIndex === 1 ? "tab no-underline tab-active" : "tab no-underline" tabIndex === 1 ? "tab no-underline tab-active" : "tab no-underline"
} }
onClick={() => { onClick={ () => {
setTabIndex(1); setTabIndex(1);
localStorage.setItem("dashboardTabIndex", "1"); localStorage.setItem("dashboardTabIndex", "1");
}} } }
> >
Room List Room List
</a> </a>
</div> </div>
{tabIndex === 0 && ( { tabIndex === 0 && (
<> <>
<input <input
type="text" type="text"
placeholder="Enter Room ID" placeholder="Enter Room ID"
className="input input-bordered input-primary mb-4" className="input input-bordered input-primary mb-4"
onChange={(event) => { onChange={ (event) => {
console.log(event.target.value); console.log(event.target.value);
setJoinRoomTextBox(event.target.value); setJoinRoomTextBox(event.target.value);
}} } }
/> />
<Link <Link
href={joinRoomTextBox.length > 0 ? `/room/${joinRoomTextBox}` : "/"} href={ joinRoomTextBox.length > 0 ? `/room/${joinRoomTextBox}` : "/" }
className="btn btn-secondary" className="btn btn-secondary"
> >
Join Room Join Room
</Link> </Link>
</> </>
)} ) }
{tabIndex === 1 && <RoomList />} { tabIndex === 1 && <RoomList /> }
</> </>
); );
}; };

View file

@ -21,22 +21,22 @@ const HomePageBody: React.FC = () => {
return ( return (
<> <>
<h1 className="text-6xl font-bold"> <h1 className="text-6xl font-bold">
Sprint{" "} Sprint{ " " }
<span className="bg-gradient-to-br from-pink-600 to-cyan-400 bg-clip-text text-transparent box-decoration-clone"> <span className="bg-gradient-to-br from-pink-600 to-cyan-400 bg-clip-text text-transparent box-decoration-clone">
Padawan Padawan
</span> </span>
</h1> </h1>
<h2 className="my-4 text-3xl font-bold"> <h2 className="my-4 text-3xl font-bold">
A{" "} A{ " " }
<span className="bg-gradient-to-br from-pink-600 to-pink-400 bg-clip-text text-transparent box-decoration-clone"> <span className="bg-gradient-to-br from-pink-600 to-pink-400 bg-clip-text text-transparent box-decoration-clone">
scrum poker{" "} scrum poker{ " " }
</span>{" "} </span>{ " " }
tool that helps{" "} tool that helps{ " " }
<span className="bg-gradient-to-br from-purple-600 to-purple-400 bg-clip-text text-transparent box-decoration-clone"> <span className="bg-gradient-to-br from-purple-600 to-purple-400 bg-clip-text text-transparent box-decoration-clone">
agile teams{" "} agile teams{ " " }
</span>{" "} </span>{ " " }
plan their sprints in{" "} plan their sprints in{ " " }
<span className="bg-gradient-to-br from-cyan-600 to-cyan-400 bg-clip-text text-transparent box-decoration-clone"> <span className="bg-gradient-to-br from-cyan-600 to-cyan-400 bg-clip-text text-transparent box-decoration-clone">
real-time real-time
</span> </span>

View file

@ -1,15 +1,14 @@
import { type NextPage } from "next"; import { type GetServerSideProps, type NextPage } from "next";
import Image from "next/image";
import Head from "next/head"; import Head from "next/head";
import { type GetServerSideProps } from "next"; import Image from "next/image";
import { getServerAuthSession } from "../../server/auth";
import { api } from "~/utils/api";
import { signIn, useSession } from "next-auth/react"; import { signIn, useSession } from "next-auth/react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { SiGoogle, SiGithub } from "react-icons/si";
import { FaShieldAlt } from "react-icons/fa"; import { FaShieldAlt } from "react-icons/fa";
import { SiGithub, SiGoogle } from "react-icons/si";
import { api } from "~/utils/api";
import { getServerAuthSession } from "../../server/auth";
export const getServerSideProps: GetServerSideProps = async (ctx) => { export const getServerSideProps: GetServerSideProps = async (ctx) => {
const session = await getServerAuthSession(ctx); const session = await getServerAuthSession(ctx);
@ -104,7 +103,7 @@ const ProfileBody: React.FC = () => {
<label <label
htmlFor="delete-user-modal" htmlFor="delete-user-modal"
className="btn btn-error" className="btn btn-error"
onClick={() => void deleteCurrentUser()} onClick={ () => void deleteCurrentUser() }
> >
I am sure! I am sure!
</label> </label>
@ -115,76 +114,79 @@ const ProfileBody: React.FC = () => {
<div className="card w-90 bg-neutral shadow-xl"> <div className="card w-90 bg-neutral shadow-xl">
<div className="card-body"> <div className="card-body">
<h2 className="card-title">Profile:</h2> <h2 className="card-title">Profile:</h2>
{sessionData.user.image && ( { sessionData.user.image && (
<div className="indicator mx-auto m-4"> <div className="indicator mx-auto m-4">
<span className="indicator-item indicator-bottom badge badge-primary"> { sessionData.user.role === "ADMIN" && (
<div className="tooltip tooltip-primary" data-tip="Admin"> <span className="indicator-item indicator-bottom badge badge-primary">
<FaShieldAlt className="text-xl" /> <div className="tooltip tooltip-primary" data-tip="Admin">
</div> <FaShieldAlt className="text-xl" />
</span> </div>
</span>
) }
<Image <Image
className="mx-auto" className="mx-auto"
src={sessionData.user.image} src={ sessionData.user.image }
alt="Profile picture." alt="Profile picture."
height={100} height={ 100 }
width={100} width={ 100 }
priority priority
/> />
</div> </div>
)} ) }
{providersLoading ? ( { providersLoading ? (
<div className="mx-auto"> <div className="mx-auto">
<span className="loading loading-dots loading-lg"></span>{" "} <span className="loading loading-dots loading-lg"></span>{ " " }
</div> </div>
) : ( ) : (
<div className="mx-auto"> <div className="mx-auto">
<button <button
className={`btn btn-square btn-outline mx-2`} className={ `btn btn-square btn-outline mx-2` }
disabled={providers?.includes("github")} disabled={ providers?.includes("github") }
onClick={() => void signIn("github")} onClick={ () => void signIn("github") }
> >
<SiGithub /> <SiGithub />
</button> </button>
<button <button
className={`btn btn-square btn-outline mx-2`} className={ `btn btn-square btn-outline mx-2` }
disabled={providers?.includes("google")} disabled={ providers?.includes("google") }
onClick={() => void signIn("google")} onClick={ () => void signIn("google") }
> >
<SiGoogle /> <SiGoogle />
</button> </button>
</div> </div>
)} ) }
{sessionData.user.name && ( { sessionData.user.name && (
<input <input
type="text" type="text"
placeholder="Name" placeholder="Name"
className="input input-bordered" className="input input-bordered"
value={nameText} value={ nameText }
onChange={(event) => setNameText(event.target.value)} onChange={ (event) => setNameText(event.target.value) }
/> />
)} ) }
{sessionData.user.email && ( { sessionData.user.email && (
<input <input
type="text" type="text"
placeholder="Email" placeholder="Email"
className="input input-bordered" className="input input-bordered"
value={sessionData.user.email} value={ sessionData.user.email }
disabled disabled
/> />
)} ) }
<button <button
onClick={() => void saveUser()} onClick={ () => void saveUser() }
className="btn btn-secondary" className="btn btn-secondary"
> >
Save Account Save Account
</button> </button>
{/* <button className="btn btn-error">Delete Account</button> */} {/* <button className="btn btn-error">Delete Account</button> */ }
<label htmlFor="delete-user-modal" className="btn btn-error"> <label htmlFor="delete-user-modal" className="btn btn-error">
Delete Account Delete Account

View file

@ -6,14 +6,14 @@ import { useEffect, useState } from "react";
import { useSession } from "next-auth/react"; import { useSession } from "next-auth/react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { import {
IoCheckmarkCircleOutline, IoCheckmarkCircleOutline,
IoCopyOutline, IoCopyOutline,
IoDownloadOutline, IoDownloadOutline,
IoEyeOffOutline, IoEyeOffOutline,
IoEyeOutline, IoEyeOutline,
IoHourglassOutline, IoHourglassOutline,
IoReloadOutline, IoReloadOutline,
IoSaveOutline, IoSaveOutline,
} from "react-icons/io5"; } from "react-icons/io5";
import { z } from "zod"; import { z } from "zod";
import { api } from "~/utils/api"; import { api } from "~/utils/api";
@ -224,7 +224,7 @@ const RoomBody: React.FC = () => {
if (visible) { if (visible) {
if (!!matchedVote) { if (!!matchedVote) {
return <p>{matchedVote.value}</p>; return <p>{ matchedVote.value }</p>;
} else { } else {
return <IoHourglassOutline className="text-xl mx-auto text-red-400" />; return <IoHourglassOutline className="text-xl mx-auto text-red-400" />;
} }
@ -243,39 +243,39 @@ const RoomBody: React.FC = () => {
if (roomFromDb === undefined) { if (roomFromDb === undefined) {
return ( return (
<div className="flex flex-col items-center justify-center text-center"> <div className="flex flex-col items-center justify-center text-center">
<span className="loading loading-dots loading-lg"></span>{" "} <span className="loading loading-dots loading-lg"></span>{ " " }
</div> </div>
); );
// Room has been loaded // Room has been loaded
} else if (roomFromDb) { } else if (roomFromDb) {
return ( return (
<span className="text-center"> <span className="text-center">
<div className="text-2xl">{roomFromDb.roomName}</div> <div className="text-2xl">{ roomFromDb.roomName }</div>
<div className="flex flex-row flex-wrap text-center justify-center items-center gap-1 text-md mx-auto"> <div className="flex flex-row flex-wrap text-center justify-center items-center gap-1 text-md mx-auto">
<div>ID:</div> <div>ID:</div>
<div>{roomFromDb.id}</div> <div>{ roomFromDb.id }</div>
<button> <button>
{copied ? ( { copied ? (
<IoCheckmarkCircleOutline className="mx-1 text-green-400 animate-bounce" /> <IoCheckmarkCircleOutline className="mx-1 text-green-400 animate-bounce" />
) : ( ) : (
<IoCopyOutline <IoCopyOutline
className="mx-1 hover:text-primary" className="mx-1 hover:text-primary"
onClick={copyRoomURLHandler} onClick={ copyRoomURLHandler }
></IoCopyOutline> ></IoCopyOutline>
)} ) }
</button> </button>
</div> </div>
{roomFromDb && ( { roomFromDb && (
<div className="card card-compact bg-neutral shadow-xl mx-auto m-4"> <div className="card card-compact bg-neutral shadow-xl mx-auto m-4">
<div className="card-body"> <div className="card-body">
<h2 className="card-title mx-auto"> <h2 className="card-title mx-auto">
Story: {roomFromDb.storyName} Story: { roomFromDb.storyName }
</h2> </h2>
<ul className="p-0 mx-auto flex flex-row flex-wrap justify-center items-center text-ceter gap-4"> <ul className="p-0 mx-auto flex flex-row flex-wrap justify-center items-center text-ceter gap-4">
{presenceData && { presenceData &&
presenceData presenceData
.filter( .filter(
(value, index, self) => (value, index, self) =>
@ -288,73 +288,72 @@ const RoomBody: React.FC = () => {
.map((presenceItem) => { .map((presenceItem) => {
return ( return (
<li <li
key={presenceItem.clientId} key={ presenceItem.clientId }
className="flex flex-row items-center justify-center gap-2" className="flex flex-row items-center justify-center gap-2"
> >
<div className="w-10 rounded-full avatar mx-auto"> <div className="w-10 rounded-full avatar mx-auto">
<Image <Image
src={presenceItem.data.image} src={ presenceItem.data.image }
alt={`${presenceItem.data.name}'s Profile Picture`} alt={ `${presenceItem.data.name}'s Profile Picture` }
height={32} height={ 32 }
width={32} width={ 32 }
/> />
</div> </div>
<p className="flex flex-row flex-wrap text-center justify-center items-center gap-1 text-md mx-auto"> <p className="flex flex-row flex-wrap text-center justify-center items-center gap-1 text-md mx-auto">
{presenceItem.data.name}{" "} { presenceItem.data.name }{ " " }
{presenceItem.data.role === "ADMIN" && ( { presenceItem.data.role === "ADMIN" && (
<div <div
className="tooltip tooltip-primary" className="tooltip tooltip-primary"
data-tip="Admin" data-tip="Admin"
> >
<FaShieldAlt className="inline-block text-primary" /> <FaShieldAlt className="inline-block text-primary" />
</div> </div>
)}{" "} ) }{ " " }
{presenceItem.clientId === roomFromDb.userId && ( { presenceItem.clientId === roomFromDb.userId && (
<div <div
className="tooltip tooltip-warning" className="tooltip tooltip-warning"
data-tip="Room Owner" data-tip="Room Owner"
> >
<RiVipCrownFill className="inline-block text-yellow-500" /> <RiVipCrownFill className="inline-block text-yellow-500" />
</div> </div>
)} ) }
{" : "} { " : " }
</p> </p>
{roomFromDb && { roomFromDb &&
votesFromDb && votesFromDb &&
voteString( voteString(
roomFromDb.visible, roomFromDb.visible,
votesFromDb, votesFromDb,
presenceItem.data presenceItem.data
)} ) }
</li> </li>
); );
})} }) }
</ul> </ul>
<div className="join md:btn-group-horizontal mx-auto"> <div className="join md:btn-group-horizontal mx-auto">
{roomFromDb.scale.split(",").map((scaleItem, index) => { { roomFromDb.scale.split(",").map((scaleItem, index) => {
return ( return (
<button <button
key={index} key={ index }
className={`join-item ${ className={ `join-item ${getVoteForCurrentUser()?.value === scaleItem
getVoteForCurrentUser()?.value === scaleItem
? "btn btn-active btn-primary" ? "btn btn-active btn-primary"
: "btn" : "btn"
}`} }` }
onClick={() => setVote(scaleItem)} onClick={ () => setVote(scaleItem) }
> >
{scaleItem} { scaleItem }
</button> </button>
); );
})} }) }
</div> </div>
</div> </div>
</div> </div>
)} ) }
{sessionData && { sessionData &&
!!roomFromDb && !!roomFromDb &&
roomFromDb.userId === sessionData.user.id && ( roomFromDb.userId === sessionData.user.id && (
<> <>
@ -363,38 +362,38 @@ const RoomBody: React.FC = () => {
<h2 className="card-title mx-auto">Room Settings</h2> <h2 className="card-title mx-auto">Room Settings</h2>
<label className="label mx-auto"> <label className="label mx-auto">
{"Vote Scale (Comma Separated):"}{" "} { "Vote Scale (Comma Separated):" }{ " " }
</label> </label>
<input <input
type="text" type="text"
placeholder="Scale (Comma Separated)" placeholder="Scale (Comma Separated)"
className="input input-bordered m-auto" className="input input-bordered m-auto"
value={roomScale} value={ roomScale }
onChange={(event) => { onChange={ (event) => {
setRoomScale(event.target.value); setRoomScale(event.target.value);
}} } }
/> />
<label className="label mx-auto">{"Story Name:"} </label> <label className="label mx-auto">{ "Story Name:" } </label>
<input <input
type="text" type="text"
placeholder="Story Name" placeholder="Story Name"
className="input input-bordered m-auto" className="input input-bordered m-auto"
value={storyNameText} value={ storyNameText }
onChange={(event) => { onChange={ (event) => {
setStoryNameText(event.target.value); setStoryNameText(event.target.value);
}} } }
/> />
<div className="flex flex-row flex-wrap text-center items-center justify-center gap-2"> <div className="flex flex-row flex-wrap text-center items-center justify-center gap-2">
<div> <div>
<button <button
onClick={() => saveRoom(!roomFromDb.visible, false)} onClick={ () => saveRoom(!roomFromDb.visible, false) }
className="btn btn-primary inline-flex" className="btn btn-primary inline-flex"
> >
{roomFromDb.visible ? ( { roomFromDb.visible ? (
<> <>
<IoEyeOffOutline className="text-xl mr-1" /> <IoEyeOffOutline className="text-xl mr-1" />
Hide Hide
@ -404,13 +403,13 @@ const RoomBody: React.FC = () => {
<IoEyeOutline className="text-xl mr-1" /> <IoEyeOutline className="text-xl mr-1" />
Show Show
</> </>
)} ) }
</button> </button>
</div> </div>
<div> <div>
<button <button
onClick={() => onClick={ () =>
saveRoom( saveRoom(
false, false,
true, true,
@ -427,8 +426,8 @@ const RoomBody: React.FC = () => {
).length <= 1 ).length <= 1
} }
> >
{roomFromDb.storyName === storyNameText || { roomFromDb.storyName === storyNameText ||
votesFromDb?.length === 0 ? ( votesFromDb?.length === 0 ? (
<> <>
<IoReloadOutline className="text-xl mr-1" /> Reset <IoReloadOutline className="text-xl mr-1" /> Reset
</> </>
@ -436,16 +435,16 @@ const RoomBody: React.FC = () => {
<> <>
<IoSaveOutline className="text-xl mr-1" /> Save <IoSaveOutline className="text-xl mr-1" /> Save
</> </>
)} ) }
</button> </button>
</div> </div>
{votesFromDb && { votesFromDb &&
(roomFromDb.logs.length > 0 || (roomFromDb.logs.length > 0 ||
votesFromDb.length > 0) && ( votesFromDb.length > 0) && (
<div> <div>
<button <button
onClick={() => downloadLogs()} onClick={ () => downloadLogs() }
className="btn btn-primary inline-flex hover:animate-pulse" className="btn btn-primary inline-flex hover:animate-pulse"
> >
<> <>
@ -453,12 +452,12 @@ const RoomBody: React.FC = () => {
</> </>
</button> </button>
</div> </div>
)} ) }
</div> </div>
</div> </div>
</div> </div>
</> </>
)} ) }
</span> </span>
); );
// Room does not exist // Room does not exist