Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(game): game feedback submitter #969

Merged
merged 7 commits into from
Oct 13, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .run/Game Feedback.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Game Feedback" 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-feedback" />
<option name="workingDirectory" value="$PROJECT_DIR$" />
<envs>
<env name="NODE_OPTIONS" value="--import tsx/esm" />
</envs>
<method v="2" />
</configuration>
</component>
14 changes: 14 additions & 0 deletions app/components/pages/game/GameCanceled/GameCanceled.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@
<div class="flex flex-col gap-2 md:flex-row">
<CreateAnotherGameButton class="md:w-auto w-full"/>

<GameFeedbackSubmitterButton
id="game-feedback-submitter-button"
class="md:w-auto w-full"
@game-feedback-submitter-button-click="onClickFromGameFeedbackSubmitterButton"
/>

<BackToHomeButton class="md:w-auto w-full"/>
</div>
</div>
Expand All @@ -30,10 +36,18 @@
<script setup lang="ts">
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";

import type { GameCanceledEmits } from "~/components/pages/game/GameCanceled/game-canceled.types";
import GameFeedbackSubmitterButton from "~/components/pages/game/GameFeedbackSubmitter/GameFeedbackSubmitterButton/GameFeedbackSubmitterButton.vue";
import BackToHomeButton from "~/components/shared/buttons/BackToHomeButton/BackToHomeButton.vue";
import CreateAnotherGameButton from "~/components/shared/buttons/CreateAnotherGameButton/CreateAnotherGameButton.vue";

const emit = defineEmits<GameCanceledEmits>();

const { t } = useI18n();

useHead({ title: t("components.GameCanceled.gameCanceled") });

function onClickFromGameFeedbackSubmitterButton(): void {
emit("gameFeedbackSubmitterButtonClick");
}
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
type GameCanceledEmits = {
gameFeedbackSubmitterButtonClick: [];
};

export type { GameCanceledEmits };
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<template>
<PrimeVueDialog
id="game-feedback-submitter"
block-scroll
:closable="canDialogBeDismissed"
:close-on-escape="canDialogBeDismissed"
:dismissable-mask="canDialogBeDismissed"
:draggable="false"
modal
:pt="{
'icons': 'pb-2',
'header': '!py-2',
'content': 'w-x-screen-9/10 max-w-x-screen-9/10 !py-0',
'footer': '!py-2'
}"
:visible="isVisible"
@update:visible="close"
>
<template #header>
<DialogHeaderTitleOnly
id="game-feedback-submitter-header"
icon="star"
icon-class="text-info"
:title="$t('components.GameFeedbackSubmitter.gameFeedback')"
/>
</template>

<template #default>
<GameFeedbackSubmitterContent
id="game-feedback-submitter-content"
v-model="createGameFeedbackDto"
/>
</template>

<template #footer>
<GameFeedbackSubmitterFooter
id="game-feedback-submitter-footer"
:create-game-feedback-dto="createGameFeedbackDto"
@close-dialog="close"
/>
</template>
</PrimeVueDialog>
</template>

<script setup lang="ts">
import { storeToRefs } from "pinia";

import GameFeedbackSubmitterContent from "~/components/pages/game/GameFeedbackSubmitter/GameFeedbackSubmitterContent/GameFeedbackSubmitterContent.vue";
import GameFeedbackSubmitterFooter from "~/components/pages/game/GameFeedbackSubmitter/GameFeedbackSubmitterFooter/GameFeedbackSubmitterFooter.vue";
import DialogHeaderTitleOnly from "~/components/shared/dialogs/DialogHeaderTitleOnly/DialogHeaderTitleOnly.vue";
import { CreateGameFeedbackDto } from "~/composables/api/game/dto/create-game-feedback/create-game-feedback.dto";
import { useGameStore } from "~/stores/game/useGameStore";

const gameStore = useGameStore();
const { creatingGameFeedbackStatus } = storeToRefs(gameStore);

const isVisible = ref<boolean>(false);

const defaultCreateGameFeedbackDto: Readonly<CreateGameFeedbackDto> = {
score: 0,
hasEncounteredError: false,
} as const;

const createGameFeedbackDto = ref<CreateGameFeedbackDto>(CreateGameFeedbackDto.create(defaultCreateGameFeedbackDto));

const canDialogBeDismissed = computed<boolean>(() => creatingGameFeedbackStatus.value !== "pending");

function resetCreateGameFeedbackDto(): void {
createGameFeedbackDto.value = CreateGameFeedbackDto.create(defaultCreateGameFeedbackDto);
}

function showGameFeedbackSubmitter(): void {
resetCreateGameFeedbackDto();
isVisible.value = true;
}

function close(): void {
isVisible.value = false;
}

defineExpose({ showGameFeedbackSubmitter });
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<template>
<div id="game-feedback-submitter-button-container">
<PrimeVueButton
v-if="isButtonVisible"
id="game-feedback-submitter-button"
class="w-full"
:label="$t('components.GameFeedbackSubmitterButton.giveFeedback')"
severity="info"
@click="onClickFromGameFeedbackSubmitterButton"
>
<template #icon>
<FontAwesomeIcon
beat-fade
icon="star"
/>
</template>
</PrimeVueButton>
</div>
</template>

<script setup lang="ts">
import { storeToRefs } from "pinia";
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";

import type { GameFeedbackSubmitterButtonEmits } from "~/components/pages/game/GameFeedbackSubmitter/GameFeedbackSubmitterButton/game-feedback-submitter-button.types";
import { useGameStore } from "~/stores/game/useGameStore";

const emit = defineEmits<GameFeedbackSubmitterButtonEmits>();

const gameStore = useGameStore();
const { game } = storeToRefs(gameStore);

const isButtonVisible = computed<boolean>(() => !game.value.feedback);

function onClickFromGameFeedbackSubmitterButton(): void {
emit("gameFeedbackSubmitterButtonClick");
}
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
type GameFeedbackSubmitterButtonEmits = {
gameFeedbackSubmitterButtonClick: [];
};

export type { GameFeedbackSubmitterButtonEmits };
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<template>
<div
id="game-feedback-submitter-content"
>
<form class="flex flex-col gap-2">
<div class="flex flex-col gap-4 justify-around md:flex-row">
<GameFeedbackSubmitterRating
id="game-feedback-submitter-rating"
v-model="createGameFeedbackDto.score"
class="w-auto"
/>

<GameFeedbackSubmitterEncounteredError
id="game-feedback-submitter-encountered-error"
v-model="createGameFeedbackDto.hasEncounteredError"
class="w-auto"
/>
</div>

<PrimeVueDivider/>

<GameFeedbackSubmitterReview
id="game-feedback-submitter-review"
v-model="createGameFeedbackDto.review"
/>
</form>
</div>
</template>

<script setup lang="ts">
import GameFeedbackSubmitterEncounteredError from "~/components/pages/game/GameFeedbackSubmitter/GameFeedbackSubmitterContent/GameFeedbackSubmitterEncounteredError/GameFeedbackSubmitterEncounteredError.vue";
import GameFeedbackSubmitterRating from "~/components/pages/game/GameFeedbackSubmitter/GameFeedbackSubmitterContent/GameFeedbackSubmitterRating/GameFeedbackSubmitterRating.vue";
import GameFeedbackSubmitterReview from "~/components/pages/game/GameFeedbackSubmitter/GameFeedbackSubmitterContent/GameFeedbackSubmitterReview/GameFeedbackSubmitterReview.vue";
import type { CreateGameFeedbackDto } from "~/composables/api/game/dto/create-game-feedback/create-game-feedback.dto";

const createGameFeedbackDto = defineModel<CreateGameFeedbackDto>({ required: true });
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<template>
<div
id="game-feedback-submitter-encountered-error-container"
class="flex flex-col gap-3 items-center justify-center"
>
<label
id="game-feedback-submitter-encountered-error-label"
class="font-bold text-center text-xl"
for="game-feedback-submitter-encountered-error-input"
>
<FontAwesomeIcon
class="mr-1 text-red-500"
icon="bug"
/>

{{ $t("components.GameFeedbackSubmitterEncounteredError.wasEverythingAllRight") }}
</label>

<PrimeVueToggleButton
id="game-feedback-submitter-encountered-error-input"
v-model="hasEncounteredError"
class="!border-0"
:class="toggleButtonClasses"
:disabled="isToggleButtonDisabled"
:off-label="$t('components.GameFeedbackSubmitterEncounteredError.gameWasStable')"
:on-label="$t('components.GameFeedbackSubmitterEncounteredError.gameEncounteredError')"
>
<template #icon>
<FontAwesomeIcon
id="toggle-button-icon"
class="fa-2x"
:icon="toggleButtonIcon"
/>
</template>
</PrimeVueToggleButton>
</div>
</template>

<script setup lang="ts">
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
import { storeToRefs } from "pinia";

import { useGameStore } from "~/stores/game/useGameStore";

const hasEncounteredError = defineModel<boolean>({ required: true });

const gameStore = useGameStore();
const { creatingGameFeedbackStatus } = storeToRefs(gameStore);

const toggleButtonIcon = computed<string>(() => (hasEncounteredError.value ? "bug" : "check"));

const toggleButtonClasses = computed<string>(() => (hasEncounteredError.value ? "!bg-error" : "!bg-success"));

const isToggleButtonDisabled = computed<boolean>(() => creatingGameFeedbackStatus.value === "pending");
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
type GameFeedbackSubmitterEncounteredErrorProps = {
modelValue: boolean;
};

export type {
GameFeedbackSubmitterEncounteredErrorProps,
};
Loading
Loading