feat: Implement group management features with dialogs for editing and displaying group results, enhance event creation with a form, and update team and referee management UI
All checks were successful
SteamWarCI Build successful
All checks were successful
SteamWarCI Build successful
This commit is contained in:
@@ -20,12 +20,136 @@
|
||||
<script lang="ts">
|
||||
import { eventRepo } from "@repo/event.ts";
|
||||
import EventCard from "@components/moderator/components/EventCard.svelte";
|
||||
import { Button } from "@components/ui/button/index.js";
|
||||
import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@components/ui/dialog/index.js";
|
||||
import { Input } from "@components/ui/input/index.js";
|
||||
import { Label } from "@components/ui/label/index.js";
|
||||
import DateTimePicker from "@components/ui/datetime-picker/DateTimePicker.svelte";
|
||||
import { PlusIcon } from "lucide-svelte";
|
||||
import dayjs from "dayjs";
|
||||
import { fromAbsolute, now, ZonedDateTime } from "@internationalized/date";
|
||||
|
||||
let eventsFuture = $state($eventRepo.listEvents());
|
||||
let millis = Date.now();
|
||||
|
||||
let createOpen = $state(false);
|
||||
let newEventName = $state("");
|
||||
let newEventStart: ZonedDateTime = $state(now("Europe/Berlin"));
|
||||
let newEventEnd: ZonedDateTime = $state(
|
||||
now("Europe/Berlin").add({
|
||||
days: 1,
|
||||
})
|
||||
);
|
||||
let isSubmitting = $state(false);
|
||||
let errorMsg = $state("");
|
||||
|
||||
function resetFormFields() {
|
||||
newEventName = "";
|
||||
newEventStart = now("Europe/Berlin");
|
||||
newEventEnd = now("Europe/Berlin").add({
|
||||
days: 1,
|
||||
});
|
||||
errorMsg = "";
|
||||
isSubmitting = false;
|
||||
}
|
||||
|
||||
$effect(() => {
|
||||
if (createOpen) {
|
||||
resetFormFields();
|
||||
}
|
||||
});
|
||||
|
||||
const canSubmit = $derived(
|
||||
newEventName.trim() !== "" &&
|
||||
newEventStart &&
|
||||
newEventEnd &&
|
||||
dayjs(newEventStart.toDate()).isValid() &&
|
||||
dayjs(newEventEnd.toDate()).isValid() &&
|
||||
newEventStart.toDate() < newEventEnd.toDate() &&
|
||||
!isSubmitting
|
||||
);
|
||||
|
||||
async function submitCreateEvent() {
|
||||
if (!canSubmit) return;
|
||||
|
||||
isSubmitting = true;
|
||||
errorMsg = "";
|
||||
|
||||
const payload = {
|
||||
name: newEventName.trim(),
|
||||
start: dayjs(newEventStart.toDate()),
|
||||
end: dayjs(newEventEnd.toDate()),
|
||||
};
|
||||
|
||||
try {
|
||||
await $eventRepo.createEvent(payload);
|
||||
eventsFuture = $eventRepo.listEvents(); // Refresh the list
|
||||
createOpen = false;
|
||||
} catch (e: any) {
|
||||
errorMsg = e.message || "Failed to create event. Please try again.";
|
||||
console.error("Failed to create event:", e);
|
||||
} finally {
|
||||
isSubmitting = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="p-4">
|
||||
<div class="flex justify-between items-center mb-6">
|
||||
<h1 class="text-3xl font-semibold">Events</h1>
|
||||
<Dialog bind:open={createOpen}>
|
||||
<DialogTrigger>
|
||||
{#snippet child({ props })}
|
||||
<Button variant="outline" {...props}>
|
||||
<PlusIcon class="mr-2" />
|
||||
Create Event
|
||||
</Button>
|
||||
{/snippet}
|
||||
</DialogTrigger>
|
||||
<DialogContent class="sm:max-w-[425px]">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Create New Event</DialogTitle>
|
||||
<DialogDescription>Fill in the details for the new event. Click create when you're done.</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div class="grid gap-4 py-4">
|
||||
<div class="grid grid-cols-4 items-center gap-4">
|
||||
<Label for="eventName" class="text-right">Name</Label>
|
||||
<Input id="eventName" bind:value={newEventName} class="col-span-3" placeholder="Event Name" />
|
||||
</div>
|
||||
<div class="grid grid-cols-4 items-center gap-4">
|
||||
<Label for="eventStart" class="text-right">Start</Label>
|
||||
<div class="col-span-3">
|
||||
<DateTimePicker bind:value={newEventStart} />
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-cols-4 items-center gap-4">
|
||||
<Label for="eventEnd" class="text-right">End</Label>
|
||||
<div class="col-span-3">
|
||||
<DateTimePicker bind:value={newEventEnd} />
|
||||
</div>
|
||||
</div>
|
||||
{#if errorMsg}
|
||||
<p class="col-span-4 text-sm text-red-600 dark:text-red-500 text-center">{errorMsg}</p>
|
||||
{/if}
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<DialogClose>
|
||||
{#snippet child({ props })}
|
||||
<Button variant="outline" {...props}>Cancel</Button>
|
||||
{/snippet}
|
||||
</DialogClose>
|
||||
<Button onclick={submitCreateEvent} disabled={!canSubmit}>
|
||||
{#if isSubmitting}
|
||||
Creating...
|
||||
{:else}
|
||||
Create Event
|
||||
{/if}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</div>
|
||||
|
||||
{#await eventsFuture}
|
||||
<p>Loading...</p>
|
||||
{:then events}
|
||||
@@ -45,7 +169,5 @@
|
||||
</a>
|
||||
{/each}
|
||||
</div>
|
||||
{:catch e}
|
||||
|
||||
{/await}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user