Skip to content

Commit

Permalink
* migrate a couple components over to composition
Browse files Browse the repository at this point in the history
  • Loading branch information
ConorMurphy21 committed Feb 2, 2024
1 parent 0e49079 commit 6032e81
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 180 deletions.
48 changes: 24 additions & 24 deletions client/src/components/countdown/Countdown.vue
Original file line number Diff line number Diff line change
@@ -1,35 +1,35 @@
<template>
<div class="w-100 d-flex justify-content-center bounce">
<h1 class="flip">{{ $n(timer) }}</h1>
</div>
</template>

<script lang="ts">
<script setup lang="ts">
import timerMp3 from '@/assets/audio/countdown.mp3';
import { AudioWrap } from '@/mixins/audiowrap.js';
import { useGameStore } from '@/stores/game.js';
import { onMounted, watch } from 'vue';
import { useSettingsStore } from '@/stores/settings.js';
import { mapState } from 'pinia';
import { defineComponent } from 'vue';
import { useI18n } from 'vue-i18n';
import { useGameStore } from '@/stores/game.js';
const timerAudio = new AudioWrap(timerMp3);
const timer = new AudioWrap(timerMp3);
const gameStore = useGameStore();
const settingsStore = useSettingsStore();
export default defineComponent({
computed: {
...mapState(useGameStore, ['timer']),
...mapState(useSettingsStore, ['volume'])
},
watch: {
volume(val: number) {
timer.volume = val;
}
},
mounted() {
timer.play();
}
onMounted(() => {
timerAudio.play();
});
watch(
() => settingsStore.volume,
(val: number) => {
timerAudio.volume = val;
}
);
const { n } = useI18n();
</script>

<template>
<div class="w-100 d-flex justify-content-center bounce">
<h1 class="flip">{{ n(gameStore.timer) }}</h1>
</div>
</template>

<style lang="scss" scoped>
h1 {
font-family: $header-font;
Expand Down
77 changes: 37 additions & 40 deletions client/src/components/endGame/EndGame.vue
Original file line number Diff line number Diff line change
@@ -1,52 +1,49 @@
<script setup lang="ts">
import ClickMp3 from '@/assets/audio/click2.mp3';
import { AudioWrap } from '@/mixins/audiowrap.js';
import { computed } from 'vue';
import { useGameStore } from '@/stores/game.js';
import { useI18n } from 'vue-i18n';
const click = new AudioWrap(ClickMp3);
const gameStore = useGameStore();
const rank = computed((): number[] => {
let result = [];
let lastScore = -1;
let lastRank = 1;
for (const [rank, score] of gameStore.scores.entries()) {
if (score.points < lastScore) {
result.push(rank + 1);
lastRank = rank + 1;
} else {
result.push(lastRank);
}
lastScore = score.points;
}
return result;
});
function toLobby() {
click.play();
gameStore.setScene('Lobby');
}
const { n } = useI18n();
</script>

<template>
<div class="w-100 d-flex flex-column justify-content-start align-items-center gap-3 py-3 px-4">
<h1 v-t="'playerScores'" class="mt-2 text-center display-1 text-red font-fancy" />

<div class="list-group w-75 w-xl-50">
<div v-for="(score, index) in scores" :key="score.player.id" class="list-group-item">
{{ rank[index] }}. {{ score.player.name }}: {{ $n(score.points) }}
<div v-for="(score, index) in gameStore.scores" :key="score.player.id" class="list-group-item">
{{ rank[index] }}. {{ score.player.name }}: {{ n(score.points) }}
</div>
</div>

<div class="flex-grow-1" />
<button v-t="'toLobby'" class="btn btn-blue w-75 w-lg-50 fs-4 mb-4" @click="toLobby" />
</div>
</template>

<script lang="ts">
import { mapActions, mapState } from 'pinia';
import ClickMp3 from '@/assets/audio/click2.mp3';
import { AudioWrap } from '@/mixins/audiowrap.js';
import { useGameStore } from '@/stores/game.js';
import { defineComponent } from 'vue';
const click = new AudioWrap(ClickMp3);
export default defineComponent({
computed: {
...mapState(useGameStore, ['scores']),
rank() {
let result = [];
let lastScore = -1;
let lastRank = 1;
for (const [rank, score] of this.scores.entries()) {
if (score.points < lastScore) {
result.push(rank + 1);
lastRank = rank + 1;
} else {
result.push(lastRank);
}
lastScore = score.points;
}
return result;
}
},
methods: {
...mapActions(useGameStore, ['setScene']),
toLobby() {
click.play();
this.setScene('Lobby');
}
}
});
</script>
103 changes: 46 additions & 57 deletions client/src/components/endRound/EndRound.vue
Original file line number Diff line number Diff line change
@@ -1,68 +1,57 @@
<script setup lang="ts">
import { onMounted, ref, watch } from 'vue';
import { AudioWrap } from '@/mixins/audiowrap.js';
import ClickMp3 from '@/assets/audio/click2.mp3';
import socket from '@/socket/socket.js';
import { useRoomStore } from '@/stores/room.js';
import { useGameStore } from '@/stores/game.js';
import NotificationCount from '@/components/gameShared/NotificationCount.vue';
import PlayerChooser from '@/components/endRound/PlayerChooser.vue';
import ResponseList from '@/components/gameShared/ResponseList.vue';
import Prompt from '@/components/gameShared/Prompt.vue';
import { useI18n } from 'vue-i18n';
const roomStore = useRoomStore();
const gameStore = useGameStore();
const responsesId = ref('');
const selectedId = ref('');
watch(selectedId, async (val: string) => {
if (val) {
await gameStore.getResponses(val).then(() => {
responsesId.value = val;
});
}
});
onMounted(() => {
selectedId.value = roomStore.self!.id;
});
function sendVote() {
new AudioWrap(ClickMp3).play();
socket.emit('pollVote', 'startNextRound');
}
const { t, n } = useI18n();
</script>

<template>
<div class="w-100 d-flex flex-column justify-content-between align-items-center py-3 px-4">
<prompt :prompt="prompt" />
<prompt :prompt="gameStore.prompt" />
<response-list :selectable="false" :height="45" :player-id="responsesId" />
<player-chooser v-model="selectedId" class="w-50 w-lg-25 fs-4 mb-3" />
<button
class="btn btn-orange w-75 w-lg-50 w-xl-25 fs-4 mb-3 position-relative"
:class="{ 'btn-blue': !startNextRoundNext }"
:class="{ 'btn-blue': !gameStore.startNextRoundNext }"
@click="sendVote">
{{ hasNextRound ? $t('startNextRound') : $t('viewResults') }}
<notification-count v-if="startNextRoundCount" class="position-absolute top-0 start-100 translate-middle fs-6">
{{ $n(startNextRoundCount) }}
{{ gameStore.hasNextRound ? t('startNextRound') : t('viewResults') }}
<notification-count
v-if="gameStore.startNextRoundCount"
class="position-absolute top-0 start-100 translate-middle fs-6">
{{ n(gameStore.startNextRoundCount) }}
</notification-count>
</button>
</div>
</template>

<script lang="ts">
import Prompt from '@/components/gameShared/Prompt.vue';
import ResponseList from '@/components/gameShared/ResponseList.vue';
import NotificationCount from '@/components/gameShared/NotificationCount.vue';
import ClickMp3 from '@/assets/audio/click2.mp3';
import PlayerChooser from '@/components/endRound/PlayerChooser.vue';
import { AudioWrap } from '@/mixins/audiowrap.js';
import socket from '@/socket/socket';
import { useGameStore } from '@/stores/game.js';
import { useRoomStore } from '@/stores/room.js';
import { mapState, mapActions } from 'pinia';
import { defineComponent } from 'vue';
export default defineComponent({
components: {
PlayerChooser,
Prompt,
ResponseList,
NotificationCount
},
data() {
return {
responsesId: '',
selectedId: ''
};
},
computed: {
...mapState(useGameStore, ['prompt', 'hasNextRound', 'startNextRoundCount', 'startNextRoundNext']),
...mapState(useRoomStore, ['self'])
},
watch: {
selectedId(val: string) {
if (val) {
void this.getResponses(val).then(() => {
this.responsesId = val;
});
}
}
},
mounted() {
this.selectedId = this.self!.id;
},
methods: {
sendVote() {
new AudioWrap(ClickMp3).play();
socket.emit('pollVote', 'startNextRound');
},
...mapActions(useGameStore, ['getResponses'])
}
});
</script>
93 changes: 36 additions & 57 deletions client/src/components/endRound/PlayerChooser.vue
Original file line number Diff line number Diff line change
@@ -1,3 +1,38 @@
<script setup lang="ts">
import { computed, ref } from 'vue';
import { AudioWrap } from '@/mixins/audiowrap.js';
import Click2Mp3 from '@/assets/audio/click2.mp3';
import Click1Mp3 from '@/assets/audio/click1.mp3';
import { useRoomStore } from '@/stores/room';
import { type Player } from ':common/stateTypes';
const roomStore = useRoomStore();
const hoverLeft = ref(false);
const hoverRight = ref(false);
const model = defineModel({ type: String, required: true });
const selectedName = computed((): string => {
if (!model.value) return '';
const name = roomStore.players.find((player: Player) => player.id === model.value)?.name;
return name === undefined ? '' : name;
});
function nextPlayer(right: boolean) {
const direction = right ? 1 : -1;
let index = roomStore.players.findIndex((player: Player) => player.id === model.value);
index = (index + direction + roomStore.players.length) % roomStore.players.length;
model.value = roomStore.players[index].id;
new AudioWrap(Click2Mp3).play();
}
function clickOption(value: string) {
model.value = value;
new AudioWrap(Click2Mp3).play();
}
function clickDropdown() {
new AudioWrap(Click1Mp3).play();
}
</script>

<template>
<div class="d-flex flex-row justify-content-center align-items-center gap-2">
<a
Expand All @@ -17,7 +52,7 @@
{{ selectedName }}
</button>
<ul class="dropdown-menu w-100" aria-labelledby="playerChooser">
<li v-for="player in players" :key="player.id">
<li v-for="player in roomStore.players" :key="player.id">
<button class="btn dropdown-item cutoff-text text-center" @click="clickOption(player.id)">
{{ player.name }}
</button>
Expand All @@ -33,62 +68,6 @@
</div>
</template>

<script lang="ts">
import Click1Mp3 from '@/assets/audio/click1.mp3';
import Click2Mp3 from '@/assets/audio/click2.mp3';
import { AudioWrap } from '@/mixins/audiowrap.js';
import { useRoomStore } from '@/stores/room.js';
import { mapState } from 'pinia';
import { defineComponent } from 'vue';
export default defineComponent({
props: {
modelValue: {
type: String,
required: true
}
},
emits: ['update:modelValue'],
data() {
return {
hoverLeft: false,
hoverRight: false
};
},
computed: {
...mapState(useRoomStore, ['players']),
value: {
get(): string {
return this.modelValue;
},
set(value: string) {
this.$emit('update:modelValue', value);
}
},
selectedName() {
if (!this.modelValue) return '';
return this.players.find((player) => player.id === this.modelValue)?.name;
}
},
methods: {
nextPlayer(right: boolean) {
const direction = right ? 1 : -1;
let index = this.players.findIndex((player) => player.id === this.modelValue);
index = (index + direction + this.players.length) % this.players.length;
this.value = this.players[index].id;
new AudioWrap(Click2Mp3).play();
},
clickOption(value: string) {
this.value = value;
new AudioWrap(Click2Mp3).play();
},
clickDropdown() {
new AudioWrap(Click1Mp3).play();
}
}
});
</script>

<style lang="scss" scoped>
.cutoff-text {
text-overflow: ellipsis;
Expand Down
4 changes: 2 additions & 2 deletions client/src/views/Game.vue
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ onMounted(() => {
}
});
const helpLink = computed(() => {
const helpLink = computed((): string => {
const tips = {
Lobby: '#overview',
Countdown: '#prompt',
Expand All @@ -60,7 +60,7 @@ const helpLink = computed(() => {
return router.resolve({ name: 'howToPlay', hash: tips[gameStore.scene] }).href;
});
const isMobile = computed(() => {
const isMobile = computed((): boolean => {
return /Android|webOS|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
});
</script>
Expand Down

0 comments on commit 6032e81

Please sign in to comment.