Compare commits

...

5 Commits

Author SHA1 Message Date
9cd78231c3 add rules read timeout of 30 seconds
All checks were successful
delpoy / build-and-deploy (push) Successful in 42s
2023-11-29 01:25:50 +01:00
47867738f8 update rules 2023-11-29 00:23:21 +01:00
a872613f1e add more stats 2023-11-29 00:15:25 +01:00
38906df545 update 2022 stats 2023-11-28 22:16:43 +01:00
05ddd05a5b update dependencies 2023-11-28 22:15:12 +01:00
23 changed files with 743 additions and 629 deletions

View File

@ -4,6 +4,5 @@
"trailingComma": "none", "trailingComma": "none",
"printWidth": 100, "printWidth": 100,
"plugins": ["prettier-plugin-svelte"], "plugins": ["prettier-plugin-svelte"],
"pluginSearchDirs": ["."],
"overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }] "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
} }

949
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -9,45 +9,45 @@
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"test": "vitest", "test": "vitest",
"lint": "prettier --plugin-search-dir . --check . && eslint .", "lint": "prettier --check . && eslint .",
"format": "prettier --plugin-search-dir . --write ." "format": "prettier --write ."
}, },
"devDependencies": { "devDependencies": {
"@sveltejs/adapter-node": "^1.3.1", "@sveltejs/adapter-node": "^1.3.1",
"@sveltejs/kit": "^1.20.4", "@sveltejs/kit": "^1.27.6",
"@types/bcrypt": "^5.0.0", "@types/bcrypt": "^5.0.2",
"@types/node": "^20.5.6", "@types/node": "^20.10.0",
"@types/validator": "^13.11.1", "@types/validator": "^13.11.7",
"@typescript-eslint/eslint-plugin": "^5.45.0", "@typescript-eslint/eslint-plugin": "^6.13.1",
"@typescript-eslint/parser": "^5.45.0", "@typescript-eslint/parser": "^6.13.1",
"autoprefixer": "^10.4.14", "autoprefixer": "^10.4.16",
"daisyui": "^4.4.10", "daisyui": "^4.4.14",
"eslint": "^8.28.0", "eslint": "^8.54.0",
"eslint-config-prettier": "^8.5.0", "eslint-config-prettier": "^9.0.0",
"eslint-plugin-svelte": "^2.30.0", "eslint-plugin-svelte": "^2.35.1",
"postcss": "^8.4.27", "postcss": "^8.4.31",
"prettier": "^2.8.8", "prettier": "^3.1.0",
"prettier-plugin-svelte": "^2.10.1", "prettier-plugin-svelte": "^3.1.2",
"sass": "^1.66.1", "sass": "^1.69.5",
"svelte": "^4.0.5", "svelte": "^4.2.7",
"svelte-check": "^3.4.3", "svelte-check": "^3.6.2",
"svelte-heros-v2": "^0.9.3", "svelte-heros-v2": "^0.10.12",
"svelte-local-storage-store": "^0.6.0", "svelte-local-storage-store": "^0.6.4",
"svelte-multicssclass": "^2.1.1", "svelte-multicssclass": "^2.1.1",
"svelte-preprocess": "^5.0.4", "svelte-preprocess": "^5.1.1",
"tailwindcss": "^3.3.3", "tailwindcss": "^3.3.5",
"tslib": "^2.4.1", "tslib": "^2.6.2",
"typescript": "^5.0.0", "typescript": "^5.3.2",
"vite": "^4.4.2", "vite": "^4.5.0",
"vitest": "^0.34.1" "vitest": "^0.34.6"
}, },
"type": "module", "type": "module",
"dependencies": { "dependencies": {
"bcrypt": "^5.1.1", "bcrypt": "^5.1.1",
"dotenv": "^16.3.1", "dotenv": "^16.3.1",
"mariadb": "^3.2.0", "mariadb": "^3.2.2",
"sequelize": "^6.32.1", "sequelize": "^6.35.1",
"sequelize-typescript": "^2.1.5", "sequelize-typescript": "^2.1.6",
"sqlite3": "^5.1.6" "sqlite3": "^5.1.6"
} }
} }

View File

@ -1,4 +1,4 @@
<!DOCTYPE html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />

View File

@ -0,0 +1,10 @@
<script lang="ts">
export let size = '24';
export let fill = 'currentColor';
</script>
<svg xmlns="http://www.w3.org/2000/svg" height={size} width={size} {fill} viewBox="0 0 512 512"
><path
d="M256 0c17.7 0 32 14.3 32 32V42.4c93.7 13.9 167.7 88 181.6 181.6H480c17.7 0 32 14.3 32 32s-14.3 32-32 32H469.6c-13.9 93.7-88 167.7-181.6 181.6V480c0 17.7-14.3 32-32 32s-32-14.3-32-32V469.6C130.3 455.7 56.3 381.7 42.4 288H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H42.4C56.3 130.3 130.3 56.3 224 42.4V32c0-17.7 14.3-32 32-32zM107.4 288c12.5 58.3 58.4 104.1 116.6 116.6V384c0-17.7 14.3-32 32-32s32 14.3 32 32v20.6c58.3-12.5 104.1-58.4 116.6-116.6H384c-17.7 0-32-14.3-32-32s14.3-32 32-32h20.6C392.1 165.7 346.3 119.9 288 107.4V128c0 17.7-14.3 32-32 32s-32-14.3-32-32V107.4C165.7 119.9 119.9 165.7 107.4 224H128c17.7 0 32 14.3 32 32s-14.3 32-32 32H107.4zM256 224a32 32 0 1 1 0 64 32 32 0 1 1 0-64z"
/></svg
>

View File

@ -0,0 +1,10 @@
<script lang="ts">
export let size = '24';
export let fill = 'currentColor';
</script>
<svg xmlns="http://www.w3.org/2000/svg" height={size} width={size} {fill} viewBox="0 0 512 512"
><path
d="M416 398.9c58.5-41.1 96-104.1 96-174.9C512 100.3 397.4 0 256 0S0 100.3 0 224c0 70.7 37.5 133.8 96 174.9c0 .4 0 .7 0 1.1v64c0 26.5 21.5 48 48 48h48V464c0-8.8 7.2-16 16-16s16 7.2 16 16v48h64V464c0-8.8 7.2-16 16-16s16 7.2 16 16v48h48c26.5 0 48-21.5 48-48V400c0-.4 0-.7 0-1.1zM96 256a64 64 0 1 1 128 0A64 64 0 1 1 96 256zm256-64a64 64 0 1 1 0 128 64 64 0 1 1 0-128z"
/></svg
>

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { IconSolid } from 'svelte-heros-v2'; import { Eye, EyeSlash } from 'svelte-heros-v2';
import { createEventDispatcher } from 'svelte'; import { createEventDispatcher } from 'svelte';
export let id: string | null = null; export let id: string | null = null;
@ -12,6 +12,7 @@
export let readonly = false; export let readonly = false;
export let size: 'xs' | 'sm' | 'md' | 'lg' = 'md'; export let size: 'xs' | 'sm' | 'md' | 'lg' = 'md';
export let pickyWidth = true; export let pickyWidth = true;
export let containerClass = '';
export let inputElement: HTMLInputElement | undefined = undefined; export let inputElement: HTMLInputElement | undefined = undefined;
@ -34,7 +35,7 @@
</script> </script>
<!-- the cursor-not-allowed class must be set here because a disabled button does not respect the 'cursor' css property --> <!-- the cursor-not-allowed class must be set here because a disabled button does not respect the 'cursor' css property -->
<div class={type === 'submit' && disabled ? 'cursor-not-allowed' : ''}> <div class={containerClass} class:cursor-not-allowed={type === 'submit' && disabled}>
{#if type === 'submit'} {#if type === 'submit'}
<input <input
class="btn" class="btn"
@ -106,17 +107,9 @@
}} }}
> >
{#if type === 'password'} {#if type === 'password'}
<IconSolid <EyeSlash variation="solid" size={passwordEyeSize[size]} />
name="eye-slash-solid"
width={passwordEyeSize[size]}
height={passwordEyeSize[size]}
/>
{:else} {:else}
<IconSolid <Eye variation="solid" size={passwordEyeSize[size]} />
name="eye-solid"
width={passwordEyeSize[size]}
height={passwordEyeSize[size]}
/>
{/if} {/if}
</button> </button>
{/if} {/if}

View File

@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import { createEventDispatcher, getContext, onDestroy } from 'svelte'; import { createEventDispatcher, getContext, onDestroy } from 'svelte';
import type { Writable } from 'svelte/store'; import type { Writable } from 'svelte/store';
import { IconSolid } from 'svelte-heros-v2'; import { ChevronDown, ChevronUp } from 'svelte-heros-v2';
let id = crypto.randomUUID(); let id = crypto.randomUUID();
let asc = false; let asc = false;
@ -26,10 +26,10 @@
}} }}
> >
<span class="mr-1"><slot /></span> <span class="mr-1"><slot /></span>
<IconSolid {#if $ascHeader === id && asc}
name={$ascHeader === id && asc ? 'chevron-up-solid' : 'chevron-down-solid'} <ChevronUp variation="solid" />
width="12" {:else}
height="12" <ChevronDown variation="solid" />
/> {/if}
</button> </button>
</th> </th>

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { IconOutline } from 'svelte-heros-v2'; import { ExclamationCircle } from 'svelte-heros-v2';
import { fly } from 'svelte/transition'; import { fly } from 'svelte/transition';
import { onDestroy } from 'svelte'; import { onDestroy } from 'svelte';
@ -45,7 +45,7 @@
> >
<div class="alert alert-error border-none relative text-gray-900 overflow-hidden"> <div class="alert alert-error border-none relative text-gray-900 overflow-hidden">
<div class="flex gap-2 z-10"> <div class="flex gap-2 z-10">
<IconOutline name="exclamation-circle-outline" /> <ExclamationCircle />
<slot /> <slot />
</div> </div>
<progress <progress

View File

@ -1,4 +1,108 @@
export const rules = { export const rulesShort = {
header: `
Das Lesen der Regeln ist für alle Teilnehmer verpflichtend. Die Regeln sollen für einen reibungslosen und
strukturierte Ablauf des Projekts sorgen, weshalb das Lesen der Regeln ein essenzieller Bestandteil für das Gelingen
von CraftAttack 6 ist. Die Regeln sind wörtlich zu verstehen und sind Grundlage für das Projekt. Zur Vereinfachung
gehen sie nicht zu weit ins Detail und deuten teils nur umfangreiche Themengebiete an. Entscheidungen werden, wenn
von Spielern angeregt, dann durch die Administratoren getroffen, die sich an den Regeln orientieren.
`,
sections: [
{
title: 'Respektvoller Umgang',
content: `
Oberste Priorität hat der respektvolle und tolerante Umgang der Spieler untereinander. Der Spielspaß, der
offene Umgang miteinander und die Interaktion aller steht im Vordergrund, weshalb Drohungen, Belästigungen
oder sonstige gegenüber anderen Spielern respektlose Aktivitäten strengstens verboten sind und auch hart
geahndet werden.`
},
{
title: 'Einschränkungen von Minecraft-Namen, Skins, Chat-Nachrichten, Links, etc.',
content: `
Selbstverständlich sind sämtliche Inhalte (Minecraft-Namen, Skins, Chat-Nachrichten, Links, etc.) mit
sexistischen, diskriminierenden, rassistischen, pornographischen oder illegalen Inhalten nicht erlaubt.
Außerdem ist es nicht gestattet, den Chat mit Nachrichten jeglicher Art vollzuspammen. Des Weiteren sollte
der MC-Name des Spielers, der bei der Anmeldung angegeben wird, bis zum Ende des Projekts nicht geändert
werden. Das Nutzen bzw. Anmelden von Zweitaccounts ist nicht gestattet.
`
},
{
title: 'Clientmodifikationen',
content: `
Jegliche Clientmodifications, die deutliche Vorteile gegenüber anderen Spielern erbringen, sind nicht
gestattet.
`
},
{
title: 'Redstone bauten und überdimensionierte Villager-Baukomplexe',
content: `
Das Erbauen und Betreiben lag-erzeugender Maschinen, Farmen (Zero-Tick-Farmen etc.) oder andere Bauten, die
den Spielfluss stören könnten, ist verboten.
`
},
{
title: 'Verkauf von Items',
content: `
Das Verkaufen von Items ist allgemein jedem Spieler überall gestattet. Jedoch bietet es sich an und ist
wünschenswert, die Shops aller Spieler in einem Shoppingdistrict beim Spawn gemeinsam anzusiedeln, um die
Interaktion zu fördern. Ein angemessener Abstand der privaten Strukturen vom Shoppingdisrict ist
inzuhalten.
`
},
{
title: 'Abstecken von Gebieten und Grundstücken',
content: `
Das Abstecken bestimmter Gebiete ist grundsätzlich erlaubt, jedoch sind unangemessen große Grundstücke
untersagt. Das maximale Maß ist im Einzelfall zu entscheiden. Die Grenzen bereits abgesteckter Grundstücke
sind unveränderlich.
`
},
{
title: 'Verhalten gegenüber anderen Spielern',
content: `
Das Töten, und Beklauen von Spielern ist verboten. Ebenso ist es nicht erlaubt, andere Bauten zu zerstören
(Griefing). Ein gewisser Toleranzspielraum besteht, der im Einzelfall zu bewerten ist.
`
},
{
title: 'Rolle der Administratoren',
content: `
Allgemein liegt es in der Hand der Administratoren einzelne Situation zu bewerten, Strafen zu verhängen und
Entscheidungen zu treffen. Den Entscheidungen und Anweisungen der Administratoren ist stets Folge zu
leisten. Allgemein gilt immer der Grundsatz, dass ein Eingriff der Administratoren nur dann erfolgt, wenn
dies die Spieler auch fordern. Solange beide Parteien zufrieden sind und sich niemand beschwert, passiert
natürlich auch nichts.
`
},
{
title: 'Kontakt zum Administratoren-Team',
content: `
Jedem Teilnehmer ist es möglich sich an den Support/das Administratoren-Team zu wenden. Zu den
Administratoren gehören die Spieler, die auf dem Server mit einem Admin-Tag versehen sind. Zwei von diesen
sind außerdem Administrator der WhatsApp-Gruppe. Eine Kontaktaufnahme ist direkt auf dem Server im Chat
oder auf dem Teamspeak: mhsl.eu möglich. Außerdem können sie über WhatsApp angeschrieben werden, wenn
sich z.B. gerade kein Administrator auf dem Server befindet oder bei anderen Rückfragen. Bei
Unzufriedenheit, Meldung eines Regelverstoßen, Anregungen oder Fragen steht das Administratoren-Team allen
Spielern jederzeit zu Verfügung.
`
},
{
title: 'Konfliktlösung und mögliche Konsequenzen',
content: `
Konflikte sollen grundlegend zuerst auf einer Ebene zwischen den Spielern geschlichtet werden, bevor ein
Administrator kontaktiert wird. Jeder Regelverstoß zieht unterschiedliche Folgen nach sich, die von
Ermahnungen, über Tagesbänne bis zum permanenten Bann führen können. Diese möglichen Konsequenzen sind von
allen Teilnehmern zu akzeptieren.
`
}
],
footer: `
Alle aufgeführten Regeln und die damit in Verbindung stehende Angaben erfolgen ohne Gewähr auf Vollständigkeit,
Richtigkeit und Aktualität. Das Durchsetzen der Regeln liegt im Ermessen der Administratoren, die vorher in
Absprache mit dem Geschädigten eine der Situation angemessene Maßnahmen getroffen haben.
`
};
export const rulesLong = {
header: ` header: `
Das Lesen der Regeln ist für alle Teilnehmer verpflichtend. Die Regeln sollen für einen reibungslosen und Das Lesen der Regeln ist für alle Teilnehmer verpflichtend. Die Regeln sollen für einen reibungslosen und
strukturierte Ablauf des Projekts sorgen, weshalb das Lesen der Regeln ein essenzieller Bestandteil für das Gelingen strukturierte Ablauf des Projekts sorgen, weshalb das Lesen der Regeln ein essenzieller Bestandteil für das Gelingen

View File

@ -25,13 +25,6 @@
active: false active: false
} }
]; ];
let footerLinks = [
{
name: 'Teamspeak',
icon: '<svg xmlns="http://www.w3.org/2000/svg" height="1em" viewBox="0 0 576 512"><!--! Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M152.8 37.2c-32.2 38.1-56.1 82.6-69.9 130.5c0 .2-.1 .3-.1 .5C43.5 184.4 16 223 16 268c0 59.6 48.4 108 108 108s108-48.4 108-108c0-53.5-38.9-97.9-90-106.5c15.7-41.8 40.4-79.6 72.3-110.7c1.8-1.6 4-2.6 6.3-3.1c37.2-11.5 76.7-13.3 114.8-5.2C454.7 67.6 534 180.7 517.1 301.3c-8.4 62.6-38.6 112.7-87.7 151.4c-50.1 39.7-107.5 54.3-170.2 52.2l-24-1c12.4 2.8 25 4.9 37.6 6.3c40.7 4.2 81.4 2.1 120.1-12.5c94-35.5 149.3-102.3 162.9-202.5c4.8-52.6-5.8-105.4-30.8-152C454.6 11.3 290.8-38.4 159 32c-2.4 1.4-4.5 3.1-6.3 5.2zM309.4 433.9c-2.1 11.5-4.2 21.9-14.6 31.3c53.2-1 123.2-29.2 161.8-97.1c39.7-69.9 37.6-139.9-6.3-207.8C413.8 105 360.5 77.9 293.7 73.7c1.5 2.3 3.2 4.4 5.2 6.3l5.2 6.3c25.1 31.3 37.6 67.9 42.8 107.5c2.1 15.7-1 30.3-13.6 41.8c-4.2 3.1-5.2 6.3-4.2 10.4l7.3 17.7L365.7 318c5.2 11.5 4.2 19.8-6.3 28.2c-3.2 2.5-6.7 4.6-10.4 6.3l-18.8 8.4 3.1 13.6c3.1 6.3 1 12.5-3.1 17.7c-2.5 2.4-3.8 5.9-3.1 9.4c2.1 11.5-2.1 19.8-12.5 25.1c-2.1 1-4.2 5.2-5.2 7.3zm-133.6-3.1c16.7 11.5 34.5 20.9 53.2 26.1c24 5.2 41.8-6.3 44.9-30.3c1-8.4 5.2-14.6 12.5-17.7c7.3-4.2 8.4-7.3 2.1-13.6l-9.4-8.4 13.6-4.2c6.3-2.1 7.3-5.2 5.2-11.5c-1.4-3-2.4-6.2-3.1-9.4c-3.1-14.6-2.1-15.7 11.5-18.8c8.4-3.1 15.7-6.3 21.9-12.5c3.1-2.1 3.1-4.2 1-8.4l-16.7-30.3c-1-1.9-2.1-3.8-3.1-5.7c-6.4-11.7-13-23.6-15.7-37.1c-2.1-9.4-1-17.7 8.4-24c5.2-4.2 8.4-9.4 8.4-16.7c-.4-10.1-1.5-20.3-3.1-30.3c-6.3-37.6-23-68.9-51.2-95c-5.2-4.2-9.4-6.3-16.7-4.2L203.9 91.5c2 1.2 4 2.4 6 3.6l0 0c6.3 3.7 12.2 7.3 17 12.1c30.3 26.1 41.8 61.6 45.9 100.2c1 8.4 0 16.7-7.3 21.9c-8.4 5.2-10.4 12.5-7.3 20.9c4.9 13.2 10.4 26 16.7 38.6L291.6 318c-6.3 8.4-13.6 11.5-21.9 14.6c-12.5 3.1-14.6 7.3-10.4 20.9c.6 1.5 1.4 2.8 2.1 4.2c2.1 5.2 1 8.4-4.2 10.4l-12.5 3.1 5.2 4.2 4.2 4.2c4.2 5.2 4.2 8.4-2.1 10.4c-7.3 4.2-11.5 9.4-11.5 17.7c0 12.5-7.3 19.8-18.8 24c-3.8 1-7.6 1.5-11.5 1l-34.5-2.1z"/></svg>',
href: 'ts3server://mhsl.eu'
}
];
let showMenuPermanent = false; let showMenuPermanent = false;
let menuButtonScrollIndex: number | null = null; let menuButtonScrollIndex: number | null = null;
@ -81,7 +74,7 @@
/> />
<main> <main>
<div class="min-h-screen w-full"> <div class="h-screen w-full">
<slot /> <slot />
</div> </div>
</main> </main>

View File

@ -1,7 +1,9 @@
<script lang="ts"> <script lang="ts">
import { env } from '$env/dynamic/public'; import { env } from '$env/dynamic/public';
import Countdown from '$lib/components/Countdown/Countdown.svelte'; import Countdown from '$lib/components/Countdown/Countdown.svelte';
import { IconOutline } from 'svelte-heros-v2'; import { User, WrenchScrewdriver } from 'svelte-heros-v2';
import Crosshairs from '$lib/components/CustomIcons/Crosshairs.svelte';
import Skull from '$lib/components/CustomIcons/Skull.svelte';
let information = [ let information = [
{ {
@ -83,25 +85,40 @@
<div class="flex flex-col xl:flex-row justify-center items-center py-20 bg-base-100"> <div class="flex flex-col xl:flex-row justify-center items-center py-20 bg-base-100">
<div> <div>
<h3 class="text-center text-2xl mb-6">2022 in Zahlen</h3> <h3 class="text-center text-2xl mb-6">2022 in Zahlen</h3>
<div class="stats stats-vertical sm:stats-horizontal shadow"> <div class="flex flex-col lg:flex-row gap-4">
<div class="stat"> <div class="stats stats-vertical sm:stats-horizontal shadow">
<div class="stat-figure"> <div class="stat">
<img <div class="stat-figure">
class="w-8 h-8" <WrenchScrewdriver />
src="{env.PUBLIC_BASE_PATH}/img/netherrack.webp" </div>
alt="" <div class="stat-title">Abgebaute Blöcke</div>
title="Netherrack" <div class="stat-value">26.5M</div>
/> <div class="stat-desc"><span class="underline">2.3M</span> davon Netherrack</div>
</div>
<div class="stat">
<div class="stat-figure">
<User />
</div>
<div class="stat-title">Teilnehmer</div>
<div class="stat-value">135</div>
</div> </div>
<div class="stat-title">Meistabgebauter Block</div>
<div class="stat-value">2.3M</div>
</div> </div>
<div class="stat"> <div class="stats stats-vertical sm:stats-horizontal shadow">
<div class="stat-figure"> <div class="stat">
<IconOutline name="user-outline" /> <div class="stat-figure">
<Crosshairs />
</div>
<div class="stat-title">Getötete Mobs</div>
<div class="stat-value">1.2M</div>
</div>
<div class="stat">
<div class="stat-figure">
<Skull />
</div>
<div class="stat-title">Spieler Tode</div>
<div class="stat-value">3996</div>
<div class="stat-desc"><span class="underline">578</span> davon durch andere Spieler</div>
</div> </div>
<div class="stat-title">Angemeldete Spieler</div>
<div class="stat-value">156</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import { page } from '$app/stores'; import { page } from '$app/stores';
import { env } from '$env/dynamic/public'; import { env } from '$env/dynamic/public';
import { IconOutline } from 'svelte-heros-v2'; import { ArrowLeftOnRectangle, Flag, UserGroup, Users } from 'svelte-heros-v2';
import { buttonTriggeredRequest } from '$lib/components/utils'; import { buttonTriggeredRequest } from '$lib/components/utils';
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import type { LayoutData } from './$types'; import type { LayoutData } from './$types';
@ -26,21 +26,21 @@
let tabs = [ let tabs = [
{ {
path: `${env.PUBLIC_BASE_PATH}/admin/users`, path: `${env.PUBLIC_BASE_PATH}/admin/users`,
icon: 'user-group-outline', icon: UserGroup,
name: 'Registrierte Nutzer', name: 'Registrierte Nutzer',
badge: data.userCount, badge: data.userCount,
enabled: data.userCount != null enabled: data.userCount != null
}, },
{ {
path: `${env.PUBLIC_BASE_PATH}/admin/reports`, path: `${env.PUBLIC_BASE_PATH}/admin/reports`,
icon: 'flag-outline', icon: Flag,
name: 'Reports', name: 'Reports',
badge: $reportCount, badge: $reportCount,
enabled: data.reportCount != null enabled: data.reportCount != null
}, },
{ {
path: `${env.PUBLIC_BASE_PATH}/admin/admin`, path: `${env.PUBLIC_BASE_PATH}/admin/admin`,
icon: 'users-outline', icon: Users,
name: 'Website Admins', name: 'Website Admins',
badge: $adminCount, badge: $adminCount,
enabled: data.adminCount != null enabled: data.adminCount != null
@ -55,7 +55,7 @@
{#if tab.enabled} {#if tab.enabled}
<li> <li>
<a href={tab.path}> <a href={tab.path}>
<IconOutline name={tab.icon} /> <svelte:component this={tab.icon} />
<span class="mr-1" class:underline={$page.url.pathname === tab.path}>{tab.name}</span> <span class="mr-1" class:underline={$page.url.pathname === tab.path}>{tab.name}</span>
<div class="badge">{tab.badge}</div> <div class="badge">{tab.badge}</div>
</a> </a>
@ -67,7 +67,7 @@
<ul class="menu menu-vertical"> <ul class="menu menu-vertical">
<li> <li>
<button on:click={(e) => buttonTriggeredRequest(e, logout())}> <button on:click={(e) => buttonTriggeredRequest(e, logout())}>
<IconOutline name="arrow-left-on-rectangle-outline" /> <ArrowLeftOnRectangle />
<span>Ausloggen</span> <span>Ausloggen</span>
</button> </button>
</li> </li>

View File

@ -1,26 +1,26 @@
<script lang="ts"> <script lang="ts">
import type { PageData } from './$types'; import type { PageData } from './$types';
import { env } from '$env/dynamic/public'; import { env } from '$env/dynamic/public';
import { IconOutline } from 'svelte-heros-v2'; import { Flag, UserGroup, Users } from 'svelte-heros-v2';
export let data: PageData; export let data: PageData;
let tabs = [ let tabs = [
{ {
path: `${env.PUBLIC_BASE_PATH}/admin/users`, path: `${env.PUBLIC_BASE_PATH}/admin/users`,
icon: 'user-group-outline', icon: UserGroup,
name: 'Registrierte Nutzer', name: 'Registrierte Nutzer',
enabled: data.userCount != null enabled: data.userCount != null
}, },
{ {
path: `${env.PUBLIC_BASE_PATH}/admin/reports`, path: `${env.PUBLIC_BASE_PATH}/admin/reports`,
icon: 'flag-outline', icon: Flag,
name: 'Reports', name: 'Reports',
enabled: data.reportCount != null enabled: data.reportCount != null
}, },
{ {
path: `${env.PUBLIC_BASE_PATH}/admin/admin`, path: `${env.PUBLIC_BASE_PATH}/admin/admin`,
icon: 'users-outline', icon: Users,
name: 'Website Admins', name: 'Website Admins',
enabled: data.adminCount != null enabled: data.adminCount != null
} }
@ -36,7 +36,7 @@
href={tab.path} href={tab.path}
title={tab.name} title={tab.name}
> >
<IconOutline width="5rem" height="5rem" name={tab.icon} /> <svelte:component this={tab.icon} width="5rem" height="5rem" />
</a> </a>
<span>{tab.name}</span> <span>{tab.name}</span>
</div> </div>

View File

@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import type { PageData } from './$types'; import type { PageData } from './$types';
import Badges from '$lib/components/Input/Badges.svelte'; import Badges from '$lib/components/Input/Badges.svelte';
import { IconOutline } from 'svelte-heros-v2'; import { Check, NoSymbol, PencilSquare, Trash, UserPlus } from 'svelte-heros-v2';
import Input from '$lib/components/Input/Input.svelte'; import Input from '$lib/components/Input/Input.svelte';
import { Permissions } from '$lib/permissions'; import { Permissions } from '$lib/permissions';
import { env } from '$env/dynamic/public'; import { env } from '$env/dynamic/public';
@ -155,7 +155,7 @@
admin.edit = false; admin.edit = false;
}} }}
> >
<IconOutline name="check-outline" width="18" height="18" /> <Check size="18" />
</button> </button>
</span> </span>
<span class="w-min" class:cursor-not-allowed={!permissions.adminWrite()}> <span class="w-min" class:cursor-not-allowed={!permissions.adminWrite()}>
@ -167,7 +167,7 @@
admin = admin.before; admin = admin.before;
}} }}
> >
<IconOutline name="no-symbol-outline" width="18" height="18" /> <NoSymbol size="18" />
</button> </button>
</span> </span>
{:else} {:else}
@ -180,7 +180,7 @@
admin.before = structuredClone(admin); admin.before = structuredClone(admin);
}} }}
> >
<IconOutline name="pencil-square-outline" width="18" height="18" /> <PencilSquare size="18" />
</button> </button>
</span> </span>
<span class="w-min" class:cursor-not-allowed={!permissions.adminWrite()}> <span class="w-min" class:cursor-not-allowed={!permissions.adminWrite()}>
@ -189,7 +189,7 @@
disabled={!permissions.adminWrite()} disabled={!permissions.adminWrite()}
on:click={(e) => buttonTriggeredRequest(e, deleteAdmin(admin.id))} on:click={(e) => buttonTriggeredRequest(e, deleteAdmin(admin.id))}
> >
<IconOutline name="trash-outline" width="18" height="18" /> <Trash size="18" />
</button> </button>
</span> </span>
{/if} {/if}
@ -228,7 +228,7 @@
newAdminPermissions = []; newAdminPermissions = [];
}} }}
> >
<IconOutline name="user-plus-outline" width="18" height="18" /> <UserPlus size="18" />
</button> </button>
</span> </span>
</td> </td>

View File

@ -9,7 +9,7 @@
import Textarea from '$lib/components/Input/Textarea.svelte'; import Textarea from '$lib/components/Input/Textarea.svelte';
import { reportCount } from '$lib/stores'; import { reportCount } from '$lib/stores';
import HeaderBar from './HeaderBar.svelte'; import HeaderBar from './HeaderBar.svelte';
import { IconOutline } from 'svelte-heros-v2'; import { MagnifyingGlass, Plus, Share } from 'svelte-heros-v2';
import NewReportModal from './NewReportModal.svelte'; import NewReportModal from './NewReportModal.svelte';
import { onDestroy, onMount } from 'svelte'; import { onDestroy, onMount } from 'svelte';
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
@ -139,7 +139,7 @@
title="Nach Ersteller filtern" title="Nach Ersteller filtern"
on:click|stopPropagation={() => (reportFilter.reporter = report.reporter.username)} on:click|stopPropagation={() => (reportFilter.reporter = report.reporter.username)}
> >
<IconOutline name="magnifying-glass-outline" width="14" height="14" /> <MagnifyingGlass size="14" />
</button> </button>
</td> </td>
<td> <td>
@ -151,7 +151,7 @@
on:click|stopPropagation={() => on:click|stopPropagation={() =>
(reportFilter.reported = report.reported.username)} (reportFilter.reported = report.reported.username)}
> >
<IconOutline name="magnifying-glass-outline" width="14" height="14" /> <MagnifyingGlass size="14" />
</button> </button>
{/if} {/if}
</td> </td>
@ -168,10 +168,10 @@
{report.status === 'none' {report.status === 'none'
? 'Unbearbeitet' ? 'Unbearbeitet'
: report.status === 'review' : report.status === 'review'
? 'In Bearbeitung' ? 'In Bearbeitung'
: report.status === 'reviewed' : report.status === 'reviewed'
? 'Bearbeitet' ? 'Bearbeitet'
: ''} : ''}
</td> </td>
<td>{report.draft ? 'Entwurf' : 'Erstellt'}</td> <td>{report.draft ? 'Entwurf' : 'Erstellt'}</td>
</tr> </tr>
@ -180,7 +180,7 @@
<td colspan="100"> <td colspan="100">
<div class="flex justify-center items-center"> <div class="flex justify-center items-center">
<button class="btn btn-sm" on:click={() => newReportModal.show()}> <button class="btn btn-sm" on:click={() => newReportModal.show()}>
<IconOutline name="plus-outline" /> <Plus />
<span>Neuer Report</span> <span>Neuer Report</span>
</button> </button>
</div> </div>
@ -198,7 +198,7 @@
<form class="dropdown dropdown-end"> <form class="dropdown dropdown-end">
<!-- svelte-ignore a11y-no-noninteractive-tabindex a11y-label-has-associated-control --> <!-- svelte-ignore a11y-no-noninteractive-tabindex a11y-label-has-associated-control -->
<label tabindex="0" class="btn btn-sm btn-circle btn-ghost text-center"> <label tabindex="0" class="btn btn-sm btn-circle btn-ghost text-center">
<IconOutline name="share-outline" height="1rem" width="auto" /> <Share size="1rem" />
</label> </label>
<!-- svelte-ignore a11y-no-noninteractive-tabindex --> <!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<ul <ul

View File

@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import type { PageData } from './$types'; import type { PageData } from './$types';
import { IconOutline } from 'svelte-heros-v2'; import { Check, NoSymbol, PencilSquare, Trash } from 'svelte-heros-v2';
import Input from '$lib/components/Input/Input.svelte'; import Input from '$lib/components/Input/Input.svelte';
import Select from '$lib/components/Input/Select.svelte'; import Select from '$lib/components/Input/Select.svelte';
import { env } from '$env/dynamic/public'; import { env } from '$env/dynamic/public';
@ -172,7 +172,7 @@
user.edit = false; user.edit = false;
}} }}
> >
<IconOutline name="check-outline" width="18" height="18" /> <Check size="18" />
</button> </button>
<button <button
class="btn btn-sm btn-square" class="btn btn-sm btn-square"
@ -181,7 +181,7 @@
user = user.before; user = user.before;
}} }}
> >
<IconOutline name="no-symbol-outline" width="18" height="18" /> <NoSymbol size="18" />
</button> </button>
{:else} {:else}
<button <button
@ -191,13 +191,13 @@
user.edit = true; user.edit = true;
}} }}
> >
<IconOutline name="pencil-square-outline" width="18" height="18" /> <PencilSquare size="18" />
</button> </button>
<button <button
class="btn btn-sm btn-square" class="btn btn-sm btn-square"
on:click={(e) => buttonTriggeredRequest(e, deleteUser(user.id))} on:click={(e) => buttonTriggeredRequest(e, deleteUser(user.id))}
> >
<IconOutline name="trash-outline" width="18" height="18" /> <Trash size="18" />
</button> </button>
{/if} {/if}
</div> </div>

View File

@ -1,23 +1,3 @@
<script> <div class="flex justify-center w-full bg-base-200">
import { env } from '$env/dynamic/public';
</script>
<div class="fixed top-0 left-0 h-full w-full bg-[#050505]" />
<img
class="bg-snipped bg-black fixed top-0 left-0 h-full w-full object-cover pointer-events-none blur-[2px]"
src="{env.PUBLIC_BASE_PATH}/img/register-background.webp"
alt=""
/>
<div class="flex justify-center w-full">
<slot /> <slot />
</div> </div>
<style>
.bg-snipped {
/* prettier-ignore */
clip-path: polygon(
0 20%, 100% -35%, 100% -5%, 0 50%,
0 110%, 100% 50%, 100% 80%, 0 140%
);
}
</style>

View File

@ -12,7 +12,7 @@
<!--the tooltip when not all fields are correctly filled won't completely show if the overflow is hidden--> <!--the tooltip when not all fields are correctly filled won't completely show if the overflow is hidden-->
<div <div
class="grid card w-11/12 xl:w-2/3 2xl:w-1/2 p-6 my-12 bg-base-100 shadow-[0_0_10px_10px_rgba(0,0,0,0.7)]" class="grid card w-11/12 xl:w-2/3 2xl:w-1/2 p-6 my-12 bg-base-100 shadow-lg"
class:overflow-hidden={registered} class:overflow-hidden={registered}
> >
{#if !registered} {#if !registered}

View File

@ -3,7 +3,7 @@
import Input from '$lib/components/Input/Input.svelte'; import Input from '$lib/components/Input/Input.svelte';
import { createEventDispatcher, onMount } from 'svelte'; import { createEventDispatcher, onMount } from 'svelte';
import { env } from '$env/dynamic/public'; import { env } from '$env/dynamic/public';
import { rules } from '$lib/rules'; import { rulesShort } from '$lib/rules';
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
@ -55,7 +55,9 @@
} }
let rulesAccepted = false; let rulesAccepted = false;
let rulesModal: HTMLDialogElement | null = null; let rulesModal: HTMLDialogElement;
let rulesModalSecondsOpened = 0;
let rulesModalTimer: number | null = null;
let inputsInvalidMessage: string | null = 'Bitte fülle alle erforderlichen Felder aus'; let inputsInvalidMessage: string | null = 'Bitte fülle alle erforderlichen Felder aus';
let registerRequest: Promise<void> | null = null; let registerRequest: Promise<void> | null = null;
@ -162,6 +164,7 @@
if (!rulesAccepted) { if (!rulesAccepted) {
e.detail.target.checked = false; e.detail.target.checked = false;
rulesModal.show(); rulesModal.show();
rulesModalTimer = setInterval(() => rulesModalSecondsOpened++, 1000);
} }
}} }}
bind:inputElement={rulesInput} bind:inputElement={rulesInput}
@ -219,7 +222,14 @@
</div> </div>
</form> </form>
<dialog class="modal" bind:this={rulesModal}> <dialog
class="modal"
on:close={() => {
clearInterval(rulesModalTimer);
rulesModalTimer = null;
}}
bind:this={rulesModal}
>
<form method="dialog" class="modal-box flex max-w-[95%] md:max-w-[90%] lg:max-w-[75%]"> <form method="dialog" class="modal-box flex max-w-[95%] md:max-w-[90%] lg:max-w-[75%]">
<button class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"></button> <button class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"></button>
<div class="overflow-auto"> <div class="overflow-auto">
@ -230,12 +240,12 @@
<p>0. Vorwort</p> <p>0. Vorwort</p>
</div> </div>
<div class="collapse-content"> <div class="collapse-content">
<p>{rules.header}</p> <p>{rulesShort.header}</p>
<p class="mt-1 text-[.75rem]">{rules.footer}</p> <p class="mt-1 text-[.75rem]">{rulesShort.footer}</p>
</div> </div>
<span class="block w-full h-[1px] mx-auto mb-1 bg-gray-600" /> <span class="block w-full h-[1px] mx-auto mb-1 bg-gray-600" />
</div> </div>
{#each rules.sections as section, i} {#each rulesShort.sections as section, i}
<div class="collapse collapse-arrow"> <div class="collapse collapse-arrow">
<input type="checkbox" autocomplete="off" /> <input type="checkbox" autocomplete="off" />
<div class="collapse-title"> <div class="collapse-title">
@ -248,15 +258,30 @@
<span class="block w-full h-[1px] mx-auto mb-1 bg-gray-600" /> <span class="block w-full h-[1px] mx-auto mb-1 bg-gray-600" />
{/each} {/each}
</div> </div>
<div> <div
class="relative w-min"
title={rulesModalSecondsOpened < 30
? `Regeln können in ${Math.max(
30 - rulesModalSecondsOpened,
0
)} Sekunden akzeptiert werden`
: ''}
>
<div class="absolute top-0 left-0 h-full w-full overflow-hidden rounded-lg">
<div
style="width: {Math.min((rulesModalSecondsOpened / 30) * 100, 100)}%"
class="h-full bg-base-300"
/>
</div>
<Input <Input
id="rules-accept" id="rules-accept"
type="submit" type="submit"
value="Akzeptieren" value="Akzeptieren"
disabled={rulesModalSecondsOpened < 30}
containerClass="bg-transparent z-[1] relative"
on:click={() => { on:click={() => {
rulesAccepted = true; rulesAccepted = true;
rulesInput.checked = true; rulesInput.checked = true;
// doesn't get triggered by `rulesInput.checked = true` so it must be called manually
checkInputs(); checkInputs();
}} }}
/> />

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { IconSolid } from 'svelte-heros-v2'; import { ChevronRight } from 'svelte-heros-v2';
import { createEventDispatcher } from 'svelte'; import { createEventDispatcher } from 'svelte';
import { env } from '$env/dynamic/public'; import { env } from '$env/dynamic/public';
@ -18,7 +18,7 @@
<div class="flex items-center h-12 mb-2"> <div class="flex items-center h-12 mb-2">
<button class="sm:absolute btn btn-sm btn-square" on:click={() => dispatch('close')}> <button class="sm:absolute btn btn-sm btn-square" on:click={() => dispatch('close')}>
<IconSolid name="chevron-left-solid" /> <ChevronRight variation="outline" />
</button> </button>
<h1 class="text-center text-xl sm:text-3xl m-auto">Registrierung erfolgreich</h1> <h1 class="text-center text-xl sm:text-3xl m-auto">Registrierung erfolgreich</h1>
</div> </div>

View File

@ -1,3 +1,3 @@
<div class="mx-4 sm:mx-48"> <div class="mx-4 my-6 sm:mx-48 sm:my-12">
<slot /> <slot />
</div> </div>

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { rules } from '$lib/rules'; import { rulesLong } from '$lib/rules';
</script> </script>
<svelte:head> <svelte:head>
@ -7,14 +7,14 @@
</svelte:head> </svelte:head>
<h1 class="text-3xl lg:text-5xl mb-4">CraftAttack 6 Regelwerk</h1> <h1 class="text-3xl lg:text-5xl mb-4">CraftAttack 6 Regelwerk</h1>
<p>{rules.header}</p> <p>{rulesLong.header}</p>
<ol class="p-[revert] list-decimal my-6"> <ol class="p-[revert] list-decimal my-6">
{#each rules.sections as section} {#each rulesLong.sections as section}
<li class="mb-2"> <li class="mb-2">
{section.content} {section.content}
</li> </li>
{/each} {/each}
</ol> </ol>
<p> <p>
{rules.footer} {rulesLong.footer}
</p> </p>