Keep improving

This commit is contained in:
aronmal 2023-04-24 18:56:56 +02:00
parent d3e8a43b34
commit da53662d6e
Signed by: aronmal
GPG key ID: 816B7707426FC612
8 changed files with 165 additions and 60 deletions

View file

@ -20,14 +20,13 @@ function OptionButton({
<button
className={classNames(
"flex w-full flex-row items-center justify-between rounded-xl py-2 pl-8 pr-4 text-lg text-grayish duration-100 first:mt-4 last:mt-4 sm:py-4 sm:pl-16 sm:pr-8 sm:text-4xl sm:first:mt-8 sm:last:mt-8",
{
"bg-voidDark border-shield-gray border-b-4 active:border-b-0 active:border-t-4":
!disabled,
"bg-red-950 border-slate-600 border-4 border-dashed": disabled,
}
!disabled
? "bg-voidDark border-shield-gray border-b-4 active:border-b-0 active:border-t-4"
: "bg-red-950 border-slate-600 border-4 border-dashed"
)}
onClick={() => action && setTimeout(action, 200)}
disabled={disabled}
title={!disabled ? "" : "Please login"}
>
<span className="mx-auto">{children}</span>
<FontAwesomeIcon

View file

@ -6,19 +6,27 @@ import { toast } from "react-toastify"
function useGameState() {
const [gameProps, setGameProps] = useContext(gameContext)
const { data: session, status } = useSession()
useEffect(() => {
if (!session) return
toast(session.user.email, {
toastId: "user",
position: "top-center",
icon: session.user.image ? (
<img
style={{ transform: "scale(1.5)", borderRadius: "100%" }}
src={session.user.image}
/>
) : undefined,
})
if (status === "loading") return
if (!session)
toast("Nicht angemeldet.", {
toastId: "user",
position: "top-center",
})
else
toast(session.user.email, {
toastId: "user",
position: "top-center",
icon: session.user.image ? (
<img
style={{ transform: "scale(1.5)", borderRadius: "100%" }}
src={session.user.image}
/>
) : undefined,
})
}, [session])
return {
gameProps,
setGameProps,

View file

@ -0,0 +1,46 @@
import { authOptions } from "../auth/[...nextauth]"
import { rejectionErrors } from "@lib/backend/errors"
import sendResponse from "@lib/backend/sendResponse"
import prisma from "@lib/prisma"
import { Game } from "@prisma/client"
import type { NextApiRequest, NextApiResponse } from "next"
import { getServerSession } from "next-auth"
interface Data {
game: Game
}
export default async function id(
req: NextApiRequest,
res: NextApiResponse<Data>
) {
const gameId = req.query.id
const session = await getServerSession(req, res, authOptions)
if (!session?.user || typeof gameId !== "string") {
return sendResponse(req, res, rejectionErrors.unauthorized)
}
let game: Game | null
switch (req.method) {
case "DELETE":
game = await prisma.game.delete({
where: { id: gameId },
})
break
default:
game = await prisma.game.findFirst({
where: { id: gameId },
})
}
if (!game) {
return sendResponse(req, res, rejectionErrors.gameNotFound)
}
sendResponse(req, res, {
message: "Here is the game.",
body: { game },
})
}

View file

@ -28,10 +28,10 @@ export default async function create(
let created = false
let game = await getAnyRunningGame(id)
if (!game) {
let gameDB = await getAnyRunningGame(id)
if (!gameDB) {
created = true
game = await prisma.game.create({
gameDB = await prisma.game.create({
data: {
gamePin: {
create: {
@ -52,12 +52,14 @@ export default async function create(
})
}
const { users, gamePin, ...game } = gameDB
return sendResponse(req, res, {
message: `User <${email}> created game: ${game.id}`,
statusCode: created ? 201 : 200,
body: {
game,
pin: game.gamePin?.pin,
pin: gamePin?.pin,
player: {
id,
name: name ?? undefined,

View file

@ -38,15 +38,17 @@ export default async function create(
const { email, id } = session.user
const game = await getAnyRunningGame(id)
const gameDB = await getAnyRunningGame(id)
if (!game)
if (!gameDB)
return sendResponse(req, res, {
message: `User <${email}> is in no game.`,
statusCode: 204,
type: ["debug", "infoCyan"],
})
const { users, gamePin, ...game } = gameDB
return sendResponse(req, res, {
message: `User <${email}> asked for game: ${game.id}`,
statusCode: 200,

View file

@ -0,0 +1,60 @@
import { authOptions } from "../api/auth/[...nextauth]"
import { getAnyRunningGame } from "../api/game/running"
import { GetServerSideProps } from "next"
import { Session, getServerSession } from "next-auth"
import { useRouter } from "next/router"
import React, { useEffect } from "react"
import { toast } from "react-toastify"
interface Props {
gameId: string
session: Session | null
}
export default function Game({ gameId, session }: Props) {
const router = useRouter()
useEffect(() => {
const path = gameId ? "/game/" + gameId : "/start"
toast.promise(router.push(path), {
pending: {
render: "Wird weitergeleitet...",
toastId: "redirect",
},
success: {
render: gameId
? "Spiel gefunden!"
: session?.user
? "Kein laufendes Spiel."
: "Kein laufendes Spiel. Bitte anmelden.",
toastId: session?.user ? "postRedirect" : "user",
theme: session?.user ? "dark" : undefined,
type: gameId ? "success" : "info",
},
error: {
render: "Es ist ein Fehler aufgetreten 🤯",
type: "error",
theme: "colored",
},
})
})
return (
<div className="h-full bg-theme">
<div className="mx-auto flex h-full max-w-screen-md flex-col items-center justify-evenly"></div>
</div>
)
}
export const getServerSideProps: GetServerSideProps<Props> = async (
context
) => {
const session = await getServerSession(context.req, context.res, authOptions)
let gameId = ""
if (session?.user.id) {
const game = await getAnyRunningGame(session?.user.id)
if (game && game.id) gameId = game?.id
}
return { props: { gameId, session } }
}

View file

@ -79,7 +79,6 @@ export default function Home({ q }: Props) {
},
})
console.log(res)
setGameProps(res)
await toast.promise(router.push("/lobby"), {
@ -101,14 +100,12 @@ export default function Home({ q }: Props) {
useEffect(() => {
if (otp.length !== 4) return
if (!isInputOnlyNumbers(otp)) {
if (!isInputOnlyNumbers(otp))
toast("Der Code darf nur Zahlen beinhalten!", {
type: "warning",
theme: "dark",
})
return
}
gameFetch(otp)
else gameFetch(otp)
}, [otp, gameFetch])
return (
@ -121,11 +118,7 @@ export default function Home({ q }: Props) {
className="-mt-2 w-20 self-start rounded-xl border-b-4 border-shield-gray bg-voidDark text-2xl text-grayish duration-100 active:border-b-0 active:border-t-4 sm:-mt-6 sm:w-40 sm:px-2 sm:text-5xl"
onClick={() =>
setTimeout(() => {
// Navigate to the same page with the `start` query parameter set to `false`
router.push({
pathname: router.pathname,
query: null,
})
router.push("/")
}, 200)
}
>
@ -149,9 +142,7 @@ export default function Home({ q }: Props) {
icon={faUserPlus}
disabled={!session}
>
{q === "join" ? (
"Raum beitreten"
) : (
{q === "join" && session?.user ? (
<OtpInput
shouldAutoFocus
containerStyle={{ color: "initial" }}
@ -162,6 +153,8 @@ export default function Home({ q }: Props) {
renderSeparator={<span>-</span>}
renderInput={(props) => <input {...props} />}
/>
) : (
"Raum beitreten"
)}
</OptionButton>
<OptionButton icon={faEye}>Zuschauen</OptionButton>

View file

@ -68,11 +68,6 @@ model VerificationToken {
@@map("verificationtokens")
}
enum TokenType {
REFRESH
ACCESS
}
enum GameState {
launching
running
@ -88,6 +83,14 @@ model Game {
users User_Game[]
}
model Gamepin {
id String @id @default(cuid())
createdAt DateTime @default(now())
pin String @unique
gameId String @unique
game Game @relation(fields: [gameId], references: [id], onDelete: Cascade)
}
model User_Game {
id String @id @default(cuid())
createdAt DateTime @default(now())
@ -96,33 +99,25 @@ model User_Game {
isOwner Boolean
moves Move[]
chats Chat[]
game Game @relation(fields: [gameId], references: [id])
game Game @relation(fields: [gameId], references: [id], onDelete: Cascade)
user User @relation(fields: [userId], references: [id])
@@unique([gameId, userId])
}
model Move {
id String @id @default(cuid())
createdAt DateTime @default(now())
index Int
gameId String
game User_Game @relation(fields: [gameId], references: [id])
}
model Gamepin {
id String @id @default(cuid())
createdAt DateTime @default(now())
pin String @unique
gameId String @unique
game Game @relation(fields: [gameId], references: [id])
id String @id @default(cuid())
createdAt DateTime @default(now())
index Int
user_game_id String
user_game User_Game @relation(fields: [user_game_id], references: [id], onDelete: Cascade)
}
model Chat {
id String @id @default(cuid())
createdAt DateTime @default(now())
message String?
event String?
gameId String
game User_Game @relation(fields: [gameId], references: [id])
id String @id @default(cuid())
createdAt DateTime @default(now())
message String?
event String?
user_game_id String
user_game User_Game @relation(fields: [user_game_id], references: [id], onDelete: Cascade)
}