88 lines
2.3 KiB
Vue
88 lines
2.3 KiB
Vue
<script setup lang="ts">
|
||
import { onMounted } from 'vue'
|
||
import { useRouter } from 'vue-router'
|
||
import AppHeader from '@/components/common/AppHeader.vue'
|
||
import GameCard from '@/components/common/GameCard.vue'
|
||
import PrimaryButton from '@/components/common/PrimaryButton.vue'
|
||
import { useGamesStore } from '@/stores/games'
|
||
import type { GameCatalogItem } from '@/types/catalog.types'
|
||
import { useToast } from '@/composables/useToast'
|
||
|
||
const router = useRouter()
|
||
const gamesStore = useGamesStore()
|
||
const toast = useToast()
|
||
|
||
onMounted(() => {
|
||
void gamesStore.loadCatalog()
|
||
})
|
||
|
||
function retryLoad() {
|
||
void gamesStore.loadCatalog({ force: true })
|
||
}
|
||
|
||
function startGame(game: GameCatalogItem) {
|
||
game.route ? router.push(game.route) : toast.show('به زودی!', 'info')
|
||
}
|
||
</script>
|
||
|
||
<template>
|
||
<div class="page-content page-content--no-nav">
|
||
<AppHeader title="بازیها" show-back @back="router.back()" />
|
||
|
||
<div v-if="gamesStore.catalogLoadStatus === 'loading'" class="games-status card-enter">
|
||
در حال بارگذاری بازیها...
|
||
</div>
|
||
|
||
<div
|
||
v-else-if="gamesStore.catalogLoadStatus === 'error'"
|
||
class="games-status games-status--error card-enter"
|
||
>
|
||
<p>{{ gamesStore.catalogLoadError ?? 'خطا در دریافت بازیها' }}</p>
|
||
<PrimaryButton variant="gold" size="sm" @click="retryLoad">تلاش مجدد</PrimaryButton>
|
||
</div>
|
||
|
||
<div
|
||
v-else-if="gamesStore.catalogLoadStatus === 'ready' && gamesStore.catalog.length === 0"
|
||
class="games-status card-enter"
|
||
>
|
||
فعلاً بازیای برای نمایش نیست.
|
||
</div>
|
||
|
||
<div v-else class="games-list">
|
||
<GameCard
|
||
v-for="(game, i) in gamesStore.catalog"
|
||
:key="game.id"
|
||
:id="game.id"
|
||
:title="game.title"
|
||
:description="game.description"
|
||
:icon="game.icon"
|
||
:color="game.color"
|
||
class="card-enter"
|
||
:style="{ animationDelay: `${i * 0.05}s` }"
|
||
@start="startGame(game)"
|
||
/>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<style scoped>
|
||
.games-list {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 12px;
|
||
}
|
||
|
||
.games-status {
|
||
text-align: center;
|
||
padding: 32px 16px;
|
||
color: var(--text-muted);
|
||
font-size: 0.9375rem;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.games-status--error p {
|
||
margin-bottom: 14px;
|
||
color: #f87171;
|
||
}
|
||
</style>
|