Refactor stores and types for improved data handling and schema definitions
All checks were successful
SteamWarCI Build successful
All checks were successful
SteamWarCI Build successful
- Consolidated player fetching logic in stores.ts to utilize dataRepo. - Introduced teams fetching logic in stores.ts. - Updated permissions structure in stores.ts for better clarity. - Enhanced data schemas in data.ts with new ResponseUser and ResponseTeam schemas. - Expanded event-related schemas in event.ts to include groups, relations, and event creation/update structures. - Improved code formatting for consistency and readability across files.
This commit is contained in:
@@ -33,19 +33,17 @@
|
|||||||
"/": Dashboard,
|
"/": Dashboard,
|
||||||
"/events": Events,
|
"/events": Events,
|
||||||
"/players": Players,
|
"/players": Players,
|
||||||
"/event/:id": Event
|
"/event/:id": Event,
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex flex-col bg-background min-w-full min-h-screen">
|
<div class="flex flex-col bg-background min-w-full min-h-screen">
|
||||||
<div class="border-b">
|
<div class="border-b">
|
||||||
<div class="flex h-16 items-center px-4">
|
<div class="flex h-16 items-center px-4">
|
||||||
<a href="/" class="text-sm font-bold transition-colors text-primary">
|
<a href="/" class="text-sm font-bold transition-colors text-primary"> SteamWar </a>
|
||||||
SteamWar
|
|
||||||
</a>
|
|
||||||
<NavLinks />
|
<NavLinks />
|
||||||
<div class="ml-auto flex items-center space-x-4">
|
<div class="ml-auto flex items-center space-x-4">
|
||||||
<Switch id="new-ui-switch" checked={true} on:click={() => navigate("/admin")} />
|
<Switch id="new-ui-switch" checked={true} onclick={() => navigate("/admin")} />
|
||||||
<Label for="new-ui-switch">New UI!</Label>
|
<Label for="new-ui-switch">New UI!</Label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -22,19 +22,9 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<nav class="flex items-center space-x-4 lg:space-x-6 mx-6">
|
<nav class="flex items-center space-x-4 lg:space-x-6 mx-6">
|
||||||
<a href="#/" class="hover:text-primary text-sm font-medium transition-colors" class:text-muted={$location !== "/"}>
|
<a href="#/" class="hover:text-primary text-sm font-medium transition-colors" class:text-muted-foreground={$location !== "/"}> Dashboard </a>
|
||||||
Dashboard
|
<a href="#/events" class="hover:text-primary text-sm font-medium transition-colors" class:text-muted-foreground={!$location.startsWith("/event")}> Events </a>
|
||||||
</a>
|
<a href="#/players" class="hover:text-primary text-sm font-medium transition-colors" class:text-muted-foreground={$location !== "/players"}> Players </a>
|
||||||
<a href="#/events" class="hover:text-primary text-sm font-medium transition-colors" class:text-muted={$location !== "/events"}>
|
<a href="#/pages" class="hover:text-primary text-sm font-medium transition-colors" class:text-muted-foreground={$location !== "/pages"}> Pages </a>
|
||||||
Events
|
<a href="#/schematics" class="hover:text-primary text-sm font-medium transition-colors" class:text-muted-foreground={$location !== "/schematics"}> Schematics </a>
|
||||||
</a>
|
|
||||||
<a href="#/players" class="hover:text-primary text-sm font-medium transition-colors" class:text-muted={$location !== "/players"}>
|
|
||||||
Players
|
|
||||||
</a>
|
|
||||||
<a href="#/pages" class="hover:text-primary text-sm font-medium transition-colors" class:text-muted={$location !== "/pages"}>
|
|
||||||
Pages
|
|
||||||
</a>
|
|
||||||
<a href="#/schematics" class="hover:text-primary text-sm font-medium transition-colors" class:text-muted={$location !== "/schematics"}>
|
|
||||||
Schematics
|
|
||||||
</a>
|
|
||||||
</nav>
|
</nav>
|
||||||
@@ -28,22 +28,16 @@
|
|||||||
|
|
||||||
const { event }: { event: ExtendedEvent } = $props();
|
const { event }: { event: ExtendedEvent } = $props();
|
||||||
|
|
||||||
let referees = $state(event.event.referees);
|
let referees = $state(event.referees);
|
||||||
|
|
||||||
async function addReferee(value: string) {
|
async function addReferee(value: string) {
|
||||||
referees = (
|
await $eventRepo.updateReferees(event.event.id.toString(), [value]);
|
||||||
await $eventRepo.updateEvent(event.event.id.toString(), {
|
referees = await $eventRepo.listReferees(event.event.id.toString());
|
||||||
addReferee: [value],
|
|
||||||
})
|
|
||||||
).referees;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function removeReferee(value: string) {
|
async function removeReferee(value: string) {
|
||||||
referees = (
|
await $eventRepo.deleteReferees(event.event.id.toString(), [value]);
|
||||||
await $eventRepo.updateEvent(event.event.id.toString(), {
|
referees = await $eventRepo.listReferees(event.event.id.toString());
|
||||||
removeReferee: [value],
|
|
||||||
})
|
|
||||||
).referees;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let playerSearch = $state("");
|
let playerSearch = $state("");
|
||||||
|
|||||||
@@ -21,14 +21,29 @@
|
|||||||
import { Button } from "@components/ui/button";
|
import { Button } from "@components/ui/button";
|
||||||
import { Table, TableHeader, TableRow, TableHead, TableBody, TableCell, TableCaption } from "@components/ui/table";
|
import { Table, TableHeader, TableRow, TableHead, TableBody, TableCell, TableCaption } from "@components/ui/table";
|
||||||
import type { ExtendedEvent } from "@type/event.ts";
|
import type { ExtendedEvent } from "@type/event.ts";
|
||||||
|
import { eventRepo } from "@repo/event";
|
||||||
|
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";
|
||||||
|
|
||||||
const { event }: { event: ExtendedEvent } = $props();
|
const { event }: { event: ExtendedEvent } = $props();
|
||||||
|
|
||||||
|
let team = $state(event.teams);
|
||||||
|
|
||||||
|
async function addTeam(value: number) {
|
||||||
|
await $eventRepo.updateTeams(event.event.id.toString(), [value]);
|
||||||
|
team = 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());
|
||||||
|
}
|
||||||
|
|
||||||
|
let teamSearch = $state("");
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Table>
|
<Table>
|
||||||
<TableCaption>
|
|
||||||
<Button disabled>Add Team</Button>
|
|
||||||
</TableCaption>
|
|
||||||
<TableHeader>
|
<TableHeader>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableHead>Team</TableHead>
|
<TableHead>Team</TableHead>
|
||||||
@@ -37,19 +52,42 @@
|
|||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{#each event.teams as team (team.id)}
|
{#each team as t (t.id)}
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell>{team.kuerzel}</TableCell>
|
<TableCell>{t.kuerzel}</TableCell>
|
||||||
<TableCell>{team.name}</TableCell>
|
<TableCell>{t.name}</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<Button disabled>Remove</Button>
|
<Button onclick={() => removeTeam(t.id)}>Remove</Button>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
{/each}
|
{/each}
|
||||||
{#if event.teams.length === 0}
|
{#if team.length === 0}
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell class="text-center col-span-3">No teams available</TableCell>
|
<TableCell class="text-center col-span-3">No teams available</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
{/if}
|
{/if}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
|
<Popover>
|
||||||
|
<TableCaption>
|
||||||
|
<PopoverTrigger>
|
||||||
|
<Button>Add Team</Button>
|
||||||
|
</PopoverTrigger>
|
||||||
|
</TableCaption>
|
||||||
|
<PopoverContent class="p-0">
|
||||||
|
<Command shouldFilter={false}>
|
||||||
|
<CommandInput bind:value={teamSearch} placeholder="Search teams..." />
|
||||||
|
<CommandList>
|
||||||
|
<CommandEmpty>No teams found :(</CommandEmpty>
|
||||||
|
<CommandGroup heading="Teams">
|
||||||
|
{#each $teams
|
||||||
|
.filter((v) => v.name.includes(teamSearch))
|
||||||
|
.filter((v) => !team.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}
|
||||||
|
</CommandGroup>
|
||||||
|
</CommandList>
|
||||||
|
</Command>
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
</Table>
|
</Table>
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ export const columns: ColumnDef<EventFight> = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: "Gruppe",
|
header: "Gruppe",
|
||||||
accessorKey: "group",
|
accessorKey: "group.name",
|
||||||
id: "group",
|
id: "group",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -21,21 +21,33 @@ import type {Player, Server} from "@type/data.ts";
|
|||||||
import { PlayerSchema, ServerSchema } from "@type/data.ts";
|
import { PlayerSchema, ServerSchema } from "@type/data.ts";
|
||||||
import { fetchWithToken, tokenStore } from "./repo.ts";
|
import { fetchWithToken, tokenStore } from "./repo.ts";
|
||||||
import { derived, get } from "svelte/store";
|
import { derived, get } from "svelte/store";
|
||||||
|
import { TeamSchema, type Team } from "@components/types/team.ts";
|
||||||
|
|
||||||
export class DataRepo {
|
export class DataRepo {
|
||||||
constructor(private token: string) {
|
constructor(private token: string) {}
|
||||||
}
|
|
||||||
|
|
||||||
public async getServer(): Promise<Server> {
|
public async getServer(): Promise<Server> {
|
||||||
return await fetchWithToken(this.token, "/data/server").then(value => value.json()).then(ServerSchema.parse);
|
return await fetchWithToken(this.token, "/data/server")
|
||||||
|
.then((value) => value.json())
|
||||||
|
.then(ServerSchema.parse);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getMe(): Promise<Player> {
|
public async getMe(): Promise<Player> {
|
||||||
return await fetchWithToken(this.token, "/data/me").then(value => value.json()).then(PlayerSchema.parse);
|
return await fetchWithToken(this.token, "/data/me")
|
||||||
|
.then((value) => value.json())
|
||||||
|
.then(PlayerSchema.parse);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getPlayers(): Promise<Player[]> {
|
public async getPlayers(): Promise<Player[]> {
|
||||||
return await fetchWithToken(get(tokenStore), "/data/admin/users").then(value => value.json()).then(PlayerSchema.array().parse);
|
return await fetchWithToken(get(tokenStore), "/data/admin/users")
|
||||||
|
.then((value) => value.json())
|
||||||
|
.then(PlayerSchema.array().parse);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getTeams(): Promise<Team[]> {
|
||||||
|
return await fetchWithToken(get(tokenStore), "/data/admin/teams")
|
||||||
|
.then((value) => value.json())
|
||||||
|
.then(TeamSchema.array().parse);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,12 +17,26 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type {ExtendedEvent, ShortEvent, SWEvent} from "@type/event";
|
import type { ExtendedEvent, ShortEvent, SWEvent, EventFight, ResponseGroups, ResponseRelation, ResponseTeam } from "@type/event";
|
||||||
import { fetchWithToken, tokenStore } from "./repo";
|
import { fetchWithToken, tokenStore } from "./repo";
|
||||||
import {ExtendedEventSchema, ShortEventSchema, SWEventSchema} from "@type/event.js";
|
import {
|
||||||
|
ExtendedEventSchema,
|
||||||
|
ShortEventSchema,
|
||||||
|
SWEventSchema,
|
||||||
|
EventFightSchema,
|
||||||
|
ResponseGroupsSchema,
|
||||||
|
ResponseRelationSchema,
|
||||||
|
ResponseTeamSchema,
|
||||||
|
CreateEventGroupSchema,
|
||||||
|
UpdateEventGroupSchema,
|
||||||
|
CreateEventRelationSchema,
|
||||||
|
UpdateEventRelationSchema,
|
||||||
|
} from "@type/event.js";
|
||||||
|
import type { CreateEventGroup, UpdateEventGroup, CreateEventRelation, UpdateEventRelation } from "@type/event.js";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import type { Dayjs } from "dayjs";
|
import type { Dayjs } from "dayjs";
|
||||||
import { derived } from "svelte/store";
|
import { derived } from "svelte/store";
|
||||||
|
import { ResponseUserSchema } from "@components/types/data";
|
||||||
|
|
||||||
export interface CreateEvent {
|
export interface CreateEvent {
|
||||||
name: string;
|
name: string;
|
||||||
@@ -42,19 +56,25 @@ export interface UpdateEvent {
|
|||||||
removeReferee?: string[] | null;
|
removeReferee?: string[] | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class EventRepo {
|
export interface ResponseUser {
|
||||||
constructor(private token: string) {
|
name: string;
|
||||||
|
uuid: string;
|
||||||
|
prefix: string;
|
||||||
|
perms: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class EventRepo {
|
||||||
|
constructor(private token: string) {}
|
||||||
|
|
||||||
public async listEvents(): Promise<ShortEvent[]> {
|
public async listEvents(): Promise<ShortEvent[]> {
|
||||||
return await fetchWithToken(this.token, "/events")
|
return await fetchWithToken(this.token, "/events")
|
||||||
.then(value => value.json())
|
.then((value) => value.json())
|
||||||
.then(value => z.array(ShortEventSchema).parse(value));
|
.then((value) => z.array(ShortEventSchema).parse(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getEvent(id: string): Promise<ExtendedEvent> {
|
public async getEvent(id: string): Promise<ExtendedEvent> {
|
||||||
return await fetchWithToken(this.token, `/events/${id}`)
|
return await fetchWithToken(this.token, `/events/${id}`)
|
||||||
.then(value => value.json())
|
.then((value) => value.json())
|
||||||
.then(ExtendedEventSchema.parse);
|
.then(ExtendedEventSchema.parse);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +86,8 @@ export class EventRepo {
|
|||||||
start: +event.start,
|
start: +event.start,
|
||||||
end: +event.end,
|
end: +event.end,
|
||||||
}),
|
}),
|
||||||
}).then(value => value.json())
|
})
|
||||||
|
.then((value) => value.json())
|
||||||
.then(SWEventSchema.parse);
|
.then(SWEventSchema.parse);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,7 +108,8 @@ export class EventRepo {
|
|||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
}).then(value => value.json())
|
})
|
||||||
|
.then((value) => value.json())
|
||||||
.then(SWEventSchema.parse);
|
.then(SWEventSchema.parse);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,6 +120,150 @@ export class EventRepo {
|
|||||||
|
|
||||||
return res.ok;
|
return res.ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fights
|
||||||
|
public async listFights(eventId: string): Promise<EventFight[]> {
|
||||||
|
return await fetchWithToken(this.token, `/events/${eventId}/fights`)
|
||||||
|
.then((value) => value.json())
|
||||||
|
.then((value) => z.array(EventFightSchema).parse(value));
|
||||||
|
}
|
||||||
|
public async createFight(eventId: string, fight: any): Promise<EventFight> {
|
||||||
|
return await fetchWithToken(this.token, `/events/${eventId}/fights`, {
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify(fight),
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
})
|
||||||
|
.then((value) => value.json())
|
||||||
|
.then(EventFightSchema.parse);
|
||||||
|
}
|
||||||
|
public async deleteFight(eventId: string, fightId: string): Promise<boolean> {
|
||||||
|
const res = await fetchWithToken(this.token, `/events/${eventId}/fights/${fightId}`, {
|
||||||
|
method: "DELETE",
|
||||||
|
});
|
||||||
|
return res.ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Groups
|
||||||
|
public async listGroups(eventId: string): Promise<ResponseGroups[]> {
|
||||||
|
return await fetchWithToken(this.token, `/events/${eventId}/groups`)
|
||||||
|
.then((value) => value.json())
|
||||||
|
.then((value) => z.array(ResponseGroupsSchema).parse(value));
|
||||||
|
}
|
||||||
|
public async createGroup(eventId: string, group: CreateEventGroup): Promise<ResponseGroups> {
|
||||||
|
CreateEventGroupSchema.parse(group);
|
||||||
|
return await fetchWithToken(this.token, `/events/${eventId}/groups`, {
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify(group),
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
})
|
||||||
|
.then((value) => value.json())
|
||||||
|
.then(ResponseGroupsSchema.parse);
|
||||||
|
}
|
||||||
|
public async getGroup(eventId: string, groupId: string): Promise<ResponseGroups> {
|
||||||
|
return await fetchWithToken(this.token, `/events/${eventId}/groups/${groupId}`)
|
||||||
|
.then((value) => value.json())
|
||||||
|
.then(ResponseGroupsSchema.parse);
|
||||||
|
}
|
||||||
|
public async updateGroup(eventId: string, groupId: string, group: UpdateEventGroup): Promise<ResponseGroups> {
|
||||||
|
UpdateEventGroupSchema.parse(group);
|
||||||
|
return await fetchWithToken(this.token, `/events/${eventId}/groups/${groupId}`, {
|
||||||
|
method: "PUT",
|
||||||
|
body: JSON.stringify(group),
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
})
|
||||||
|
.then((value) => value.json())
|
||||||
|
.then(ResponseGroupsSchema.parse);
|
||||||
|
}
|
||||||
|
public async deleteGroup(eventId: string, groupId: string): Promise<boolean> {
|
||||||
|
const res = await fetchWithToken(this.token, `/events/${eventId}/groups/${groupId}`, {
|
||||||
|
method: "DELETE",
|
||||||
|
});
|
||||||
|
return res.ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Relations
|
||||||
|
public async listRelations(eventId: string): Promise<ResponseRelation[]> {
|
||||||
|
return await fetchWithToken(this.token, `/events/${eventId}/relations`)
|
||||||
|
.then((value) => value.json())
|
||||||
|
.then((value) => z.array(ResponseRelationSchema).parse(value));
|
||||||
|
}
|
||||||
|
public async createRelation(eventId: string, relation: CreateEventRelation): Promise<ResponseRelation> {
|
||||||
|
CreateEventRelationSchema.parse(relation);
|
||||||
|
return await fetchWithToken(this.token, `/events/${eventId}/relations`, {
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify(relation),
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
})
|
||||||
|
.then((value) => value.json())
|
||||||
|
.then(ResponseRelationSchema.parse);
|
||||||
|
}
|
||||||
|
public async getRelation(eventId: string, relationId: string): Promise<ResponseRelation> {
|
||||||
|
return await fetchWithToken(this.token, `/events/${eventId}/relations/${relationId}`)
|
||||||
|
.then((value) => value.json())
|
||||||
|
.then(ResponseRelationSchema.parse);
|
||||||
|
}
|
||||||
|
public async updateRelation(eventId: string, relationId: string, relation: UpdateEventRelation): Promise<ResponseRelation> {
|
||||||
|
UpdateEventRelationSchema.parse(relation);
|
||||||
|
return await fetchWithToken(this.token, `/events/${eventId}/relations/${relationId}`, {
|
||||||
|
method: "PUT",
|
||||||
|
body: JSON.stringify(relation),
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
})
|
||||||
|
.then((value) => value.json())
|
||||||
|
.then(ResponseRelationSchema.parse);
|
||||||
|
}
|
||||||
|
public async deleteRelation(eventId: string, relationId: string): Promise<boolean> {
|
||||||
|
const res = await fetchWithToken(this.token, `/events/${eventId}/relations/${relationId}`, {
|
||||||
|
method: "DELETE",
|
||||||
|
});
|
||||||
|
return res.ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Teams
|
||||||
|
public async listTeams(eventId: string): Promise<ResponseTeam[]> {
|
||||||
|
return await fetchWithToken(this.token, `/events/${eventId}/teams`)
|
||||||
|
.then((value) => value.json())
|
||||||
|
.then((value) => z.array(ResponseTeamSchema).parse(value));
|
||||||
|
}
|
||||||
|
public async updateTeams(eventId: string, teams: number[]): Promise<boolean> {
|
||||||
|
const res = await fetchWithToken(this.token, `/events/${eventId}/teams`, {
|
||||||
|
method: "PUT",
|
||||||
|
body: JSON.stringify(teams),
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
});
|
||||||
|
return res.ok;
|
||||||
|
}
|
||||||
|
public async deleteTeams(eventId: string, teams: number[]): Promise<boolean> {
|
||||||
|
const res = await fetchWithToken(this.token, `/events/${eventId}/teams`, {
|
||||||
|
method: "DELETE",
|
||||||
|
body: JSON.stringify(teams),
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
});
|
||||||
|
return res.ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Referees
|
||||||
|
public async listReferees(eventId: string): Promise<ResponseUser[]> {
|
||||||
|
return await fetchWithToken(this.token, `/events/${eventId}/referees`)
|
||||||
|
.then((value) => value.json())
|
||||||
|
.then((value) => z.array(ResponseUserSchema).parse(value));
|
||||||
|
}
|
||||||
|
public async updateReferees(eventId: string, refereeUuids: string[]): Promise<boolean> {
|
||||||
|
const res = await fetchWithToken(this.token, `/events/${eventId}/referees`, {
|
||||||
|
method: "PUT",
|
||||||
|
body: JSON.stringify(refereeUuids),
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
});
|
||||||
|
return res.status === 204;
|
||||||
|
}
|
||||||
|
public async deleteReferees(eventId: string, refereeUuids: string[]): Promise<boolean> {
|
||||||
|
const res = await fetchWithToken(this.token, `/events/${eventId}/referees`, {
|
||||||
|
method: "DELETE",
|
||||||
|
body: JSON.stringify(refereeUuids),
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
});
|
||||||
|
return res.status === 204;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const eventRepo = derived(tokenStore, ($token) => new EventRepo($token));
|
export const eventRepo = derived(tokenStore, ($token) => new EventRepo($token));
|
||||||
|
|||||||
2210
src/components/repo/openapi.yaml
Normal file
2210
src/components/repo/openapi.yaml
Normal file
File diff suppressed because it is too large
Load Diff
@@ -29,21 +29,25 @@ import {pageRepo} from "@repo/page.ts";
|
|||||||
import { dataRepo } from "@repo/data.ts";
|
import { dataRepo } from "@repo/data.ts";
|
||||||
import { permsRepo } from "@repo/perms.ts";
|
import { permsRepo } from "@repo/perms.ts";
|
||||||
|
|
||||||
export const schemTypes = cached<SchematicType[]>([], () =>
|
export const schemTypes = cached<SchematicType[]>([], () => fetchWithToken(get(tokenStore), "/data/admin/schematicTypes").then((res) => res.json()));
|
||||||
fetchWithToken(get(tokenStore), "/data/admin/schematicTypes")
|
|
||||||
.then(res => res.json()));
|
|
||||||
|
|
||||||
export const players = cached<Player[]>([], async () => {
|
export const players = cached<Player[]>([], async () => {
|
||||||
const res = await fetchWithToken(get(tokenStore), "/data/admin/users");
|
return get(dataRepo).getPlayers();
|
||||||
return z.array(PlayerSchema).parse(await res.json());
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export const permissions = cached({
|
export const teams = cached<Team[]>([], async () => {
|
||||||
|
return get(dataRepo).getTeams();
|
||||||
|
});
|
||||||
|
|
||||||
|
export const permissions = cached(
|
||||||
|
{
|
||||||
perms: [],
|
perms: [],
|
||||||
prefixes: {},
|
prefixes: {},
|
||||||
}, async () => {
|
},
|
||||||
|
async () => {
|
||||||
return get(permsRepo).listPerms();
|
return get(permsRepo).listPerms();
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
export const gamemodes = cached<string[]>([], async () => {
|
export const gamemodes = cached<string[]>([], async () => {
|
||||||
const res = await fetchWithToken(get(tokenStore), "/data/admin/gamemodes");
|
const res = await fetchWithToken(get(tokenStore), "/data/admin/gamemodes");
|
||||||
@@ -51,7 +55,7 @@ export const gamemodes = cached<string[]>([], async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
export const maps = cachedFamily<string, string[]>([], async (gamemode) => {
|
export const maps = cachedFamily<string, string[]>([], async (gamemode) => {
|
||||||
if (get(gamemodes).every(value => value !== gamemode)) return [];
|
if (get(gamemodes).every((value) => value !== gamemode)) return [];
|
||||||
|
|
||||||
const res = await fetchWithToken(get(tokenStore), `/data/admin/gamemodes/${gamemode}/maps`);
|
const res = await fetchWithToken(get(tokenStore), `/data/admin/gamemodes/${gamemode}/maps`);
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
@@ -66,17 +70,12 @@ export const groups = cached<string[]>([], async () => {
|
|||||||
return z.array(z.string()).parse(await res.json());
|
return z.array(z.string()).parse(await res.json());
|
||||||
});
|
});
|
||||||
|
|
||||||
export const teams = cached<Team[]>([], async () => {
|
|
||||||
const res = await fetchWithToken(get(tokenStore), "/team");
|
|
||||||
return z.array(TeamSchema).parse(await res.json());
|
|
||||||
});
|
|
||||||
|
|
||||||
export const branches = cached<string[]>([], async () => {
|
export const branches = cached<string[]>([], async () => {
|
||||||
const res = await get(pageRepo).getBranches();
|
const res = await get(pageRepo).getBranches();
|
||||||
return z.array(z.string()).parse(res);
|
return z.array(z.string()).parse(res);
|
||||||
});
|
});
|
||||||
|
|
||||||
export const server = derived(dataRepo, $dataRepo => $dataRepo.getServer());
|
export const server = derived(dataRepo, ($dataRepo) => $dataRepo.getServer());
|
||||||
|
|
||||||
export const isWide = writable(typeof window !== "undefined" && window.innerWidth >= 640);
|
export const isWide = writable(typeof window !== "undefined" && window.innerWidth >= 640);
|
||||||
|
|
||||||
|
|||||||
@@ -57,3 +57,12 @@ export const ResponseErrorSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type ResponseError = z.infer<typeof ResponseErrorSchema>;
|
export type ResponseError = z.infer<typeof ResponseErrorSchema>;
|
||||||
|
|
||||||
|
export const ResponseUserSchema = z.object({
|
||||||
|
name: z.string(),
|
||||||
|
uuid: z.string(),
|
||||||
|
prefix: z.string(),
|
||||||
|
perms: z.array(z.string()),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type ResponseUser = z.infer<typeof ResponseUserSchema>;
|
||||||
|
|||||||
@@ -19,7 +19,44 @@
|
|||||||
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { TeamSchema } from "./team.js";
|
import { TeamSchema } from "./team.js";
|
||||||
import {PlayerSchema} from "./data.js";
|
import { PlayerSchema, ResponseUserSchema } from "./data.js";
|
||||||
|
|
||||||
|
export const ResponseGroupsSchema = z.object({
|
||||||
|
id: z.number(),
|
||||||
|
name: z.string(),
|
||||||
|
pointsPerWin: z.number(),
|
||||||
|
pointsPerLoss: z.number(),
|
||||||
|
pointsPerDraw: z.number(),
|
||||||
|
type: z.enum(["GROUP_STAGE", "ELIMINATION_STAGE"]),
|
||||||
|
points: z.record(z.string(), z.number()).nullable(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const EventFightSchema = z.object({
|
||||||
|
id: z.number(),
|
||||||
|
spielmodus: z.string(),
|
||||||
|
map: z.string(),
|
||||||
|
blueTeam: TeamSchema,
|
||||||
|
redTeam: TeamSchema,
|
||||||
|
start: z.number(),
|
||||||
|
ergebnis: z.number(),
|
||||||
|
spectatePort: z.number().nullable(),
|
||||||
|
group: ResponseGroupsSchema.nullable(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type EventFight = z.infer<typeof EventFightSchema>;
|
||||||
|
|
||||||
|
export type ResponseGroups = z.infer<typeof ResponseGroupsSchema>;
|
||||||
|
|
||||||
|
export const ResponseRelationSchema = z.object({
|
||||||
|
id: z.number(),
|
||||||
|
fight: EventFightSchema,
|
||||||
|
type: z.enum(["FIGHT", "GROUP"]),
|
||||||
|
fromFight: EventFightSchema.nullable(),
|
||||||
|
fromGroup: ResponseGroupsSchema.nullable(),
|
||||||
|
fromPlace: z.number(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type ResponseRelation = z.infer<typeof ResponseRelationSchema>;
|
||||||
|
|
||||||
export const ShortEventSchema = z.object({
|
export const ShortEventSchema = z.object({
|
||||||
id: z.number(),
|
id: z.number(),
|
||||||
@@ -35,29 +72,63 @@ export const SWEventSchema = ShortEventSchema.extend({
|
|||||||
maxTeamMembers: z.number(),
|
maxTeamMembers: z.number(),
|
||||||
schemType: z.string().nullable(),
|
schemType: z.string().nullable(),
|
||||||
publicSchemsOnly: z.boolean(),
|
publicSchemsOnly: z.boolean(),
|
||||||
referees: z.array(PlayerSchema),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export type SWEvent = z.infer<typeof SWEventSchema>;
|
export type SWEvent = z.infer<typeof SWEventSchema>;
|
||||||
|
|
||||||
export const EventFightSchema = z.object({
|
|
||||||
id: z.number(),
|
|
||||||
spielmodus: z.string(),
|
|
||||||
map: z.string(),
|
|
||||||
blueTeam: TeamSchema,
|
|
||||||
redTeam: TeamSchema,
|
|
||||||
start: z.number(),
|
|
||||||
ergebnis: z.number(),
|
|
||||||
spectatePort: z.number().nullable(),
|
|
||||||
group: z.string().nullable(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export type EventFight = z.infer<typeof EventFightSchema>;
|
|
||||||
|
|
||||||
export const ExtendedEventSchema = z.object({
|
export const ExtendedEventSchema = z.object({
|
||||||
event: SWEventSchema,
|
event: SWEventSchema,
|
||||||
teams: z.array(TeamSchema),
|
teams: z.array(TeamSchema),
|
||||||
|
groups: z.array(ResponseGroupsSchema),
|
||||||
fights: z.array(EventFightSchema),
|
fights: z.array(EventFightSchema),
|
||||||
|
referees: z.array(ResponseUserSchema),
|
||||||
|
relations: z.array(ResponseRelationSchema),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type ExtendedEvent = z.infer<typeof ExtendedEventSchema>;
|
export type ExtendedEvent = z.infer<typeof ExtendedEventSchema>;
|
||||||
|
|
||||||
|
export const ResponseTeamSchema = z.object({
|
||||||
|
id: z.number(),
|
||||||
|
name: z.string(),
|
||||||
|
kuerzel: z.string(),
|
||||||
|
color: z.string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type ResponseTeam = z.infer<typeof ResponseTeamSchema>;
|
||||||
|
|
||||||
|
export const CreateEventGroupSchema = z.object({
|
||||||
|
name: z.string(),
|
||||||
|
type: z.enum(["GROUP_STAGE", "ELIMINATION_STAGE"]),
|
||||||
|
});
|
||||||
|
export type CreateEventGroup = z.infer<typeof CreateEventGroupSchema>;
|
||||||
|
|
||||||
|
export const UpdateEventGroupSchema = z.object({
|
||||||
|
name: z.string().nullable().optional(),
|
||||||
|
type: z.enum(["GROUP_STAGE", "ELIMINATION_STAGE"]).nullable().optional(),
|
||||||
|
pointsPerWin: z.number().nullable().optional(),
|
||||||
|
pointsPerLoss: z.number().nullable().optional(),
|
||||||
|
pointsPerDraw: z.number().nullable().optional(),
|
||||||
|
});
|
||||||
|
export type UpdateEventGroup = z.infer<typeof UpdateEventGroupSchema>;
|
||||||
|
|
||||||
|
export const CreateEventRelationSchema = z.object({
|
||||||
|
fightId: z.number(),
|
||||||
|
team: z.enum(["RED", "BLUE"]),
|
||||||
|
fromType: z.enum(["FIGHT", "GROUP"]),
|
||||||
|
fromId: z.number(),
|
||||||
|
fromPlace: z.number(),
|
||||||
|
});
|
||||||
|
export type CreateEventRelation = z.infer<typeof CreateEventRelationSchema>;
|
||||||
|
|
||||||
|
export const UpdateFromRelationSchema = z.object({
|
||||||
|
fromType: z.enum(["FIGHT", "GROUP"]),
|
||||||
|
fromId: z.number(),
|
||||||
|
fromPlace: z.number(),
|
||||||
|
});
|
||||||
|
export type UpdateFromRelation = z.infer<typeof UpdateFromRelationSchema>;
|
||||||
|
|
||||||
|
export const UpdateEventRelationSchema = z.object({
|
||||||
|
team: z.enum(["RED", "BLUE"]).nullable().optional(),
|
||||||
|
from: UpdateFromRelationSchema.nullable().optional(),
|
||||||
|
});
|
||||||
|
export type UpdateEventRelation = z.infer<typeof UpdateEventRelationSchema>;
|
||||||
|
|||||||
Reference in New Issue
Block a user