From a8809ace9b9bfdd5d8e092e76718c8414512edc3 Mon Sep 17 00:00:00 2001 From: Esa Kataja Date: Mon, 2 Dec 2024 16:18:31 +0200 Subject: [PATCH] Add admin panel --- src/routes/admin/+page.server.ts | 186 +++++++++++++++++------- src/routes/admin/+page.svelte | 233 ++++++++++++++++++++++++------- 2 files changed, 317 insertions(+), 102 deletions(-) diff --git a/src/routes/admin/+page.server.ts b/src/routes/admin/+page.server.ts index 14e8286..6860304 100644 --- a/src/routes/admin/+page.server.ts +++ b/src/routes/admin/+page.server.ts @@ -1,60 +1,131 @@ import { error } from '@sveltejs/kit'; -import type { Actions } from './$types'; +import type { Actions, PageServerLoad } from './$types'; const api_url = import.meta.env.VITE_API_URL; +interface Movie { + name: string; + imdb_id: string; + showtime: string; + plot: string; + actors: string[]; + release_date: string; + poster_url: string; + id: string; + created_at: string; + modified_at: string; + is_watched: boolean; +} + +export const load: PageServerLoad = async ({ fetch }) => { + try { + const [usersRes, moviesRes, cardsRes] = await Promise.all([ + fetch(`${api_url}/user`), + fetch(`${api_url}/movie`), + fetch(`${api_url}/card`) + ]); + + if (!usersRes.ok) throw error(usersRes.status, 'Failed to load users'); + if (!moviesRes.ok) throw error(moviesRes.status, 'Failed to load movies'); + if (!cardsRes.ok) throw error(cardsRes.status, 'Failed to load cards'); + + const users = await usersRes.json(); + const movies: Movie[] = await moviesRes.json(); + const cards = await cardsRes.json(); + + return { + users, + movies, + cards + }; + } catch (error) { + console.error('Error loading data:', error); + return { + users: [], + movies: [], + cards: [] + }; + } +}; + export const actions: Actions = { - addUser: async ({ request, fetch }) => { - const formData = await request.formData(); - const userData = Object.fromEntries(formData); - - const response = await fetch(`${api_url}/admin/user`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify(userData) - }); + addUser: async ({ request }) => { + const data = await request.formData(); + const username = data.get('username'); + const password = data.get('password'); - if (!response.ok) { - throw error(response.status, 'Failed to add user'); + try { + const response = await fetch(`${api_url}/admin/user`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + username, + password + }) + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + return { success: true }; + } catch (error) { + console.error('Error adding user:', error); + return { success: false, message: 'Failed to add user' }; } - - return { success: true }; }, - deleteUser: async ({ request, fetch }) => { - const formData = await request.formData(); - const userId = formData.get('userId'); + deleteUser: async ({ request }) => { + const data = await request.formData(); + const userId = data.get('userId'); - const response = await fetch(`${api_url}/admin/user/${userId}`, { - method: 'DELETE' - }); + try { + const response = await fetch(`${api_url}/admin/user?user_id=${userId}`, { + method: 'DELETE', + headers: { + 'Content-Type': 'application/json' + } + }); - if (!response.ok) { - throw error(response.status, 'Failed to delete user'); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + return { success: true }; + } catch (error) { + console.error('Error deleting user:', error); + return { success: false, message: 'Failed to delete user' }; } - - return { success: true }; }, - addMovie: async ({ request, fetch }) => { - const formData = await request.formData(); - const movieData = Object.fromEntries(formData); + addMovie: async ({ request }) => { + const data = await request.formData(); + const movieData = { + imdb_id: data.get('imdb_id'), + showtime: data.get('showtime'), + plot: data.get('plot') + }; - const response = await fetch(`${api_url}/admin/movie`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify(movieData) - }); + try { + const response = await fetch(`${api_url}/admin/movie`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(movieData) + }); - if (!response.ok) { - throw error(response.status, 'Failed to add movie'); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + return { success: true }; + } catch (error) { + console.error('Error adding movie:', error); + return { success: false, message: 'Failed to add movie' }; } - - return { success: true }; }, setMovieWatched: async ({ request, fetch }) => { @@ -77,22 +148,31 @@ export const actions: Actions = { }, addCard: async ({ request, fetch }) => { - const formData = await request.formData(); - const cardData = Object.fromEntries(formData); + const data = await request.formData(); + const cardData = { + title: data.get('title'), + description: data.get('description'), + point_value: Number(data.get('point_value')) + }; - const response = await fetch(`${api_url}/admin/card`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify(cardData) - }); + try { + const response = await fetch(`${api_url}/admin/card`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(cardData) + }); - if (!response.ok) { - throw error(response.status, 'Failed to add card'); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + return { success: true }; + } catch (error) { + console.error('Error adding card:', error); + return { success: false, message: 'Failed to add card' }; } - - return { success: true }; }, deleteCard: async ({ request, fetch }) => { diff --git a/src/routes/admin/+page.svelte b/src/routes/admin/+page.svelte index 5988f2a..0f63c51 100644 --- a/src/routes/admin/+page.svelte +++ b/src/routes/admin/+page.svelte @@ -1,6 +1,9 @@
@@ -19,79 +22,153 @@
{#if activeTab === 'users'}
+

Existing Users

+
+ + + + + + + + + {#each users as user} + + + + + {/each} + +
UsernameActions
{user.username} +
+ + +
+
+
+

Add User

- +
- - + +
- -

Delete User

-
-
- - -
- -
{/if} {#if activeTab === 'movies'}
+

Existing Movies

+
+ + + + + + + + + + + + + {#each movies as movie} + + + + + + + + + {/each} + +
NamePlotIMDBShowtimeWatchedActions
{movie.name}{movie.plot} + + View on IMDB + + {new Date(movie.showtime).toLocaleDateString()}{movie.is_watched ? 'Yes' : 'No'} + {#if !movie.is_watched} +
+ + +
+ {/if} +
+
+

Add Movie

- - + +
- - + + +
+
+ +
- -

Mark Movie as Watched

-
-
- - -
- -
{/if} {#if activeTab === 'cards'}
+

Existing Cards

+
+ + + + + + + + + + + {#each cards as card} + + + + + + + {/each} + +
TitleDescriptionPointsActions
{card.title}{card.description}{card.point_value} +
+ + +
+
+
+

Add Card

- - + +
- - + + +
+
+ +
- -

Delete Card

-
-
- - -
- -
{/if}
@@ -99,16 +176,19 @@ \ No newline at end of file