Files
polylan-submitter/polylan_submitter/src/SubmissionsSelect.vue
T
2026-09-17 00:56:17 +02:00

91 lines
2.9 KiB
Vue

<script setup lang="ts">
import { computed, onMounted, ref } from "vue";
import { useRouter } from "vue-router";
import { useI18n } from "vue-i18n";
import { useTitle } from "@vueuse/core";
import { gamesApiListEventGames, submissionsApiListAvailableScopes } from "@/api";
import type { ScopeOut } from "@/api/types.gen";
interface Props {
eventPath: string;
gamePath: string;
}
const props = defineProps<Props>();
const router = useRouter();
const { t } = useI18n();
useTitle(computed(() => t("submissionsSelect.title")));
const gameName = ref("");
const scopes = ref<ScopeOut[]>([]);
const loading = ref(true);
const notAssigned = ref(false);
const scopeRoute = (scope: ScopeOut) => ({
name: "submissions",
params: { eventPath: props.eventPath, gamePath: props.gamePath, scopeId: scope.id },
});
const goToScope = (scope: ScopeOut) => {
router.push(scopeRoute(scope));
};
onMounted(async () => {
const [gamesResponse, scopesResponse] = await Promise.all([
gamesApiListEventGames({ path: { event_path: props.eventPath } }),
submissionsApiListAvailableScopes({
path: { event_path: props.eventPath, game_path: props.gamePath },
}),
]);
gameName.value = gamesResponse.data?.find((game) => game.path === props.gamePath)?.name ?? "";
const availableScopes = scopesResponse.data ?? [];
// Mirrors the server-side behavior this replaced: skip the picker
// straight to the only option, or bounce out if there's nothing to pick.
if (availableScopes.length === 1) {
router.replace(scopeRoute(availableScopes[0]));
return;
}
if (availableScopes.length === 0) {
notAssigned.value = true;
loading.value = false;
return;
}
scopes.value = availableScopes;
loading.value = false;
});
</script>
<template>
<div class="flex-1 bg-base-200 flex items-center justify-center p-4">
<div v-if="loading" class="flex justify-center py-20">
<span class="loading loading-spinner loading-lg"></span>
</div>
<div v-else-if="notAssigned" class="text-center max-w-md">
<i class="mdi mdi-account-alert-outline text-6xl text-warning"></i>
<h2 class="text-2xl font-semibold mt-4">{{ t("submissionsSelect.notAssignedTitle") }}</h2>
<p class="text-base-content/70 mt-2">{{ t("submissionsSelect.notAssignedMessage") }}</p>
</div>
<div v-else class="card bg-base-100 shadow-lg w-full max-w-md">
<div class="card-body">
<h2 class="card-title">{{ t("submissionsSelect.title") }}</h2>
<p class="text-base-content/70 mb-2">
{{ t("submissionsSelect.description", { game: gameName }) }}
</p>
<div class="flex flex-col gap-2 mt-2">
<button v-for="scope in scopes" :key="scope.id" @click="goToScope(scope)"
class="btn btn-outline justify-start">
<i class="mdi mdi-sword-cross mr-2"></i>
{{ scope.name }}
</button>
</div>
</div>
</div>
</div>
</template>