mirror of
https://github.com/ericasch6/scrum-poker-internal.git
synced 2026-10-13 22:52:09 +00:00
144 lines
4.8 KiB
Vue
144 lines
4.8 KiB
Vue
<script setup lang="ts">
|
|
import { Link, useHttp } from '@inertiajs/vue3';
|
|
import { Check, Copy } from '@lucide/vue';
|
|
import { ref, watch } from 'vue';
|
|
|
|
import { Checkbox } from '@/components/ui/checkbox';
|
|
import { favorite } from '@/routes/room';
|
|
import { update as updatePermissions } from '@/routes/room/permissions';
|
|
import type { RoomHeaderEmits, RoomHeaderProps } from '@/types/room';
|
|
|
|
const props = defineProps<RoomHeaderProps>();
|
|
const emit = defineEmits<RoomHeaderEmits>();
|
|
|
|
const copied = ref(false);
|
|
const allowParticipantControls = ref(props.allowParticipantControls);
|
|
const permissionRequest = useHttp(() => updatePermissions(props.id), {
|
|
allow_participant_controls: props.allowParticipantControls,
|
|
});
|
|
|
|
watch(
|
|
() => props.allowParticipantControls,
|
|
(value) => {
|
|
allowParticipantControls.value = value;
|
|
|
|
if (!permissionRequest.processing) {
|
|
permissionRequest.allow_participant_controls = value;
|
|
}
|
|
},
|
|
);
|
|
|
|
async function copyInviteLink(): Promise<void> {
|
|
const inviteUrl = new URL('/room/join', window.location.origin);
|
|
inviteUrl.searchParams.set('join_code', props.join_code);
|
|
|
|
await navigator.clipboard.writeText(inviteUrl.toString());
|
|
copied.value = true;
|
|
window.setTimeout(() => {
|
|
copied.value = false;
|
|
}, 1_800);
|
|
}
|
|
|
|
function updateParticipantControls(value: boolean): void {
|
|
if (permissionRequest.processing) {
|
|
return;
|
|
}
|
|
|
|
const previousValue = allowParticipantControls.value;
|
|
|
|
allowParticipantControls.value = value;
|
|
permissionRequest.allow_participant_controls = value;
|
|
|
|
void permissionRequest.submit({
|
|
onError: () => {
|
|
allowParticipantControls.value = previousValue;
|
|
permissionRequest.allow_participant_controls = previousValue;
|
|
},
|
|
});
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<header
|
|
class="mx-auto flex w-full max-w-6xl flex-col gap-4 sm:flex-row sm:items-center sm:justify-between"
|
|
>
|
|
<div>
|
|
<h1 class="text-2xl font-bold sm:text-3xl">
|
|
{{ title ?? 'Scrum Poker' }}
|
|
</h1>
|
|
|
|
<Link
|
|
v-if="canFavorite"
|
|
:href="favorite(id)"
|
|
method="post"
|
|
as="button"
|
|
class="mt-2 inline-flex items-center gap-2"
|
|
>
|
|
<span>Favorit</span>
|
|
<span class="material-icons" aria-hidden="true">
|
|
{{ is_favorite ? 'favorite' : 'favorite_border' }}
|
|
</span>
|
|
</Link>
|
|
</div>
|
|
|
|
<div class="flex flex-col items-end gap-2">
|
|
<button
|
|
type="button"
|
|
class="flex w-fit items-center gap-3 rounded-xl border border-slate-700 bg-slate-800 px-4 py-2.5 text-left transition hover:bg-slate-700 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-cyan-300"
|
|
@click="copyInviteLink"
|
|
>
|
|
<span>
|
|
<span
|
|
class="block text-sm tracking-[0.18em] text-slate-400"
|
|
>
|
|
Raumcode
|
|
</span>
|
|
<strong class="font-mono text-lg tracking-[0.2em]">
|
|
{{ join_code }}
|
|
</strong>
|
|
</span>
|
|
<Check v-if="copied" class="size-5 text-emerald-300" />
|
|
<Copy v-else class="size-5 text-slate-300" />
|
|
</button>
|
|
|
|
<label
|
|
v-if="isModerator"
|
|
for="participant-controls"
|
|
class="flex cursor-pointer items-center gap-2 text-sm text-slate-300"
|
|
>
|
|
<Checkbox
|
|
id="participant-controls"
|
|
:model-value="allowParticipantControls"
|
|
:disabled="permissionRequest.processing"
|
|
@update:model-value="
|
|
updateParticipantControls($event === true)
|
|
"
|
|
/>
|
|
<span>Alle dürfen die Runde steuern</span>
|
|
</label>
|
|
|
|
<p
|
|
v-if="permissionRequest.errors.allow_participant_controls"
|
|
class="max-w-xs text-right text-sm text-rose-300"
|
|
role="alert"
|
|
>
|
|
{{ permissionRequest.errors.allow_participant_controls }}
|
|
</p>
|
|
|
|
<label
|
|
for="presenter-mode"
|
|
class="flex cursor-pointer items-center gap-2 text-sm text-slate-300"
|
|
>
|
|
<Checkbox
|
|
id="presenter-mode"
|
|
:model-value="presenterMode"
|
|
@update:model-value="
|
|
emit('update:presenterMode', $event === true)
|
|
"
|
|
/>
|
|
<span>Präsentatormodus</span>
|
|
</label>
|
|
</div>
|
|
</header>
|
|
</template>
|