Keep improving
This commit is contained in:
parent
d3e8a43b34
commit
da53662d6e
8 changed files with 165 additions and 60 deletions
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
46
leaky-ships/pages/api/game/[id].ts
Normal file
46
leaky-ships/pages/api/game/[id].ts
Normal 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 },
|
||||
})
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
60
leaky-ships/pages/game/index.tsx
Normal file
60
leaky-ships/pages/game/index.tsx
Normal 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 } }
|
||||
}
|
|
@ -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>
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue