feat: Refactor event management components and introduce EventModel for better state handling
All checks were successful
SteamWarCI Build successful
All checks were successful
SteamWarCI Build successful
This commit is contained in:
@@ -18,8 +18,11 @@
|
||||
-->
|
||||
|
||||
<script lang="ts">
|
||||
import {eventRepo} from "@repo/event.ts";
|
||||
import { eventRepo } from "@repo/event.ts";
|
||||
import EventView from "@components/moderator/pages/event/EventView.svelte";
|
||||
import type { ExtendedEvent } from "@components/types/event";
|
||||
import { onMount } from "svelte";
|
||||
import { EventModel } from "./eventmodel.svelte";
|
||||
|
||||
interface Props {
|
||||
params: { id: number };
|
||||
@@ -28,11 +31,21 @@
|
||||
let { params }: Props = $props();
|
||||
|
||||
let id = params.id;
|
||||
let event = $eventRepo.getEvent(id.toString());
|
||||
let data: EventModel | undefined = $state(undefined);
|
||||
let loaded = $state(false);
|
||||
|
||||
onMount(async () => {
|
||||
refresh();
|
||||
});
|
||||
|
||||
async function refresh() {
|
||||
data = new EventModel(await $eventRepo.getEvent(id.toString()));
|
||||
loaded = true;
|
||||
}
|
||||
</script>
|
||||
|
||||
{#await event}
|
||||
{#if loaded}
|
||||
<EventView bind:event={data!!} {refresh} />
|
||||
{:else}
|
||||
<p>Loading...</p>
|
||||
{:then data}
|
||||
<EventView event={data} />
|
||||
{/await}
|
||||
{/if}
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<script lang="ts">
|
||||
import FightEditRow from "./FightEditRow.svelte";
|
||||
|
||||
import type { EventFightEdit, ExtendedEvent } from "@type/event";
|
||||
import type { EventFight, EventFightEdit, ExtendedEvent } from "@type/event";
|
||||
import { createSvelteTable, FlexRender } from "@components/ui/data-table";
|
||||
import { type ColumnFiltersState, getCoreRowModel, getFilteredRowModel, getGroupedRowModel, getSortedRowModel, type RowSelectionState, type SortingState } from "@tanstack/table-core";
|
||||
import { columns } from "./columns";
|
||||
@@ -36,11 +36,12 @@
|
||||
import type { ResponseGroups } from "@type/event";
|
||||
import { EditIcon, GroupIcon, LinkIcon } from "lucide-svelte";
|
||||
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@components/ui/dropdown-menu";
|
||||
import GroupSelector from "@components/moderator/components/GroupSelector.svelte";
|
||||
import { fightRepo } from "@components/repo/fight";
|
||||
import type { Team } from "@components/types/team";
|
||||
import type { EventModel } from "./eventmodel.svelte";
|
||||
|
||||
let { data = $bindable() }: { data: ExtendedEvent } = $props();
|
||||
|
||||
let fights = $state(data.fights);
|
||||
let groups = $state(data.groups);
|
||||
let { data = $bindable(), refresh }: { data: EventModel; refresh: () => void } = $props();
|
||||
|
||||
let sorting = $state<SortingState>([]);
|
||||
let columnFilters = $state<ColumnFiltersState>([]);
|
||||
@@ -48,7 +49,7 @@
|
||||
|
||||
const table = createSvelteTable({
|
||||
get data() {
|
||||
return fights;
|
||||
return data.fights;
|
||||
},
|
||||
initialState: {
|
||||
columnOrder: ["auswahl", "begegnung", "group"],
|
||||
@@ -103,6 +104,9 @@
|
||||
let groupResultsOpen = $state(false);
|
||||
let selectedGroupForResults: ResponseGroups | null = $state(null);
|
||||
|
||||
let groupChangeOpen = $state(false);
|
||||
let groupChangeSelected: number | null = $state(null);
|
||||
|
||||
async function handleSave(fight: EventFightEdit) {
|
||||
await $eventRepo.createFight(data.event.id.toString(), {
|
||||
...fight,
|
||||
@@ -110,7 +114,7 @@
|
||||
redTeam: fight.redTeam.id,
|
||||
});
|
||||
|
||||
reload();
|
||||
refresh();
|
||||
createOpen = false;
|
||||
}
|
||||
|
||||
@@ -123,10 +127,6 @@
|
||||
selectedGroupForResults = group;
|
||||
groupResultsOpen = true;
|
||||
}
|
||||
|
||||
async function reload() {
|
||||
fights = await $eventRepo.listFights(data.event.id.toString());
|
||||
}
|
||||
</script>
|
||||
|
||||
<Dialog bind:open={createOpen}>
|
||||
@@ -146,19 +146,53 @@
|
||||
</Dialog>
|
||||
|
||||
{#if selectedGroup}
|
||||
<GroupEditDialog bind:open={editGroupOpen} group={selectedGroup} event={data.event} bind:groups />
|
||||
<GroupEditDialog bind:open={editGroupOpen} group={selectedGroup} event={data.event} bind:groups={data.groups} />
|
||||
{/if}
|
||||
|
||||
{#if selectedGroupForResults}
|
||||
<GroupResultsDialog bind:open={groupResultsOpen} group={selectedGroupForResults} teams={data.teams} {fights} />
|
||||
<GroupResultsDialog bind:open={groupResultsOpen} group={selectedGroupForResults} teams={data.teams} fights={data.fights} />
|
||||
{/if}
|
||||
|
||||
<Dialog bind:open={groupChangeOpen}>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>Gruppe Ändern</DialogTitle>
|
||||
<DialogDescription>Hier kannst du die Gruppe der ausgewählten Kämpfe ändern</DialogDescription>
|
||||
</DialogHeader>
|
||||
<GroupSelector event={data.event} bind:groups={data.groups} bind:value={groupChangeSelected} />
|
||||
<DialogFooter>
|
||||
<Button
|
||||
onclick={async () => {
|
||||
groupChangeOpen = false;
|
||||
let group = data.groups.find((g) => g.id === groupChangeSelected);
|
||||
if (group) {
|
||||
let selectedGroups = table.getSelectedRowModel().rows.map((row) => row.original);
|
||||
for (const g of selectedGroups) {
|
||||
await $fightRepo.updateFight(data.event.id, g.id, {
|
||||
group: group.id,
|
||||
spielmodus: null,
|
||||
map: null,
|
||||
blueTeam: null,
|
||||
redTeam: null,
|
||||
start: null,
|
||||
spectatePort: null,
|
||||
});
|
||||
}
|
||||
|
||||
refresh();
|
||||
}
|
||||
}}>Speichern</Button
|
||||
>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
<div class="flex items-center justify-between">
|
||||
<Menubar>
|
||||
<MenubarMenu>
|
||||
<MenubarTrigger>Mehrfach Bearbeiten</MenubarTrigger>
|
||||
<MenubarContent>
|
||||
<MenubarItem disabled>Gruppe Ändern</MenubarItem>
|
||||
<MenubarItem onclick={() => (groupChangeOpen = true)}>Gruppe Ändern</MenubarItem>
|
||||
<MenubarItem disabled>Startzeit Verschieben</MenubarItem>
|
||||
<MenubarItem disabled>Spectate Port Ändern</MenubarItem>
|
||||
</MenubarContent>
|
||||
@@ -175,9 +209,9 @@
|
||||
</MenubarContent>
|
||||
</MenubarMenu>
|
||||
<MenubarMenu>
|
||||
<MenubarTrigger disabled={!groups.length}>Gruppen</MenubarTrigger>
|
||||
<MenubarTrigger disabled={!data.groups.length}>Gruppen</MenubarTrigger>
|
||||
<MenubarContent>
|
||||
{#each groups as group (group.id)}
|
||||
{#each data.groups as group (group.id)}
|
||||
<MenubarSub>
|
||||
<MenubarSubTrigger>
|
||||
{group.name}
|
||||
@@ -191,7 +225,7 @@
|
||||
</MenubarContent>
|
||||
</MenubarMenu>
|
||||
</Menubar>
|
||||
<Button variant="outline" class="ml-4" onclick={reload}>Neu laden</Button>
|
||||
<Button variant="outline" class="ml-4" onclick={refresh}>Neu laden</Button>
|
||||
</div>
|
||||
|
||||
<Table>
|
||||
@@ -205,13 +239,14 @@
|
||||
{/if}
|
||||
</TableHead>
|
||||
{/each}
|
||||
<TableHead></TableHead>
|
||||
</TableRow>
|
||||
{/each}
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{#each table.getRowModel().rows as groupRow (groupRow.id)}
|
||||
{#if groupRow.getIsGrouped()}
|
||||
{@const group = groups.find((g) => g.id == groupRow.getValue("group"))}
|
||||
{@const group = data.groups.find((g) => g.id == groupRow.getValue("group"))}
|
||||
<TableRow class="font-bold">
|
||||
<TableCell colspan={columns.length - 1}>
|
||||
<Checkbox
|
||||
@@ -256,7 +291,12 @@
|
||||
</TableCell>
|
||||
{/each}
|
||||
<TableCell class="text-right">
|
||||
<FightEditRow fight={row.original} teams={data.teams} bind:groups event={data.event} onupdate={(update) => (fights = fights.map((v) => (v.id === update.id ? update : v)))}
|
||||
<FightEditRow
|
||||
fight={row.original}
|
||||
teams={data.teams}
|
||||
bind:groups={data.groups}
|
||||
event={data.event}
|
||||
onupdate={(update) => (data.fights = data.fights.map((v) => (v.id === update.id ? update : v)))}
|
||||
></FightEditRow>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
|
||||
@@ -18,13 +18,13 @@
|
||||
-->
|
||||
|
||||
<script lang="ts">
|
||||
import type { ExtendedEvent } from "@type/event.ts";
|
||||
import EventEdit from "@components/moderator/pages/event/EventEdit.svelte";
|
||||
import EventFightList from "@components/moderator/pages/event/EventFightList.svelte";
|
||||
import RefereesList from "@components/moderator/pages/event/RefereesList.svelte";
|
||||
import TeamTable from "@components/moderator/pages/event/TeamTable.svelte";
|
||||
import type { EventModel } from "./eventmodel.svelte";
|
||||
|
||||
let { event = $bindable() }: { event: ExtendedEvent } = $props();
|
||||
let { event = $bindable(), refresh }: { event: EventModel; refresh: () => void } = $props();
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col m-4 p-4 rounded-md border gap-4">
|
||||
@@ -42,5 +42,5 @@
|
||||
<RefereesList {event} />
|
||||
</div>
|
||||
</div>
|
||||
<EventFightList bind:data={event} />
|
||||
<EventFightList bind:data={event} {refresh} />
|
||||
</div>
|
||||
|
||||
@@ -25,21 +25,19 @@
|
||||
import { Popover, PopoverContent, PopoverTrigger } from "@components/ui/popover";
|
||||
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@components/ui/command";
|
||||
import { teams } from "@components/stores/stores";
|
||||
import type { Team } from "@components/types/team";
|
||||
import type { EventModel } from "./eventmodel.svelte";
|
||||
|
||||
const { event = $bindable() }: { event: ExtendedEvent } = $props();
|
||||
|
||||
let team = $state(event.teams);
|
||||
let { event = $bindable() }: { event: EventModel } = $props();
|
||||
|
||||
async function addTeam(value: number) {
|
||||
await $eventRepo.updateTeams(event.event.id.toString(), [value]);
|
||||
team = await $eventRepo.listTeams(event.event.id.toString());
|
||||
event.teams = team;
|
||||
event.teams = await $eventRepo.listTeams(event.event.id.toString());
|
||||
}
|
||||
|
||||
async function removeTeam(value: number) {
|
||||
await $eventRepo.deleteTeams(event.event.id.toString(), [value]);
|
||||
team = await $eventRepo.listTeams(event.event.id.toString());
|
||||
event.teams = team;
|
||||
event.teams = await $eventRepo.listTeams(event.event.id.toString());
|
||||
}
|
||||
|
||||
let teamSearch = $state("");
|
||||
@@ -54,7 +52,7 @@
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{#each team as t (t.id)}
|
||||
{#each event.teams as t (t.id)}
|
||||
<TableRow>
|
||||
<TableCell>{t.kuerzel}</TableCell>
|
||||
<TableCell>{t.name}</TableCell>
|
||||
@@ -63,7 +61,7 @@
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
{/each}
|
||||
{#if team.length === 0}
|
||||
{#if event.teams.length === 0}
|
||||
<TableRow>
|
||||
<TableCell class="text-center col-span-3">No teams available</TableCell>
|
||||
</TableRow>
|
||||
@@ -83,7 +81,7 @@
|
||||
<CommandGroup heading="Teams">
|
||||
{#each $teams
|
||||
.filter((v) => v.name.includes(teamSearch))
|
||||
.filter((v) => !team.some((k) => k.id === v.id))
|
||||
.filter((v) => !event.teams.some((k) => k.id === v.id))
|
||||
.filter((v, i) => i < 50) as t (t.id)}
|
||||
<CommandItem value={t.id.toString()} onSelect={() => addTeam(t.id)} keywords={[t.name, t.kuerzel]}>{t.name}</CommandItem>
|
||||
{/each}
|
||||
|
||||
21
src/components/moderator/pages/event/eventmodel.svelte.ts
Normal file
21
src/components/moderator/pages/event/eventmodel.svelte.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import type { ResponseUser } from "@components/repo/event";
|
||||
import type { EventFight, ExtendedEvent, ResponseGroups, ResponseRelation, SWEvent } from "@components/types/event";
|
||||
import type { Team } from "@components/types/team";
|
||||
|
||||
export class EventModel {
|
||||
public event: SWEvent = $state({} as SWEvent);
|
||||
public teams: Array<Team> = $state([]);
|
||||
public groups: Array<ResponseGroups> = $state([]);
|
||||
public fights: Array<EventFight> = $state([]);
|
||||
public referees: Array<ResponseUser> = $state([]);
|
||||
public relations: Array<ResponseRelation> = $state([]);
|
||||
|
||||
constructor(data: ExtendedEvent) {
|
||||
this.event = data.event;
|
||||
this.teams = data.teams;
|
||||
this.groups = data.groups;
|
||||
this.fights = data.fights;
|
||||
this.referees = data.referees;
|
||||
this.relations = data.relations;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user