I hate frontend
This commit is contained in:
parent
7e6daf94cc
commit
6ae3cfe0d8
|
@ -0,0 +1,3 @@
|
|||
#!/bin/sh
|
||||
|
||||
npx openapi-typescript http://localhost:8000/api/openapi.json --output src/apiScheme.ts
|
|
@ -0,0 +1,516 @@
|
|||
/**
|
||||
* This file was auto-generated by openapi-typescript.
|
||||
* Do not make direct changes to the file.
|
||||
*/
|
||||
|
||||
export interface paths {
|
||||
"/user/": {
|
||||
/** Returns an array of all users sorted by the given sort field and ordering */
|
||||
get: operations["get_all_users"];
|
||||
/** Returns the created user */
|
||||
post: operations["add_user"];
|
||||
};
|
||||
"/user/{id}": {
|
||||
/** Returns a single user by id */
|
||||
get: operations["get_user"];
|
||||
delete: operations["delete_user"];
|
||||
};
|
||||
"/user/{id}/score": {
|
||||
/** Returns the score of a single user by id */
|
||||
get: operations["get_score"];
|
||||
post: operations["set_score"];
|
||||
};
|
||||
"/event/": {
|
||||
/** Returns all events */
|
||||
get: operations["get_all_events"];
|
||||
/**
|
||||
* If an `id` is supplied, it will be replaced by a randomly generated one.
|
||||
*
|
||||
* Returns the created event.
|
||||
*/
|
||||
post: operations["create_event"];
|
||||
};
|
||||
"/event/{id}/stop": {
|
||||
/** This will conclude the event, apply the outcome to the users and return the outcome. */
|
||||
post: operations["stop_event"];
|
||||
};
|
||||
"/event/{id}": {
|
||||
/** Returns the event with the given id */
|
||||
get: operations["get_event"];
|
||||
/** Update the supplied values in the event with the given id. The `id` of an event cannot be changed and `concluded` will always be false. */
|
||||
post: operations["update_event"];
|
||||
};
|
||||
"/event/{id}/outcome": {
|
||||
/** Returns the outcome of an event. */
|
||||
get: operations["event_outcome"];
|
||||
};
|
||||
}
|
||||
|
||||
export interface components {
|
||||
schemas: {
|
||||
/**
|
||||
* User
|
||||
* @description A user that represents a person participating in the LAN party
|
||||
*/
|
||||
User: {
|
||||
/** @description Name of the user */
|
||||
name: string;
|
||||
/**
|
||||
* Format: int64
|
||||
* @description Score of the user
|
||||
*/
|
||||
score: number;
|
||||
/** @description Unique identifier of the user */
|
||||
id: string;
|
||||
};
|
||||
/**
|
||||
* UserSort
|
||||
* @description Field used to sort users
|
||||
* @enum {string}
|
||||
*/
|
||||
UserSort: "score" | "name" | "id";
|
||||
/**
|
||||
* Ordering
|
||||
* @description Ordering of data in an array, ascending or descending
|
||||
* @enum {string}
|
||||
*/
|
||||
Ordering: "desc" | "asc";
|
||||
/**
|
||||
* Event
|
||||
* @description An event in which participants can win or lose points
|
||||
*/
|
||||
Event: {
|
||||
/**
|
||||
* @description Unique identifier of the event. This will be randomly generated and cannot be modified.
|
||||
* @default 6dcf4a26-87fe-4a43-be93-f315527d104a
|
||||
*/
|
||||
id?: string;
|
||||
/**
|
||||
* @description Has this event concluded?
|
||||
* @default false
|
||||
*/
|
||||
concluded?: boolean;
|
||||
/**
|
||||
* @description Name of the event
|
||||
* @default
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* @description Description of the event
|
||||
* @default
|
||||
*/
|
||||
description?: string;
|
||||
/** @description Event type */
|
||||
event_type: components["schemas"]["EventType"];
|
||||
};
|
||||
/**
|
||||
* EventType
|
||||
* @description An enumeration of event types
|
||||
*/
|
||||
EventType:
|
||||
| {
|
||||
Test: components["schemas"]["Test"];
|
||||
}
|
||||
| {
|
||||
TeamGame: components["schemas"]["TeamGame"];
|
||||
}
|
||||
| {
|
||||
FreeForAllGame: components["schemas"]["FreeForAllGame"];
|
||||
};
|
||||
Test: {
|
||||
/** Format: int64 */
|
||||
num_players: number;
|
||||
};
|
||||
TeamGame: {
|
||||
/** @description Map of teams with a name as key and an array of players as value */
|
||||
teams: { [key: string]: string[] };
|
||||
/** @description Ranking of participants by user id or team name (first element is first place, second element is second place, etc.) */
|
||||
ranking?: components["schemas"]["FreeForAllGameRanking"] | null;
|
||||
/** @description Array of user ids that participate in the game */
|
||||
participants: string[];
|
||||
/**
|
||||
* @description Rewards for winning the game (first element for first place, second element for second place, etc.)
|
||||
* @example [
|
||||
* 10,
|
||||
* 7,
|
||||
* 5,
|
||||
* 3,
|
||||
* 2,
|
||||
* 1
|
||||
* ]
|
||||
*/
|
||||
win_rewards: number[];
|
||||
/**
|
||||
* @description Rewards for losing the game (first element for last place, second element for second to last place, etc.)
|
||||
* @example [
|
||||
* -3,
|
||||
* -2,
|
||||
* -1
|
||||
* ]
|
||||
*/
|
||||
lose_rewards: number[];
|
||||
};
|
||||
FreeForAllGameRanking:
|
||||
| {
|
||||
Ranking: string[];
|
||||
}
|
||||
| {
|
||||
Scores: { [key: string]: number };
|
||||
};
|
||||
FreeForAllGame: {
|
||||
/** @description Ranking of participants by user id or team name (first element is first place, second element is second place, etc.) */
|
||||
ranking?: components["schemas"]["FreeForAllGameRanking"] | null;
|
||||
/** @description Array of user ids that participate in the game */
|
||||
participants: string[];
|
||||
/**
|
||||
* @description Rewards for winning the game (first element for first place, second element for second place, etc.)
|
||||
* @example [
|
||||
* 10,
|
||||
* 7,
|
||||
* 5,
|
||||
* 3,
|
||||
* 2,
|
||||
* 1
|
||||
* ]
|
||||
*/
|
||||
win_rewards: number[];
|
||||
/**
|
||||
* @description Rewards for losing the game (first element for last place, second element for second to last place, etc.)
|
||||
* @example [
|
||||
* -3,
|
||||
* -2,
|
||||
* -1
|
||||
* ]
|
||||
*/
|
||||
lose_rewards: number[];
|
||||
};
|
||||
/**
|
||||
* EventSpec
|
||||
* @description A specification of an event
|
||||
*/
|
||||
EventSpec: {
|
||||
name: string;
|
||||
description: string;
|
||||
event_type: components["schemas"]["EventTypeSpec"];
|
||||
};
|
||||
/**
|
||||
* EventTypeSpec
|
||||
* @description A specification of an event type
|
||||
*/
|
||||
EventTypeSpec:
|
||||
| {
|
||||
Test: components["schemas"]["TestSpec"];
|
||||
}
|
||||
| {
|
||||
TeamGame: components["schemas"]["TeamGameSpec"];
|
||||
}
|
||||
| {
|
||||
FreeForAllGame: components["schemas"]["FreeForAllGameSpec"];
|
||||
};
|
||||
TestSpec: {
|
||||
/** Format: int64 */
|
||||
num_players: number;
|
||||
};
|
||||
TeamGameSpec: {
|
||||
/** @description Map of teams with a name as key and an array of players as value */
|
||||
teams: { [key: string]: string[] };
|
||||
/**
|
||||
* @description Rewards for winning the game (first element for first place, second element for second place, etc.)
|
||||
* @example [
|
||||
* 10,
|
||||
* 7,
|
||||
* 5,
|
||||
* 3,
|
||||
* 2,
|
||||
* 1
|
||||
* ]
|
||||
*/
|
||||
win_rewards: number[];
|
||||
/**
|
||||
* @description Rewards for losing the game (first element for last place, second element for second to last place, etc.)
|
||||
* @example [
|
||||
* -3,
|
||||
* -2,
|
||||
* -1
|
||||
* ]
|
||||
*/
|
||||
lose_rewards: number[];
|
||||
};
|
||||
FreeForAllGameSpec: {
|
||||
/** @description Array of user ids that participate in the game */
|
||||
participants: string[];
|
||||
/**
|
||||
* @description Rewards for winning the game (first element for first place, second element for second place, etc.)
|
||||
* @example [
|
||||
* 10,
|
||||
* 7,
|
||||
* 5,
|
||||
* 3,
|
||||
* 2,
|
||||
* 1
|
||||
* ]
|
||||
*/
|
||||
win_rewards: number[];
|
||||
/**
|
||||
* @description Rewards for losing the game (first element for last place, second element for second to last place, etc.)
|
||||
* @example [
|
||||
* -3,
|
||||
* -2,
|
||||
* -1
|
||||
* ]
|
||||
*/
|
||||
lose_rewards: number[];
|
||||
};
|
||||
EventOutcome: {
|
||||
points: { [key: string]: number };
|
||||
};
|
||||
/**
|
||||
* EventUpdate
|
||||
* @description An update that can be applied to an event
|
||||
*/
|
||||
EventUpdate:
|
||||
| {
|
||||
Test: components["schemas"]["TestUpdate"];
|
||||
}
|
||||
| {
|
||||
TeamGame: components["schemas"]["TeamGameUpdate"];
|
||||
}
|
||||
| {
|
||||
FreeForAllGame: components["schemas"]["FreeForAllGameUpdate"];
|
||||
};
|
||||
TestUpdate: {
|
||||
win_game: boolean;
|
||||
};
|
||||
TeamGameUpdate: Partial<components["schemas"]["TeamGameUpdateInner"]> &
|
||||
Partial<components["schemas"]["TeamGameFfaInheritedUpdate"]>;
|
||||
TeamGameUpdateInner:
|
||||
| {
|
||||
SetTeam: {
|
||||
team: string;
|
||||
members: string[];
|
||||
};
|
||||
}
|
||||
| {
|
||||
RemoveTeam: string;
|
||||
};
|
||||
TeamGameFfaInheritedUpdate: Partial<
|
||||
components["schemas"]["FreeForAllGameUpdateRanking"]
|
||||
> &
|
||||
Partial<components["schemas"]["FreeForAllGameUpdateRewards"]>;
|
||||
FreeForAllGameUpdateRanking:
|
||||
| {
|
||||
SetRanking: components["schemas"]["FreeForAllGameRanking"];
|
||||
}
|
||||
| {
|
||||
ScoreDelta: { [key: string]: number };
|
||||
};
|
||||
FreeForAllGameUpdateRewards:
|
||||
| {
|
||||
SetWinRewards: number[];
|
||||
}
|
||||
| {
|
||||
SetLoseRewards: number[];
|
||||
};
|
||||
FreeForAllGameUpdate: Partial<
|
||||
components["schemas"]["FreeForAllGameUpdateRanking"]
|
||||
> &
|
||||
Partial<components["schemas"]["FreeForAllGameUpdateRewards"]> &
|
||||
Partial<components["schemas"]["FreeForAllGameUpdateParticipants"]>;
|
||||
FreeForAllGameUpdateParticipants:
|
||||
| {
|
||||
SetParticipants: string[];
|
||||
}
|
||||
| {
|
||||
AddParticipant: string;
|
||||
}
|
||||
| {
|
||||
RemoveParticipant: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export interface operations {
|
||||
/** Returns an array of all users sorted by the given sort field and ordering */
|
||||
get_all_users: {
|
||||
parameters: {
|
||||
query: {
|
||||
sort?: components["schemas"]["UserSort"] | null;
|
||||
order?: components["schemas"]["Ordering"] | null;
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
200: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["User"][];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
/** Returns the created user */
|
||||
add_user: {
|
||||
responses: {
|
||||
201: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["User"];
|
||||
};
|
||||
};
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": string;
|
||||
};
|
||||
};
|
||||
};
|
||||
/** Returns a single user by id */
|
||||
get_user: {
|
||||
parameters: {
|
||||
path: {
|
||||
id: string;
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
200: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["User"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
delete_user: {
|
||||
parameters: {
|
||||
path: {
|
||||
id: string;
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
default: unknown;
|
||||
};
|
||||
};
|
||||
/** Returns the score of a single user by id */
|
||||
get_score: {
|
||||
parameters: {
|
||||
path: {
|
||||
id: string;
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
200: {
|
||||
content: {
|
||||
"application/json": number;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
set_score: {
|
||||
parameters: {
|
||||
path: {
|
||||
id: string;
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
default: unknown;
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": number;
|
||||
};
|
||||
};
|
||||
};
|
||||
/** Returns all events */
|
||||
get_all_events: {
|
||||
parameters: {
|
||||
query: {
|
||||
concluded?: boolean | null;
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
200: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["Event"][];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
/**
|
||||
* If an `id` is supplied, it will be replaced by a randomly generated one.
|
||||
*
|
||||
* Returns the created event.
|
||||
*/
|
||||
create_event: {
|
||||
responses: {
|
||||
200: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["Event"];
|
||||
};
|
||||
};
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["EventSpec"];
|
||||
};
|
||||
};
|
||||
};
|
||||
/** This will conclude the event, apply the outcome to the users and return the outcome. */
|
||||
stop_event: {
|
||||
parameters: {
|
||||
path: {
|
||||
id: string;
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
200: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["EventOutcome"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
/** Returns the event with the given id */
|
||||
get_event: {
|
||||
parameters: {
|
||||
path: {
|
||||
id: string;
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
200: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["Event"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
/** Update the supplied values in the event with the given id. The `id` of an event cannot be changed and `concluded` will always be false. */
|
||||
update_event: {
|
||||
parameters: {
|
||||
path: {
|
||||
id: string;
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
default: unknown;
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["EventUpdate"];
|
||||
};
|
||||
};
|
||||
};
|
||||
/** Returns the outcome of an event. */
|
||||
event_outcome: {
|
||||
parameters: {
|
||||
path: {
|
||||
id: string;
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
200: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["EventOutcome"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export interface external {}
|
|
@ -1 +1,49 @@
|
|||
<h1>Events</h1>
|
||||
<script context="module" lang="ts">
|
||||
import type { components } from "../../apiScheme";
|
||||
|
||||
type Event = components["schemas"]["Event"];
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { onMount } from "svelte";
|
||||
import Button from "../../Button.svelte";
|
||||
import Loading from "../../Loading.svelte";
|
||||
import { apiRequest } from "../../util";
|
||||
import EventCard from "./EventCard.svelte";
|
||||
|
||||
let events: Event[] = [];
|
||||
let loading: boolean = false;
|
||||
let openedEvent: number | undefined;
|
||||
|
||||
const loadEvents = async () => {
|
||||
loading = true;
|
||||
|
||||
let response = await apiRequest('GET', '/event');
|
||||
|
||||
if (response.status == 200) {
|
||||
events = await response.json();
|
||||
} else {
|
||||
console.error(`Request failed: got code ${response.status}, expected 200`);
|
||||
}
|
||||
|
||||
loading = false;
|
||||
};
|
||||
|
||||
onMount(async () => {
|
||||
await loadEvents();
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<div class="max-w-7xl mx-auto">
|
||||
{#if loading === true}
|
||||
<div class="grid place-items-center">
|
||||
<Loading />
|
||||
</div>
|
||||
{/if}
|
||||
{#each events as event, i}
|
||||
<div class="py-2">
|
||||
<EventCard {event} open={openedEvent === i} on:click={() => openedEvent = i} />
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
<script lang="ts">
|
||||
import Block from "./Block.svelte";
|
||||
import AutoDisplay from "./AutoDisplay.svelte";
|
||||
|
||||
export let object: Object;
|
||||
|
||||
const titleCase = (s: string) => s.replace(/^_*(.)|_+(.)/g, (_s, c, d) => c ? c.toUpperCase() : ' ' + d.toUpperCase())
|
||||
|
||||
const name = (key: string) => {
|
||||
switch (key) {
|
||||
default: return titleCase(key);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<Block>
|
||||
{#each Object.entries(object) as [key, value]}
|
||||
{#if value}
|
||||
<p>{name(key)}</p>
|
||||
{#if typeof value === 'object'}
|
||||
<AutoDisplay object={value} />
|
||||
{:else}
|
||||
{value}
|
||||
{/if}
|
||||
{/if}
|
||||
{/each}
|
||||
</Block>
|
|
@ -0,0 +1,3 @@
|
|||
<div class="px-3 py-3 rounded-lg border-solid border-gray-800 border-2 my-3">
|
||||
<slot />
|
||||
</div>
|
|
@ -0,0 +1,19 @@
|
|||
<script context="module" lang="ts">
|
||||
import type { components } from "../../apiScheme";
|
||||
|
||||
type Event = components["schemas"]["Event"];
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import Button from "../../Button.svelte";
|
||||
import { apiRequest } from "../../util";
|
||||
|
||||
export let event: Event;
|
||||
</script>
|
||||
|
||||
|
||||
<p>{event.name} ({event.id}): {event.description}</p>
|
||||
|
||||
{#if 'FreeForAllGame' in event.event_type}
|
||||
{event.event_type['FreeForAllGame'].participants}
|
||||
{/if}
|
|
@ -0,0 +1,33 @@
|
|||
<script context="module" lang="ts">
|
||||
import type { components } from "../../apiScheme";
|
||||
|
||||
type Event = components["schemas"]["Event"];
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import TeamGame from "./TeamGame.svelte";
|
||||
import FreeForAllGame from "./FreeForAllGame.svelte";
|
||||
|
||||
export let event: Event;
|
||||
export let open: boolean = false;
|
||||
</script>
|
||||
|
||||
|
||||
<div class="bg-gray-800 px-5 py-5 rounded-lg" on:click>
|
||||
<p class="text-xl font-bold">{event.name} <span class="text-sm font-normal">[{Object.keys(event.event_type)[0]}]</span></p>
|
||||
<p class="text-sm font-mono">{event.id}</p>
|
||||
|
||||
<p>{event.description}</p>
|
||||
|
||||
{#if open}
|
||||
<div class="bg-gray-700 px-3 py-3 rounded-lg mt-5">
|
||||
{#if 'FreeForAllGame' in event.event_type}
|
||||
{@const et = event.event_type['FreeForAllGame']}
|
||||
<FreeForAllGame event={et} />
|
||||
{:else if 'TeamGame' in event.event_type}
|
||||
{@const et = event.event_type['TeamGame']}
|
||||
<TeamGame event={et} />
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
|
@ -0,0 +1,36 @@
|
|||
<script context="module" lang="ts">
|
||||
import type { components } from "../../apiScheme";
|
||||
|
||||
type EventType = components["schemas"]["FreeForAllGame"];
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import AutoDisplay from "./AutoDisplay.svelte";
|
||||
import Block from "./Block.svelte";
|
||||
|
||||
export let event: EventType;
|
||||
</script>
|
||||
|
||||
|
||||
<AutoDisplay object={event} />
|
||||
<!--
|
||||
<Block>
|
||||
<p>Participants</p>
|
||||
<Block>
|
||||
{#each event.participants as participant}
|
||||
<p>{participant}</p>
|
||||
{/each}
|
||||
</Block>
|
||||
<p>Rewards</p>
|
||||
<Block>
|
||||
<p>Win</p>
|
||||
<Block>
|
||||
<p>{event.win_rewards}</p>
|
||||
</Block>
|
||||
<p>Lose</p>
|
||||
<Block>
|
||||
<p>{event.lose_rewards}</p>
|
||||
</Block>
|
||||
</Block>
|
||||
</Block>
|
||||
-->
|
|
@ -0,0 +1,11 @@
|
|||
<script context="module" lang="ts">
|
||||
import type { components } from "../../apiScheme";
|
||||
|
||||
type TeamGame = components["schemas"]["TeamGame"];
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export let event: TeamGame;
|
||||
</script>
|
||||
|
||||
{event.participants}
|
Loading…
Reference in New Issue