Skip to content

Commit

Permalink
Syndote modals updates
Browse files Browse the repository at this point in the history
  • Loading branch information
Yauheni committed Mar 21, 2024
1 parent 49eeaea commit 739b217
Show file tree
Hide file tree
Showing 8 changed files with 207 additions and 30 deletions.
7 changes: 3 additions & 4 deletions frontend/apps/syndote/src/components/layout/header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@ function Header() {
const { state, isStateRead } = useReadGameSessionState();
const { isMeta, sendMessage } = useSyndoteMessage();
const { account } = useAccount();
const { adminId, gameStatus, winner, players } = state || {};
const { adminId, gameStatus } = state || {};
const isAdmin = account?.decodedAddress === adminId;
const playerStrategyId = players?.find((player) => player[1].ownerId === account?.decodedAddress)?.[0];

const handleCancelGame = () => {
if (!isMeta || !account?.decodedAddress || !isStateRead) {
Expand Down Expand Up @@ -65,7 +64,7 @@ function Header() {
}
menu={
<div className={styles.headerContent}>
{adminId === account?.decodedAddress && gameStatus !== 'Finished' && (
{account?.decodedAddress && adminId === account?.decodedAddress && gameStatus !== 'Finished' && (
<Button
color="light"
text="Cancel game"
Expand All @@ -74,7 +73,7 @@ function Header() {
onClick={handleCancelGame}
/>
)}
{gameStatus === 'Finished' && (
{account?.decodedAddress && gameStatus === 'Finished' && (
<>
{isAdmin ? (
<Button text="Remove game" onClick={deleteGame} />
Expand Down
138 changes: 115 additions & 23 deletions frontend/apps/syndote/src/pages/home/Home.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
import { useEffect, useState } from 'react';
import { useEffect, useRef, useState } from 'react';
import { useAtomValue, useSetAtom, useAtom } from 'jotai';
import {
useAccount,
useApi,
useBalanceFormat,
useReadFullState,
useSendMessageHandler,
withoutCommas,
} from '@gear-js/react-hooks';
import { useAccount, useApi, withoutCommas } from '@gear-js/react-hooks';
import { useCheckBalance } from '@dapps-frontend/hooks';
import { HexString } from '@polkadot/util/types';
import { ADDRESS, fields, INIT_PLAYERS, LocalStorage } from 'consts';
import { MessageDetails, MessageHandlePayload, MessagePayload, State, Step } from 'types';
import { ADDRESS, fields, INIT_PLAYERS } from 'consts';
import { MessageHandlePayload, MessagePayload, PlayersByStrategyAddress, Step } from 'types';
import meta from 'assets/meta/syndote_meta.txt';
import { UnsubscribePromise } from '@polkadot/api/types';
import { Loader } from 'components';
Expand All @@ -21,22 +14,28 @@ import { Roll } from './roll';
import styles from './Home.module.scss';
import { Players } from './players/Players';
import { Button } from '@gear-js/vara-ui';
import { Buttons } from './buttons';
import { Cell } from './cell';
import { RequestGame } from 'pages/welcome/components/request-game';
import { CURRENT_GAME_ADMIN_ATOM, CURRENT_STRATEGY_ID_ATOM, IS_LOADING } from 'atoms';
import { SessionInfo } from './session-info';
import clsx from 'clsx';
import { TextModal } from './game-not-found-modal';
import { ContinueGameModal } from './continue-game-modal';
import { ReserveModal } from './reserve-modal';

function Home() {
const { account } = useAccount();
const { api } = useApi();
const metadata = useProgramMetadata(meta);
const [isLoading, setIsLoading] = useAtom(IS_LOADING);
const [isContinueGameModalOpen, setIsContinueGameModalOpen] = useState(false);
const [isPlayerRemovedModalOpen, setIsPlayerRemovedModalOpen] = useState(false);
const [isGameCancelledModalOpen, setIsGameCancelledModalOpen] = useState(false);
const [currentGame, setCurrentGame] = useAtom(CURRENT_GAME_ADMIN_ATOM);
const [isReserveModalOpen, setIsReserveModalOpen] = useState(false);
const [isReserveInfoModalOpen, setIsReserveInfoModalOpen] = useState(false);
const [isContinueGameInfoModalOpen, setIsContinueGameInfoModalOpen] = useState(false);
const admin = useRef<null | HexString>(null);
const setCurrentGame = useSetAtom(CURRENT_GAME_ADMIN_ATOM);
const { state, isStateRead } = useReadGameSessionState();
const { isMeta, sendMessage, sendPlayMessage } = useSyndoteMessage();
const { checkBalance } = useCheckBalance();
Expand All @@ -53,15 +52,22 @@ function Home() {
const playersArray = state?.players || [];

const getPlayers = () => (isGameStarted ? roll.players : state!.players!);

console.log('==STATE==');
console.log(state);
const players = playersArray.map(([address], index) => ({
...INIT_PLAYERS[index],
address,
...getPlayers().find(([newAddress]) => newAddress === address)![1],
}));
const playersByStrategyAddress = players.reduce((acc, item) => {
return {
...acc,
[item.address]: item,
};
}, {}) as PlayersByStrategyAddress;
const isAnyPlayer = players.length > 0;
const playerStrategyId = players.find((player) => player.ownerId === account?.decodedAddress)?.address;

console.log(players);
const register = () => {
const payload = { Register: { adminId, strategyId } };

Expand All @@ -73,7 +79,8 @@ function Home() {
},
});
};

console.log('isRes');
console.log(isReserveModalOpen);
const startGame = () => {
const payload = {
Play: {
Expand Down Expand Up @@ -112,6 +119,64 @@ function Home() {
});
};

const addGasToPlayerStrategy = () => {
const payload = {
AddGasToPlayerStrategy: {
adminId,
},
};

sendMessage({
payload,
onInBlock: () => {
setIsReserveModalOpen(false);
},
});
};

const continueGame = () => {
setIsContinueGameModalOpen(false);
startGame();
};

useEffect(() => {
console.log('SET ADMIN');
console.log(adminId);
if (adminId) {
admin.current = adminId;
}
}, [adminId]);

useEffect(() => {
if (gameStatus !== 'WaitingForGasForGameContract') {
setIsContinueGameInfoModalOpen(false);
setIsContinueGameModalOpen(false);
return;
}

if (isAdmin) {
setIsContinueGameModalOpen(true);
} else {
setIsContinueGameInfoModalOpen(false);
}
}, [gameStatus, isAdmin]);

useEffect(() => {
if (!gameStatus?.WaitingForGasForStrategy) {
setIsReserveModalOpen(false);
setIsReserveInfoModalOpen(false);
return;
}

if (gameStatus.WaitingForGasForStrategy === playerStrategyId) {
setIsReserveModalOpen(true);
} else {
setIsReserveInfoModalOpen(true);
}
}, [gameStatus, playerStrategyId]);
console.log(api?.blockGasLimit.toNumber());
console.log('ADMIN');
console.log(admin);
const getDecodedPayload = (payload: Bytes) => {
if (!metadata) return;

Expand Down Expand Up @@ -160,10 +225,9 @@ function Home() {
console.log(source.toHex());
console.log(ADDRESS.CONTRACT);
console.log(destination.toHex());
console.log(adminId);
console.log(currentGame);
console.log(admin);

if (source.toHex() === ADDRESS.CONTRACT) {
if (source.toHex() === ADDRESS.CONTRACT && destination.toHex() === admin.current) {
console.log('----------MESSAGE RECEIVED-----------');
const decodedPayload = getDecodedPayload(payload) as MessagePayload;

Expand All @@ -181,8 +245,19 @@ function Home() {
console.log('============ DECODED HANDLE PAYLOAD ==============');
console.log(decodedPayloadHandle);

if (['GameDeleted', 'GameWasCancelled'].includes(decodedPayloadHandle.Ok)) {
setIsGameCancelledModalOpen(true);
if (decodedPayloadHandle?.Ok && ['GameDeleted', 'GameWasCancelled'].includes(decodedPayloadHandle.Ok)) {
console.log('-----------');
console.log(admin.current);
console.log(account?.decodedAddress);
console.log(admin.current !== account?.decodedAddress);
console.log('-----------');
if (admin.current !== account?.decodedAddress) {
console.log('lalalalalala');
setIsGameCancelledModalOpen(true);
}

admin.current = null;
setSteps([]);
}
}
});
Expand Down Expand Up @@ -221,6 +296,8 @@ function Home() {
const handleCloseModal = () => {
setIsPlayerRemovedModalOpen(false);
setIsGameCancelledModalOpen(false);
setIsContinueGameModalOpen(false);
setIsReserveModalOpen(false);
};

return isStateRead ? (
Expand Down Expand Up @@ -274,7 +351,6 @@ function Home() {
)}
{gameStatus === 'Play' && (
<>
{/* <Buttons onMainClick={isAdmin ? startGame : undefined} /> */}
<div className={clsx(styles.headingWrapper, styles.headingWrapperAdmin)}>
<h1 className={styles.heading}>Registration...</h1>
</div>
Expand Down Expand Up @@ -324,7 +400,23 @@ function Home() {
{isGameCancelledModalOpen && (
<TextModal
heading="The game has been canceled by the administrator"
text="Game administrator Samovit has ended the game. All spent VARA tokens for the entry fee will be refunded."
text="Game administrator has ended the game. All spent VARA tokens for the entry fee will be refunded."
onClose={handleCloseModal}
/>
)}
{isContinueGameModalOpen && <ContinueGameModal onReserve={continueGame} onClose={handleCloseModal} />}
{isContinueGameInfoModalOpen && (
<TextModal
heading={`Game administrator reserves extra gas to continue the game`}
text="Once he reserves the required amount, the game will continue."
onClose={handleCloseModal}
/>
)}
{isReserveModalOpen && <ReserveModal onReserve={addGasToPlayerStrategy} onClose={handleCloseModal} />}
{isReserveInfoModalOpen && gameStatus?.WaitingForGasForStrategy && (
<TextModal
heading={`Player ${playersByStrategyAddress[gameStatus.WaitingForGasForStrategy].name} pays extra gas`}
text="Once he reserves the required amount, the game will continue. If he fails to do so before the timer expires, he will lose and can only observe the game"
onClose={handleCloseModal}
/>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,7 @@
.modalHeader {
margin-bottom: 10px;
}

.gameDetailsItem {
grid-template-columns: auto 200px;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Modal } from 'components/layout/modal';
import { Button } from '@gear-js/vara-ui';
import styles from './GameCancelledModal.module.scss';
import styles from './ContinueGameModal.module.scss';
import { GameDetails } from 'components/layout/game-details';
import { ReactComponent as VaraSVG } from 'assets/images/icons/vara-coin.svg';
import { ReactComponent as TVaraSVG } from 'assets/images/icons/tvara-coin.svg';
Expand Down Expand Up @@ -36,7 +36,7 @@ function ContinueGameModal({ onReserve, onClose }: Props) {
Please reserve a new gas amount to continue the game. Any unused gas will be refunded upon completion of the
game. If you don't reserve the required amount of gas, you won't be able to continue the game.
</p>
<GameDetails items={items} />
<GameDetails items={items} className={{ item: styles.gameDetailsItem }} />
<Button text="Reserve gas" className={styles.button} onClick={onReserve} />
</div>
</Modal>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
.modal {
min-width: 670px;
}

.container {
display: flex;
flex-direction: column;
gap: 28px;
}

.text {
font-size: 14px;
}

.button {
width: 45%;
}

.modalHeader {
margin-bottom: 10px;
}

.gameDetailsItem {
grid-template-columns: auto 200px;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { Modal } from 'components/layout/modal';
import { Button } from '@gear-js/vara-ui';
import styles from './ReserveModal.module.scss';
import { GameDetails } from 'components/layout/game-details';
import { ReactComponent as VaraSVG } from 'assets/images/icons/vara-coin.svg';
import { ReactComponent as TVaraSVG } from 'assets/images/icons/tvara-coin.svg';
import { useAccountDeriveBalancesAll, useApi, useBalanceFormat } from '@gear-js/react-hooks';

type Props = {
onReserve: () => void;
onClose: () => void;
};

function ReserveModal({ onReserve, onClose }: Props) {
const { isApiReady, api } = useApi();
const { getFormattedBalance, getFormattedGasValue } = useBalanceFormat();
const balances = useAccountDeriveBalancesAll();
const balance =
isApiReady && balances?.freeBalance ? getFormattedBalance(balances.freeBalance.toString()) : undefined;

const VaraSvg = balance?.unit?.toLowerCase() === 'vara' ? <VaraSVG /> : <TVaraSVG />;
const items = [
{
name: 'Required amount of gas required for the game',
value: (
<>
{VaraSvg} {getFormattedGasValue(api?.blockGasLimit.toNumber() || 0).toFixed()} VARA
</>
),
},
];

return (
<Modal heading="The reserved gas is exhausted" className={{ header: styles.modalHeader }} onClose={onClose}>
<div className={styles.container}>
<p className={styles.text}>
Please reserve a new gas amount to continue the game. Any unused gas will be refunded upon completion of the
game. If you don't reserve the required amount of gas before the timer expires, you won't be able to continue
playing and can only observe the game in progress.
</p>
<GameDetails items={items} className={{ item: styles.gameDetailsItem }} />
<Button text="Reserve gas" className={styles.button} onClick={onReserve} />
</div>
</Modal>
);
}

export { ReserveModal };
3 changes: 3 additions & 0 deletions frontend/apps/syndote/src/pages/home/reserve-modal/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { ReserveModal } from './ReserveModal';

export { ReserveModal };
8 changes: 7 additions & 1 deletion frontend/apps/syndote/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,15 @@ type PlayerState = {
penalty: string;
lost: boolean;
ownerId: HexString;
name: string;
};

type Players = [HexString, PlayerState][];

type PlayersByStrategyAddress = {
[key: HexString]: PlayerState;
};

type GameSessionState = {
GameSession: {
gameSession: State;
Expand All @@ -24,7 +29,7 @@ type State = {
adminId: HexString;
currentTurn: string;
currentStep: string;
gameStatus: string;
gameStatus: string & { WaitingForGasForStrategy: HexString };
numberOfPlayers: string;
ownership: {};
players: Players;
Expand Down Expand Up @@ -80,4 +85,5 @@ export type {
Properties,
CellValues,
GameSessionState,
PlayersByStrategyAddress,
};

0 comments on commit 739b217

Please sign in to comment.