diff --git a/web/src/components/Playing.tsx b/web/src/components/Playing.tsx index 1d956596..df541c37 100644 --- a/web/src/components/Playing.tsx +++ b/web/src/components/Playing.tsx @@ -22,6 +22,7 @@ import { getMulticallResults } from "../utils/multicall"; import { AbiItem } from "web3-utils"; import FullcountABIImported from "../web3/abi/FullcountABI.json"; import { useSound } from "../hooks/useSound"; +import { useRouter } from "next/router"; const FullcountABI = FullcountABIImported as unknown as AbiItem[]; const Playing = () => { @@ -38,6 +39,28 @@ const Playing = () => { } = useGameContext(); const { user } = useUser(); const playSound = useSound(); + const [inviteFrom, setInviteFrom] = useState(""); + const [inviteSession, setInviteSession] = useState(""); + const [inviteCode, setInviteCode] = useState(""); + const router = useRouter(); + + useEffect(() => { + if (router.query.invite_from && typeof router.query.invite_from === "string") { + setInviteFrom(router.query.invite_from); + } else { + setInviteFrom(""); + } + if (router.query.id && typeof router.query.id === "string") { + setInviteSession(router.query.id); + } else { + setInviteSession(""); + } + if (router.query.invite_code && typeof router.query.invite_code === "string") { + setInviteCode(router.query.invite_code); + } else { + setInviteCode(""); + } + }, [router.query.invite_from, router.query.id, router.query.invite_code]); const ownedTokens = useQuery( ["owned_tokens", user], @@ -47,6 +70,15 @@ const Playing = () => { if (ownedTokens.length > 0 && !selectedToken && ownedTokens[selectedTokenIdx]) { updateContext({ selectedToken: { ...ownedTokens[selectedTokenIdx] } }); } + //first response from the FCPLayer API after token creation has empty name and p0 image + if ( + selectedToken && + !selectedToken.name && + ownedTokens[selectedTokenIdx] && + selectedToken.id === ownedTokens[selectedTokenIdx].id + ) { + updateContext({ selectedToken: { ...ownedTokens[selectedTokenIdx] } }); + } return ownedTokens; }, { @@ -192,26 +224,26 @@ const Playing = () => { ownedTokens.data && ownedTokens.data.length >= 1 && !invitedTo && + !inviteFrom && !isCreateCharacter && ( )} - - {invitedTo && ownedTokens.data && !isCreateCharacter && ( + {inviteFrom && inviteSession && ownedTokens.data && ownedTokens.data.length > 0 && ( { - updateContext({ selectedToken: token, invitedTo: undefined }); + tokens={ownedTokens.data.filter((t) => !t.isStaked)} + sessionID={Number(inviteSession)} + inviteCode={inviteCode} + inviteFrom={inviteFrom} + onClose={() => { + router.push("/"); + setInviteCode(""); + setInviteFrom(""); + setInviteSession(""); }} - onClose={() => updateContext({ invitedTo: undefined })} /> )} - - {selectedSession && watchingToken && } - {selectedSession && !watchingToken && selectedToken && ( - - )} ); }; diff --git a/web/src/components/TitleScreen.tsx b/web/src/components/TitleScreen.tsx index dade513f..b34db863 100644 --- a/web/src/components/TitleScreen.tsx +++ b/web/src/components/TitleScreen.tsx @@ -7,19 +7,34 @@ import Playing from "./Playing"; import SignUpForm from "./account/SignUpForm"; import LoginForm from "./account/LoginForm"; -import { FULLCOUNT_ASSETS, FULLCOUNT_ASSETS_PATH } from "../constants"; +import { FULLCOUNT_ASSETS } from "../constants"; import LoadingView from "./HomePage/LoadingView"; import LaunchForm from "./LaunchForm"; import MoonstreamLogo2 from "./icons/MoonstreamLogo2"; import { useGameContext } from "../contexts/GameContext"; +import { useRouter } from "next/router"; const TitleScreen = () => { const { user, isLoading } = useUser(); + const router = useRouter(); const [isLogging, setIsLogging] = useState(false); // login or signUp const [isSuccess, setIsSuccess] = useState(false); const [isFirstSeconds, setIsFirstSeconds] = useState(true); const { isLaunching, updateContext } = useGameContext(); + const [inviteFrom, setInviteFrom] = useState(""); + + useEffect(() => { + if ( + router.isReady && + router.query.invite_from && + typeof router.query.invite_from === "string" + ) { + setInviteFrom(router.query.invite_from); + setIsLogging(true); + } + }, [router.isReady, router.query]); + useEffect(() => { setTimeout(() => setIsFirstSeconds(false), 2000); }, []); @@ -40,14 +55,20 @@ const TitleScreen = () => { src={`${FULLCOUNT_ASSETS}/banners/Bl-banner-updated-logo.jpeg`} alt={""} /> - {isLaunching ? ( + {isLaunching && !inviteFrom ? ( updateContext({ isLaunching: false })} /> ) : ( <> {!isLogging ? ( - setIsSuccess(value)} /> + setIsSuccess(value)} + /> ) : ( - setIsSuccess(value)} /> + setIsSuccess(value)} + /> )} {!isSuccess && (
diff --git a/web/src/components/account/Account.module.css b/web/src/components/account/Account.module.css index a775d05b..e8d0601b 100644 --- a/web/src/components/account/Account.module.css +++ b/web/src/components/account/Account.module.css @@ -58,3 +58,14 @@ opacity: 0; transition: opacity 1s ease-out; } + +.invitePrompt { + color: #262019; + text-align: center; + font-family: Pangolin, cursive; + font-size: 14px; + font-style: normal; + font-weight: 700; + line-height: normal; + margin-bottom: 20px; +} diff --git a/web/src/components/account/LoginForm.tsx b/web/src/components/account/LoginForm.tsx index f27f4dcc..f957ce0f 100644 --- a/web/src/components/account/LoginForm.tsx +++ b/web/src/components/account/LoginForm.tsx @@ -5,7 +5,13 @@ import { Spinner } from "@chakra-ui/react"; import styles from "./Account.module.css"; import useLogin from "../../hooks/useLogin"; -const LoginForm = ({ setIsSuccess }: { setIsSuccess: (isSuccess: boolean) => void }) => { +const LoginForm = ({ + setIsSuccess, + inviteFrom, +}: { + setIsSuccess: (isSuccess: boolean) => void; + inviteFrom?: string; +}) => { const [username, setUsername] = useState(""); const [password, setPassword] = useState(""); const { login, isLoading, isSuccess } = useLogin(); @@ -30,7 +36,13 @@ const LoginForm = ({ setIsSuccess }: { setIsSuccess: (isSuccess: boolean) => voi return (
{/*
*/} -
Welcome back!
+ {inviteFrom ? ( +
+ {`${inviteFrom} is inviting you to play Fullcount.xyz.`} +
+ ) : ( +
Welcome back!
+ )} void }) => { +const SignUpForm = ({ + setIsSuccess, + inviteFrom, +}: { + setIsSuccess: (isSuccess: boolean) => void; + inviteFrom?: string; +}) => { const [username, setUsername] = useState(""); const [password, setPassword] = useState(""); const [email, setEmail] = useState(""); @@ -32,7 +38,13 @@ const SignUpForm = ({ setIsSuccess }: { setIsSuccess: (isSuccess: boolean) => vo return ( {/*
*/} -
Welcome!
+ {inviteFrom ? ( +
+ {`${inviteFrom} is inviting you to play Fullcount.xyz.`} +
+ ) : ( +
Welcome!
+ )} {
)} - {atBatState.data && !isBigView && ( + {atBatState.data && !isBigView && atBatState.data.atBat.pitches[0].progress !== 2 && ( { {atBatState.data && isBigView && atBatState.data?.atBat.outcome === 0 && - !showPitchOutcome && ( + !showPitchOutcome && + atBatState.data.atBat.pitches[0].progress !== 2 && ( { : "you lose!"}
)} + {atBatState.data && atBatState.data.atBat.pitches[0].progress === 2 && ( + <> +
+ Waiting for Opponent. +
+ Invite Friend? +
+ + + )} {atBatState.data?.atBat.outcome === 0 && !showPitchOutcome && atBatState.data.atBat.pitches[atBatState.data.atBat.numberOfSessions - 1].progress !== 2 && @@ -338,9 +350,12 @@ const AtBatView: React.FC = () => { )} )} - {atBatState.data && !showPitchOutcome && !isBigView && ( - - )} + {atBatState.data && + !showPitchOutcome && + !isBigView && + atBatState.data.atBat.pitches[0].progress !== 2 && ( + + )}
); }; diff --git a/web/src/components/atbat/InviteLinkView.module.css b/web/src/components/atbat/InviteLinkView.module.css new file mode 100644 index 00000000..b4146fe2 --- /dev/null +++ b/web/src/components/atbat/InviteLinkView.module.css @@ -0,0 +1,111 @@ +.container { + display: flex; + flex-direction: column; + align-items: center; + gap: 15px; + height: 100%; + width: 100vw; + justify-content: center; +} +.tokens { + display: flex; + width: 100%; + padding: 10px; + justify-content: center; + align-items: center; + gap: 15px; + + border-top: 1px solid #262019; + border-bottom: 1px solid #262019; + background: #FCECD9; +} + +.player, .opponent { + width: 110px; + height: 110px; + position: relative; +} + +.player { + border: 4px solid #328449; + position: relative; + +} + +.opponent { + display: flex; + border: 1px solid #262019; + background: linear-gradient(0deg, #EBE4DC 0%, #EBE4DC 100%), #F9F0E3; + align-items: center; + justify-content: center; +} + +.vs { + color: #262019; + text-align: center; + font-family: Bangers, cursive; + font-size: 24px; + font-style: normal; + font-weight: 400; + line-height: 120%; /* 28.8px */ +} + +.linkContainer { + display: flex; + max-width: 270px; + align-items: center; + gap: -1px; +} + +.link { + display: flex; + padding: 10px; + align-items: center; + gap: 10px; + flex: 1 0 0; + background: #262019; + white-space: nowrap; + overflow: clip; + color: #FFF; + font-family: Pangolin, cursive; + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: 100%; /* 14px */ + letter-spacing: 0.7px; +} + +.copyButton, .copyButtonSuccess { + display: flex; + padding: 9px; + align-items: center; + gap: 10px; + border: 1px solid #262019; + background: #328449; + color: #FFF; + font-family: Pangolin, cursive; + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: 100%; /* 14px */ + letter-spacing: 0.7px; +} + +.copyButtonSuccess { + background: #01641d; + +} + +.ball { + position: absolute; + left: 0; + top: 50%; + transform: translateY(-50%) translateX(-50%); +} + +.bat { + position: absolute; + right: 0; + top: 50%; + transform: translateY(-50%) translateX(50%); +} \ No newline at end of file diff --git a/web/src/components/atbat/InviteLinkView.tsx b/web/src/components/atbat/InviteLinkView.tsx new file mode 100644 index 00000000..0c4fd0bc --- /dev/null +++ b/web/src/components/atbat/InviteLinkView.tsx @@ -0,0 +1,61 @@ +import styles from "./InviteLinkView.module.css"; +import { AtBatStatus } from "../../types"; +import { Image, useClipboard } from "@chakra-ui/react"; +import QuestionMarkIcon from "../icons/QuestionMarkIcon"; +import BallIconWhite from "../icons/BallIconWhite"; +import BatIconWhite from "../icons/BatIconWhite"; +import LinkIcon from "../icons/LinkIcon"; + +const InviteLinkView = ({ atBat }: { atBat: AtBatStatus }) => { + const link = `${window.location.protocol}//${ + window.location.host + }/?invite_from=${encodeURIComponent( + atBat.pitcher ? atBat.pitcher.name : atBat.batter ? atBat.batter.name : "", + )}&id=${atBat.pitches[0].sessionID}`; + const { onCopy, hasCopied } = useClipboard(link); + + return ( +
+
+ {atBat.pitcher ? ( +
+ {atBat.pitcher.name} + +
+ ) : ( +
+ + +
+ )} +
VS
+ {atBat.batter ? ( +
+ {atBat.batter.name} + +
+ ) : ( +
+ + +
+ )} +
+
+
+ {link} +
+ +
+
+ ); +}; + +export default InviteLinkView; diff --git a/web/src/components/icons/BallIconWhite.tsx b/web/src/components/icons/BallIconWhite.tsx new file mode 100644 index 00000000..138faadc --- /dev/null +++ b/web/src/components/icons/BallIconWhite.tsx @@ -0,0 +1,42 @@ +import React from "react"; + +const BallIconWhite: React.FC> = (props) => ( + + + + + + + + +); + +export default BallIconWhite; diff --git a/web/src/components/icons/BatIconWhite.tsx b/web/src/components/icons/BatIconWhite.tsx new file mode 100644 index 00000000..dae213b1 --- /dev/null +++ b/web/src/components/icons/BatIconWhite.tsx @@ -0,0 +1,42 @@ +import React from "react"; + +const BatIconWhite: React.FC> = (props) => ( + + + + + + + + +); + +export default BatIconWhite; diff --git a/web/src/components/icons/LinkIcon.tsx b/web/src/components/icons/LinkIcon.tsx new file mode 100644 index 00000000..38b18cee --- /dev/null +++ b/web/src/components/icons/LinkIcon.tsx @@ -0,0 +1,36 @@ +import React from "react"; + +const LinkIcon: React.FC> = (props) => ( + + + + + + + + + + + +); + +export default LinkIcon; diff --git a/web/src/components/icons/PvPIcon.tsx b/web/src/components/icons/PvPIcon.tsx index c0e237ce..0ebba71e 100644 --- a/web/src/components/icons/PvPIcon.tsx +++ b/web/src/components/icons/PvPIcon.tsx @@ -6,19 +6,19 @@ const PvPIcon: React.FC> = (props) => ( width="50" height="51" viewBox="0 0 50 51" - fill="none" {...props} + fill="none" //fill here should be none > ); diff --git a/web/src/components/icons/QuestionMarkIcon.tsx b/web/src/components/icons/QuestionMarkIcon.tsx new file mode 100644 index 00000000..db955472 --- /dev/null +++ b/web/src/components/icons/QuestionMarkIcon.tsx @@ -0,0 +1,29 @@ +import React from "react"; + +const QuestionMarkIcon: React.FC> = (props) => ( + + + + +); + +export default QuestionMarkIcon; diff --git a/web/src/components/tokens/ChooseToken.module.css b/web/src/components/tokens/ChooseToken.module.css index 464ae622..3aaf01dd 100644 --- a/web/src/components/tokens/ChooseToken.module.css +++ b/web/src/components/tokens/ChooseToken.module.css @@ -1,24 +1,71 @@ +.background { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + min-height: 100vh; + width: 100%; + background-size: cover; + background-position: center; +} + + + .container { + position: absolute; + top: 50vh; + left: 50%; + transform: translateX(-50%) translateY(-50%); flex-direction: column; display: flex; - height: 100vh; - width: 100vw; + height: 603px; + min-width: 322px; padding: 20px; justify-content: center; align-items: center; gap: 20px; background: #FCECD9; + z-index: 3; +} + + + +.headerContainer { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 10px; + align-self: stretch; } .header { - color: #262019; + color: #328449; text-align: center; font-family: Bangers, cursive; font-size: 30px; font-style: normal; font-weight: 400; - line-height: 100%; /* 30px */ - letter-spacing: 1.5px; + line-height: normal; +} + +.prompt { + color: #262019; + text-align: center; + font-family: Pangolin, cursive; + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: normal; +} + +.error { + color: #CD7676; + text-align: center; + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: normal; } .content { @@ -27,7 +74,7 @@ align-items: center; gap: 15px; flex: 1 0 0; - width: 286px; + max-height: 310px; } .title { @@ -39,23 +86,21 @@ line-height: normal; } -.prompt { - color: #262019; - text-align: center; - font-family: Pangolin, cursive; - font-size: 14px; - font-style: normal; - font-weight: 400; - line-height: normal; -} - - .cards { - width: 279px; display: flex; - justify-content: flex-start; + justify-content: center; gap: 15px; flex-wrap: wrap; overflow-y: auto; - max-height: calc(100vh - 221px); /*console.log(20 + 30 + 20 + 25.5 + 15 + 17.5 + 15 + 20 + 37.5 + 20);*/ + max-height: calc(100vh - 221px); + padding-bottom: 15px; +} + +@media (min-width: 362px) and (min-height: 643px) { + .background { + background-image: url('https://static.fullcount.xyz/web/landing/Bl-banner-background-tinted.jpeg'); + } + .container { + border: 1px solid black; + } } \ No newline at end of file diff --git a/web/src/components/tokens/ChooseToken.tsx b/web/src/components/tokens/ChooseToken.tsx index 1d5c8a3f..2d49ab05 100644 --- a/web/src/components/tokens/ChooseToken.tsx +++ b/web/src/components/tokens/ChooseToken.tsx @@ -1,23 +1,54 @@ import styles from "./ChooseToken.module.css"; import parentStyles from "./CreateNewCharacter.module.css"; -import { OwnedToken } from "../../types"; +import { AtBat, OwnedToken, Token } from "../../types"; import TokenCard from "./TokenCard"; -import { useGameContext } from "../../contexts/GameContext"; -import { useEffect, useRef, useState } from "react"; +import React, { useEffect, useRef, useState } from "react"; import NewCharacterButton from "./NewCharacterButton"; +import { useMutation, useQuery, useQueryClient } from "react-query"; +import { joinSessionFullcountPlayer } from "../../tokenInterfaces/FullcountPlayerAPI"; +import { useRouter } from "next/router"; +import { sendReport } from "../../utils/humbug"; +import useMoonToast from "../../hooks/useMoonToast"; +import useUser from "../../contexts/UserContext"; +import { useSound } from "../../hooks/useSound"; +import { Spinner } from "@chakra-ui/react"; +import PvPIcon from "../icons/PvPIcon"; +import { useGameContext } from "../../contexts/GameContext"; +import { getContracts } from "../../utils/getWeb3Contracts"; + +const getErrorMessage = (sessionProgress: number) => { + switch (sessionProgress) { + case 0: + return "At-bat not found"; + case 2: + return undefined; + default: + return "Invitation is no longer valid"; + } +}; const ChooseToken = ({ tokens, - onChoose, onClose, + sessionID, + inviteCode, + inviteFrom, }: { tokens: OwnedToken[]; - onChoose: (token: OwnedToken) => void; onClose: () => void; + sessionID: number; + inviteCode: string; + inviteFrom: string; }) => { - const [selectedTokenIdx, setSelectedTokenIdx] = useState(0); + const { updateContext, selectedTokenIdx } = useGameContext(); + const elementRef = useRef(null); const [drawBottomLine, setDrawBottomLine] = useState(false); + const toast = useMoonToast(); + const { user } = useUser(); + const playSound = useSound(); + const { isCreateCharacter } = useGameContext(); + const router = useRouter(); useEffect(() => { const element = elementRef.current; @@ -26,36 +57,158 @@ const ChooseToken = ({ } }, [tokens]); + const handleClick = () => { + playSound("batButton"); + joinSession.mutate({ sessionID, token: tokens[selectedTokenIdx], inviteCode }); + }; + + const handleExitClick = () => { + router.push("/"); + sendReport("Invite is invalid", { sessionID }, ["type:click", "click:close_invite"]); + }; + + const sessionProgress = useQuery(["session_status", sessionID], () => { + const { gameContract } = getContracts(); + return gameContract.methods.sessionProgress(sessionID).call(); + }); + + const queryClient = useQueryClient(); + const joinSession = useMutation( + async ({ + sessionID, + token, + inviteCode, + }: { + sessionID: number; + token: OwnedToken; + inviteCode: string; + }): Promise => { + return joinSessionFullcountPlayer({ token, sessionID, inviteCode }); + }, + { + onSuccess: async (data, variables) => { + let atBatId: number | undefined = undefined; + queryClient.setQueryData( + ["atBats"], + (oldData: { atBats: AtBat[]; tokens: Token[] } | undefined) => { + if (!oldData) { + return { atBats: [], tokens: [] }; + } + const newAtBats = oldData.atBats.map((atBat) => { + if (atBat.lastSessionId !== variables.sessionID) { + return atBat; + } + atBatId = atBat.id; + if (!atBat.pitcher) { + return { ...atBat, progress: 3, pitcher: { ...variables.token } }; + } + if (!atBat.batter) { + return { ...atBat, progress: 3, batter: { ...variables.token } }; + } + return atBat; + }); + + return { atBats: newAtBats, tokens: oldData.tokens }; + }, + ); + queryClient.setQueryData(["owned_tokens", user], (oldData: OwnedToken[] | undefined) => { + if (!oldData) { + return []; + } + return oldData.map((t) => { + if (t.address === variables.token.address && t.id === variables.token.id) { + return { + ...t, + isStaked: true, + stakedSessionID: variables.sessionID, + tokenProgress: 3, + }; + } + return t; + }); + }); + queryClient.invalidateQueries("owned_tokens"); + if (atBatId) { + router.push(`atbats/?id=${atBatId}`); + } + }, + retryDelay: (attemptIndex) => (attemptIndex < 1 ? 5000 : 10000), + retry: (failureCount, error) => { + console.log(error); + if (failureCount < 3) { + console.log("Will retry in 5, maybe 10 seconds"); + } + return failureCount < 3; + }, + onError: (e: Error) => { + toast("Join failed" + e?.message, "error"); + sendReport("Error toast", { error: e }, ["type:error_toast"]); + }, + }, + ); + return ( -
-
Choose character
-
-
Play
-
Choose a character to play with.
-
- {tokens.map((t, idx) => ( - setSelectedTokenIdx(idx)} - /> - ))} - -
-
-
-
- Cancel -
-
onChoose(tokens[selectedTokenIdx])}> - Play + <> + {!isCreateCharacter && ( +
+
+
+ +
BATTER UP
+
+ {sessionProgress.data && getErrorMessage(Number(sessionProgress.data)) ? ( + <> +
+ {`${inviteFrom} is inviting you to play Fullcount.xyz.`}
+
+
{getErrorMessage(Number(sessionProgress.data))}
+
+ +
+ + ) : ( + <> +
+ {`${inviteFrom} is inviting you to play Fullcount.xyz.`}
+ {`Choose a character to play with.`} +
+
+
+ {tokens.map((t, idx) => ( + + updateContext({ + selectedToken: { ...tokens[idx] }, + selectedTokenIdx: idx, + }) + } + /> + ))} + +
+
+
+ + +
+ + )} +
-
-
+ )} + ); }; diff --git a/web/src/components/tokens/CreateCharacterForm.tsx b/web/src/components/tokens/CreateCharacterForm.tsx index 3eb6aaa2..d7789f62 100644 --- a/web/src/components/tokens/CreateCharacterForm.tsx +++ b/web/src/components/tokens/CreateCharacterForm.tsx @@ -1,15 +1,16 @@ -import { Flex, Spinner } from "@chakra-ui/react"; +import { Spinner } from "@chakra-ui/react"; import Image from "next/image"; import styles from "./CreateNewCharacter.module.css"; import React, { useEffect, useState } from "react"; -import { TokenSource } from "../../types"; +import { OwnedToken, TokenSource } from "../../types"; import { useMutation, useQueryClient } from "react-query"; import { mintFullcountPlayerToken } from "../../tokenInterfaces/FullcountPlayerAPI"; import useMoonToast from "../../hooks/useMoonToast"; import { blbImage, NUMBER_OF_BLB_IMAGES } from "../../constants"; import { sendReport } from "../../utils/humbug"; import { useSound } from "../../hooks/useSound"; +import useUser from "../../contexts/UserContext"; const images: number[] = []; for (let i = 0; i < NUMBER_OF_BLB_IMAGES; i += 1) { @@ -21,6 +22,7 @@ const CreateCharacterForm = ({ onClose }: { onClose?: () => void }) => { const [imageIndex, setImageIndex] = useState(0); const source: TokenSource = "FullcountPlayerAPI"; const queryClient = useQueryClient(); + const { user } = useUser(); const toast = useMoonToast(); const playSound = useSound(); @@ -34,11 +36,26 @@ const CreateCharacterForm = ({ onClose }: { onClose?: () => void }) => { } }, { - onSuccess: () => { + onSuccess: (data, variables) => { if (onClose) { onClose(); } - queryClient.invalidateQueries("owned_tokens"); //TODO data update + queryClient.setQueryData(["owned_tokens", user], (oldData: OwnedToken[] | undefined) => { + if (!oldData) { + return []; + } + const newToken: OwnedToken = { + address: data.erc721_address, + id: data.token_id, + image: blbImage(variables.imageIndex), + isStaked: false, + name: variables.name, + source: "FullcountPlayerAPI", + stakedSessionID: 0, + tokenProgress: 0, + }; + return [...oldData, newToken]; + }); }, onError: (e: Error) => { console.log(e); diff --git a/web/src/components/tokens/NewCharacterButton.tsx b/web/src/components/tokens/NewCharacterButton.tsx index 31a13766..cf571ba4 100644 --- a/web/src/components/tokens/NewCharacterButton.tsx +++ b/web/src/components/tokens/NewCharacterButton.tsx @@ -15,7 +15,7 @@ const NewCharacterButton = ({ small }: { small: boolean }) => { updateContext({ isCreateCharacter: true }); }} > - {small ? : "+ Mint new Beer League Baller"} + {small ? : "+ Create new Beer League Baller"}
); }; diff --git a/web/src/components/tokens/TokenCard.module.css b/web/src/components/tokens/TokenCard.module.css index 0812ae7f..94cba682 100644 --- a/web/src/components/tokens/TokenCard.module.css +++ b/web/src/components/tokens/TokenCard.module.css @@ -5,6 +5,7 @@ align-items: center; border: 1px solid #7E8E7F; background: #262019; + cursor: pointer; }