172 lines
14 KiB
Vue
172 lines
14 KiB
Vue
<script setup lang="ts">
|
|
import { Toaster } from '#shared/components.util';
|
|
|
|
definePageMeta({
|
|
guestsGoesTo: '/user/login',
|
|
});
|
|
|
|
const { user, loggedIn } = useUserSession();
|
|
const { data: campaigns, error, status } = await useFetch(`/api/campaign`);
|
|
const archives = computed(() => campaigns.value?.filter(e => e.status === 'ARCHIVED'));
|
|
const valids = computed(() => campaigns.value?.filter(e => e.status !== 'ARCHIVED'));
|
|
|
|
async function leaveCampaign(id: number)
|
|
{
|
|
try
|
|
{
|
|
await useRequestFetch()(`/api/campaign/${id}/leave`, { method: 'POST', });
|
|
campaigns.value = campaigns.value?.filter(e => e.id !== id);
|
|
}
|
|
catch(e)
|
|
{
|
|
Toaster.add({ duration: 10000, content: (e as Error).message ?? e, title: 'Une erreur est survenue.', type: 'error', timer: true, });
|
|
}
|
|
}
|
|
async function removeCampaign(id: number)
|
|
{
|
|
try
|
|
{
|
|
await useRequestFetch()(`/api/campaign/${id}`, { method: 'DELETE', });
|
|
campaigns.value = campaigns.value?.filter(e => e.id !== id);
|
|
}
|
|
catch(e)
|
|
{
|
|
Toaster.add({ duration: 10000, content: (e as Error).message ?? e, title: 'Une erreur est survenue.', type: 'error', timer: true, });
|
|
}
|
|
}
|
|
function create()
|
|
{
|
|
useRequestFetch()('/api/campaign', {
|
|
method: 'POST',
|
|
body: { name: 'Margooning', public_notes: '', dm_notes: '', settings: {} },
|
|
}).then(() => Toaster.add({ duration: 8000, content: 'Campagne créée', type: 'info' })).catch((e) => Toaster.add({ duration: 8000, title: 'Une erreur est survenue', content: e, type: 'error' }))
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<Head>
|
|
<Title>d[any] - Mes campagnes</Title>
|
|
</Head>
|
|
<div class="flex flex-col">
|
|
<div v-if="status === 'pending'" class="flex flex-1 justify-center align-center">
|
|
<Loading size="large" />
|
|
</div>
|
|
<template v-else-if="status === 'success' && loggedIn && user">
|
|
<div class="flex flex-row items-center w-full"><Button @click="() => create()">Nouvelle campagne</Button></div>
|
|
<div v-if="campaigns && campaigns.length > 0" class="flex flex-col gap-4">
|
|
<div v-if="valids && valids.length > 0" class="grid p-6 2xl:grid-cols-3 lg:grid-cols-2 grid-cols-1 gap-4 w-full">
|
|
<div class="flex flex-col w-[360px] border border-light-35 dark:border-dark-35" v-for="campaign of valids">
|
|
<NuxtLink :to="{ name: 'campaign-id', params: { id: campaign.id } }" class="group bg-light-10 dark:bg-dark-10 border-b border-light-35 dark:border-dark-35 p-2 flex flex-col gap-2">
|
|
<div class="flex flex-row gap-8 ps-4 items-center">
|
|
<div class="flex flex-1 flex-col gap-2 justify-center">
|
|
<span class="text-lg font-bold group-hover:text-accent-blue">{{ campaign.name }}</span>
|
|
<span class="border-b w-full border-light-50 dark:border-dark-50"></span>
|
|
<div class="flex flex-row flex-1 items-stretch gap-4">
|
|
<span class="text-sm">{{ campaign.members.length }} joueur{{ campaign.members.length === 1 ? '' : 's' }}</span>
|
|
</div>
|
|
</div>
|
|
<div class="rounded-full w-[96px] h-[96px] border border-light-50 dark:border-dark-50 bg-light-100 dark:bg-dark-100 !bg-opacity-10"></div>
|
|
</div>
|
|
</NuxtLink>
|
|
<div class="flex justify-around items-center py-2 px-4 gap-4">
|
|
<AlertDialogRoot>
|
|
<AlertDialogTrigger>
|
|
<span class="text-sm font-bold text-light-red dark:text-dark-red">{{ user.id !== campaign.owner.id ? 'Quitter' : 'Supprimer' }}</span>
|
|
</AlertDialogTrigger>
|
|
<AlertDialogPortal>
|
|
<AlertDialogOverlay class="bg-light-0 dark:bg-dark-0 opacity-70 fixed inset-0 z-40" />
|
|
<AlertDialogContent
|
|
class="data-[state=open]:animate-contentShow fixed top-[50%] left-[50%] max-h-[85vh] w-[90vw] max-w-[800px] translate-x-[-50%] translate-y-[-50%] bg-light-10 dark:bg-dark-10 border border-light-30 dark:border-dark-30 p-6 z-50 text-light-100 dark:text-dark-100">
|
|
<AlertDialogTitle class="text-3xl font-light relative -top-2">Vous vous appretez à {{ user.id !== campaign.owner.id ? 'quitter' : 'supprimer' }} "{{ campaign.name }}". Etes vous sûr ?</AlertDialogTitle>
|
|
<div class="flex flex-1 justify-end gap-4">
|
|
<AlertDialogCancel asChild><Button>Non</Button></AlertDialogCancel>
|
|
<AlertDialogAction asChild><Button @click="() => user?.id !== campaign.owner.id ? leaveCampaign(campaign.id) : removeCampaign(campaign.id)" class="border-light-red dark:border-dark-red hover:border-light-red dark:hover:border-dark-red hover:bg-light-redBack dark:hover:bg-dark-redBack text-light-red dark:text-dark-red focus:shadow-light-red dark:focus:shadow-dark-red">Oui</Button></AlertDialogAction>
|
|
</div>
|
|
</AlertDialogContent>
|
|
</AlertDialogPortal>
|
|
</AlertDialogRoot>
|
|
</div>
|
|
</div>
|
|
<div class="flex flex-col w-[360px] border border-light-35 dark:border-dark-35" v-for="campaign of campaigns.filter(e => e.status === 'ARCHIVED')">
|
|
<NuxtLink :to="{ name: 'campaign-id', params: { id: campaign.id } }" class="group bg-light-10 dark:bg-dark-10 border-b border-light-35 dark:border-dark-35 p-2 flex flex-col gap-2">
|
|
<div class="flex flex-row gap-8 ps-4 items-center">
|
|
<div class="flex flex-1 flex-col gap-2 justify-center">
|
|
<span class="text-lg font-bold group-hover:text-accent-blue">{{ campaign.name }}</span>
|
|
<span class="border-b w-full border-light-50 dark:border-dark-50"></span>
|
|
<div class="flex flex-row flex-1 items-stretch gap-4">
|
|
<span class="text-sm">{{ campaign.members.length }} joueur{{ campaign.members.length === 1 ? '' : 's' }}</span>
|
|
</div>
|
|
</div>
|
|
<div class="rounded-full w-[96px] h-[96px] border border-light-50 dark:border-dark-50 bg-light-100 dark:bg-dark-100 !bg-opacity-10"></div>
|
|
</div>
|
|
</NuxtLink>
|
|
</div>
|
|
</div>
|
|
<div v-if="archives && archives.length > 0" class="flex flex-row w-full gap-8 justify-center items-center"><span class="border-t border-light-35 dark:border-dark-35 flex-1"></span><span class="text-lg font-semibold">Archives</span><span class="border-t border-light-35 dark:border-dark-35 flex-1"></span></div>
|
|
<div v-if="archives && archives.length > 0" class="grid p-6 2xl:grid-cols-3 lg:grid-cols-2 grid-cols-1 gap-4 w-full">
|
|
<div class="flex flex-col w-[360px] border border-light-35 dark:border-dark-35" v-for="campaign of archives">
|
|
<NuxtLink :to="{ name: 'campaign-id', params: { id: campaign.id } }" class="group bg-light-10 dark:bg-dark-10 border-b border-light-35 dark:border-dark-35 p-2 flex flex-col gap-2">
|
|
<div class="flex flex-row gap-8 ps-4 items-center">
|
|
<div class="flex flex-1 flex-col gap-2 justify-center">
|
|
<span class="text-lg font-bold group-hover:text-accent-blue">{{ campaign.name }}</span>
|
|
<span class="border-b w-full border-light-50 dark:border-dark-50"></span>
|
|
<div class="flex flex-row flex-1 items-stretch gap-4">
|
|
<span class="text-sm">{{ campaign.members.length }} joueur{{ campaign.members.length === 1 ? '' : 's' }}</span>
|
|
</div>
|
|
</div>
|
|
<div class="rounded-full w-[96px] h-[96px] border border-light-50 dark:border-dark-50 bg-light-100 dark:bg-dark-100 !bg-opacity-10"></div>
|
|
</div>
|
|
</NuxtLink>
|
|
<div class="flex justify-around items-center py-2 px-4 gap-4">
|
|
<AlertDialogRoot>
|
|
<AlertDialogTrigger>
|
|
<span class="text-sm font-bold text-light-red dark:text-dark-red">{{ user.id !== campaign.owner.id ? 'Quitter' : 'Supprimer' }}</span>
|
|
</AlertDialogTrigger>
|
|
<AlertDialogPortal>
|
|
<AlertDialogOverlay class="bg-light-0 dark:bg-dark-0 opacity-70 fixed inset-0 z-40" />
|
|
<AlertDialogContent
|
|
class="data-[state=open]:animate-contentShow fixed top-[50%] left-[50%] max-h-[85vh] w-[90vw] max-w-[800px] translate-x-[-50%] translate-y-[-50%] bg-light-10 dark:bg-dark-10 border border-light-30 dark:border-dark-30 p-6 z-50 text-light-100 dark:text-dark-100">
|
|
<AlertDialogTitle class="text-3xl font-light relative -top-2">Vous vous appretez à {{ user.id !== campaign.owner.id ? 'quitter' : 'supprimer' }} "{{ campaign.name }}". Etes vous sûr ?</AlertDialogTitle>
|
|
<div class="flex flex-1 justify-end gap-4">
|
|
<AlertDialogCancel asChild><Button>Non</Button></AlertDialogCancel>
|
|
<AlertDialogAction asChild><Button @click="() => user?.id !== campaign.owner.id ? leaveCampaign(campaign.id) : removeCampaign(campaign.id)" class="border-light-red dark:border-dark-red hover:border-light-red dark:hover:border-dark-red hover:bg-light-redBack dark:hover:bg-dark-redBack text-light-red dark:text-dark-red focus:shadow-light-red dark:focus:shadow-dark-red">Oui</Button></AlertDialogAction>
|
|
</div>
|
|
</AlertDialogContent>
|
|
</AlertDialogPortal>
|
|
</AlertDialogRoot>
|
|
</div>
|
|
</div>
|
|
<div class="flex flex-col w-[360px] border border-light-35 dark:border-dark-35" v-for="campaign of campaigns.filter(e => e.status === 'ARCHIVED')">
|
|
<NuxtLink :to="{ name: 'campaign-id', params: { id: campaign.id } }" class="group bg-light-10 dark:bg-dark-10 border-b border-light-35 dark:border-dark-35 p-2 flex flex-col gap-2">
|
|
<div class="flex flex-row gap-8 ps-4 items-center">
|
|
<div class="flex flex-1 flex-col gap-2 justify-center">
|
|
<span class="text-lg font-bold group-hover:text-accent-blue">{{ campaign.name }}</span>
|
|
<span class="border-b w-full border-light-50 dark:border-dark-50"></span>
|
|
<div class="flex flex-row flex-1 items-stretch gap-4">
|
|
<span class="text-sm">{{ campaign.members.length }} joueur{{ campaign.members.length === 1 ? '' : 's' }}</span>
|
|
</div>
|
|
</div>
|
|
<div class="rounded-full w-[96px] h-[96px] border border-light-50 dark:border-dark-50 bg-light-100 dark:bg-dark-100 !bg-opacity-10"></div>
|
|
</div>
|
|
</NuxtLink>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div v-else class="flex flex-col gap-2 items-center flex-1">
|
|
<span class="text-lg font-bold">Vous n'avez pas encore rejoint de campagne</span>
|
|
<div class="inline-flex justify-center items-center outline-none leading-none transition-[box-shadow]
|
|
text-light-100 dark:text-dark-100 bg-light-20 dark:bg-dark-20 border border-light-40 dark:border-dark-40
|
|
hover:bg-light-25 dark:hover:bg-dark-25 hover:border-light-50 dark:hover:border-dark-50
|
|
focus:bg-light-30 dark:focus:bg-dark-30 focus:border-light-50 dark:focus:border-dark-50 focus:shadow-raw focus:shadow-light-50 dark:focus:shadow-dark-50 py-2 px-4" @click="create">Créer ma campagne</div>
|
|
<!-- <NuxtLink class="inline-flex justify-center items-center outline-none leading-none transition-[box-shadow]
|
|
text-light-100 dark:text-dark-100 bg-light-20 dark:bg-dark-20 border border-light-40 dark:border-dark-40
|
|
hover:bg-light-25 dark:hover:bg-dark-25 hover:border-light-50 dark:hover:border-dark-50
|
|
focus:bg-light-30 dark:focus:bg-dark-30 focus:border-light-50 dark:focus:border-dark-50 focus:shadow-raw focus:shadow-light-50 dark:focus:shadow-dark-50 py-2 px-4" :to="{ name: 'campaign-id-edit', params: { id: 'new' } }">Créer ma campagne</NuxtLink> -->
|
|
</div>
|
|
</template>
|
|
<div v-else>
|
|
<span>Erreur de chargement</span>
|
|
<span>{{ error?.message }}</span>
|
|
</div>
|
|
</div>
|
|
</template> |