Refactor event and fight repositories to use numeric IDs for groups; update datetime picker input handling; add new generator components for event fights and group phases.
All checks were successful
SteamWarCI Build successful
All checks were successful
SteamWarCI Build successful
This commit is contained in:
@ -18,12 +18,14 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {createEventDispatcher} from "svelte";
|
import { Card } from "@components/ui/card";
|
||||||
interface Props {
|
|
||||||
children?: import('svelte').Snippet;
|
|
||||||
}
|
|
||||||
|
|
||||||
let { children }: Props = $props();
|
interface Props {
|
||||||
|
children?: import("svelte").Snippet;
|
||||||
|
ondrop: (event: DragEvent) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
let { children, ondrop }: Props = $props();
|
||||||
|
|
||||||
let dragover = $state(false);
|
let dragover = $state(false);
|
||||||
|
|
||||||
@ -32,19 +34,16 @@
|
|||||||
dragover = true;
|
dragover = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const dispatch = createEventDispatcher();
|
|
||||||
|
|
||||||
function handleDrop(ev: DragEvent) {
|
function handleDrop(ev: DragEvent) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
dragover = false;
|
dragover = false;
|
||||||
dispatch("drop", ev);
|
ondrop(ev);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="w-56 bg-gray-800 p-4 rounded" class:border={dragover} class:m-px={!dragover} ondrop={handleDrop}
|
<Card class="w-56 p-4 rounded m-px {dragover ? 'border-white' : ''}" ondrop={handleDrop} ondragover={handleDragOver} ondragleave={() => (dragover = false)} role="none">
|
||||||
ondragover={handleDragOver} ondragleave={() => dragover = false} role="none">
|
|
||||||
{@render children?.()}
|
{@render children?.()}
|
||||||
</div>
|
</Card>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
div {
|
div {
|
||||||
|
|||||||
@ -18,28 +18,28 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { createBubbler } from 'svelte/legacy';
|
import type { Team } from "@type/team.ts";
|
||||||
|
import { brightness, colorFromTeam, lighten } from "../../util";
|
||||||
|
|
||||||
const bubble = createBubbler();
|
interface Props {
|
||||||
import type {Team} from "@type/team.ts";
|
team: Team;
|
||||||
import {brightness, colorFromTeam, lighten} from "../../util";
|
ondragstart: (event: DragEvent) => void;
|
||||||
|
}
|
||||||
|
|
||||||
interface Props {
|
let { team, ondragstart }: Props = $props();
|
||||||
team: Team;
|
|
||||||
}
|
|
||||||
|
|
||||||
let { team }: Props = $props();
|
|
||||||
|
|
||||||
let hover = $state(false);
|
let hover = $state(false);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="rounded w-fit p-2 border-gray-600 border cursor-grab select-none m-1 flex place-items-center"
|
<div
|
||||||
style:background-color={hover ? lighten(colorFromTeam(team)) : colorFromTeam(team)}
|
class="rounded w-fit p-2 border-gray-600 border cursor-grab select-none m-1 flex place-items-center"
|
||||||
class:text-black={brightness(colorFromTeam(team))} draggable="true"
|
style:background-color={hover ? lighten(colorFromTeam(team)) : colorFromTeam(team)}
|
||||||
ondragstart={bubble('dragstart')}
|
class:text-black={brightness(colorFromTeam(team))}
|
||||||
onmouseenter={() => hover = true}
|
draggable="true"
|
||||||
onmouseleave={() => hover = false}
|
{ondragstart}
|
||||||
role="figure">
|
onmouseenter={() => (hover = true)}
|
||||||
|
onmouseleave={() => (hover = false)}
|
||||||
|
role="figure"
|
||||||
|
>
|
||||||
<span>{team.name}</span>
|
<span>{team.name}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -29,12 +29,14 @@
|
|||||||
import Dashboard from "@components/moderator/pages/dashboard/Dashboard.svelte";
|
import Dashboard from "@components/moderator/pages/dashboard/Dashboard.svelte";
|
||||||
import Event from "@components/moderator/pages/event/Event.svelte";
|
import Event from "@components/moderator/pages/event/Event.svelte";
|
||||||
import Pages from "@components/moderator/pages/pages/Pages.svelte";
|
import Pages from "@components/moderator/pages/pages/Pages.svelte";
|
||||||
|
import Generator from "@components/moderator/pages/generators/Generator.svelte";
|
||||||
|
|
||||||
const routes: RouteDefinition = {
|
const routes: RouteDefinition = {
|
||||||
"/": Dashboard,
|
"/": Dashboard,
|
||||||
"/events": Events,
|
"/events": Events,
|
||||||
"/players": Players,
|
"/players": Players,
|
||||||
"/event/:id": Event,
|
"/event/:id": Event,
|
||||||
|
"/event/:id/generate": Generator,
|
||||||
"/pages": Pages,
|
"/pages": Pages,
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -25,7 +25,7 @@
|
|||||||
let groupSelectOpen = $state(false);
|
let groupSelectOpen = $state(false);
|
||||||
|
|
||||||
async function handleGroupSave(group: GroupUpdateEdit) {
|
async function handleGroupSave(group: GroupUpdateEdit) {
|
||||||
let g = await $eventRepo.createGroup(event.id.toString(), group);
|
let g = await $eventRepo.createGroup(event.id, group);
|
||||||
groups.push(g);
|
groups.push(g);
|
||||||
value = g.id;
|
value = g.id;
|
||||||
createOpen = false;
|
createOpen = false;
|
||||||
|
|||||||
@ -202,8 +202,9 @@
|
|||||||
<MenubarItem onclick={() => (createOpen = true)}>Fight Erstellen</MenubarItem>
|
<MenubarItem onclick={() => (createOpen = true)}>Fight Erstellen</MenubarItem>
|
||||||
<MenubarGroup>
|
<MenubarGroup>
|
||||||
<MenubarGroupHeading>Generatoren</MenubarGroupHeading>
|
<MenubarGroupHeading>Generatoren</MenubarGroupHeading>
|
||||||
<MenubarItem disabled>Gruppenphase</MenubarItem>
|
<a href="#/event/{data.event.id}/generate">
|
||||||
<MenubarItem disabled>K.O. Phase</MenubarItem>
|
<MenubarItem>Gruppenphase</MenubarItem>
|
||||||
|
</a>
|
||||||
</MenubarGroup>
|
</MenubarGroup>
|
||||||
</MenubarContent>
|
</MenubarContent>
|
||||||
</MenubarMenu>
|
</MenubarMenu>
|
||||||
|
|||||||
@ -0,0 +1,22 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { ExtendedEvent } from "@components/types/event";
|
||||||
|
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@components/ui/tabs";
|
||||||
|
import GroupPhaseGenerator from "./gens/group/GroupPhaseGenerator.svelte";
|
||||||
|
let {
|
||||||
|
data,
|
||||||
|
}: {
|
||||||
|
data: ExtendedEvent;
|
||||||
|
} = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="m-4">
|
||||||
|
<Tabs value="group">
|
||||||
|
<TabsList class="mb-4">
|
||||||
|
<TabsTrigger value="group">Gruppenphase</TabsTrigger>
|
||||||
|
<TabsTrigger value="ko">K.O. Phase</TabsTrigger>
|
||||||
|
</TabsList>
|
||||||
|
<TabsContent value="group">
|
||||||
|
<GroupPhaseGenerator {data} />
|
||||||
|
</TabsContent>
|
||||||
|
</Tabs>
|
||||||
|
</div>
|
||||||
22
src/components/moderator/pages/generators/Generator.svelte
Normal file
22
src/components/moderator/pages/generators/Generator.svelte
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { eventRepo } from "@components/repo/event";
|
||||||
|
import FightsGenerator from "./FightsGenerator.svelte";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
params: { id: number };
|
||||||
|
}
|
||||||
|
|
||||||
|
let { params }: Props = $props();
|
||||||
|
|
||||||
|
let id = params.id;
|
||||||
|
|
||||||
|
let future = $eventRepo.getEvent(id.toString());
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#await future}
|
||||||
|
<p>Loading...</p>
|
||||||
|
{:then event}
|
||||||
|
<FightsGenerator data={event} />
|
||||||
|
{:catch error}
|
||||||
|
<p class="text-red-500">Error loading event: {error.message}</p>
|
||||||
|
{/await}
|
||||||
@ -0,0 +1,306 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import DragAcceptor from "@components/admin/pages/generate/DragAcceptor.svelte";
|
||||||
|
import TeamChip from "@components/admin/pages/generate/TeamChip.svelte";
|
||||||
|
import { eventRepo } from "@components/repo/event";
|
||||||
|
import { fightRepo } from "@components/repo/fight";
|
||||||
|
import { gamemodes, maps } from "@components/stores/stores";
|
||||||
|
import type { ExtendedEvent } from "@components/types/event";
|
||||||
|
import type { Team } from "@components/types/team";
|
||||||
|
import { Button } from "@components/ui/button";
|
||||||
|
import { Card } from "@components/ui/card";
|
||||||
|
import DateTimePicker from "@components/ui/datetime-picker/DateTimePicker.svelte";
|
||||||
|
import { Dialog } from "@components/ui/dialog";
|
||||||
|
import { Input } from "@components/ui/input";
|
||||||
|
import { Label } from "@components/ui/label";
|
||||||
|
import { Select, SelectContent, SelectItem, SelectTrigger } from "@components/ui/select";
|
||||||
|
import { Slider } from "@components/ui/slider";
|
||||||
|
import { fromAbsolute, fromDate, parseDateTime, parseDuration } from "@internationalized/date";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import { Plus } from "lucide-svelte";
|
||||||
|
import { replace } from "svelte-spa-router";
|
||||||
|
let {
|
||||||
|
data,
|
||||||
|
}: {
|
||||||
|
data: ExtendedEvent;
|
||||||
|
} = $props();
|
||||||
|
|
||||||
|
let teams = $derived(new Map<number, Team>(data.teams.map((team) => [team.id, team])));
|
||||||
|
|
||||||
|
let groups: number[][] = $state([]);
|
||||||
|
let teamsNotInGroup = $derived(data.teams.filter((team) => !groups.flat().includes(team.id)));
|
||||||
|
|
||||||
|
function dragToNewGroup(event: DragEvent) {
|
||||||
|
event.preventDefault();
|
||||||
|
let teamId = parseInt(event.dataTransfer!.getData("team"));
|
||||||
|
groups = [...groups.map((value) => value.filter((value1) => value1 != teamId)), [teamId]].filter((value) => value.length > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function teamDragStart(ev: DragEvent, team: Team) {
|
||||||
|
ev.dataTransfer!.setData("team", team.id.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
let resetDragOver = $state(false);
|
||||||
|
|
||||||
|
function resetDragOverEvent(ev: DragEvent) {
|
||||||
|
resetDragOver = true;
|
||||||
|
ev.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
function dropReset(ev: DragEvent) {
|
||||||
|
ev.preventDefault();
|
||||||
|
let teamId = parseInt(ev.dataTransfer!.getData("team"));
|
||||||
|
groups = groups.map((group) => group.filter((team) => team !== teamId)).filter((group) => group.length > 0);
|
||||||
|
resetDragOver = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function dropGroup(ev: DragEvent, groupIndex: number) {
|
||||||
|
ev.preventDefault();
|
||||||
|
let teamId = parseInt(ev.dataTransfer!.getData("team"));
|
||||||
|
groups = groups.map((group, i) => (i === groupIndex ? [...group.filter((value) => value != teamId), teamId] : group.filter((value) => value != teamId))).filter((group) => group.length > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
let startTime = $state(fromAbsolute(data.event.start, "Europe/Berlin"));
|
||||||
|
let gamemode = $state("");
|
||||||
|
let map = $state("");
|
||||||
|
|
||||||
|
let selectableGamemodes = $derived(
|
||||||
|
$gamemodes
|
||||||
|
.map((gamemode) => {
|
||||||
|
return {
|
||||||
|
name: gamemode,
|
||||||
|
value: gamemode,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.sort((a, b) => a.name.localeCompare(b.name))
|
||||||
|
);
|
||||||
|
|
||||||
|
let mapsStore = $derived(maps(gamemode));
|
||||||
|
let selectableMaps = $derived(
|
||||||
|
$mapsStore
|
||||||
|
.map((map) => {
|
||||||
|
return {
|
||||||
|
name: map,
|
||||||
|
value: map,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.sort((a, b) => a.name.localeCompare(b.name))
|
||||||
|
);
|
||||||
|
|
||||||
|
let roundTime = $state(30);
|
||||||
|
let startDelay = $state(30);
|
||||||
|
|
||||||
|
let showAutoGrouping = $state(false);
|
||||||
|
let groupCount = $state(Math.floor(data.teams.length / 2));
|
||||||
|
|
||||||
|
function createGroups() {
|
||||||
|
let teams = data.teams.map((team) => team.id).sort(() => Math.random() - 0.5);
|
||||||
|
groups = [];
|
||||||
|
for (let i = 0; i < groupCount; i++) {
|
||||||
|
groups.push([]);
|
||||||
|
}
|
||||||
|
while (teams.length > 0) {
|
||||||
|
groups[teams.length % groupCount].push(teams.pop() as number);
|
||||||
|
}
|
||||||
|
showAutoGrouping = false;
|
||||||
|
groups = groups.filter((group) => group.length > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateGroups(groups: number[][]): number[][][][] {
|
||||||
|
const groupFights: number[][][][] = [];
|
||||||
|
groups.forEach((group) => {
|
||||||
|
let round = group.length + (group.length % 2) - 1;
|
||||||
|
let groupFight = [];
|
||||||
|
for (let i = 0; i < round; i++) {
|
||||||
|
let availableTeams = [...group];
|
||||||
|
if (group.length % 2 === 1) {
|
||||||
|
availableTeams = availableTeams.filter((team, index) => index !== i);
|
||||||
|
}
|
||||||
|
let roundFights = [];
|
||||||
|
while (availableTeams.length > 0) {
|
||||||
|
let team1 = availableTeams.pop() as number;
|
||||||
|
let team2 = availableTeams.at(i % availableTeams.length) as number;
|
||||||
|
availableTeams = availableTeams.filter((team) => team !== team2);
|
||||||
|
let fight = [team1, team2];
|
||||||
|
fight.sort(() => Math.random() - 0.5);
|
||||||
|
roundFights.push(fight);
|
||||||
|
}
|
||||||
|
groupFight.push(roundFights);
|
||||||
|
}
|
||||||
|
groupFights.push(groupFight);
|
||||||
|
});
|
||||||
|
return groupFights;
|
||||||
|
}
|
||||||
|
|
||||||
|
let groupsFights = $derived(generateGroups(groups));
|
||||||
|
|
||||||
|
let generateDisabled = $derived(groupsFights.length > 0 && groupsFights.every((value) => value.every((value1) => value1.length > 0)) && gamemode !== "" && map !== "");
|
||||||
|
|
||||||
|
async function generateFights() {
|
||||||
|
groupsFights.forEach((group, i) => {
|
||||||
|
$eventRepo
|
||||||
|
.createGroup(data.event.id, {
|
||||||
|
name: "Gruppe " + (i + 1),
|
||||||
|
type: "GROUP_STAGE",
|
||||||
|
})
|
||||||
|
.then((v) => {
|
||||||
|
group.forEach((round, j) => {
|
||||||
|
round.forEach(async (fight, k) => {
|
||||||
|
const blueTeam = teams.get(fight[0])!;
|
||||||
|
const redTeam = teams.get(fight[1])!;
|
||||||
|
|
||||||
|
let karte = map;
|
||||||
|
|
||||||
|
if (karte === "%random%") {
|
||||||
|
karte = selectableMaps[Math.floor(Math.random() * selectableMaps.length)].value;
|
||||||
|
}
|
||||||
|
|
||||||
|
await $fightRepo.createFight(data.event.id, {
|
||||||
|
blueTeam: blueTeam.id,
|
||||||
|
redTeam: redTeam.id,
|
||||||
|
group: v.id,
|
||||||
|
map: karte,
|
||||||
|
spectatePort: null,
|
||||||
|
spielmodus: gamemode,
|
||||||
|
start: dayjs(
|
||||||
|
startTime
|
||||||
|
.copy()
|
||||||
|
.add({
|
||||||
|
minutes: roundTime * j,
|
||||||
|
})
|
||||||
|
.add({
|
||||||
|
seconds: startDelay * (k + i * round.length),
|
||||||
|
})
|
||||||
|
.toDate()
|
||||||
|
),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
await replace("#/event/" + data.event.id);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="flex justify-between">
|
||||||
|
<Card
|
||||||
|
id="reseter"
|
||||||
|
class="flex w-fit p-2 border border-gray-700 rounded h-20 pt-6 relative {resetDragOver ? 'border-white' : ''}"
|
||||||
|
ondragover={resetDragOverEvent}
|
||||||
|
ondragleave={() => (resetDragOver = false)}
|
||||||
|
ondrop={dropReset}
|
||||||
|
role="group"
|
||||||
|
>
|
||||||
|
{#each teamsNotInGroup as team (team.id)}
|
||||||
|
<TeamChip {team} ondragstart={(ev) => teamDragStart(ev, team)} />
|
||||||
|
{/each}
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<div class="flex items-center mr-4">
|
||||||
|
<Button onclick={() => (showAutoGrouping = true)}>Automatische Gruppen</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex mt-4 gap-4 border-b border-gray-700 pb-4">
|
||||||
|
{#each groups as group, i (i)}
|
||||||
|
<DragAcceptor ondrop={(ev) => dropGroup(ev, i)}>
|
||||||
|
<h1>Gruppe {i + 1} ({group.length})</h1>
|
||||||
|
{#each group as teamId (teamId)}
|
||||||
|
<TeamChip team={teams.get(teamId)!} ondragstart={(ev) => teamDragStart(ev, teams.get(teamId)!)} />
|
||||||
|
{/each}
|
||||||
|
</DragAcceptor>
|
||||||
|
{/each}
|
||||||
|
<DragAcceptor ondrop={dragToNewGroup}>
|
||||||
|
<h1>Neue Gruppe</h1>
|
||||||
|
</DragAcceptor>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="border-b mt-4 border-gray-700 pb-4">
|
||||||
|
<Label for="event-end">Startzeit</Label>
|
||||||
|
<DateTimePicker bind:value={startTime} />
|
||||||
|
<div class="mt-2">
|
||||||
|
<Label for="event-roundtime">Rundenzeit: {roundTime}m</Label>
|
||||||
|
<Slider id="event-roundtime" type="single" bind:value={roundTime} step={1} min={5} max={60} />
|
||||||
|
</div>
|
||||||
|
<div class="mt-2">
|
||||||
|
<Label for="event-member">Startverzögerung: {startDelay}</Label>
|
||||||
|
<Slider id="event-member" type="single" bind:value={startDelay} step={1} min={0} max={30} />
|
||||||
|
</div>
|
||||||
|
<div class="mt-2">
|
||||||
|
<Label for="fight-gamemode">Spielmodus</Label>
|
||||||
|
<Select type="single" bind:value={gamemode}>
|
||||||
|
<SelectTrigger id="fight-gamemode">{gamemode}</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{#each selectableGamemodes as gamemodeOption}
|
||||||
|
<SelectItem value={gamemodeOption.value}>{gamemodeOption.name}</SelectItem>
|
||||||
|
{/each}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
<div class="mt-2">
|
||||||
|
<Label for="fight-maps">Map</Label>
|
||||||
|
<Select type="single" bind:value={map}>
|
||||||
|
<SelectTrigger id="fight-maps">{map}</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="%random%">Zufällige Map</SelectItem>
|
||||||
|
{#each selectableMaps as mapOption}
|
||||||
|
<SelectItem value={mapOption.value}>{mapOption.name}</SelectItem>
|
||||||
|
{/each}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="text-center mx-2">
|
||||||
|
{#each groupsFights as fightsGroup, i}
|
||||||
|
<div>
|
||||||
|
<h1 class="text-4xl">Gruppe: {i + 1}</h1>
|
||||||
|
{#each fightsGroup as fightsRound, j}
|
||||||
|
<div class="border-b border-gray-700">
|
||||||
|
<h1 class="text-2xl">Runde: {j + 1}</h1>
|
||||||
|
{#each fightsRound as fightTeams, k}
|
||||||
|
<div class="text-left p-4">
|
||||||
|
<span class="p-2 border border-gray-700 rounded"
|
||||||
|
>{new Intl.DateTimeFormat("de-DE", {
|
||||||
|
day: "2-digit",
|
||||||
|
month: "2-digit",
|
||||||
|
year: "2-digit",
|
||||||
|
|
||||||
|
hour: "2-digit",
|
||||||
|
minute: "2-digit",
|
||||||
|
second: "2-digit",
|
||||||
|
}).format(
|
||||||
|
startTime
|
||||||
|
.copy()
|
||||||
|
.add({
|
||||||
|
minutes: roundTime * j,
|
||||||
|
seconds: startDelay * (k + i * fightsRound.length),
|
||||||
|
})
|
||||||
|
.toDate()
|
||||||
|
)}</span
|
||||||
|
>
|
||||||
|
{teams.get(fightTeams[0])!.name} vs. {teams.get(fightTeams[1])!.name}
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Button class="!p-4 fixed bottom-4 right-4" disabled={!generateDisabled} onclick={generateFights}>
|
||||||
|
<Plus />
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
:global(#reseter::before) {
|
||||||
|
content: "Reset";
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(#reseter) {
|
||||||
|
min-width: 14rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -150,7 +150,7 @@ export class EventRepo {
|
|||||||
.then((value) => value.json())
|
.then((value) => value.json())
|
||||||
.then((value) => z.array(ResponseGroupsSchema).parse(value));
|
.then((value) => z.array(ResponseGroupsSchema).parse(value));
|
||||||
}
|
}
|
||||||
public async createGroup(eventId: string, group: CreateEventGroup): Promise<ResponseGroups> {
|
public async createGroup(eventId: number, group: CreateEventGroup): Promise<ResponseGroups> {
|
||||||
CreateEventGroupSchema.parse(group);
|
CreateEventGroupSchema.parse(group);
|
||||||
return await fetchWithToken(this.token, `/events/${eventId}/groups`, {
|
return await fetchWithToken(this.token, `/events/${eventId}/groups`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
|
|||||||
@ -31,7 +31,7 @@ export interface CreateFight {
|
|||||||
redTeam: number;
|
redTeam: number;
|
||||||
start: Dayjs;
|
start: Dayjs;
|
||||||
spectatePort: number | null;
|
spectatePort: number | null;
|
||||||
group: string | null;
|
group: number | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UpdateFight {
|
export interface UpdateFight {
|
||||||
@ -57,7 +57,6 @@ export class FightRepo {
|
|||||||
return await fetchWithToken(this.token, `/events/${eventId}/fights`, {
|
return await fetchWithToken(this.token, `/events/${eventId}/fights`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
event: eventId,
|
|
||||||
spielmodus: fight.spielmodus,
|
spielmodus: fight.spielmodus,
|
||||||
map: fight.map,
|
map: fight.map,
|
||||||
blueTeam: fight.blueTeam,
|
blueTeam: fight.blueTeam,
|
||||||
|
|||||||
@ -81,7 +81,7 @@
|
|||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
|
|
||||||
<PopoverContent class="w-auto p-0">
|
<PopoverContent class="w-auto p-0">
|
||||||
<Input type="datetime-local" value={value.toDate().toISOString().slice(0, 16)} onchange={(e) => handleDateSelect(fromDate(e.target.valueAsDate, "Europe/Berlin"))} />
|
<Input type="datetime-local" value={value.toString().slice(0, 16)} onchange={(e) => handleDateSelect(fromDate(e.target.valueAsDate, "Europe/Berlin"))} />
|
||||||
<div class="sm:flex">
|
<div class="sm:flex">
|
||||||
<Calendar mode="single" bind:value onValueChange={(date) => handleDateSelect(date)} initialFocus />
|
<Calendar mode="single" bind:value onValueChange={(date) => handleDateSelect(date)} initialFocus />
|
||||||
<div class="flex flex-col sm:flex-row sm:h-[300px] divide-y sm:divide-y-0 sm:divide-x">
|
<div class="flex flex-col sm:flex-row sm:h-[300px] divide-y sm:divide-y-0 sm:divide-x">
|
||||||
|
|||||||
@ -13,7 +13,7 @@ SteamWar ist ein Minecraft Java Server.
|
|||||||
<Tabs>
|
<Tabs>
|
||||||
<TabItem label="Java Edition">
|
<TabItem label="Java Edition">
|
||||||
- IP: `steamwar.de`
|
- IP: `steamwar.de`
|
||||||
- Empholene Version: `1.21.5`
|
- Empholene Version: `1.21.6`
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem label="Bedrock Edition">
|
<TabItem label="Bedrock Edition">
|
||||||
- IP: `steamwar.de`
|
- IP: `steamwar.de`
|
||||||
|
|||||||
Reference in New Issue
Block a user