Add hunt detail
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
<script setup lang="ts">
|
||||
const { locale, locales } = useI18n();
|
||||
|
||||
const availableLocales = computed(() => {
|
||||
return locales.value.filter((i) => i.code !== locale.value);
|
||||
});
|
||||
|
||||
function l(locale: (typeof locales.value)[0]) {
|
||||
return typeof locale === 'string' ? locale : locale.code;
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VaSidebarItem
|
||||
v-for="loc in availableLocales"
|
||||
:key="loc.code"
|
||||
:to="$switchLocalePath(loc.code)"
|
||||
:title="$t('layouts.switch_lang', { locale: $t(`locales.${l(loc)}`) })"
|
||||
>
|
||||
<VaSidebarItemContent>
|
||||
<VaIcon name="language" />
|
||||
<VaSidebarItemTitle>
|
||||
{{ $t('layouts.switch_lang', { locale: $t(`locales.${l(loc)}`) }) }}
|
||||
</VaSidebarItemTitle>
|
||||
</VaSidebarItemContent>
|
||||
</VaSidebarItem>
|
||||
</template>
|
||||
@@ -0,0 +1,30 @@
|
||||
<script setup lang="ts">
|
||||
const props = defineProps<{
|
||||
quest: {
|
||||
title: string;
|
||||
textRequired: boolean;
|
||||
pictureRequired: boolean;
|
||||
optional: boolean;
|
||||
points: number;
|
||||
extraPoints: number | null;
|
||||
answer?: {
|
||||
score: number | null;
|
||||
} | null;
|
||||
};
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<span>{{ quest.pictureRequired ? '📸' : '📷' }}</span>
|
||||
<span title="aaa">{{ quest.textRequired ? '❓' : '❔' }}</span>
|
||||
<span class="mx-2">{{ quest.title }}</span>
|
||||
<VaChip v-if="quest.answer?.score" color="success" class="float-right">{{
|
||||
quest.answer?.score || 0
|
||||
}}</VaChip>
|
||||
<VaChip v-else class="float-right"
|
||||
>{{ quest.points
|
||||
}}{{ quest.extraPoints ? ` +${quest.extraPoints}` : '' }}</VaChip
|
||||
>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -4,6 +4,10 @@
|
||||
"en": "Englisch",
|
||||
"de": "Deutsch"
|
||||
},
|
||||
"auth": {
|
||||
"login": "Anmelden",
|
||||
"logout": "Abmelden"
|
||||
},
|
||||
"layouts": {
|
||||
"title": "{title} {'|'} PicHunt",
|
||||
"default_tile": "PicHunt",
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
"en": "English",
|
||||
"de": "German"
|
||||
},
|
||||
"auth": {
|
||||
"login": "Login",
|
||||
"logout": "Logout"
|
||||
},
|
||||
"layouts": {
|
||||
"title": "{title} {'|'} PicHunt",
|
||||
"default_tile": "PicHunt",
|
||||
|
||||
+73
-27
@@ -1,34 +1,80 @@
|
||||
<script setup lang="ts">
|
||||
const { locale, locales } = useI18n();
|
||||
const switchLocalePath = useSwitchLocalePath();
|
||||
const { loggedIn, clear } = useUserSession();
|
||||
|
||||
const availableLocales = computed(() => {
|
||||
return locales.value.filter((i) => l(i) !== locale.value);
|
||||
const route = useRoute();
|
||||
const breakpoints = useBreakpoint();
|
||||
|
||||
const isSidebarVisible = ref(breakpoints.mdUp);
|
||||
|
||||
watchEffect(() => {
|
||||
isSidebarVisible.value = breakpoints.smUp;
|
||||
});
|
||||
|
||||
const { loggedIn, clear, user } = useUserSession();
|
||||
const localePath = useLocalePath();
|
||||
function l(locale: (typeof locales.value)[0]) {
|
||||
return typeof locale === 'string' ? locale : locale.code;
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div class="m-2 flex flex-row gap-4 underline">
|
||||
<NuxtLink
|
||||
v-for="loc in availableLocales"
|
||||
:key="l(loc)"
|
||||
:to="switchLocalePath(l(loc))"
|
||||
:title="$t('layouts.switch_lang', { locale: $t(`locales.${l(loc)}`) })"
|
||||
>{{ $t(`locales.${l(loc)}`) }}
|
||||
</NuxtLink>
|
||||
<a v-if="loggedIn" href="#" @click.prevent="clear">Logout</a>
|
||||
<NuxtLink v-else :to="localePath('/login')">Login</NuxtLink>
|
||||
<NuxtLink :to="localePath('/')">Home</NuxtLink>
|
||||
</div>
|
||||
<Suspense>
|
||||
<slot />
|
||||
</Suspense>
|
||||
</div>
|
||||
<VaLayout
|
||||
:top="{ fixed: true, order: 2 }"
|
||||
:left="{
|
||||
fixed: true,
|
||||
absolute: breakpoints.smDown,
|
||||
order: 1,
|
||||
overlay: breakpoints.smDown && isSidebarVisible
|
||||
}"
|
||||
@left-overlay-click="isSidebarVisible = false"
|
||||
>
|
||||
<template #top>
|
||||
<VaNavbar shadowed>
|
||||
<template #left>
|
||||
<VaButton
|
||||
preset="secondary"
|
||||
:icon="isSidebarVisible ? 'menu_open' : 'menu'"
|
||||
@click="isSidebarVisible = !isSidebarVisible"
|
||||
/>
|
||||
</template>
|
||||
<template #center>{{ $t('layouts.default_tile') }}</template>
|
||||
</VaNavbar>
|
||||
</template>
|
||||
|
||||
<template #left>
|
||||
<VaSidebar v-model="isSidebarVisible">
|
||||
<VaSidebarItem
|
||||
:to="$localePath('/')"
|
||||
:active="$localePath('/') === route.path"
|
||||
>
|
||||
<VaSidebarItemContent>
|
||||
<VaIcon name="home" />
|
||||
<VaSidebarItemTitle>Home</VaSidebarItemTitle>
|
||||
</VaSidebarItemContent>
|
||||
</VaSidebarItem>
|
||||
<VaSpacer />
|
||||
<VaSidebarItem v-if="loggedIn" @click="clear">
|
||||
<VaSidebarItemContent>
|
||||
<VaIcon name="logout" />
|
||||
<VaSidebarItemTitle>
|
||||
{{ $t('auth.logout') }}
|
||||
</VaSidebarItemTitle>
|
||||
</VaSidebarItemContent>
|
||||
</VaSidebarItem>
|
||||
<VaSidebarItem v-else :to="$localePath('/login')">
|
||||
<VaSidebarItemContent>
|
||||
<VaIcon name="login" />
|
||||
<VaSidebarItemTitle>
|
||||
{{ $t('auth.login') }}
|
||||
</VaSidebarItemTitle>
|
||||
</VaSidebarItemContent>
|
||||
</VaSidebarItem>
|
||||
<LangSwitcher />
|
||||
</VaSidebar>
|
||||
</template>
|
||||
|
||||
<template #content>
|
||||
<main>
|
||||
<article class="p-4">
|
||||
<Suspense>
|
||||
<slot />
|
||||
</Suspense>
|
||||
</article>
|
||||
</main>
|
||||
</template>
|
||||
</VaLayout>
|
||||
</template>
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
const app = useNuxtApp();
|
||||
const { huntSlug, questSlug } = app.$slugData;
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h1>{{ huntSlug!.name }} - {{ questSlug!.name }}</h1>
|
||||
<VaButton :to="$localePath(`/hunt/${sluggy(huntSlug!)}`)"
|
||||
>Back to Hunt</VaButton
|
||||
>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -0,0 +1,67 @@
|
||||
<script setup lang="ts">
|
||||
const app = useNuxtApp();
|
||||
const { user } = useUserSession();
|
||||
const localePath = useLocalePath();
|
||||
|
||||
const { name, id } = app.$slugData.huntSlug!;
|
||||
|
||||
const { data, pending } = await useFetch(`/api/hunt/${id}`);
|
||||
|
||||
const hideAnswers = ref(true);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h1 class="text-2xl">
|
||||
{{ data?.name || name }}
|
||||
<VaChip v-if="data?.totalScore" class="float-right" color="success"
|
||||
>Total points: {{ data!!.totalScore }}</VaChip
|
||||
>
|
||||
</h1>
|
||||
<div v-if="data">
|
||||
<p>{{ data.description }}</p>
|
||||
<p v-if="data.start">Start: {{ $d(data.start) }}</p>
|
||||
<p v-if="data.end">End: {{ $d(data.end) }}</p>
|
||||
<p>
|
||||
{{ data._count.teams }} teams joined{{
|
||||
data.ownTeam !== null ? ', just like you' : ', unlike you'
|
||||
}}!
|
||||
</p>
|
||||
<div class="flex flex-row gap-2" v-if="data.ownTeam !== null">
|
||||
<VaSwitch v-model="hideAnswers" icon="image">Hide answers</VaSwitch>
|
||||
</div>
|
||||
<VaDivider />
|
||||
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-4">
|
||||
<VaCard
|
||||
v-for="quest in data.quests"
|
||||
:key="`q-${quest.id}`"
|
||||
:to="$localePath(`/hunt/${sluggy(data)}/${sluggy(quest)}`)"
|
||||
:stripe="quest.answer !== null"
|
||||
:stripe-color="
|
||||
quest.answer?.score && quest.answer?.score > 0 ? 'success' : 'primary'
|
||||
"
|
||||
>
|
||||
<VaCardTitle><QuestTags :quest="quest" /></VaCardTitle>
|
||||
<VaImage
|
||||
v-if="!hideAnswers && quest?.answer?.picture"
|
||||
:src="quest?.answer?.picture"
|
||||
class="h-32"
|
||||
fit="cover"
|
||||
lazy
|
||||
>
|
||||
<template #loader> <VaProgressCircle indeterminate /> </template
|
||||
></VaImage>
|
||||
<VaCardContent>
|
||||
<p class="line-clamp-1">{{ quest.description }}</p>
|
||||
<div v-if="!hideAnswers && quest.answer?.text">
|
||||
<VaDivider />
|
||||
<p class="line-clamp-1">
|
||||
{{ quest.answer?.text }}
|
||||
</p>
|
||||
</div>
|
||||
</VaCardContent>
|
||||
</VaCard>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
+2
-1
@@ -1,7 +1,8 @@
|
||||
<script setup lang="ts"></script>
|
||||
|
||||
<template>
|
||||
<h1 class="text-3xl">{{ $t('hello') }}</h1>
|
||||
<h1 class="text-primary text-3xl">{{ $t('hello') }}</h1>
|
||||
<VaButton icon="home" :to="$localePath('/hunt/bremer-stadtrallye-1')" />
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
|
||||
Reference in New Issue
Block a user