172 lines
5.9 KiB
Svelte
172 lines
5.9 KiB
Svelte
<script lang="ts">
|
|
import axios from "axios";
|
|
import {
|
|
isWall,
|
|
type Category,
|
|
type CategoryId,
|
|
type QuestionId,
|
|
type VisitedQuestions,
|
|
type Wall
|
|
} from "./Types";
|
|
import { url } from "./util";
|
|
import { onMount } from "svelte";
|
|
import type { FullWall } from "./games/games";
|
|
import Button from "./Button.svelte";
|
|
import Modal from "./Modal.svelte";
|
|
import Textfield from "./Textfield.svelte";
|
|
import { fetchCategory } from "../routes/editor/fetchers";
|
|
|
|
interface Props {
|
|
wall: Wall | FullWall | undefined;
|
|
onclick?: (catIndex: number, questionIndex: number) => unknown;
|
|
onclickIds?: (catId: CategoryId, questionId: QuestionId) => unknown;
|
|
visited: VisitedQuestions;
|
|
isEditor?: boolean;
|
|
}
|
|
|
|
function isVisited(catIndex: number, queIndex: number): boolean {
|
|
return visited[catIndex] && visited[catIndex].includes(queIndex);
|
|
}
|
|
|
|
let { wall, onclick, onclickIds, visited, isEditor = false }: Props = $props();
|
|
|
|
let categories: Category[] = $state([]);
|
|
|
|
let showRenameCategory = $state(false);
|
|
let catToRename: Category | undefined = $state();
|
|
let newCatName = $state("");
|
|
let error = $state("");
|
|
|
|
async function fetchCategories(wall: Wall | FullWall | undefined) {
|
|
if (wall && isWall(wall)) {
|
|
let cats: Promise<Category>[] = [];
|
|
for (const catId of wall.categories) {
|
|
cats.push(fetchCategory(catId));
|
|
}
|
|
return Promise.all(cats).then((cats) => {
|
|
categories = cats;
|
|
});
|
|
}
|
|
}
|
|
|
|
async function renameCategory() {
|
|
if (!newCatName || !catToRename) return false;
|
|
return axios
|
|
.post(
|
|
url(`/category/rename`),
|
|
{
|
|
categoryid: catToRename._id,
|
|
name: newCatName
|
|
},
|
|
{ withCredentials: true }
|
|
)
|
|
.then((response) => {
|
|
if (response.status === 200) {
|
|
newCatName = "";
|
|
catToRename = undefined;
|
|
fetchCategories(wall);
|
|
return true;
|
|
} else {
|
|
console.error(`Failed to rename category: ${response.status}`);
|
|
return false;
|
|
}
|
|
})
|
|
.catch((err) => {
|
|
console.error(err);
|
|
return false;
|
|
});
|
|
}
|
|
|
|
function renameCategoryCancel() {
|
|
newCatName = "";
|
|
catToRename = undefined;
|
|
}
|
|
|
|
$effect(() => {
|
|
fetchCategories(wall);
|
|
});
|
|
|
|
onMount(() => {
|
|
fetchCategories(wall);
|
|
});
|
|
</script>
|
|
|
|
{#if wall != undefined}
|
|
<div class="grid h-full grow grid-flow-col grid-cols-5 grid-rows-6 gap-4 pb-4">
|
|
{#if isWall(wall)}
|
|
{#each categories as category, catIndex}
|
|
<div class="flex items-center justify-center gap-2 text-3xl font-semibold">
|
|
<div>{category.name}</div>
|
|
{#if isEditor}
|
|
<Button
|
|
onclick={() => {
|
|
catToRename = category;
|
|
newCatName = category.name;
|
|
showRenameCategory = true;
|
|
}}><i class="fa-solid fa-pen"></i></Button
|
|
>
|
|
{/if}
|
|
</div>
|
|
{#each category.questions as question, queIndex}
|
|
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
<div
|
|
class="card {isVisited(catIndex, queIndex) ? 'visited' : ''}"
|
|
role="button"
|
|
aria-pressed="false"
|
|
tabindex="0"
|
|
onclick={() => {
|
|
if (onclickIds) onclickIds(category._id, question._id);
|
|
}}
|
|
>
|
|
<div class="text-6xl font-thin">
|
|
{question.points >= 0 ? question.points : "???"}
|
|
</div>
|
|
</div>
|
|
{/each}
|
|
{/each}
|
|
{:else}
|
|
{#each wall.categories as category, catIndex}
|
|
<div class="flex items-center justify-center text-3xl font-semibold">
|
|
<div>{category.name}</div>
|
|
</div>
|
|
{#each category.questions as question, queIndex}
|
|
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
<div
|
|
class="card {isVisited(catIndex, queIndex) ? 'visited' : ''}"
|
|
role="button"
|
|
aria-pressed="false"
|
|
tabindex="0"
|
|
onclick={() => {
|
|
if (onclick) onclick(catIndex, queIndex);
|
|
}}
|
|
>
|
|
<div class="text-6xl font-thin">
|
|
{question.points >= 0 ? question.points : "???"}
|
|
</div>
|
|
</div>
|
|
{/each}
|
|
{/each}
|
|
{/if}
|
|
</div>
|
|
{:else}
|
|
<p>Wall is undefined</p>
|
|
{/if}
|
|
|
|
<Modal bind:showModal={showRenameCategory} okFn={renameCategory} cancelFn={renameCategoryCancel}>
|
|
{#snippet header()}
|
|
<h2 class="text-3xl">Kategorie umbenennen</h2>
|
|
{/snippet}
|
|
<div>
|
|
<Textfield bind:value={newCatName} label="Name"></Textfield>
|
|
{#if error.length > 0}
|
|
<div class="text-red-700">{error}</div>
|
|
{/if}
|
|
</div>
|
|
</Modal>
|
|
|
|
<style>
|
|
.visited {
|
|
background-color: gray;
|
|
}
|
|
</style>
|