lan-party-frontend/src/routes/users/+page.svelte

143 lines
4.8 KiB
Svelte
Raw Normal View History

2022-09-01 16:03:36 +02:00
<script context="module" lang="ts">
export type User = {
id: string,
name: string,
score: number,
};
</script>
<script lang="ts">
import { onMount } from "svelte";
import Table from "../../Table.svelte";
import { mdiPlus, mdiDelete, mdiPencil, mdiCheck } from '@mdi/js';
import Button from "../../Button.svelte";
import { apiRequest } from "../../util";
let headers = ["Id", "Username", "Score", ""];
let users: User[] | undefined;
let loading = false;
let newUsername: string | undefined;
let scoreEdit: string | undefined;
let newScore: string | undefined;
const loadUsers = async () => {
loading = true;
let response = await apiRequest('GET', '/user');
if (response.status == 200) {
users = await response.json();
} else {
console.error(`Request failed: got code ${response.status}, expected 200`);
}
loading = false;
};
const addUser = async () => {
loading = true;
let response = await apiRequest('POST', '/user', JSON.stringify(newUsername));
if (response.status == 201) {
let user: User = await response.json();
if (users !== undefined) {
users = [...users, user];
} else {
users = [user];
}
} else {
console.error(`Request failed: got code ${response.status}, expected 201`);
}
loading = false;
};
const removeUser = async (id: string) => {
loading = true;
let response = await apiRequest('DELETE', `/user/${id}`);
if (response.status == 200) {
users = users?.filter(user => user.id != id);
} else {
console.error(`Request failed: got code ${response.status}, expected 200`);
}
loading = false;
};
const updateScore = async (id: string) => {
loading = true;
scoreEdit = undefined;
if (newScore !== undefined) {
let response = await apiRequest('POST', `/user/${id}/score`, JSON.stringify(parseInt(newScore)));
if (response.status == 200) {
users = users?.map(u => {
if (u.id == id && newScore !== undefined) {
u.score = parseInt(newScore);
}
return u
});
} else {
console.error(`Request failed: got code ${response.status}, expected 200`);
scoreEdit = id;
}
}
loading = false;
};
onMount(async () => {
await loadUsers();
});
</script>
<div class="max-w-7xl mx-auto">
<Table {headers} {loading}>
{#if users !== undefined}
{#each users as user}
<tr>
<td class="font-mono whitespace-nowrap px-3 py-4 text-sm text-slate-500">{user.id}</td>
<td class="whitespace-nowrap px-3 py-4 text-sm text-slate-400">{user.name}</td>
<td class="whitespace-nowrap px-3 text-sm text-slate-400">
{#if scoreEdit === user.id}
<span class="inline-block">
<input class="mx-2 appearance-none block bg-gray-700 text-slate-400 border border-gray-600 rounded py-2 px-2 w-10 leading-tight focus:outline-none focus:ring-1 focus:ring-gray-500 focus:border-gray-500" placeholder={user.score.toString()} bind:value={newScore}>
</span>
<Button icon={mdiCheck} on:click={() => updateScore(user.id)} />
{:else}
<span class="my-3 w-20">
{user.score}
</span>
<Button icon={mdiPencil} on:click={() => scoreEdit = user.id} />
{/if}
</td>
<td class="whitespace-nowrap py-4 text-sm text-slate-400">
<Button icon={mdiDelete} on:click={() => removeUser(user.id)} />
</td>
</tr>
{/each}
{/if}
<tr>
<td colspan={1} />
<td colspan={1}>
<input class="mx-2 appearance-none block bg-gray-700 text-slate-400 border border-gray-600 rounded py-2 px-4 leading-tight focus:outline-none focus:ring-1 focus:ring-gray-500 focus:border-gray-500" placeholder="username" bind:value={newUsername}>
</td>
<td colspan={1} />
{#if loading === false}
<td colspan={1} class="py-3">
<Button icon={mdiPlus} on:click={() => addUser()} />
</td>
{/if}
</tr>
</Table>
</div>