diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index b3ecdec..cf0b463 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -7,6 +7,9 @@
"": {
"name": "frontend",
"version": "0.0.1",
+ "dependencies": {
+ "zod": "^4.0.14"
+ },
"devDependencies": {
"@sveltejs/adapter-auto": "^6.0.0",
"@sveltejs/kit": "^2.22.0",
@@ -2304,6 +2307,15 @@
"integrity": "sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w==",
"dev": true,
"license": "MIT"
+ },
+ "node_modules/zod": {
+ "version": "4.0.14",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-4.0.14.tgz",
+ "integrity": "sha512-nGFJTnJN6cM2v9kXL+SOBq3AtjQby3Mv5ySGFof5UGRHrRioSJ5iG680cYNjE/yWk671nROcpPj4hAS8nyLhSw==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
}
}
}
diff --git a/frontend/package.json b/frontend/package.json
index cee9931..cdbbe97 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -26,5 +26,8 @@
"tailwindcss": "^4.0.0",
"typescript": "^5.0.0",
"vite": "^7.0.4"
+ },
+ "dependencies": {
+ "zod": "^4.0.14"
}
}
diff --git a/frontend/src/app.css b/frontend/src/app.css
index d4b5078..90d8258 100644
--- a/frontend/src/app.css
+++ b/frontend/src/app.css
@@ -1 +1,15 @@
@import 'tailwindcss';
+
+@keyframes spin-slower {
+ from {
+ transform: rotate(0deg);
+ }
+
+ to {
+ transform: rotate(360deg);
+ }
+}
+
+.spin-slower {
+ animation: spin-slower 15s linear infinite;
+}
diff --git a/frontend/src/lib/components/Error.svelte b/frontend/src/lib/components/Error.svelte
new file mode 100644
index 0000000..47e6a19
--- /dev/null
+++ b/frontend/src/lib/components/Error.svelte
@@ -0,0 +1,8 @@
+
+
+
+
Error {code}
+
{message}
+
diff --git a/frontend/src/lib/components/QueueSlider.svelte b/frontend/src/lib/components/QueueSlider.svelte
index 1db4c6a..dec52c5 100644
--- a/frontend/src/lib/components/QueueSlider.svelte
+++ b/frontend/src/lib/components/QueueSlider.svelte
@@ -1,30 +1,38 @@
{#each displaySongs as song, i}
- {#if song.name != ""}
+ {#if song?.title && song.title != ""}
-

+
+ {#if i === 1}
+
+ {/if}
+

+
{#if i === 1}
-
{song.name}
+
{song.title} - {song.artist}
{/if}
{:else}
-
+
+ {#if i === 1}
+
No song in queue
+ {/if}
+
{/if}
{/each}
diff --git a/frontend/src/lib/types.ts b/frontend/src/lib/types.ts
index 29c7bd9..85dff04 100644
--- a/frontend/src/lib/types.ts
+++ b/frontend/src/lib/types.ts
@@ -1,9 +1,27 @@
-import * as z from "zod"
+import { z } from "zod"
export const SongSchema = z.object({
- name: z.string(),
- image: z.string(),
- points: z.number().optional().default(0),
+ uuid: z.string(),
+ title: z.string(),
+ artist: z.string(),
+ tags: z.array(z.string()),
+ image_id: z.string(),
+ youtube_id: z.number().optional().default(0),
})
-
export type Song = z.infer
+
+export const parseSong = async function (song: any): Promise {
+ let resp = await SongSchema.parseAsync(song)
+ return resp
+}
+
+export const createEmptySong = function (): Song {
+ return {
+ uuid: "-1",
+ title: "",
+ artist: "",
+ tags: [""],
+ image_id: "",
+ youtube_id: 0,
+ }
+}
diff --git a/frontend/src/routes/+page.svelte b/frontend/src/routes/+page.svelte
index 6741d1c..48f1755 100644
--- a/frontend/src/routes/+page.svelte
+++ b/frontend/src/routes/+page.svelte
@@ -1,21 +1,12 @@
-
-
+
diff --git a/frontend/src/routes/admin/[id]/+page.svelte b/frontend/src/routes/admin/[id]/+page.svelte
new file mode 100644
index 0000000..7573aa2
--- /dev/null
+++ b/frontend/src/routes/admin/[id]/+page.svelte
@@ -0,0 +1,37 @@
+
+
+
+
+
diff --git a/frontend/src/routes/room/[id]/+page.svelte b/frontend/src/routes/room/[id]/+page.svelte
index eb0a4dc..31254dd 100644
--- a/frontend/src/routes/room/[id]/+page.svelte
+++ b/frontend/src/routes/room/[id]/+page.svelte
@@ -1,45 +1,56 @@
-
-
-
-
+
+{#if error.code != 0}
+
+{:else}
+
-
-
-
-
+{/if}
diff --git a/frontend/src/routes/room/[id]/+page.ts b/frontend/src/routes/room/[id]/+page.ts
new file mode 100644
index 0000000..1776db6
--- /dev/null
+++ b/frontend/src/routes/room/[id]/+page.ts
@@ -0,0 +1,11 @@
+import { error, type Load, type ServerLoad } from "@sveltejs/kit"
+import type { PageLoad } from "./$types"
+
+export const load: PageLoad = async ({ params }) => {
+ if (params.id) {
+ return {
+ roomId: params.id,
+ }
+ }
+ error(400, "Please provide a room id")
+}