From 8cd60e33e7eb0004abffd99a877f072508a59cbd Mon Sep 17 00:00:00 2001 From: okhai <57156589+okhaimie-dev@users.noreply.github.com> Date: Thu, 19 Sep 2024 09:25:01 -0400 Subject: [PATCH] controller naming (#171) --- client/src/components/header.tsx | 27 +- client/src/components/message-area.tsx | 121 +++++---- .../src/components/profile/user-section.tsx | 253 +++++++++++------- client/src/hooks/useControllerUsername.ts | 28 ++ client/src/pages/Profile.tsx | 191 +++++++------ 5 files changed, 362 insertions(+), 258 deletions(-) create mode 100644 client/src/hooks/useControllerUsername.ts diff --git a/client/src/components/header.tsx b/client/src/components/header.tsx index 4c375b5a..c7a4b87f 100644 --- a/client/src/components/header.tsx +++ b/client/src/components/header.tsx @@ -30,6 +30,7 @@ import { MancalaGameEdge, useFetchModelsForHeaderQuery, } from "@/generated/graphql.tsx"; +import useControllerUsername from "@/hooks/useControllerUsername"; export default function Header() { const { provider } = useProvider(); @@ -79,9 +80,10 @@ export default function Header() { const account = { account: { - address: "0x05e01dB693CBF7461a016343042786DaC5A6000104813cF134a1E8B1D0a6810b" - } - } + address: + "0x05e01dB693CBF7461a016343042786DaC5A6000104813cF134a1E8B1D0a6810b", + }, + }; const { data, startPolling } = useFetchModelsForHeaderQuery(); startPolling(1000); @@ -110,6 +112,7 @@ export default function Header() { setIsDropdownClose(!isDropdownClose); disconnectWallet(); }; + const username = useControllerUsername(); return (
@@ -185,7 +188,7 @@ export default function Header() { onClick={handleDropdownToggleClose} >
-

{truncateString(address)}

+

{username || truncateString(address)}

@@ -194,25 +197,19 @@ export default function Header() { diff --git a/client/src/components/message-area.tsx b/client/src/components/message-area.tsx index f7445c3d..fdd0f513 100644 --- a/client/src/components/message-area.tsx +++ b/client/src/components/message-area.tsx @@ -3,70 +3,77 @@ import { useToast } from "./ui/use-toast.ts"; import { useEffect } from "react"; interface IMessageAreaProps { - game_metadata_error: any, - game_players_error: any, - game_metadata: any, - address: string | undefined, - game_metadata_loading: any, - game_players_loading: any, - game_players: any, - moveMessage: any + game_metadata_error: any; + game_players_error: any; + game_metadata: any; + address: string | undefined; + game_metadata_loading: any; + game_players_loading: any; + game_players: any; + moveMessage: any; } -export default function MessageArea( - { game_metadata_error, game_players_error, game_metadata, address, - game_metadata_loading, game_players_loading, game_players, moveMessage }: IMessageAreaProps -) { +export default function MessageArea({ + game_metadata_error, + game_players_error, + game_metadata, + address, + game_metadata_loading, + game_players_loading, + game_players, + moveMessage, +}: IMessageAreaProps) { + const game_has_error = game_metadata_error || game_players_error; + const game_is_loading = game_metadata_loading || game_players_loading; + const { player_one, player_two, current_player, status, winner } = + game_metadata?.game_data?.edges?.[0]?.node ?? {}; - const game_has_error = game_metadata_error || game_players_error; - const game_is_loading = game_metadata_loading || game_players_loading; - const { - player_one, player_two, current_player, status, winner - } = game_metadata?.game_data?.edges?.[0]?.node ?? {} + const active_players_addrs = [player_one, player_two]; + const player_includes_myself = active_players_addrs.includes(address); + const is_any_player_empty = active_players_addrs.some( + (individualAddr) => + isEmptyString(individualAddr) || individualAddr === "0x0", + ); - const active_players_addrs = [player_one, player_two] - const player_includes_myself = active_players_addrs.includes(address); - const is_any_player_empty = active_players_addrs.some(individualAddr => isEmptyString(individualAddr) || individualAddr === "0x0"); + const { toast } = useToast(); - const { toast } = useToast(); - - const generate_error_message = (): string => { - if (game_is_loading) return "Loading game data..."; // loading case - if (status === "Finished") { - if (winner === address) { - return "Congratulations! You won the game" - } - else { - return "You lost the game" - } - } - else { - if ( // guard clause for both players are present - game_metadata && game_players && player_includes_myself) { - if (current_player === address) { // I'm the one to play - if (is_any_player_empty) return "Waiting for another player to join"; // case opponent isn't in - if (moveMessage === undefined) { - return ""; - } - return "Not your pit" - } - return ""; - } - else { - return "Player has not joined game or try connecting your wallet again in the lobby"; - } + const generate_error_message = (): string => { + if (game_is_loading) return "Loading game data..."; // loading case + if (status === "Finished") { + if (winner === address) { + return "Congratulations! You won the game"; + } else { + return "You lost the game"; + } + } else { + if ( + // guard clause for both players are present + game_metadata && + game_players && + player_includes_myself + ) { + if (current_player === address) { + // I'm the one to play + if (is_any_player_empty) return "Waiting for another player to join"; // case opponent isn't in + if (moveMessage === undefined) { + return ""; + } + return "Not your pit"; } + return ""; + } else { + return "Player has not joined game or try connecting your wallet again in the lobby"; + } } + }; - useEffect(() => { - if (generate_error_message()) { - toast({ - title: generate_error_message(), - }) - } - }, [generate_error_message()]) + useEffect(() => { + if (generate_error_message()) { + toast({ + title: generate_error_message(), + }); + } + }, [generate_error_message(), toast]); - return ( - <> - ) + return <>; } diff --git a/client/src/components/profile/user-section.tsx b/client/src/components/profile/user-section.tsx index f702a102..15ee810d 100644 --- a/client/src/components/profile/user-section.tsx +++ b/client/src/components/profile/user-section.tsx @@ -7,111 +7,158 @@ import { FormEventHandler, useRef, useState } from "react"; import { Dialog } from "@material-tailwind/react"; import { truncateString } from "@/lib/utils"; import { useAccount } from "@starknet-react/core"; +import useControllerUsername from "@/hooks/useControllerUsername"; -export default function UserSection({ level, wins, losses, total }: { level: number, wins: number, losses: number, total: number }) { - const [open, setOpen] = useState(false); - const [selectedImage, setSelectedImage] = useState(null); - const ref: any = useRef(); - const handleOpen = () => setOpen(!open); - const handleImageChange = (event: React.ChangeEvent) => { - if (event.target.files && event.target.files[0]) { - setSelectedImage(URL.createObjectURL(event.target.files[0])); - } - }; - const account = useAccount(); - return ( -
-
-
- -
-

{truncateString(account?.address) || "Guest user"}

- -
-
-
-
-
-
-
-
-
-
-
-

Level {level}

-

{level}/100

-
-
-
-
-
-

Total Played

-

{total}

-
-
-

Total Won

-

{wins}

-
-
-

Total Lost

-

{losses}

-
+export default function UserSection({ + level, + wins, + losses, + total, +}: { + level: number; + wins: number; + losses: number; + total: number; +}) { + const [open, setOpen] = useState(false); + const [selectedImage, setSelectedImage] = useState(null); + const ref: any = useRef(); + const username = useControllerUsername(); + const handleOpen = () => setOpen(!open); + const handleImageChange = (event: React.ChangeEvent) => { + if (event.target.files && event.target.files[0]) { + setSelectedImage(URL.createObjectURL(event.target.files[0])); + } + }; + const account = useAccount(); + return ( +
+
+
+ +
+

+ {username || truncateString(account?.address) || "Guest user"} +

+ +
+
+
+
+
+
+
+
+
+
+
+

Level {level}

+

{level}/100

+
+
+
+
+
+

Total Played

+

{total}

+
+
+

Total Won

+

{wins}

+
+
+

Total Lost

+

{losses}

+
+
+
+

Share

+
+ + + + + + +
+
+
+ +
+
+
+
+
+
+ Profile Photo +
+

+ This image will be displayed on your profile +

+
-
-

Share

-
- - - - - - -
+ +
+
+
+
+ Display Name +
+

+ This name will be displayed on your profile +

+ +
+
+ +
- -
-
-
-
-
-
Profile Photo
-

This image will be displayed on your profile

- -
- -
-
-
-
Display Name
-

This name will be displayed on your profile

-
- -
-
- -
-
-
-
-
+
- ) -} \ No newline at end of file +
+
+ ); +} diff --git a/client/src/hooks/useControllerUsername.ts b/client/src/hooks/useControllerUsername.ts new file mode 100644 index 00000000..5241c50a --- /dev/null +++ b/client/src/hooks/useControllerUsername.ts @@ -0,0 +1,28 @@ +import ControllerConnector from "@cartridge/connector"; +import { useAccount, useConnect } from "@starknet-react/core"; +import { useEffect, useState } from "react"; + +export default function useControllerUsername() { + const { connector } = useConnect(); + const { account } = useAccount(); + const [username, setUsername] = useState(); + + useEffect(() => { + if (account && connector?.id === "controller") { + const contollerConnector = connector as unknown as ControllerConnector; + contollerConnector.username()?.then(setUsername); + } else { + setUsername(undefined); + } + }, [account, connector]); + + if (username !== undefined) { + return username; + } else if (account) { + return formatAddress(account.address); + } +} + +function formatAddress(address: string) { + return `${address.slice(0, 6)}...${address.slice(-4)}`; +} diff --git a/client/src/pages/Profile.tsx b/client/src/pages/Profile.tsx index b66d3f79..c6f13829 100644 --- a/client/src/pages/Profile.tsx +++ b/client/src/pages/Profile.tsx @@ -2,102 +2,129 @@ import Header from "@/components/header"; import GameHistory from "@/components/profile/game-history"; import UserSection from "@/components/profile/user-section"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; -import { MancalaGameEdge, useFetchModelsForHeaderQuery, useMancalaModelsFetchQuery } from "@/generated/graphql"; +import { + MancalaGameEdge, + useFetchModelsForHeaderQuery, + useMancalaModelsFetchQuery, +} from "@/generated/graphql"; import { getPlayer } from "@/lib/utils"; import { useAccount } from "@starknet-react/core"; export default function Profile() { - const { data, startPolling, loading } = useMancalaModelsFetchQuery(); - startPolling(1000); - const account = useAccount(); - const filteredGames = data?.mancalaAlphaMancalaGameModels?.edges?.filter( - (game) => - game?.node?.player_one === account.address || - game?.node?.player_two === account.address - ); + const { data, startPolling, loading } = useMancalaModelsFetchQuery(); + startPolling(1000); + const account = useAccount(); + const filteredGames = data?.mancalaAlphaMancalaGameModels?.edges?.filter( + (game) => + game?.node?.player_one === account.address || + game?.node?.player_two === account.address, + ); - // const filteredTransactions = data?.mancalaAlphaMancalaGameModels?.edges?.reduce( - // (acc: any[], game: any) => { - // if ( - // (game?.node?.player_one === account.address || - // game?.node?.player_two === account.address) && - // game?.node?.entity?.executedAt - // ) { - // acc.push({ - // ...game.node, - // executedAt: game?.node?.entity?.executedAt, - // }); - // } - // return acc; - // }, - // [] - // ) || []; + // const filteredTransactions = data?.mancalaAlphaMancalaGameModels?.edges?.reduce( + // (acc: any[], game: any) => { + // if ( + // (game?.node?.player_one === account.address || + // game?.node?.player_two === account.address) && + // game?.node?.entity?.executedAt + // ) { + // acc.push({ + // ...game.node, + // executedAt: game?.node?.entity?.executedAt, + // }); + // } + // return acc; + // }, + // [] + // ) || []; - const filteredWonGames = filteredGames?.filter(game => game?.node?.winner === account.address) || []; - const filteredLostGames = filteredGames?.filter(game => game?.node?.winner !== "0x0" && game?.node?.winner !== account.address) || []; + const filteredWonGames = + filteredGames?.filter((game) => game?.node?.winner === account.address) || + []; + const filteredLostGames = + filteredGames?.filter( + (game) => + game?.node?.winner !== "0x0" && game?.node?.winner !== account.address, + ) || []; - const { data: playerData, startPolling: startPollingPlayer } = useFetchModelsForHeaderQuery(); - startPollingPlayer(1000); + const { data: playerData, startPolling: startPollingPlayer } = + useFetchModelsForHeaderQuery(); + startPollingPlayer(1000); - const player = getPlayer( - playerData?.mancalaAlphaMancalaGameModels?.edges as MancalaGameEdge[], - account.account?.address || "", - ); + const player = getPlayer( + playerData?.mancalaAlphaMancalaGameModels?.edges as MancalaGameEdge[], + account.account?.address || "", + ); - - return ( -
-
-
-
- - -
- - +
+
+
+ + +
+ + - All games - - - Won - - - Lost - - -
-
- - - - - - - - - -
-
-
+ > + Lost + + +
+
+ + + + + + + + +
+
- ) -} \ No newline at end of file +
+
+ ); +}