diff --git a/components/shared/Cover/index.tsx b/components/shared/Cover/index.tsx deleted file mode 100644 index f53f5b1a..00000000 --- a/components/shared/Cover/index.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { ReactEventHandler } from "react"; -import Image, { ImageProps } from "next/image"; -import gameDefaultCoverImg from "@/public/images/game-default-cover.png"; - -function Cover({ alt, onError, ...restProps }: ImageProps) { - const handleError: ReactEventHandler = (e) => { - if (e.target instanceof HTMLImageElement) { - e.target.src = gameDefaultCoverImg.src; - } - onError?.(e); - }; - return {alt}; -} - -export default Cover; diff --git a/components/shared/Header.tsx b/components/shared/Header.tsx index 401ec33b..c0dee8f0 100644 --- a/components/shared/Header.tsx +++ b/components/shared/Header.tsx @@ -5,7 +5,7 @@ import { cn } from "@/lib/utils"; import { UserInfoForm } from "@/features/user"; import useAuth from "@/hooks/context/useAuth"; import Modal from "./Modal"; -import Cover from "./Cover"; +import Image from "./Image"; enum HeaderActions { CHAT = "CHAT", @@ -65,7 +65,7 @@ export default function Header({ )} >
- + logo

遊戲微服務大平台

diff --git a/components/shared/Cover/Cover.stories.tsx b/components/shared/Image/Image.stories.tsx similarity index 59% rename from components/shared/Cover/Cover.stories.tsx rename to components/shared/Image/Image.stories.tsx index 29a889e9..0ffc9d8f 100644 --- a/components/shared/Cover/Cover.stories.tsx +++ b/components/shared/Image/Image.stories.tsx @@ -1,13 +1,13 @@ import type { Meta, StoryObj } from "@storybook/react"; -import Cover from "./index"; +import Image from "."; -const meta: Meta = { - title: "Data Display/ Cover", - component: Cover, +const meta: Meta = { + title: "Data Display/ Image", + component: Image, tags: ["autodocs"], args: { src: "https://images.unsplash.com/photo-1684006231760-3f0290bf42a6?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1550&q=80", - alt: "Cover", + alt: "image", width: 100, height: 130, }, @@ -21,17 +21,17 @@ const meta: Meta = { }, }; -type Story = StoryObj; +type Story = StoryObj; export const Playground: Story = { - render: (args) => , + render: (args) => {args.alt}, }; -export const DefaultErrorCover: Story = { - render: (args) => , +export const DefaultErrorImage: Story = { + render: (args) => {args.alt}, }; -DefaultErrorCover.args = { +DefaultErrorImage.args = { src: "error src", }; diff --git a/components/shared/Image/Image.tsx b/components/shared/Image/Image.tsx new file mode 100644 index 00000000..df75c3ea --- /dev/null +++ b/components/shared/Image/Image.tsx @@ -0,0 +1,41 @@ +import { ReactEventHandler } from "react"; +import gameDefaultCoverImg from "@/public/images/game-default-cover.png"; +import { cn } from "@/lib/utils"; + +interface ImageProps extends React.ImgHTMLAttributes { + priority?: boolean; + fill?: boolean; +} + +function Image({ + alt, + onError, + priority, + fill, + className, + ...restProps +}: ImageProps) { + const handleError: ReactEventHandler = (e) => { + if (e.target instanceof HTMLImageElement) { + e.target.src = gameDefaultCoverImg.src; + } + onError?.(e); + }; + return ( + + {alt} + + ); +} + +export default Image; diff --git a/components/shared/Cover/cover.test.tsx b/components/shared/Image/image.test.tsx similarity index 55% rename from components/shared/Cover/cover.test.tsx rename to components/shared/Image/image.test.tsx index 9e93da95..25db1832 100644 --- a/components/shared/Cover/cover.test.tsx +++ b/components/shared/Image/image.test.tsx @@ -1,19 +1,19 @@ import React from "react"; import { render, screen } from "@testing-library/react"; -import Cover from "."; +import Image from "."; -describe("Cover", () => { - test("should render Cover component", () => { +describe("Image", () => { + test("should render Image component", () => { render( - ); - const cover = screen.getByRole("img"); - expect(cover).toBeInTheDocument(); - expect(cover).toHaveAccessibleName("Cover"); + const image = screen.getByRole("img"); + expect(image).toBeInTheDocument(); + expect(image).toHaveAccessibleName("Image"); }); }); diff --git a/components/shared/Image/index.tsx b/components/shared/Image/index.tsx new file mode 100644 index 00000000..c6cd0de8 --- /dev/null +++ b/components/shared/Image/index.tsx @@ -0,0 +1 @@ +export { default } from "./Image"; diff --git a/components/shared/SelectBoxGroup/SelectBoxGroup.tsx b/components/shared/SelectBoxGroup/SelectBoxGroup.tsx index 18e59517..0d303f74 100644 --- a/components/shared/SelectBoxGroup/SelectBoxGroup.tsx +++ b/components/shared/SelectBoxGroup/SelectBoxGroup.tsx @@ -61,28 +61,33 @@ function SelectBoxGroup({ )}
    - {items.map((item) => ( -
  • - - onChange?.(item.value)} - /> -
  • - ))} + {items.map((item) => { + const checkboxId = `${selectBoxId}_${item.key}`; + const isChecked = value === item.value; + + return ( +
  • + + onChange?.(item.value)} + /> +
  • + ); + })}
); diff --git a/containers/layout/AppLayout.tsx b/containers/layout/AppLayout.tsx index 5119ced4..0e3de97d 100644 --- a/containers/layout/AppLayout.tsx +++ b/containers/layout/AppLayout.tsx @@ -1,4 +1,4 @@ -import { PropsWithChildren, useEffect } from "react"; +import { useEffect } from "react"; import { useRouter } from "next/router"; import Header from "@/components/shared/Header"; import Sidebar from "@/components/shared/Sidebar"; @@ -9,7 +9,7 @@ import SearchBar from "@/components/shared/SearchBar"; import { useToast } from "@/components/shared/Toast"; import { GameListProvider } from "@/features/game"; -export default function AppLayout({ children }: PropsWithChildren) { +function AppLayout({ children }: React.PropsWithChildren) { const toast = useToast(); const router = useRouter(); const { @@ -85,3 +85,7 @@ export default function AppLayout({ children }: PropsWithChildren) { ); } + +export default function getAppLayout(page: React.ReactElement) { + return {page}; +} diff --git a/features/game/components/GameCardDetailed.tsx b/features/game/components/GameCardDetailed.tsx index 027a47c2..df90f5b5 100644 --- a/features/game/components/GameCardDetailed.tsx +++ b/features/game/components/GameCardDetailed.tsx @@ -3,7 +3,7 @@ import { PropsWithChildren } from "react"; import gameDefaultCoverImg from "@/public/images/game-default-cover.png"; import { GameType } from "@/requests/games"; import Icon from "@/components/shared/Icon"; -import Cover from "@/components/shared/Cover"; +import Image from "@/components/shared/Image"; function GameCardDetailed({ children, @@ -16,13 +16,11 @@ function GameCardDetailed({ return (
- {children}
@@ -48,14 +46,7 @@ function GameCardDetailed({ diff --git a/features/game/components/GameCardSimple.tsx b/features/game/components/GameCardSimple.tsx index 3e99502b..a961b4a3 100644 --- a/features/game/components/GameCardSimple.tsx +++ b/features/game/components/GameCardSimple.tsx @@ -2,20 +2,18 @@ import { PropsWithChildren } from "react"; import gameDefaultCoverImg from "@/public/images/game-default-cover.png"; import { GameType } from "@/requests/games"; -import Cover from "@/components/shared/Cover"; +import Image from "@/components/shared/Image"; function GameCardSimple({ children, img, name }: PropsWithChildren) { return (
-
diff --git a/features/room/components/RoomCard.tsx b/features/room/components/RoomCard.tsx index 0557e59d..43f2c5b5 100644 --- a/features/room/components/RoomCard.tsx +++ b/features/room/components/RoomCard.tsx @@ -1,6 +1,6 @@ import type { Room } from "@/requests/rooms"; -import Cover from "@/components/shared/Cover"; +import Image from "@/components/shared/Image"; import Button, { ButtonSize } from "@/components/shared/Button/v2"; import { useJoinRoom } from "../hooks"; @@ -22,7 +22,7 @@ function RoomCard({ room, onClick }: Readonly) { return (
- = NextPage & { - getLayout?: FC; + getLayout?: (page: React.ReactElement) => React.ReactElement; Anonymous?: boolean; }; @@ -34,9 +34,7 @@ function App({ Component, pageProps }: AppWithProps) { Component.Anonymous || !!process.env.NEXT_PUBLIC_CI_MODE || false; const isProduction = env !== Env.PROD ? false : true; - const Layout = - Component.getLayout ?? - (({ children }) => {children}); + const getLayout = Component.getLayout ?? getAppLayout; const getHistory = (children: ReactElement) => { return isProduction ? ( @@ -58,9 +56,7 @@ function App({ Component, pageProps }: AppWithProps) { - - - + {getLayout()} {!isProduction && } diff --git a/pages/auth/login.tsx b/pages/auth/login.tsx index de6d18a9..f2cb67d5 100644 --- a/pages/auth/login.tsx +++ b/pages/auth/login.tsx @@ -25,7 +25,7 @@ const Login: NextPageWithProps = () => { return <>; }; -Login.getLayout = ({ children }) => children; +Login.getLayout = (page) => page; Login.Anonymous = true; export default Login; diff --git a/pages/auth/token/[token].tsx b/pages/auth/token/[token].tsx index dd0f99b1..e56c0129 100644 --- a/pages/auth/token/[token].tsx +++ b/pages/auth/token/[token].tsx @@ -21,7 +21,7 @@ const Token: NextPageWithProps = () => { return <>; }; -Token.getLayout = ({ children }) => children; +Token.getLayout = (page) => page; Token.Anonymous = true; export default Token; diff --git a/pages/login.tsx b/pages/login.tsx index 04e0c1f4..a7ac5604 100644 --- a/pages/login.tsx +++ b/pages/login.tsx @@ -5,7 +5,7 @@ import { serverSideTranslations } from "next-i18next/serverSideTranslations"; import Link from "next/link"; import ButtonV2, { ButtonVariant } from "@/components/shared/Button/v2"; -import Cover from "@/components/shared/Cover"; +import Image from "@/components/shared/Image"; import Icon, { IconName } from "@/components/shared/Icon"; import useAuth from "@/hooks/context/useAuth"; @@ -53,7 +53,7 @@ const Login: NextPageWithProps = () => {

- + logo 遊戲微服務大平台

@@ -86,9 +86,9 @@ const Login: NextPageWithProps = () => { Login.Anonymous = true; -Login.getLayout = ({ children }) => ( +Login.getLayout = (page) => (

- ( />
- {children} + {page}
diff --git a/pages/rooms/[roomId]/index.tsx b/pages/rooms/[roomId]/index.tsx index 27488086..db6b0b5f 100644 --- a/pages/rooms/[roomId]/index.tsx +++ b/pages/rooms/[roomId]/index.tsx @@ -3,7 +3,7 @@ import { GetStaticProps, GetStaticPaths } from "next"; import { useRouter } from "next/router"; import { serverSideTranslations } from "next-i18next/serverSideTranslations"; -import Cover from "@/components/shared/Cover"; +import Image from "@/components/shared/Image"; import RoomUserCardList from "@/components/rooms/RoomUserCardList"; import RoomButtonGroup from "@/components/rooms/RoomButtonGroup"; import GameWindow from "@/components/rooms/GameWindow"; @@ -137,6 +137,7 @@ export default function Room() { currentUser?.id, roomId, updateRoomId, + updateGameUrl, addPlayer, removePlayer, updateUserReadyStatus, @@ -238,10 +239,9 @@ export default function Room() { <>
{roomInfo.currentPlayers && ( - >) { {room && (
- { ); }; -WithoutLayout.getLayout = ({ children }) => children; +WithoutLayout.getLayout = (page) => page; WithoutLayout.Anonymous = true; export default WithoutLayout;