Some after work from last commit
This commit is contained in:
parent
30db96a3f7
commit
12295b316f
14 changed files with 130 additions and 176 deletions
|
@ -1,13 +1,32 @@
|
||||||
import Icon from "./Icon"
|
import Icon from "./Icon"
|
||||||
import Player from "./Player"
|
import Player from "./Player"
|
||||||
|
import { faSpinnerThird } from "@fortawesome/pro-solid-svg-icons"
|
||||||
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
||||||
import useGameState from "@lib/hooks/useGameState"
|
import useGameState from "@lib/hooks/useGameState"
|
||||||
import useSocket from "@lib/hooks/useSocket"
|
import useSocket from "@lib/hooks/useSocket"
|
||||||
|
import { useRouter } from "next/router"
|
||||||
import { Fragment, useEffect, useState } from "react"
|
import { Fragment, useEffect, useState } from "react"
|
||||||
|
import { toast } from "react-toastify"
|
||||||
|
|
||||||
function LobbyFrame({ openSettings }: { openSettings: () => void }) {
|
function LobbyFrame({ openSettings }: { openSettings: () => void }) {
|
||||||
const { payload } = useGameState().gameProps
|
const { payload } = useGameState().gameProps
|
||||||
useSocket()
|
const { isConnected, hasJoined } = useSocket()
|
||||||
const [dots, setDots] = useState(1)
|
const [dots, setDots] = useState(3)
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isConnected && hasJoined) return
|
||||||
|
const timeout = setTimeout(() => {
|
||||||
|
toast("Es konnte keine Echtzeitverbindung aufgebaute werden.", {
|
||||||
|
toastId: "connection_error",
|
||||||
|
type: "error",
|
||||||
|
autoClose: 10000,
|
||||||
|
})
|
||||||
|
router.push("/start")
|
||||||
|
}, 15000)
|
||||||
|
|
||||||
|
return () => clearTimeout(timeout)
|
||||||
|
}, [])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (payload?.player2) return
|
if (payload?.player2) return
|
||||||
|
@ -21,7 +40,11 @@ function LobbyFrame({ openSettings }: { openSettings: () => void }) {
|
||||||
<Icon src="speech_bubble.png">Chat</Icon>
|
<Icon src="speech_bubble.png">Chat</Icon>
|
||||||
<h1 className="font-farro text-5xl font-medium">
|
<h1 className="font-farro text-5xl font-medium">
|
||||||
Game-PIN:{" "}
|
Game-PIN:{" "}
|
||||||
<span className="underline">{payload?.gamePin?.pin ?? "---"}</span>
|
{isConnected ? (
|
||||||
|
<span className="underline">{payload?.gamePin?.pin ?? "---"}</span>
|
||||||
|
) : (
|
||||||
|
<FontAwesomeIcon icon={faSpinnerThird} spin={true} />
|
||||||
|
)}
|
||||||
</h1>
|
</h1>
|
||||||
<Icon src="gear.png" onClick={openSettings}>
|
<Icon src="gear.png" onClick={openSettings}>
|
||||||
Settings
|
Settings
|
||||||
|
@ -42,7 +65,8 @@ function LobbyFrame({ openSettings }: { openSettings: () => void }) {
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<p className="font-farro w-96 text-center text-4xl font-medium">
|
<p className="font-farro w-96 text-center text-4xl font-medium">
|
||||||
Warte auf Spieler 2 {Array.from(Array(dots), () => ".").join("")}
|
Warte auf {isConnected && hasJoined ? "Spieler 2" : "Verbindung"}{" "}
|
||||||
|
{Array.from(Array(dots), () => ".").join("")}
|
||||||
{Array.from(Array(3 - dots), (_, i) => (
|
{Array.from(Array(3 - dots), (_, i) => (
|
||||||
<Fragment key={i}> </Fragment>
|
<Fragment key={i}> </Fragment>
|
||||||
))}
|
))}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import colors, { Color } from "colors"
|
import colors, { Color } from "colors"
|
||||||
import fs from "fs"
|
import fs from "fs"
|
||||||
|
import { IncomingMessage } from "http"
|
||||||
import { NextApiRequest } from "next"
|
import { NextApiRequest } from "next"
|
||||||
|
|
||||||
colors.enable()
|
colors.enable()
|
||||||
|
@ -38,7 +39,7 @@ async function logStartup() {
|
||||||
async function logging(
|
async function logging(
|
||||||
message: string,
|
message: string,
|
||||||
types: Logging[],
|
types: Logging[],
|
||||||
req?: NextApiRequest
|
req?: NextApiRequest | IncomingMessage
|
||||||
) {
|
) {
|
||||||
if (!started) await logStartup()
|
if (!started) await logStartup()
|
||||||
const messages = { console: message, file: message }
|
const messages = { console: message, file: message }
|
||||||
|
|
|
@ -3,20 +3,19 @@ import { useSession } from "next-auth/react"
|
||||||
import {
|
import {
|
||||||
Dispatch,
|
Dispatch,
|
||||||
ReactNode,
|
ReactNode,
|
||||||
SetStateAction,
|
|
||||||
createContext,
|
createContext,
|
||||||
useContext,
|
useContext,
|
||||||
useEffect,
|
useEffect,
|
||||||
useState,
|
|
||||||
useMemo,
|
useMemo,
|
||||||
|
useReducer,
|
||||||
} from "react"
|
} from "react"
|
||||||
import { toast } from "react-toastify"
|
import { toast } from "react-toastify"
|
||||||
|
|
||||||
const initialValue = { payload: null, hash: null }
|
const initialValue: GamePropsSchema = { payload: null, hash: null }
|
||||||
|
|
||||||
interface gameContext {
|
interface gameContext {
|
||||||
gameProps: GamePropsSchema
|
gameProps: GamePropsSchema
|
||||||
setGameProps: Dispatch<SetStateAction<GamePropsSchema>>
|
setGameProps: Dispatch<GamePropsSchema>
|
||||||
}
|
}
|
||||||
|
|
||||||
export const gameContext = createContext<gameContext>({
|
export const gameContext = createContext<gameContext>({
|
||||||
|
@ -24,8 +23,30 @@ export const gameContext = createContext<gameContext>({
|
||||||
setGameProps: () => {},
|
setGameProps: () => {},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function updateProps(state: GamePropsSchema, body: GamePropsSchema) {
|
||||||
|
if (state.hash === body.hash) {
|
||||||
|
console.log("Everything up to date.")
|
||||||
|
return state
|
||||||
|
} else {
|
||||||
|
console.log("Update was needed.", state.hash, body.hash)
|
||||||
|
|
||||||
|
if (
|
||||||
|
state.payload?.game?.id &&
|
||||||
|
state.payload?.game?.id !== body.payload?.game?.id
|
||||||
|
) {
|
||||||
|
console.warn(
|
||||||
|
"Different gameId detected on update: ",
|
||||||
|
state.payload?.game?.id,
|
||||||
|
body.payload?.game?.id
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return body
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function GameContextProvider({ children }: { children: ReactNode }) {
|
export function GameContextProvider({ children }: { children: ReactNode }) {
|
||||||
const [gameProps, setGameProps] = useState<GamePropsSchema>(initialValue)
|
const [gameProps, setGameProps] = useReducer(updateProps, initialValue)
|
||||||
|
|
||||||
const value = useMemo<gameContext>(
|
const value = useMemo<gameContext>(
|
||||||
() => ({ gameProps, setGameProps }),
|
() => ({ gameProps, setGameProps }),
|
||||||
|
@ -35,15 +56,10 @@ export function GameContextProvider({ children }: { children: ReactNode }) {
|
||||||
return <gameContext.Provider value={value}>{children}</gameContext.Provider>
|
return <gameContext.Provider value={value}>{children}</gameContext.Provider>
|
||||||
}
|
}
|
||||||
|
|
||||||
function useGameState(initial?: GamePropsSchema) {
|
function useGameState() {
|
||||||
const { gameProps, setGameProps } = useContext(gameContext)
|
const { gameProps, setGameProps } = useContext(gameContext)
|
||||||
const { data: session, status } = useSession()
|
const { data: session, status } = useSession()
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!initial) return
|
|
||||||
setGameProps(initial)
|
|
||||||
}, [initial, setGameProps])
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (status === "loading") return
|
if (status === "loading") return
|
||||||
if (!session)
|
if (!session)
|
||||||
|
|
|
@ -52,7 +52,7 @@ function useSocket() {
|
||||||
socket?.emit("authenticate", { token: `hello from ${session?.user.email}` })
|
socket?.emit("authenticate", { token: `hello from ${session?.user.email}` })
|
||||||
}, [isConnected, status, session?.user.email])
|
}, [isConnected, status, session?.user.email])
|
||||||
|
|
||||||
return socket
|
return { isConnected, hasJoined }
|
||||||
}
|
}
|
||||||
|
|
||||||
export default useSocket
|
export default useSocket
|
||||||
|
|
|
@ -2,5 +2,5 @@ import { cSocket } from "../interfaces/NextApiSocket"
|
||||||
import { io } from "socket.io-client"
|
import { io } from "socket.io-client"
|
||||||
|
|
||||||
export const socket: cSocket = io({
|
export const socket: cSocket = io({
|
||||||
path: "/api/ws2",
|
path: "/api/ws",
|
||||||
})
|
})
|
||||||
|
|
|
@ -2,6 +2,7 @@ import "../styles/App.scss"
|
||||||
import "../styles/globals.scss"
|
import "../styles/globals.scss"
|
||||||
import "../styles/grid2.scss"
|
import "../styles/grid2.scss"
|
||||||
import "../styles/grid.scss"
|
import "../styles/grid.scss"
|
||||||
|
import "@fortawesome/fontawesome-svg-core/styles.css"
|
||||||
import { GameContextProvider } from "@lib/hooks/useGameState"
|
import { GameContextProvider } from "@lib/hooks/useGameState"
|
||||||
import { SessionProvider } from "next-auth/react"
|
import { SessionProvider } from "next-auth/react"
|
||||||
import type { AppProps } from "next/app"
|
import type { AppProps } from "next/app"
|
||||||
|
|
|
@ -7,17 +7,16 @@ import EmailProvider from "next-auth/providers/email"
|
||||||
import {
|
import {
|
||||||
uniqueNamesGenerator,
|
uniqueNamesGenerator,
|
||||||
Config,
|
Config,
|
||||||
adjectives,
|
|
||||||
animals,
|
animals,
|
||||||
NumberDictionary,
|
NumberDictionary,
|
||||||
} from "unique-names-generator"
|
} from "unique-names-generator"
|
||||||
|
|
||||||
const numberDictionary = NumberDictionary.generate({ min: 0, max: 999 })
|
const numberDictionary = NumberDictionary.generate({ min: 0, max: 9999 })
|
||||||
const customConfig: Config = {
|
const customConfig: Config = {
|
||||||
dictionaries: [adjectives, animals, numberDictionary],
|
dictionaries: [animals, numberDictionary],
|
||||||
separator: " ",
|
separator: " ",
|
||||||
style: "capital",
|
style: "capital",
|
||||||
length: 3,
|
length: 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
const options: NextAuthOptions = {
|
const options: NextAuthOptions = {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import sendError from "@backend/sendError"
|
||||||
import sendResponse from "@backend/sendResponse"
|
import sendResponse from "@backend/sendResponse"
|
||||||
import { rejectionErrors } from "@lib/backend/errors"
|
import { rejectionErrors } from "@lib/backend/errors"
|
||||||
import getPinFromBody from "@lib/backend/getPinFromBody"
|
import getPinFromBody from "@lib/backend/getPinFromBody"
|
||||||
|
import logging from "@lib/backend/logging"
|
||||||
import prisma from "@lib/prisma"
|
import prisma from "@lib/prisma"
|
||||||
import { GamePropsSchema } from "@lib/zodSchemas"
|
import { GamePropsSchema } from "@lib/zodSchemas"
|
||||||
import type { NextApiRequest, NextApiResponse } from "next"
|
import type { NextApiRequest, NextApiResponse } from "next"
|
||||||
|
@ -57,7 +58,11 @@ export default async function join(
|
||||||
type: ["debug", "infoCyan"],
|
type: ["debug", "infoCyan"],
|
||||||
})
|
})
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
console.log("HERE".red, err.code, err.meta, err.message)
|
await logging(
|
||||||
|
"HERE".red + err.code + err.meta + err.message,
|
||||||
|
["error"],
|
||||||
|
req
|
||||||
|
)
|
||||||
throw sendError(req, res, rejectionErrors.gameNotFound)
|
throw sendError(req, res, rejectionErrors.gameNotFound)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ export function composeBody(
|
||||||
return { payload, hash }
|
return { payload, hash }
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function create(
|
export default async function running(
|
||||||
req: NextApiRequest,
|
req: NextApiRequest,
|
||||||
res: NextApiResponse<GamePropsSchema>
|
res: NextApiResponse<GamePropsSchema>
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -3,6 +3,7 @@ import {
|
||||||
cServer,
|
cServer,
|
||||||
} from "../../interfaces/NextApiSocket"
|
} from "../../interfaces/NextApiSocket"
|
||||||
import { composeBody, getAnyRunningGame } from "./game/running"
|
import { composeBody, getAnyRunningGame } from "./game/running"
|
||||||
|
import logging from "@lib/backend/logging"
|
||||||
import prisma from "@lib/prisma"
|
import prisma from "@lib/prisma"
|
||||||
import colors from "colors"
|
import colors from "colors"
|
||||||
import { NextApiRequest } from "next"
|
import { NextApiRequest } from "next"
|
||||||
|
@ -16,11 +17,11 @@ const SocketHandler = async (
|
||||||
res: NextApiResponseWithSocket
|
res: NextApiResponseWithSocket
|
||||||
) => {
|
) => {
|
||||||
if (res.socket.server.io) {
|
if (res.socket.server.io) {
|
||||||
console.log("Socket is already running " + req.url)
|
logging("Socket is already running " + req.url, ["infoCyan"], req)
|
||||||
} else {
|
} else {
|
||||||
console.log("Socket is initializing " + req.url)
|
logging("Socket is initializing " + req.url, ["infoCyan"], req)
|
||||||
const io: cServer = new Server(res.socket.server, {
|
const io: cServer = new Server(res.socket.server, {
|
||||||
path: "/api/ws2",
|
path: "/api/ws",
|
||||||
cors: {
|
cors: {
|
||||||
origin: "https://leaky-ships.mal-noh.de",
|
origin: "https://leaky-ships.mal-noh.de",
|
||||||
},
|
},
|
||||||
|
@ -41,23 +42,35 @@ const SocketHandler = async (
|
||||||
})
|
})
|
||||||
next()
|
next()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("Unauthorized")
|
logging("Unauthorized", ["warn"], socket.request)
|
||||||
next(new Error("Unauthorized"))
|
next(new Error("Unauthorized"))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
io.on("connection", (socket) => {
|
io.on("connection", (socket) => {
|
||||||
console.log(
|
logging(
|
||||||
`User connected <${socket.data.user?.email}>`.green,
|
`User connected <${socket.data.user?.email}>`.green +
|
||||||
socket.id
|
", " +
|
||||||
|
socket.id.cyan,
|
||||||
|
["infoGreen"],
|
||||||
|
socket.request
|
||||||
)
|
)
|
||||||
|
|
||||||
socket.on("join", async (userId, cb) => {
|
socket.on("join", async (userId, cb) => {
|
||||||
console.log(socket.rooms, "join")
|
logging(
|
||||||
|
"Join: " + JSON.stringify(Array.from(socket.rooms)),
|
||||||
|
["debug"],
|
||||||
|
socket.request
|
||||||
|
)
|
||||||
const game = await getAnyRunningGame(userId ?? "")
|
const game = await getAnyRunningGame(userId ?? "")
|
||||||
if (!game) {
|
if (!game) {
|
||||||
const warst = socket.emit("forbidden")
|
socket.emit("forbidden")
|
||||||
console.log("forbidden", warst)
|
logging(
|
||||||
|
"Forbidden, no game found: " +
|
||||||
|
JSON.stringify(Array.from(socket.rooms)),
|
||||||
|
["debug"],
|
||||||
|
socket.request
|
||||||
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cb()
|
cb()
|
||||||
|
@ -68,12 +81,16 @@ const SocketHandler = async (
|
||||||
})
|
})
|
||||||
|
|
||||||
socket.on("disconnecting", () => {
|
socket.on("disconnecting", () => {
|
||||||
console.log("disconnecting", socket.rooms) // the Set contains at least the socket ID
|
logging(
|
||||||
|
"Disconnecting: " + JSON.stringify(Array.from(socket.rooms)),
|
||||||
|
["debug"],
|
||||||
|
socket.request
|
||||||
|
) // the Set contains at least the socket ID
|
||||||
})
|
})
|
||||||
|
|
||||||
socket.on("disconnect", () => {
|
socket.on("disconnect", () => {
|
||||||
// socket.rooms.size === 0
|
// socket.rooms.size === 0
|
||||||
console.log("disconnect", socket.id)
|
logging("Disconnect: " + socket.id, ["debug"], socket.request)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
|
@ -1,21 +1,15 @@
|
||||||
import { authOptions } from "../api/auth/[...nextauth]"
|
import useGameState from "@lib/hooks/useGameState"
|
||||||
import { getAnyRunningGame } from "../api/game/running"
|
|
||||||
import { GetServerSideProps } from "next"
|
|
||||||
import { Session, getServerSession } from "next-auth"
|
|
||||||
import { useRouter } from "next/router"
|
import { useRouter } from "next/router"
|
||||||
import React, { useEffect } from "react"
|
import React, { useEffect } from "react"
|
||||||
import { toast } from "react-toastify"
|
import { toast } from "react-toastify"
|
||||||
|
|
||||||
interface Props {
|
export default function Game() {
|
||||||
gameId: string
|
const { gameProps, session } = useGameState()
|
||||||
session: Session | null
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function Game({ gameId, session }: Props) {
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const path = gameId ? "/game/" + gameId : "/start"
|
const gameId = gameProps.payload?.game?.id
|
||||||
|
const path = gameId ? "/game" : "/start"
|
||||||
toast.promise(router.push(path), {
|
toast.promise(router.push(path), {
|
||||||
pending: {
|
pending: {
|
||||||
render: "Wird weitergeleitet...",
|
render: "Wird weitergeleitet...",
|
||||||
|
@ -45,16 +39,3 @@ export default function Game({ gameId, session }: Props) {
|
||||||
</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.state === "running") gameId = game?.id
|
|
||||||
}
|
|
||||||
|
|
||||||
return { props: { gameId, session } }
|
|
||||||
}
|
|
|
@ -1,17 +1,14 @@
|
||||||
import BurgerMenu from "../../components/BurgerMenu"
|
import BurgerMenu from "../components/BurgerMenu"
|
||||||
import LobbyFrame from "../../components/Lobby/LobbyFrame"
|
import LobbyFrame from "../components/Lobby/LobbyFrame"
|
||||||
import Settings from "../../components/Lobby/SettingsFrame/Settings"
|
import Settings from "../components/Lobby/SettingsFrame/Settings"
|
||||||
import Logo from "../../components/Logo"
|
import Logo from "../components/Logo"
|
||||||
import { composeBody, getAnyGame } from "../api/game/running"
|
|
||||||
import useGameState from "@lib/hooks/useGameState"
|
import useGameState from "@lib/hooks/useGameState"
|
||||||
import { GamePropsSchema } from "@lib/zodSchemas"
|
|
||||||
import classNames from "classnames"
|
import classNames from "classnames"
|
||||||
import { GetServerSideProps } from "next"
|
|
||||||
import Head from "next/head"
|
import Head from "next/head"
|
||||||
import { useState } from "react"
|
import { useState } from "react"
|
||||||
|
|
||||||
export default function Home(props: GamePropsSchema) {
|
export default function Lobby() {
|
||||||
useGameState(props)
|
useGameState()
|
||||||
const [settings, setSettings] = useState(false)
|
const [settings, setSettings] = useState(false)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -36,22 +33,3 @@ export default function Home(props: GamePropsSchema) {
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getServerSideProps: GetServerSideProps<GamePropsSchema> = async (
|
|
||||||
context
|
|
||||||
) => {
|
|
||||||
const { gameId } = context.query
|
|
||||||
|
|
||||||
const gameIdString = Array.isArray(gameId) ? gameId[0] : gameId
|
|
||||||
const game = await getAnyGame(gameIdString ?? "")
|
|
||||||
if (!game)
|
|
||||||
return {
|
|
||||||
redirect: {
|
|
||||||
destination: "/start",
|
|
||||||
permanent: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
const body = composeBody(game)
|
|
||||||
|
|
||||||
return { props: body }
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
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 Lobby({ gameId, session }: Props) {
|
|
||||||
const router = useRouter()
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const path = gameId ? "/lobby/" + 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.state === "launching") gameId = game?.id
|
|
||||||
}
|
|
||||||
|
|
||||||
return { props: { gameId, session } }
|
|
||||||
}
|
|
|
@ -1,25 +1,17 @@
|
||||||
import BurgerMenu from "../components/BurgerMenu"
|
import BurgerMenu from "../components/BurgerMenu"
|
||||||
import Logo from "../components/Logo"
|
import Logo from "../components/Logo"
|
||||||
import OptionButton from "../components/OptionButton"
|
import OptionButton from "../components/OptionButton"
|
||||||
import { authOptions } from "./api/auth/[...nextauth]"
|
|
||||||
import { faEye, faLeftLong } from "@fortawesome/pro-regular-svg-icons"
|
import { faEye, faLeftLong } from "@fortawesome/pro-regular-svg-icons"
|
||||||
import { faPlus, faUserPlus } from "@fortawesome/pro-solid-svg-icons"
|
import { faPlus, faUserPlus } from "@fortawesome/pro-solid-svg-icons"
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
||||||
import useGameState from "@lib/hooks/useGameState"
|
import useGameState from "@lib/hooks/useGameState"
|
||||||
import { GamePropsSchema } from "@lib/zodSchemas"
|
import { GamePropsSchema } from "@lib/zodSchemas"
|
||||||
import status from "http-status"
|
import status from "http-status"
|
||||||
import { GetServerSideProps } from "next"
|
|
||||||
import { Session, getServerSession } from "next-auth"
|
|
||||||
import { useRouter } from "next/router"
|
import { useRouter } from "next/router"
|
||||||
import { useCallback, useEffect, useMemo, useState } from "react"
|
import { useCallback, useEffect, useMemo, useState } from "react"
|
||||||
import OtpInput from "react-otp-input"
|
import OtpInput from "react-otp-input"
|
||||||
import { toast } from "react-toastify"
|
import { toast } from "react-toastify"
|
||||||
|
|
||||||
interface Props {
|
|
||||||
q: string | string[] | undefined
|
|
||||||
session: Session | null
|
|
||||||
}
|
|
||||||
|
|
||||||
function isInputOnlyNumbers(input: string) {
|
function isInputOnlyNumbers(input: string) {
|
||||||
return /^\d+$/.test(input)
|
return /^\d+$/.test(input)
|
||||||
}
|
}
|
||||||
|
@ -51,16 +43,21 @@ const handleConfirmation = () => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Start({ q, session: initSession }: Props) {
|
export default function Start() {
|
||||||
const [otp, setOtp] = useState("")
|
const [otp, setOtp] = useState("")
|
||||||
const { gameProps, setGameProps } = useGameState()
|
const { session, setGameProps } = useGameState()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const { session: sessionUsed } = useGameState()
|
|
||||||
|
|
||||||
const session = useMemo(
|
const query = useMemo((): { join?: boolean; watch?: boolean } => {
|
||||||
() => (sessionUsed ? sessionUsed : initSession),
|
switch (router.query.q) {
|
||||||
[sessionUsed, initSession]
|
case "join":
|
||||||
)
|
return { join: true }
|
||||||
|
case "watch":
|
||||||
|
return { watch: true }
|
||||||
|
default:
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
}, [router])
|
||||||
|
|
||||||
const gameFetch = useCallback(
|
const gameFetch = useCallback(
|
||||||
async (pin?: string) => {
|
async (pin?: string) => {
|
||||||
|
@ -71,25 +68,29 @@ export default function Start({ q, session: initSession }: Props) {
|
||||||
.then(isAuthenticated)
|
.then(isAuthenticated)
|
||||||
.then((game) => GamePropsSchema.parse(game))
|
.then((game) => GamePropsSchema.parse(game))
|
||||||
|
|
||||||
|
const toastId = !pin ? "erstellt" : "angefragt"
|
||||||
const res = await toast.promise(gamePromise, {
|
const res = await toast.promise(gamePromise, {
|
||||||
pending: {
|
pending: {
|
||||||
render: "Raum wird " + (!pin ? "erstellt" : "angefragt"),
|
render: "Raum wird " + toastId,
|
||||||
|
toastId,
|
||||||
},
|
},
|
||||||
success: {
|
success: {
|
||||||
render: "Raum " + (!pin ? "erstellt" : "angefragt") + " 👌",
|
render: "Raum " + (!pin ? "erstellt" : "angefragt") + " 👌",
|
||||||
type: "info",
|
type: "info",
|
||||||
theme: "colored",
|
theme: "colored",
|
||||||
|
toastId,
|
||||||
},
|
},
|
||||||
error: {
|
error: {
|
||||||
render: "Es ist ein Fehler aufgetreten 🤯",
|
render: "Es ist ein Fehler aufgetreten 🤯",
|
||||||
type: "error",
|
type: "error",
|
||||||
theme: "colored",
|
theme: "colored",
|
||||||
|
toastId,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
setGameProps(res)
|
setGameProps(res)
|
||||||
|
|
||||||
await toast.promise(router.push("/lobby/" + res.payload.game?.id), {
|
await toast.promise(router.push("/lobby"), {
|
||||||
pending: {
|
pending: {
|
||||||
render: "Raum wird beigetreten",
|
render: "Raum wird beigetreten",
|
||||||
},
|
},
|
||||||
|
@ -150,7 +151,7 @@ export default function Start({ q, session: initSession }: Props) {
|
||||||
icon={faUserPlus}
|
icon={faUserPlus}
|
||||||
disabled={!session}
|
disabled={!session}
|
||||||
>
|
>
|
||||||
{q === "join" && session?.user ? (
|
{query.join && session?.user ? (
|
||||||
<OtpInput
|
<OtpInput
|
||||||
shouldAutoFocus
|
shouldAutoFocus
|
||||||
containerStyle={{ color: "initial" }}
|
containerStyle={{ color: "initial" }}
|
||||||
|
@ -166,7 +167,7 @@ export default function Start({ q, session: initSession }: Props) {
|
||||||
)}
|
)}
|
||||||
</OptionButton>
|
</OptionButton>
|
||||||
<OptionButton icon={faEye}>
|
<OptionButton icon={faEye}>
|
||||||
{q === "watch" && session?.user ? (
|
{query.watch && session?.user ? (
|
||||||
<OtpInput
|
<OtpInput
|
||||||
shouldAutoFocus
|
shouldAutoFocus
|
||||||
containerStyle={{ color: "initial" }}
|
containerStyle={{ color: "initial" }}
|
||||||
|
@ -187,12 +188,3 @@ export default function Start({ q, session: initSession }: Props) {
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getServerSideProps: GetServerSideProps<Props> = async (
|
|
||||||
context
|
|
||||||
) => {
|
|
||||||
const session = await getServerSession(context.req, context.res, authOptions)
|
|
||||||
const { q } = context.query
|
|
||||||
|
|
||||||
return { props: { q, session } }
|
|
||||||
}
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue