79 lines
4.4 KiB
Vue
79 lines
4.4 KiB
Vue
<script setup lang="ts">
|
|
import { Icon } from '@iconify/vue';
|
|
import { unifySlug } from '#shared/general.util';
|
|
|
|
definePageMeta({
|
|
guestsGoesTo: '/user/login',
|
|
});
|
|
|
|
const id = unifySlug(useRoute().params.id ?? '');
|
|
const { user, loggedIn } = useUserSession();
|
|
const { data: campaign, error, status } = await useFetch(`/api/campaign/${id}`);
|
|
const copied = ref(false);
|
|
const stopCopy = useDebounceFn(() => copied.value = false, 5000);
|
|
|
|
const websocket = useWebSocket(`wss://localhost:3000/ws/campaign/${id}`, { heartbeat: true });
|
|
|
|
async function copyLink()
|
|
{
|
|
await navigator.clipboard.writeText(`https://d-any.com/campaign/join/${ encodeURIComponent(campaign.value!.link) }`);
|
|
copied.value = true;
|
|
stopCopy();
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div v-if="status === 'pending'" class="flex flex-col items-center justify-center w-full h-full">
|
|
<Loading />
|
|
</div>
|
|
<div class="flex flex-col w-full h-full items-center gap-4" v-else-if="campaign && status === 'success'">
|
|
<div class="flex flex-row gap-8 items-center">
|
|
<div class="flex flex-row gap-8 items-baseline">
|
|
<span class="text-2xl font-semibold">{{ campaign.name }}</span>
|
|
<span class="italic">MJ: {{ campaign.owner.username }}</span>
|
|
</div>
|
|
<div class="border border-light-35 dark:border-dark-35 p-1 flex flex-row items-center gap-2">
|
|
<pre class="ps-1 w-[400px] truncate">https://d-any.com/campaign/join/{{ encodeURIComponent(campaign.link) }}</pre>
|
|
<div class="cursor-pointer border border-light-35 dark:border-dark-35 hover:bg-light-30 dark:hover:bg-dark-30 hover:border-light-50 dark:hover:border-dark-50 p-1" @click="copyLink">
|
|
<Icon v-if="!copied" icon="radix-icons:clipboard" class="w-4 h-4"/>
|
|
<Icon v-else icon="radix-icons:check" class="w-4 h-4"/>
|
|
</div>
|
|
</div>
|
|
<div class="cursor-pointer border border-light-35 dark:border-dark-35 hover:bg-light-30 dark:hover:bg-dark-30 hover:border-light-50 dark:hover:border-dark-50 p-1" @click="() => websocket.open()">{{ websocket.status }}</div>
|
|
</div>
|
|
<div class="flex flex-row gap-4 flex-1">
|
|
<div class="flex flex-col">
|
|
<div class="flex flex-row items-center gap-4"><span class="text-lg font-bold tracking-tight">Joueurs</span><span class="border-b border-dashed border-light-35 dark:border-dark-35 w-full"></span></div>
|
|
<div class="flex flex-col divide-y divide-light-25 dark:divide-dark-25 w-64">
|
|
<template v-if="campaign.members.length > 0">
|
|
<div v-for="player of campaign.members" class="flex flex-col py-1 my-1">
|
|
<div class="flex flex-row items-center justify-between">
|
|
<span>{{ player.member?.username }}</span>
|
|
<Tooltip message="Absent" side="right" :delay="0"><span class="rounded-full w-3 h-3 block border-light-50 dark:border-dark-50 border-2 border-dashed"></span></Tooltip>
|
|
</div>
|
|
<template v-if="player.characters.length > 0">
|
|
<div class="flex flex-col border-l-2 border-light-35 dark:border-dark-35 ps-2">
|
|
<div class="flex flex-row items-center justify-between" v-for="character of player.characters">
|
|
<span>{{ character.character.name }}</span>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<template v-else>
|
|
<span class="text-sm italic text-light-70 dark:text-dark-70">Sans personnage</span>
|
|
</template>
|
|
</div>
|
|
</template>
|
|
<template v-else>
|
|
<span class="text-sm italic py-2 text-center">Invitez des joueurs via le lien d'invitation</span>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
<div class="border-l border-light-35 dark:border-dark-35"></div>
|
|
<div class="flex flex-col divide-y divide-light-25 dark:divide-dark-25 w-[800px]">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="flex flex-col" v-else-if="status === 'error'">
|
|
|
|
</div>
|
|
</template> |