diff --git a/components/Connect/index.tsx b/components/Connect/index.tsx index 3a63f37..25e7224 100644 --- a/components/Connect/index.tsx +++ b/components/Connect/index.tsx @@ -27,6 +27,7 @@ import styled from "@emotion/styled"; import { PlusSquareIcon } from "@chakra-ui/icons"; import { useCopyToClipboard } from "@/lib/hooks/useCopyToClipboard"; import { toast } from "react-hot-toast"; +import Link from "next/link"; export const ConnectPage = () => { const router = useRouter(); @@ -111,6 +112,9 @@ export const ConnectPage = () => { {loading && } Connect to Game + {sharedDeckId === undefined && ( (props: { pool: PoolType }) => void; +}; export const HandContainer = ({ setModal, + gameState, + setPlayerState, }: { setModal: (type: ModalType) => void; + gameState: GameData["gameState"]; + setPlayerState: GameData["setPlayerState"]; }) => { const localName = useRouter().query?.name; const player = Array.isArray(localName) ? localName[0] : localName; const { starredDeck } = useLocalDeckStorage(); - const { gameState, setPlayerState } = useWebGame(); const players = gameState?.content?.players as Record< string, { pool?: PoolType } diff --git a/components/Game/game.modal-template.tsx b/components/Game/game.modal-template.tsx index 6426846..9761816 100644 --- a/components/Game/game.modal-template.tsx +++ b/components/Game/game.modal-template.tsx @@ -27,20 +27,24 @@ import { useRouter } from "next/router"; import { DeckImportCardType } from "../DeckPool/deck-import.type"; import { flow } from "lodash"; import { toast } from "react-hot-toast"; +import { WebsocketMessage } from "@/lib/gamesocket/message"; type ModalTemplateType = { isOpen: boolean; modalType: ModalType; setModalType: (type: ModalType) => void; + gameState: WebsocketMessage | undefined; + setPlayerState: () => (props: { pool: PoolType }) => void; }; export const ModalContainer: React.FC = ({ isOpen, modalType, setModalType, + gameState, + setPlayerState, }) => { const isCommit = modalType === "commit"; const player = useRouter().query?.name as string; - const { gameState, setPlayerState } = useWebGame(); const players = gameState?.content?.players as Record< string, { pool?: PoolType } @@ -117,6 +121,7 @@ export const ModalContainer: React.FC = ({ }), ); + console.log({ modalType, isOpen }); return ( <> !isCommit && onClose()}> diff --git a/pages/game.tsx b/pages/game.tsx index 3aa7ef2..9fc9331 100644 --- a/pages/game.tsx +++ b/pages/game.tsx @@ -11,7 +11,13 @@ import { WebGameProvider, useWebGame } from "@/lib/contexts/WebGameProvider"; import useDelayedTrue from "@/lib/hooks/useDelay"; import { Box, useDisclosure } from "@chakra-ui/react"; import { useRouter } from "next/router"; -import { useCallback, useEffect, useState } from "react"; +import { + Dispatch, + SetStateAction, + useCallback, + useEffect, + useState, +} from "react"; export type ModalType = "hand" | "discard" | "deck" | "commit" | false; @@ -48,14 +54,14 @@ const GamePage = () => { - {isReady && } - + @@ -63,6 +69,35 @@ const GamePage = () => { ); }; +/** + * Quick hack to reuse hand-container for offline + * */ +const HandWrapper = ({ + setModalType, +}: { + setModalType: Dispatch>; +}) => { + const { gameState, setPlayerState } = useWebGame(); + return ( + + ); +}; + +const ModalWrapper = (props: { + isOpen: boolean; + modalType: ModalType; + setModalType: (type: ModalType) => void; +}) => { + const { gameState, setPlayerState } = useWebGame(); + return ( + + ); +}; + export default GamePage; const BoardContainer = ({ self }: { self: string }) => { diff --git a/pages/offline.tsx b/pages/offline.tsx new file mode 100644 index 0000000..1025de7 --- /dev/null +++ b/pages/offline.tsx @@ -0,0 +1,133 @@ +import { HandContainer, ModalContainer } from "@/components/Game"; +import { useLocalDeckStorage } from "@/lib/hooks"; +import { + Box, + Button, + Divider, + HStack, + Input, + Text, + VStack, + useDisclosure, +} from "@chakra-ui/react"; +import { useEffect, useMemo, useState } from "react"; +import { ModalType } from "./game"; +import { PoolType, newPool } from "@/components/DeckPool/PoolFns"; +import { GameState, WebsocketMessage } from "@/lib/gamesocket/message"; +import { useRouter } from "next/router"; + +const initGamestate: GameState = { + last_updated: "foobar", + gid: "offline", + players: { + offline: { pool: undefined }, + }, +}; +const init: WebsocketMessage = { + error: "", + msgtype: "offline", + content: initGamestate, +}; + +const Offline = () => { + const { push, query } = useRouter(); + const { star, decks } = useLocalDeckStorage(); + const deck = decks?.find((deck) => deck.id === star); + const newDeck = useMemo(() => (deck ? newPool(deck) : undefined), [deck]); + + const [gameState, setGameState] = useState(init); + const players = gameState?.content?.players as Record< + string, + { pool?: PoolType } + >; + const playerState = players?.["offline"]?.pool; + + const [modalType, setModalType] = useState(false); + const disclosure = useDisclosure(); + + function setPlayerState() { + return (props: { pool: PoolType }) => { + setGameState((prev) => ({ + ...prev, + content: { + ...prev.content, + players: { + offline: { pool: props.pool }, + }, + } as GameState, + })); + }; + } + + useEffect(() => { + if (query.name) return; + push({ query: { name: "offline" } }); + }, []); + + useEffect(() => { + if (!newDeck) return; + setPlayerState()({ pool: newDeck }); + }, [newDeck]); + + useEffect(() => { + if (modalType) { + disclosure.onOpen(); + } else { + disclosure.onClose(); + } + }, [modalType, disclosure]); + + return ( + <> + + + + + + {playerState?.hero?.name} + hp:{playerState?.hero?.hp} + move:{playerState?.hero?.move} + {playerState?.hero?.isRanged ? "Ranged" : "Melee"} + + + {playerState?.sidekick?.name} + hp:{playerState?.sidekick?.hp} + quantity:{playerState?.sidekick?.quantity} + {playerState?.sidekick?.isRanged ? "Ranged" : "Melee"} + + {playerState?.hero?.specialAbility} + {playerState?.sidekick?.quote} + + + + + + + + + + ); +}; + +const HpButton = (props: { state?: number }) => { + const [hp, setHp] = useState(props?.state ?? 0); + return ( + + + + + + ); +}; + +export default Offline;