mirror of
https://github.com/ericasch6/scrum-poker-internal.git
synced 2026-10-15 13:26:10 +00:00
feat: some fixes to the ui, imlemented user and guest user, ans used the dahboard
This commit is contained in:
@@ -1,47 +1,238 @@
|
||||
<script setup lang="ts">
|
||||
import { Head } from '@inertiajs/vue3';
|
||||
import PlaceholderPattern from '@/components/PlaceholderPattern.vue';
|
||||
import { Head, Link, useForm } from '@inertiajs/vue3';
|
||||
import { CalendarClock, DoorOpen, Plus, Trash2, Users } from '@lucide/vue';
|
||||
import { ref } from 'vue';
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from '@/components/ui/dialog';
|
||||
import { dashboard } from '@/routes';
|
||||
import { create, destroy, reopen, show } from '@/routes/room';
|
||||
|
||||
type OwnedRoom = {
|
||||
id: string;
|
||||
title: string | null;
|
||||
join_code: string;
|
||||
current_round: number;
|
||||
players_count: number;
|
||||
last_activity_at: string | null;
|
||||
closed_at: string | null;
|
||||
};
|
||||
|
||||
defineOptions({
|
||||
layout: {
|
||||
breadcrumbs: [
|
||||
{
|
||||
title: 'Dashboard',
|
||||
title: 'Meine Räume',
|
||||
href: dashboard(),
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
defineProps<{
|
||||
rooms: OwnedRoom[];
|
||||
}>();
|
||||
|
||||
const selectedRoom = ref<OwnedRoom | null>(null);
|
||||
const deleteForm = useForm({});
|
||||
|
||||
const dateFormatter = new Intl.DateTimeFormat('de-DE', {
|
||||
dateStyle: 'medium',
|
||||
timeStyle: 'short',
|
||||
});
|
||||
|
||||
function formatDate(value: string | null): string {
|
||||
return value ? dateFormatter.format(new Date(value)) : 'Keine Aktivität';
|
||||
}
|
||||
|
||||
function setDeleteDialogOpen(open: boolean): void {
|
||||
if (!open && !deleteForm.processing) {
|
||||
selectedRoom.value = null;
|
||||
}
|
||||
}
|
||||
|
||||
function deleteRoom(): void {
|
||||
if (selectedRoom.value === null || deleteForm.processing) {
|
||||
return;
|
||||
}
|
||||
|
||||
deleteForm.delete(destroy(selectedRoom.value.id).url, {
|
||||
preserveScroll: true,
|
||||
onSuccess: () => {
|
||||
selectedRoom.value = null;
|
||||
},
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Head title="Dashboard" />
|
||||
<Head title="Meine Räume" />
|
||||
|
||||
<div
|
||||
class="flex h-full flex-1 flex-col gap-4 overflow-x-auto rounded-xl p-4"
|
||||
class="flex min-h-[calc(100svh-4rem)] flex-1 flex-col gap-6 overflow-x-auto bg-slate-900 p-4 text-slate-100"
|
||||
>
|
||||
<div class="grid auto-rows-min gap-4 md:grid-cols-3">
|
||||
<div
|
||||
class="relative aspect-video overflow-hidden rounded-xl border border-sidebar-border/70 dark:border-sidebar-border"
|
||||
>
|
||||
<PlaceholderPattern />
|
||||
</div>
|
||||
<div
|
||||
class="relative aspect-video overflow-hidden rounded-xl border border-sidebar-border/70 dark:border-sidebar-border"
|
||||
>
|
||||
<PlaceholderPattern />
|
||||
</div>
|
||||
<div
|
||||
class="relative aspect-video overflow-hidden rounded-xl border border-sidebar-border/70 dark:border-sidebar-border"
|
||||
>
|
||||
<PlaceholderPattern />
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="relative min-h-[100vh] flex-1 rounded-xl border border-sidebar-border/70 md:min-h-min dark:border-sidebar-border"
|
||||
class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between"
|
||||
>
|
||||
<PlaceholderPattern />
|
||||
<div>
|
||||
<h1 class="text-2xl font-bold tracking-tight">Meine Räume</h1>
|
||||
<p class="mt-1 text-sm text-muted-foreground">
|
||||
Deine erstellten Scrum-Poker-Räume auf einen Blick.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Link
|
||||
:href="create()"
|
||||
class="inline-flex w-fit items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-semibold text-primary-foreground transition hover:bg-primary/90"
|
||||
>
|
||||
<Plus class="size-4" />
|
||||
Raum erstellen
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="rooms.length > 0"
|
||||
class="grid gap-4 md:grid-cols-2 xl:grid-cols-3"
|
||||
>
|
||||
<article
|
||||
v-for="room in rooms"
|
||||
:key="room.id"
|
||||
class="flex flex-col rounded-md border border-slate-700 bg-slate-800 p-5 text-slate-100"
|
||||
>
|
||||
<div class="flex items-start justify-between gap-4">
|
||||
<div class="min-w-0">
|
||||
<h2 class="text-lg font-semibold break-words">
|
||||
{{ room.title ?? 'Scrum Poker' }}
|
||||
</h2>
|
||||
<p
|
||||
class="mt-1 font-mono text-sm tracking-[0.18em] text-muted-foreground"
|
||||
>
|
||||
{{ room.join_code }}
|
||||
</p>
|
||||
</div>
|
||||
<span
|
||||
class="shrink-0 text-sm font-semibold normal-case"
|
||||
:class="
|
||||
room.closed_at
|
||||
? 'text-muted-foreground'
|
||||
: 'text-emerald-600 dark:text-emerald-400'
|
||||
"
|
||||
>
|
||||
{{ room.closed_at ? 'Geschlossen' : 'Aktiv' }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="mt-5 grid grid-cols-2 gap-3 text-sm text-muted-foreground"
|
||||
>
|
||||
<span class="inline-flex items-center gap-2">
|
||||
<Users class="size-4" />
|
||||
{{ room.players_count }} Spieler
|
||||
</span>
|
||||
<span>Runde {{ room.current_round }}</span>
|
||||
<span class="col-span-2 inline-flex items-center gap-2">
|
||||
<CalendarClock class="size-4" />
|
||||
{{ formatDate(room.last_activity_at) }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="mt-6 flex flex-wrap items-center gap-3">
|
||||
<Link
|
||||
v-if="!room.closed_at"
|
||||
:href="show(room.id)"
|
||||
class="inline-flex items-center gap-2 rounded-md px-3 py-2 text-sm font-semibold transition hover:bg-blue-500/80"
|
||||
>
|
||||
<DoorOpen class="size-4" />
|
||||
Raum beitreten
|
||||
</Link>
|
||||
<Link
|
||||
v-else
|
||||
:href="reopen(room.id)"
|
||||
method="post"
|
||||
as="button"
|
||||
class="inline-flex items-center gap-2 rounded-md px-3 py-2 text-sm font-semibold text-primary-foreground transition hover:bg-primary/90"
|
||||
>
|
||||
<DoorOpen class="size-4" />
|
||||
Raum öffnen
|
||||
</Link>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="inline-flex items-center gap-2 rounded-md px-3 py-2 text-sm font-semibold text-rose-300 transition hover:bg-rose-500/80"
|
||||
@click="selectedRoom = room"
|
||||
>
|
||||
<Trash2 class="size-4" />
|
||||
Raum löschen
|
||||
</button>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-else
|
||||
class="grid min-h-72 place-items-center rounded-md border border-dashed border-sidebar-border p-8 text-center"
|
||||
>
|
||||
<div>
|
||||
<h2 class="text-lg font-semibold">Noch keine eigenen Räume</h2>
|
||||
<p class="mt-2 max-w-md text-sm text-muted-foreground">
|
||||
Erstelle deinen ersten Raum. Er wird automatisch in diesem
|
||||
Dashboard gespeichert.
|
||||
</p>
|
||||
<Link
|
||||
:href="create()"
|
||||
class="mt-5 inline-flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-semibold text-primary-foreground"
|
||||
>
|
||||
<Plus class="size-4" />
|
||||
Ersten Raum erstellen
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Dialog
|
||||
:open="selectedRoom !== null"
|
||||
@update:open="setDeleteDialogOpen"
|
||||
>
|
||||
<DialogContent
|
||||
class="border-slate-700 bg-slate-800 text-slate-100 sm:max-w-md"
|
||||
>
|
||||
<DialogHeader>
|
||||
<DialogTitle>Raum wirklich löschen?</DialogTitle>
|
||||
<DialogDescription class="text-slate-300">
|
||||
„{{ selectedRoom?.title ?? 'Scrum Poker' }}“ wird aus
|
||||
deinem Dashboard entfernt. Alle Spieler, die den Raum
|
||||
gerade geöffnet haben, werden automatisch
|
||||
hinausgeleitet.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<DialogFooter class="gap-6 space-x-4 sm:gap-0">
|
||||
<button
|
||||
type="button"
|
||||
class="rounded-md border border-slate-600 px-4 py-2 text-sm font-semibold text-slate-200 transition hover:bg-slate-700"
|
||||
:disabled="deleteForm.processing"
|
||||
@click="selectedRoom = null"
|
||||
>
|
||||
Abbrechen
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="rounded-md bg-rose-600 px-4 py-2 text-sm font-semibold text-white transition hover:bg-rose-500 disabled:opacity-50"
|
||||
:disabled="deleteForm.processing"
|
||||
@click="deleteRoom"
|
||||
>
|
||||
{{
|
||||
deleteForm.processing
|
||||
? 'Wird gelöscht …'
|
||||
: 'Raum löschen'
|
||||
}}
|
||||
</button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user