import { z } from "zod/v4"; import type { User } from "~/types/auth"; import type { Campaign } from "~/types/campaign"; import { div, dom, icon, span, text } from "#shared/dom.util"; import { button, loading } from "#shared/components.util"; import { CharacterCompiler } from "#shared/character.util"; import { tooltip } from "./floating.util"; export const CampaignValidation = z.object({ id: z.number(), name: z.string().nonempty(), description: z.string() }); /* const { data: campaign, error, status } = await useFetch(`/api/campaign/${id}`); const copied = ref(false); const stopCopy = useDebounceFn(() => copied.value = false, 5000); async function copyLink() { await navigator.clipboard.writeText(`https://d-any.com/campaign/join/${ encodeURIComponent(campaign.value!.link) }`); copied.value = true; stopCopy(); } */ type PlayerState = { status: boolean; statusDOM: HTMLElement; statusTooltip: Text; user: User; }; function defaultPlayerState(user: User): PlayerState { const statusTooltip = text('Absent'); return { status: false, statusDOM: tooltip(span('rounded-full w-3 h-3 block border-light-50 dark:border-dark-50 border-2 border-dashed'), statusTooltip, 'right'), statusTooltip, user } } export class CampaignSheet { user: ComputedRef; campaign?: Campaign; container: HTMLElement = div('flex flex-1 h-full w-full items-start justify-center'); dm!: PlayerState; constructor(id: string, user: ComputedRef) { this.user = user; const load = div("flex justify-center items-center w-full h-full", [ loading('large') ]); this.container.replaceChildren(load); useRequestFetch()(`/api/campaign/${id}`).then(campaign => { if(campaign) { this.campaign = campaign; this.dm = defaultPlayerState(campaign.owner); document.title = `d[any] - Campagne ${campaign.name}`; this.render(); load.remove(); } else throw new Error(); }).catch((e) => { console.error(e); this.container.replaceChildren(div('flex flex-col items-center justify-center flex-1 h-full gap-4', [ span('text-2xl font-bold tracking-wider', 'Campagne introuvable'), span(undefined, 'Cette campagne n\'existe pas ou est privé.'), div('flex flex-row gap-4 justify-center items-center', [ button(text('Mes campagnes'), () => useRouter().push({ name: 'campaign' }), 'px-2 py-1'), button(text('Créer une campagne'), () => useRouter().push({ name: 'campaign-create' }), 'px-2 py-1') ]) ])); }); } render() { this.container.replaceChildren(div('flex flex-col w-full h-full items-center gap-4', [ div('flex flex-row gap-8 items-center', [ div('text-2xl font-semibold', [text(this.campaign.name)]), div('border border-light-35 dark:border-dark-35 p-1 flex flex-row items-center gap-2', [ dom('pre', { class: 'ps-1 w-[400px] truncate' }, [ text(`https://d-any.com/campaign/join/${ encodeURIComponent(this.campaign.link) }`) ]), button(icon('radix-icons:clipboard', { width: 16, height: 16 })), ]) ]), div('flex flex-row gap-4 flex-1', [ div('flex flex-col w-64', [ div('flex flex-row items-center gap-4', [ span('text-lg font-bold tracking-tight flex-1', 'Maitre de jeu'), span('border-b border-dashed border-light-35 dark:border-dark-35 flex-1') ]), div('flex flex-col divide-y divide-light-25 dark:divide-dark-25', [ div('flex flex-col py-1 my-1', [ div('flex flex-row items-center justify-between', [ span(undefined, this.campaign.owner.username), this.dm.statusDOM, ]) ]) ]), div('flex flex-row items-center gap-4', [ span('text-lg font-bold tracking-tight', 'Joueurs'), span('border-b border-dashed border-light-35 dark:border-dark-35 flex-1') ]), div('flex flex-col divide-y divide-light-25 dark:divide-dark-25', this.campaign.members.length > 0 ? this.campaign.members.map((player: any) => div('flex flex-col py-1 my-1', [ div('flex flex-row items-center justify-between', [ span(undefined, player.member.username), undefined, ]), player.characters.length > 0 ? div('flex flex-col', player.characters.map((character: any) => div('flex flex-row items-center justify-between', [ span(undefined, 'joue'), span('text-bold', character.name) ])) ) : span('text-sm italic text-light-70 dark:text-dark-70', 'Pas de personnages'), ])) : span('text-sm italic py-2 text-center', 'Invitez des joueurs via le lien'), ) ]), div('border-l border-light-35 dark:border-dark-35'), div('flex flex-col divide-y divide-light-25 dark:divide-dark-25 w-[800px]') ]) ])); /*
Maitre de jeu
{{ campaign.owner.username }}
Joueurs
*/ } }