From acd625b45f19c71b6e359668dac99b3caa2991de Mon Sep 17 00:00:00 2001 From: Johnson Mao Date: Sun, 20 Oct 2024 14:22:20 +0800 Subject: [PATCH] refactor: website style --- components/rooms/GameWindow.tsx | 8 +-- components/shared/Chat/v2/Chat.tsx | 4 +- containers/layout/AppLayout.tsx | 27 ++++++-- hooks/useChat.ts | 7 +- hooks/useUser.ts | 17 +++-- pages/_document.tsx | 2 +- pages/auth/token/[token].tsx | 2 +- pages/index.tsx | 8 +-- pages/rooms/[roomId]/index.tsx | 107 +++++++++++++++++++---------- styles/global.css | 4 ++ 10 files changed, 123 insertions(+), 63 deletions(-) diff --git a/components/rooms/GameWindow.tsx b/components/rooms/GameWindow.tsx index bd666ea9..235ff274 100644 --- a/components/rooms/GameWindow.tsx +++ b/components/rooms/GameWindow.tsx @@ -1,14 +1,12 @@ type GameWindowProps = { + className?: string; gameUrl: string; }; -export default function GameWindow({ gameUrl }: GameWindowProps) { +export default function GameWindow({ className, gameUrl }: GameWindowProps) { return (
-
diff --git a/components/shared/Chat/v2/Chat.tsx b/components/shared/Chat/v2/Chat.tsx index 3e4567ad..ec4faee8 100644 --- a/components/shared/Chat/v2/Chat.tsx +++ b/components/shared/Chat/v2/Chat.tsx @@ -15,6 +15,7 @@ export type ChatProps = { friendList: FriendType[]; roomMessages: MessageType[]; className?: string; + defaultTarget?: ChatTab["id"]; onSubmit: (message: Pick) => void; }; @@ -25,11 +26,12 @@ export default function Chat({ friendList, roomMessages, className, + defaultTarget, onSubmit, }: Readonly) { const [messages, setMessages] = useState(lobbyMessages); const [target, setTarget] = useState<[ChatTab["id"], string | null]>([ - "lobby", + defaultTarget || "lobby", null, ]); const [activeTab, friendRoom] = target; diff --git a/containers/layout/AppLayout.tsx b/containers/layout/AppLayout.tsx index 3a1746d4..2b01e9a5 100644 --- a/containers/layout/AppLayout.tsx +++ b/containers/layout/AppLayout.tsx @@ -1,38 +1,51 @@ -import { PropsWithChildren } from "react"; +import { PropsWithChildren, useEffect } from "react"; +import { useRouter } from "next/router"; import Header from "@/components/shared/Header"; import Sidebar from "@/components/shared/Sidebar"; import Chat from "@/components/shared/Chat/v2/Chat"; import useChat from "@/hooks/useChat"; export default function Layout({ children }: PropsWithChildren) { + const router = useRouter(); const { roomId, messageList, isChatVisible, + openChat, toggleChatVisibility, handleSubmitText, } = useChat(); + const roomPathname = "/rooms/[roomId]"; + + useEffect(() => { + if (router.pathname === roomPathname) { + openChat(); + } + }, [router.pathname, openChat]); return ( <>
-
-
- +
+
+
{children}
{isChatVisible && ( -
+
diff --git a/hooks/useChat.ts b/hooks/useChat.ts index 7770dc1f..1e4614a9 100644 --- a/hooks/useChat.ts +++ b/hooks/useChat.ts @@ -1,4 +1,4 @@ -import { useEffect, useState } from "react"; +import { useCallback, useEffect, useState } from "react"; import type { MessageType } from "@/components/shared/Chat/v2/ChatMessages"; import useChatroom from "./context/useChatroom"; import useSocketCore from "./context/useSocketCore"; @@ -17,6 +17,10 @@ export default function useChat() { setIsChatVisible((prev) => !prev); }; + const openChat = useCallback(() => { + setIsChatVisible(true); + }, []); + // join chatroom by roomId useEffect(() => { if (!roomId) return; @@ -48,6 +52,7 @@ export default function useChat() { roomId, messageList, isChatVisible, + openChat, sendChatMessage, toggleChatVisibility, handleSubmitText, diff --git a/hooks/useUser.ts b/hooks/useUser.ts index 6fca55d4..5c654828 100644 --- a/hooks/useUser.ts +++ b/hooks/useUser.ts @@ -58,13 +58,16 @@ const useUser = () => { return roomIdOperator.get(); }; - const updateRoomId = (roomId?: string) => { - if (roomId) { - roomIdOperator.set(roomId); - } else { - roomIdOperator.remove(); - } - }; + const updateRoomId = useCallback( + (roomId?: string) => { + if (roomId) { + roomIdOperator.set(roomId); + } else { + roomIdOperator.remove(); + } + }, + [roomIdOperator] + ); return { getLoginEndpoint, diff --git a/pages/_document.tsx b/pages/_document.tsx index 22632ceb..ed031e8b 100644 --- a/pages/_document.tsx +++ b/pages/_document.tsx @@ -12,7 +12,7 @@ export default function Document() { - +
diff --git a/pages/auth/token/[token].tsx b/pages/auth/token/[token].tsx index 75531572..837e1b70 100644 --- a/pages/auth/token/[token].tsx +++ b/pages/auth/token/[token].tsx @@ -18,7 +18,7 @@ const Token: NextPageWithProps = () => { } }, [token, login, push]); - return

{token}

; + return <>; }; Token.getLayout = (page: ReactElement) => page; diff --git a/pages/index.tsx b/pages/index.tsx index 5f67e110..91ae05fb 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -71,7 +71,7 @@ function CarouselCard({ draggable={false} priority fill - objectFit="cover" + className="object-cover" onError={onImageError} />
@@ -106,7 +106,7 @@ function CarouselCard({ draggable={false} priority fill - objectFit="cover" + className="object-cover" onError={onImageError} /> )} @@ -181,12 +181,12 @@ const TabPaneContent = ({ > {game.name} diff --git a/pages/rooms/[roomId]/index.tsx b/pages/rooms/[roomId]/index.tsx index b0ae9c3f..f859f768 100644 --- a/pages/rooms/[roomId]/index.tsx +++ b/pages/rooms/[roomId]/index.tsx @@ -1,6 +1,7 @@ -import { useEffect, useState } from "react"; -import { useRouter } from "next/router"; +import { ReactEventHandler, useEffect, useState } from "react"; import { GetStaticProps, GetStaticPaths } from "next"; +import { useRouter } from "next/router"; +import Image from "next/image"; import { serverSideTranslations } from "next-i18next/serverSideTranslations"; import RoomUserCardList from "@/components/rooms/RoomUserCardList"; import RoomButtonGroup from "@/components/rooms/RoomButtonGroup"; @@ -22,10 +23,18 @@ import { playerCancelReady, startGame, } from "@/requests/rooms"; +import { GameType, getAllGamesEndpoint } from "@/requests/games"; import useUser from "@/hooks/useUser"; +import gameDefaultCoverImg from "@/public/images/game-default-cover.png"; type User = Omit; +const onImageError: ReactEventHandler = (e) => { + if (e.target instanceof HTMLImageElement) { + e.target.src = gameDefaultCoverImg.src; + } +}; + export default function Room() { const { roomInfo, @@ -44,16 +53,27 @@ export default function Room() { const { fetch } = useRequest(); const { query, replace } = useRouter(); const [gameUrl, setGameUrl] = useState(""); + const [gameList, setGameList] = useState([]); const roomId = query.roomId as string; const player = roomInfo.players.find( (player) => player.id === currentUser?.id ); const isHost = roomInfo.host.id === currentUser?.id; + const gameInfo = gameList.find((game) => game.id === roomInfo.game.id); + + useEffect(() => { + fetch(getAllGamesEndpoint()).then(setGameList); + }, [fetch]); useEffect(() => { async function getRoomInfo() { - const roomInfo = await fetch(getRoomInfoEndpoint(roomId)); - initializeRoom(roomInfo); + try { + const roomInfo = await fetch(getRoomInfoEndpoint(roomId)); + initializeRoom(roomInfo); + } catch (err) { + updateRoomId(); + replace("/rooms"); + } } getRoomInfo(); @@ -119,6 +139,7 @@ export default function Room() { socket, currentUser?.id, roomId, + updateRoomId, addPlayer, removePlayer, updateUserReadyStatus, @@ -211,40 +232,54 @@ export default function Room() { }; return ( -
-
- cover + {gameUrl ? ( + -
-
- -
-
- {roomInfo.isLocked ? "非公開" : "公開"} -
-
- {roomInfo.currentPlayers} / {roomInfo.maxPlayers} 人 -
-
- +
+ {roomInfo.currentPlayers && ( + {gameInfo?.name + )} +
+
+ +
+
+ {roomInfo.isLocked ? "非公開" : "公開"} +
+
+ {roomInfo.currentPlayers} / {roomInfo.maxPlayers} 人 +
+
+ +
+
+ -
-
- - {gameUrl && } + + )}
); diff --git a/styles/global.css b/styles/global.css index b5c61c95..83cb701b 100644 --- a/styles/global.css +++ b/styles/global.css @@ -1,3 +1,7 @@ @tailwind base; @tailwind components; @tailwind utilities; + +html { + color-scheme: dark; +}