Skip to content

Commit

Permalink
feat(game-lobby): game options confirm step in lobby (#845)
Browse files Browse the repository at this point in the history
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit


- **New Features**
- Introduced a confirmation dialog for game options changes in the game
lobby, enhancing user interaction before starting the game.
- Added functionality to display and manage a list of changed game
options, allowing users to revert to official rules easily.
- Enhanced the game lobby header and footer with new event handling for
game options changes.
- Updated the Elder role's elimination logic to clarify consequences
based on player interactions.

- **Bug Fixes**
- Improved error handling when game options are altered and the
corresponding actions are triggered.

- **Documentation**
- Updated localization files to include new phrases and improved clarity
for game options changes.

- **Tests**
- Expanded test coverage for game options functionality, including
scenarios for confirming changes and handling user interactions
effectively.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • Loading branch information
antoinezanardi committed Sep 10, 2024
1 parent 3a20f01 commit 20cc2ce
Show file tree
Hide file tree
Showing 66 changed files with 118,406 additions and 111,009 deletions.
12 changes: 12 additions & 0 deletions .run/Game Lobby Confirm Dialog.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Game Lobby Confirm Dialog" type="cucumber.js" factoryName="Cucumber.js" folderName="Tags">
<option name="myFilePath" value="$PROJECT_DIR$/tests/acceptance" />
<option name="myNameFilter" value="" />
<option name="cucumberJsArguments" value="--config config/cucumber/cucumber.json --parallel 1 --tags @game-lobby-confirm-dialog" />
<option name="workingDirectory" value="$PROJECT_DIR$" />
<envs>
<env name="NODE_OPTIONS" value="--import tsx/esm" />
</envs>
<method v="2" />
</configuration>
</component>
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<GameLobbyStartGameButton
id="game-lobby-start-game-button"
@reject-actor-additional-cards-placed-step="onRejectActorAdditionalCardsPlacedStep"
@reject-game-options-changed-step="onRejectGameOptionsChangedStep"
@reject-players-position-step="onRejectPlayersPositionStepFromGameLobbyStartGameButton"
@reject-thief-additional-cards-placed-step="onRejectThiefAdditionalCardsPlacedStep"
/>
Expand Down Expand Up @@ -38,4 +39,8 @@ function onRejectThiefAdditionalCardsPlacedStep(): void {
function onRejectActorAdditionalCardsPlacedStep(): void {
emit("rejectActorAdditionalCardsPlacedStep");
}
function onRejectGameOptionsChangedStep(): void {
emit("rejectGameOptionsChangedStep");
}
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
ref="gameLobbyStartGameConfirmDialog"
@confirm-start-game="onConfirmStartGameFromGameLobbyStartGameConfirmDialog"
@reject-actor-additional-cards-placed-step="onRejectActorAdditionalCardsPlacedStepFromGameLobbyStartGameConfirmDialog"
@reject-game-options-changed-step="onRejectGameOptionsChangedStep"
@reject-players-position-step="onRejectPlayersPositionStepFromGameLobbyStartGameConfirmDialog"
@reject-thief-additional-cards-placed-step="onRejectThiefAdditionalCardsPlacedStepFromGameLobbyStartGameConfirmDialog"
/>
Expand Down Expand Up @@ -93,4 +94,8 @@ function onRejectThiefAdditionalCardsPlacedStepFromGameLobbyStartGameConfirmDial
function onRejectActorAdditionalCardsPlacedStepFromGameLobbyStartGameConfirmDialog(): void {
emit("rejectActorAdditionalCardsPlacedStep");
}
function onRejectGameOptionsChangedStep(): void {
emit("rejectGameOptionsChangedStep");
}
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
@confirm-start-game="acceptCallback"
@confirm-step="onConfirmStepFromGameLobbyStartGameConfirmDialogContainer"
@reject-actor-additional-cards-placed-step="onRejectActorAdditionalCardsPlacedStepFromGameLobbyStartGameConfirmDialogContainer"
@reject-game-options-changed-step="onRejectGameOptionsChangedStepFromGameLobbyStartGameConfirmDialogContainer"
@reject-players-position-step="onRejectPlayersPositionStepFromGameLobbyStartGameConfirmDialogContainer"
@reject-start-game="rejectCallback"
@reject-thief-additional-cards-placed-step="onRejectThiefAdditionalCardsPlacedStepFromGameLobbyStartGameConfirmDialogContainer"
Expand All @@ -25,6 +26,7 @@ import { storeToRefs } from "pinia";
import { useConfirm } from "primevue/useconfirm";
import type { GameLobbyStartGameConfirmDialogEmits, GameLobbyStartGameConfirmDialogExposed, GameLobbyStartGameConfirmDialogStep } from "~/components/pages/game-lobby/GameLobbyFooter/GameLobbyStartGameButton/GameLobbyStartGameConfirmDialog/game-lobby-start-game-confirm-dialog.types";
import GameLobbyStartGameConfirmDialogContainer from "~/components/pages/game-lobby/GameLobbyFooter/GameLobbyStartGameButton/GameLobbyStartGameConfirmDialog/GameLobbyStartGameConfirmDialogContainer/GameLobbyStartGameConfirmDialogContainer.vue";
import { useGameOptionsTexts } from "~/composables/api/game/game-options/useGameOptionsTexts";
import { useArrays } from "~/composables/misc/useArrays";
import { useCreateGameDtoStore } from "~/stores/game/create-game-dto/useCreateGameDtoStore";
Expand All @@ -34,7 +36,9 @@ const confirmStepIndex = ref<number>(0);
const createGameDtoStore = useCreateGameDtoStore();
const { getPlayersWithRoleNameInCreateGameDto } = createGameDtoStore;
const { doesCreateGameDtoContainPositionDependantRoles } = storeToRefs(createGameDtoStore);
const { doesCreateGameDtoContainPositionDependantRoles, createGameOptionsDto } = storeToRefs(createGameDtoStore);
const { changedGameOptionsTexts } = useGameOptionsTexts(createGameOptionsDto);
const { require: confirmRequire } = useConfirm();
Expand All @@ -44,10 +48,13 @@ const doesCreateGameDtoContainThief = computed<boolean>(() => getPlayersWithRole
const doesCreateGameDtoContainActor = computed<boolean>(() => getPlayersWithRoleNameInCreateGameDto("actor").length > 0);
const areGameOptionsChanged = computed<boolean>(() => changedGameOptionsTexts.value.length > 0);
const confirmSteps = computed<GameLobbyStartGameConfirmDialogStep[]>(() => [
...insertIf<GameLobbyStartGameConfirmDialogStep>(doesCreateGameDtoContainPositionDependantRoles.value, "players-positioned"),
...insertIf<GameLobbyStartGameConfirmDialogStep>(doesCreateGameDtoContainThief.value, "thief-additional-cards-placed"),
...insertIf<GameLobbyStartGameConfirmDialogStep>(doesCreateGameDtoContainActor.value, "actor-additional-cards-placed"),
...insertIf<GameLobbyStartGameConfirmDialogStep>(areGameOptionsChanged.value, "game-options-changed"),
"players-ready",
]);
Expand Down Expand Up @@ -85,6 +92,11 @@ function onRejectActorAdditionalCardsPlacedStepFromGameLobbyStartGameConfirmDial
emit("rejectActorAdditionalCardsPlacedStep");
}
function onRejectGameOptionsChangedStepFromGameLobbyStartGameConfirmDialogContainer(rejectCallback: () => void): void {
rejectCallback();
emit("rejectGameOptionsChangedStep");
}
defineExpose<GameLobbyStartGameConfirmDialogExposed>({
open,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
:current-confirm-step="currentConfirmStep"
@confirm-step="onConfirmStep"
@reject-actor-additional-cards-placed-step="onRejectActorAdditionalCardsPlacedStep"
@reject-game-options-changed-step="onRejectGameOptionsChangedStep"
@reject-players-position-step="onRejectPlayersPositionStep"
@reject-thief-additional-cards-placed-step="onRejectThiefAdditionalCardsPlacedStep"
/>
Expand Down Expand Up @@ -67,6 +68,10 @@ function onRejectActorAdditionalCardsPlacedStep(): void {
emit("rejectActorAdditionalCardsPlacedStep", props.rejectCallback);
}
function onRejectGameOptionsChangedStep(): void {
emit("rejectGameOptionsChangedStep", props.rejectCallback);
}
function onConfirmStartGame(): void {
emit("confirmStartGame");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
:key="currentConfirmStep"
@confirm-step="onConfirmStepFromConfirmStepComponent"
@reject-actor-additional-cards-placed-step="onRejectActorAdditionalCardsPlacedStep"
@reject-game-options-changed-step="onRejectGameOptionsChangedStep"
@reject-players-position-step="onRejectPlayersPositionStepFromConfirmStepComponent"
@reject-thief-additional-cards-placed-step="onRejectThiefAdditionalCardsPlacedStep"
/>
Expand All @@ -17,9 +18,11 @@
</template>

<script setup lang="ts">
import type { Component } from "vue";
import type { GameLobbyStartGameConfirmDialogStep } from "~/components/pages/game-lobby/GameLobbyFooter/GameLobbyStartGameButton/GameLobbyStartGameConfirmDialog/game-lobby-start-game-confirm-dialog.types";
import type { GameLobbyStartGameConfirmDialogContentEmits, GameLobbyStartGameConfirmDialogContentProps, GameLobbyStartGameConfirmDialogStepComponents } from "~/components/pages/game-lobby/GameLobbyFooter/GameLobbyStartGameButton/GameLobbyStartGameConfirmDialog/GameLobbyStartGameConfirmDialogContainer/GameLobbyStartGameConfirmDialogContent/game-lobby-start-game-confirm-dialog-content.types";
import type { GameLobbyStartGameConfirmDialogContentEmits, GameLobbyStartGameConfirmDialogContentProps } from "~/components/pages/game-lobby/GameLobbyFooter/GameLobbyStartGameButton/GameLobbyStartGameConfirmDialog/GameLobbyStartGameConfirmDialogContainer/GameLobbyStartGameConfirmDialogContent/game-lobby-start-game-confirm-dialog-content.types";
import GameLobbyStartGameConfirmDialogActorAdditionalCardsPlaced from "~/components/pages/game-lobby/GameLobbyFooter/GameLobbyStartGameButton/GameLobbyStartGameConfirmDialog/GameLobbyStartGameConfirmDialogContainer/GameLobbyStartGameConfirmDialogContent/GameLobbyStartGameConfirmDialogActorAdditionalCardsPlaced/GameLobbyStartGameConfirmDialogActorAdditionalCardsPlaced.vue";
import GameLobbyStartGameConfirmDialogGameOptionsChanged from "~/components/pages/game-lobby/GameLobbyFooter/GameLobbyStartGameButton/GameLobbyStartGameConfirmDialog/GameLobbyStartGameConfirmDialogContainer/GameLobbyStartGameConfirmDialogContent/GameLobbyStartGameConfirmDialogGameOptionsChanged/GameLobbyStartGameConfirmDialogGameOptionsChanged.vue";
import GameLobbyStartGameConfirmDialogPlayersPositioned from "~/components/pages/game-lobby/GameLobbyFooter/GameLobbyStartGameButton/GameLobbyStartGameConfirmDialog/GameLobbyStartGameConfirmDialogContainer/GameLobbyStartGameConfirmDialogContent/GameLobbyStartGameConfirmDialogPlayersPositioned/GameLobbyStartGameConfirmDialogPlayersPositioned.vue";
import GameLobbyStartGameConfirmDialogPlayersReady from "~/components/pages/game-lobby/GameLobbyFooter/GameLobbyStartGameButton/GameLobbyStartGameConfirmDialog/GameLobbyStartGameConfirmDialogContainer/GameLobbyStartGameConfirmDialogContent/GameLobbyStartGameConfirmDialogPlayersReady/GameLobbyStartGameConfirmDialogPlayersReady.vue";
import GameLobbyStartGameConfirmDialogThiefAdditionalCardsPlaced from "~/components/pages/game-lobby/GameLobbyFooter/GameLobbyStartGameButton/GameLobbyStartGameConfirmDialog/GameLobbyStartGameConfirmDialogContainer/GameLobbyStartGameConfirmDialogContent/GameLobbyStartGameConfirmDialogThiefAdditionalCardsPlaced/GameLobbyStartGameConfirmDialogThiefAdditionalCardsPlaced.vue";
Expand All @@ -28,14 +31,15 @@ const props = defineProps<GameLobbyStartGameConfirmDialogContentProps>();
const emit = defineEmits<GameLobbyStartGameConfirmDialogContentEmits>();
const confirmStepsComponents: Record<GameLobbyStartGameConfirmDialogStep, GameLobbyStartGameConfirmDialogStepComponents> = {
const confirmStepsComponents: Record<GameLobbyStartGameConfirmDialogStep, Component> = {
"players-positioned": GameLobbyStartGameConfirmDialogPlayersPositioned,
"players-ready": GameLobbyStartGameConfirmDialogPlayersReady,
"thief-additional-cards-placed": GameLobbyStartGameConfirmDialogThiefAdditionalCardsPlaced,
"actor-additional-cards-placed": GameLobbyStartGameConfirmDialogActorAdditionalCardsPlaced,
"game-options-changed": GameLobbyStartGameConfirmDialogGameOptionsChanged,
};
const currentConfirmStepComponent = computed<GameLobbyStartGameConfirmDialogStepComponents>(() => confirmStepsComponents[props.currentConfirmStep]);
const currentConfirmStepComponent = computed<Component>(() => confirmStepsComponents[props.currentConfirmStep]);
function onConfirmStepFromConfirmStepComponent(): void {
emit("confirmStep");
Expand All @@ -52,4 +56,8 @@ function onRejectThiefAdditionalCardsPlacedStep(): void {
function onRejectActorAdditionalCardsPlacedStep(): void {
emit("rejectActorAdditionalCardsPlacedStep");
}
function onRejectGameOptionsChangedStep(): void {
emit("rejectGameOptionsChangedStep");
}
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<template>
<div id="changed-game-options-list">
<ul class="max-h-64 overflow-y-scroll px-1">
<li
v-for="gameOptionText in changedGameOptionsTexts"
:key="gameOptionText"
class="!bg-sky-950 border-2 border-gray-600 changed-game-options-list-item flex gap-4 items-center px-2 py-1 rounded-md shadow-black shadow-md"
>
<PrimeVueButton
v-p-tooltip.top="$t('components.ChangedGameOptionsList.resetToOfficialRule')"
:aria-label="$t('components.ChangedGameOptionsList.resetOptionAlt', { 'option': gameOptionText })"
class="!w-2 h-4 reset-changed-game-option-button text-xs"
raised
severity="danger"
size="small"
@click.prevent="onClickFromResetChangedGameOptionButton(gameOptionText)"
>
<template #icon>
<FontAwesomeIcon
icon="minus"
/>
</template>
</PrimeVueButton>

<p class="!leading-relaxed !mb-0">
{{ gameOptionText }}
</p>
</li>
</ul>
</div>
</template>

<script setup lang="ts">
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
import { storeToRefs } from "pinia";
import { useGameOptionsTexts } from "~/composables/api/game/game-options/useGameOptionsTexts";
import { useCreateGameDtoStore } from "~/stores/game/create-game-dto/useCreateGameDtoStore";
const createGameDtoStore = useCreateGameDtoStore();
const { resetCreateGameOptionDto } = createGameDtoStore;
const { createGameOptionsDto } = storeToRefs(createGameDtoStore);
const { changedGameOptionsTexts, getGameOptionKeyFromText } = useGameOptionsTexts(createGameOptionsDto);
function onClickFromResetChangedGameOptionButton(gameOptionText: string): void {
const key = getGameOptionKeyFromText(gameOptionText);
if (key === undefined) {
return;
}
resetCreateGameOptionDto(key);
if (key === "roles.sheriff.electedAt.turn") {
resetCreateGameOptionDto("roles.sheriff.electedAt.phaseName");
}
}
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<template>
<div
id="game-lobby-start-game-confirm-dialog-game-options-changed"
class="flex flex-col gap-6 items-center justify-center"
>
<div class="flex flex-col gap-2 items-center justify-center">
<NuxtImg
:alt="$t(`components.GameLobbyStartGameConfirmDialogGameOptionsChanged.changedGameOptionsIcon`)"
:height="svgSize"
placeholder="/svg/misc/infinite-spinner.svg"
src="/svg/misc/rabbit-in-hat.svg"
:width="svgSize"
/>
</div>

<h4
id="game-lobby-start-game-confirm-dialog-game-options-changed-text"
class="text-center"
>
{{ gameOptionsChangedText }}
</h4>

<ChangedGameOptionsList class="w-full"/>

<div
id="game-lobby-start-game-confirm-dialog-game-options-changed-actions"
class="flex gap-2 items-center justify-evenly w-full"
>
<PrimeVueButton
id="reject-step-button"
:label="$t(`components.GameLobbyStartGameConfirmDialogGameOptionsChanged.seeAllGameOptions`)"
severity="info"
@click.prevent="onRejectGameOptionsChangedStep"
>
<template #icon>
<FontAwesomeIcon icon="eye"/>
</template>
</PrimeVueButton>

<PrimeVueButton
id="confirm-step-button"
:label="$t(`shared.actions.confirm`)"
severity="success"
@click.prevent="onConfirmGameOptionsChangedStep"
>
<template #icon>
<FontAwesomeIcon icon="check"/>
</template>
</PrimeVueButton>
</div>
</div>
</template>

<script setup lang="ts">
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
import { storeToRefs } from "pinia";
import ChangedGameOptionsList from "~/components/pages/game-lobby/GameLobbyFooter/GameLobbyStartGameButton/GameLobbyStartGameConfirmDialog/GameLobbyStartGameConfirmDialogContainer/GameLobbyStartGameConfirmDialogContent/GameLobbyStartGameConfirmDialogGameOptionsChanged/ChangedGameOptionsList/ChangedGameOptionsList.vue";
import type { GameLobbyStartGameConfirmDialogGameOptionsChangedEmits } from "~/components/pages/game-lobby/GameLobbyFooter/GameLobbyStartGameButton/GameLobbyStartGameConfirmDialog/GameLobbyStartGameConfirmDialogContainer/GameLobbyStartGameConfirmDialogContent/GameLobbyStartGameConfirmDialogGameOptionsChanged/game-lobby-start-game-confirm-dialog-game-options-changed.types";
import { useGameOptionsTexts } from "~/composables/api/game/game-options/useGameOptionsTexts";
import { useCreateGameDtoStore } from "~/stores/game/create-game-dto/useCreateGameDtoStore";
const emit = defineEmits<GameLobbyStartGameConfirmDialogGameOptionsChangedEmits>();
const svgSize = 75;
const createGameDtoStore = useCreateGameDtoStore();
const { createGameOptionsDto } = storeToRefs(createGameDtoStore);
const { changedGameOptionsTexts } = useGameOptionsTexts(createGameOptionsDto);
const { t } = useI18n();
const changedGameOptionsCount = computed<number>(() => changedGameOptionsTexts.value.length);
const gameOptionsChangedText = computed<string>(() => {
const tKey = "components.GameLobbyStartGameConfirmDialogGameOptionsChanged.gameOptionsChanged";
return t(tKey, { count: changedGameOptionsCount.value }, changedGameOptionsCount.value);
});
function onConfirmGameOptionsChangedStep(): void {
emit("confirmStep");
}
function onRejectGameOptionsChangedStep(): void {
emit("rejectGameOptionsChangedStep");
}
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
type GameLobbyStartGameConfirmDialogGameOptionsChangedEmits = {
confirmStep: [];
rejectGameOptionsChangedStep: [];
};

export type { GameLobbyStartGameConfirmDialogGameOptionsChangedEmits };
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { GameLobbyStartGameConfirmDialogStep } from "~/components/pages/game-lobby/GameLobbyFooter/GameLobbyStartGameButton/GameLobbyStartGameConfirmDialog/game-lobby-start-game-confirm-dialog.types";
import type GameLobbyStartGameConfirmDialogPlayersPositioned from "~/components/pages/game-lobby/GameLobbyFooter/GameLobbyStartGameButton/GameLobbyStartGameConfirmDialog/GameLobbyStartGameConfirmDialogContent/GameLobbyStartGameConfirmDialogPlayersPositioned/GameLobbyStartGameConfirmDialogPlayersPositioned.vue";

type GameLobbyStartGameConfirmDialogContentProps = {
currentConfirmStep: GameLobbyStartGameConfirmDialogStep;
Expand All @@ -10,12 +9,10 @@ type GameLobbyStartGameConfirmDialogContentEmits = {
rejectPlayersPositionStep: [];
rejectThiefAdditionalCardsPlacedStep: [];
rejectActorAdditionalCardsPlacedStep: [];
rejectGameOptionsChangedStep: [];
};

type GameLobbyStartGameConfirmDialogStepComponents = typeof GameLobbyStartGameConfirmDialogPlayersPositioned;

export type {
GameLobbyStartGameConfirmDialogContentProps,
GameLobbyStartGameConfirmDialogContentEmits,
GameLobbyStartGameConfirmDialogStepComponents,
};
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type GameLobbyStartGameConfirmDialogContainerEmits = {
rejectPlayersPositionStep: [rejectCallback: () => void];
rejectThiefAdditionalCardsPlacedStep: [rejectCallback: () => void];
rejectActorAdditionalCardsPlacedStep: [rejectCallback: () => void];
rejectGameOptionsChangedStep: [rejectCallback: () => void];
};

export type {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const GAME_LOBBY_START_GAME_CONFIRM_DIALOG_STEPS = [
"actor-additional-cards-placed",
"players-positioned",
"players-ready",
"game-options-changed",
] as const;

export { GAME_LOBBY_START_GAME_CONFIRM_DIALOG_STEPS };
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ type GameLobbyStartGameConfirmDialogEmits = {
rejectPlayersPositionStep: [];
rejectThiefAdditionalCardsPlacedStep: [];
rejectActorAdditionalCardsPlacedStep: [];
rejectGameOptionsChangedStep: [];
};

type GameLobbyStartGameConfirmDialogExposed = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ type GameLobbyStartGameButtonEmits = {
rejectPlayersPositionStep: [];
rejectThiefAdditionalCardsPlacedStep: [];
rejectActorAdditionalCardsPlacedStep: [];
rejectGameOptionsChangedStep: [];
};

export type {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ type GameLobbyFooterEmits = {
rejectPlayersPositionStep: [];
rejectThiefAdditionalCardsPlacedStep: [];
rejectActorAdditionalCardsPlacedStep: [];
rejectGameOptionsChangedStep: [];
};

export type {
Expand Down
Loading

0 comments on commit 20cc2ce

Please sign in to comment.