Remember uploaded images
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
<script setup lang="ts">
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
title?: string;
|
||||
src: string;
|
||||
class?: string;
|
||||
}>(),
|
||||
{
|
||||
class: 'h-32'
|
||||
}
|
||||
);
|
||||
|
||||
const isOpen = ref(false);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VaImage
|
||||
:src="src"
|
||||
class="cursor-pointer"
|
||||
:class="props.class"
|
||||
:title="title || ''"
|
||||
fit="cover"
|
||||
lazy
|
||||
@click.prevent="isOpen = true"
|
||||
>
|
||||
<template #loader>
|
||||
<VaProgressCircle indeterminate />
|
||||
</template>
|
||||
</VaImage>
|
||||
<VaModal v-model="isOpen" hide-default-actions close-button size="large">
|
||||
<h1 class="mb-4 text-3xl">{{ title }}</h1>
|
||||
<VaImage
|
||||
:src="src"
|
||||
:title="title || ''"
|
||||
fit="contain"
|
||||
lazy
|
||||
class="h-screen"
|
||||
>
|
||||
<template #loader>
|
||||
<VaProgressCircle indeterminate />
|
||||
</template>
|
||||
</VaImage>
|
||||
<template #footer>
|
||||
<VaButton @click="isOpen = false">Close</VaButton>
|
||||
</template>
|
||||
</VaModal>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -90,6 +90,8 @@ const slugs = computed(() => checkSlug(route.params));
|
||||
<VaSpacer />
|
||||
<VaSidebarItem
|
||||
v-if="user"
|
||||
:to="$localePath('/profile')"
|
||||
:active="$localePath('/profile') === route.path"
|
||||
:hover-color="user.role === 'ADMIN' ? 'danger' : undefined"
|
||||
:text-color="user.role === 'ADMIN' ? 'danger' : undefined"
|
||||
>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
export default defineNuxtRouteMiddleware(() => {
|
||||
export default defineNuxtRouteMiddleware((to) => {
|
||||
const { loggedIn } = useUserSession();
|
||||
|
||||
if (!loggedIn.value) {
|
||||
const localePath = useLocalePath();
|
||||
return navigateTo(localePath('/login'));
|
||||
return navigateTo(localePath(`/login?to=${to.path}`));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import ClickableImage from '~/components/ClickableImage.vue';
|
||||
import { useTitleStore } from '~/stores/title';
|
||||
|
||||
definePageMeta({
|
||||
middleware: ['auth']
|
||||
});
|
||||
|
||||
const app = useNuxtApp();
|
||||
const { huntSlug, questSlug } = app.$slugData;
|
||||
|
||||
@@ -8,7 +13,7 @@ const { t, locale } = useI18n();
|
||||
|
||||
const titleStore = useTitleStore();
|
||||
|
||||
const { data, pending, refresh } = await useFetch(
|
||||
const { data, pending, refresh, error } = await useFetch(
|
||||
`/api/quest/${questSlug?.id}`
|
||||
);
|
||||
|
||||
@@ -69,14 +74,10 @@ const createImageURL = (file: File) => URL.createObjectURL(file);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="data">
|
||||
<h1>
|
||||
{{ data.hunt.name || huntSlug!.name }} -
|
||||
{{ data.title || questSlug!.name }}
|
||||
</h1>
|
||||
<VaButtonGroup>
|
||||
<VaButton
|
||||
icon="arrow_back"
|
||||
:to="$localePath(`/hunt/${sluggy(data.hunt || huntSlug!)}`)"
|
||||
:to="$localePath(`/hunt/${sluggy(data?.hunt || huntSlug!)}`)"
|
||||
>Back to Hunt</VaButton
|
||||
>
|
||||
<VaButton
|
||||
@@ -85,8 +86,10 @@ const createImageURL = (file: File) => URL.createObjectURL(file);
|
||||
:loading="pending"
|
||||
color="success"
|
||||
>{{ $t('layouts.refresh') }}</VaButton
|
||||
>
|
||||
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3">
|
||||
></VaButtonGroup
|
||||
>
|
||||
<div v-if="data">
|
||||
<div class="mt-4 grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3">
|
||||
<VaCard
|
||||
:stripe="data.answer !== null"
|
||||
:stripe-color="
|
||||
@@ -94,6 +97,11 @@ const createImageURL = (file: File) => URL.createObjectURL(file);
|
||||
"
|
||||
>
|
||||
<VaCardTitle><QuestTags :quest="data" /></VaCardTitle>
|
||||
<ClickableImage
|
||||
v-if="data?.picture"
|
||||
:src="data?.picture?.url"
|
||||
:title="data?.title || questSlug?.name || ''"
|
||||
/>
|
||||
<VaCardContent>
|
||||
<div class="flex flex-col gap-4">
|
||||
<p class="text-lg">{{ data.description }}</p>
|
||||
@@ -158,7 +166,7 @@ const createImageURL = (file: File) => URL.createObjectURL(file);
|
||||
/>
|
||||
<VaImage
|
||||
v-else-if="data.answer?.picture"
|
||||
:src="data.answer?.picture"
|
||||
:src="data.answer?.picture?.url"
|
||||
class="max-h-60 w-full"
|
||||
fit="contain"
|
||||
lazy
|
||||
@@ -198,6 +206,9 @@ const createImageURL = (file: File) => URL.createObjectURL(file);
|
||||
</VaCard>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="error" class="mt-8 text-3xl">
|
||||
{{ $t(parseError(error)) }}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
|
||||
@@ -11,7 +11,7 @@ const { name, id } = app.$slugData.huntSlug!;
|
||||
|
||||
const titleStore = useTitleStore();
|
||||
|
||||
const { data, pending, refresh } = await useFetch(`/api/hunt/${id}`);
|
||||
const { data, pending, refresh, error } = await useFetch(`/api/hunt/${id}`);
|
||||
|
||||
const hideAnswers = ref(true);
|
||||
|
||||
@@ -50,6 +50,12 @@ async function invite() {
|
||||
</h1>
|
||||
<div v-if="data">
|
||||
<p>{{ data.description }}</p>
|
||||
<ClickableImage
|
||||
v-if="data?.picture"
|
||||
:src="data?.picture?.url"
|
||||
class="h-48"
|
||||
:title="data?.name || name"
|
||||
/>
|
||||
<p v-if="data.start">
|
||||
Start:
|
||||
{{
|
||||
@@ -110,7 +116,10 @@ async function invite() {
|
||||
<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">
|
||||
<div
|
||||
v-if="data.revealQuests"
|
||||
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}`"
|
||||
@@ -123,7 +132,7 @@ async function invite() {
|
||||
<VaCardTitle><QuestTags :quest="quest" /></VaCardTitle>
|
||||
<VaImage
|
||||
v-if="!hideAnswers && quest?.answer?.picture"
|
||||
:src="quest?.answer?.picture"
|
||||
:src="quest?.answer?.picture?.url"
|
||||
class="h-32"
|
||||
fit="cover"
|
||||
lazy
|
||||
@@ -141,6 +150,18 @@ async function invite() {
|
||||
</VaCardContent>
|
||||
</VaCard>
|
||||
</div>
|
||||
<VaCard v-else color="warning" class="mt-4"
|
||||
><VaCardTitle>Quests not revealed yet!</VaCardTitle>
|
||||
<VaCardContent
|
||||
>Soon all {{ data._count.quests }} quests will be
|
||||
revealed!</VaCardContent
|
||||
>
|
||||
</VaCard>
|
||||
</div>
|
||||
|
||||
<div v-if="error">
|
||||
<h1 class="mt-8 text-3xl">{{ $t(parseError(error)) }}</h1>
|
||||
<VaButton icon="arrow_back" :to="$localePath(`/`)">Back home</VaButton>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
+16
-3
@@ -7,12 +7,14 @@ watch(loggedIn, () => refresh());
|
||||
|
||||
<template>
|
||||
<h1 class="text-primary text-3xl">{{ $t('hello') }}</h1>
|
||||
<VaButton icon="refresh" @click="refresh" :disabled="pending" />
|
||||
<VaButton icon="refresh" @click="refresh" :disabled="pending">{{
|
||||
$t('layouts.refresh')
|
||||
}}</VaButton>
|
||||
|
||||
<div v-if="data">
|
||||
<div v-if="data.own !== null">
|
||||
<h2 class="my-4 text-2xl font-bold">Joined hunts:</h2>
|
||||
<div class="lg-grid-cols-3 grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3">
|
||||
<VaCard
|
||||
v-for="hunt in data.own"
|
||||
:key="hunt.id"
|
||||
@@ -20,6 +22,12 @@ watch(loggedIn, () => refresh());
|
||||
:to="$localePath(`/hunt/${sluggy(hunt)}`)"
|
||||
>
|
||||
<VaCardTitle>{{ hunt.name }}</VaCardTitle>
|
||||
|
||||
<ClickableImage
|
||||
v-if="hunt.picture"
|
||||
:src="hunt.picture?.url"
|
||||
:title="hunt.name"
|
||||
/>
|
||||
<VaCardContent>
|
||||
<h3 class="text-xl">{{ hunt.name }}</h3>
|
||||
{{ hunt.description }}
|
||||
@@ -62,13 +70,18 @@ watch(loggedIn, () => refresh());
|
||||
<div class="mt-8">
|
||||
<VaDivider />
|
||||
<h2 class="my-4 text-2xl font-bold">Open to join hunts:</h2>
|
||||
<div class="lg-grid-cols-3 grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3">
|
||||
<VaCard
|
||||
v-for="hunt in data.others"
|
||||
:key="hunt.id"
|
||||
:to="$localePath(`/hunt/${sluggy(hunt)}`)"
|
||||
>
|
||||
<VaCardTitle>{{ hunt.name }}</VaCardTitle>
|
||||
<ClickableImage
|
||||
v-if="hunt.picture"
|
||||
:src="hunt.picture?.url"
|
||||
:title="hunt.name"
|
||||
/>
|
||||
<VaCardContent>
|
||||
<h3 class="text-xl">{{ hunt.name }}</h3>
|
||||
{{ hunt.description }}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
definePageMeta({
|
||||
middleware: ['auth']
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h1>profile</h1>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
Reference in New Issue
Block a user