diff --git a/.gitignore b/.gitignore index 6c501fd..bf051b6 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,4 @@ data/ .env .env.* !.env.example -games/ +/games/ diff --git a/src/routes/games/[slug]/+page.server.ts b/src/routes/games/[slug]/+page.server.ts new file mode 100644 index 0000000..0456851 --- /dev/null +++ b/src/routes/games/[slug]/+page.server.ts @@ -0,0 +1,91 @@ +import { error, fail } from '@sveltejs/kit'; +import type { Actions, PageServerLoad } from './$types'; +import { getDb } from '$lib/server/db'; +import { getSession } from '$lib/server/auth'; +import type { Game, GameFile, Screenshot, Tag } from '$lib/types'; + +export const load: PageServerLoad = async ({ params, parent, cookies }) => { + const { loggedIn } = await parent(); + const db = getDb(); + + const total = (db.prepare('SELECT COUNT(*) as n FROM games').get() as { n: number }).n; + console.log(`[games/${params.slug}] page server: slug="${params.slug}" total_games_in_db=${total}`); + + const game = db.prepare('SELECT * FROM games WHERE slug = ?').get(params.slug) as + | Game + | undefined; + if (!game) { + const inSeries = db.prepare('SELECT slug, title FROM series WHERE slug = ?').get(params.slug) as { slug: string; title: string } | undefined; + console.log( + `[games/${params.slug}] 404 — not in games table. Total games in DB: ${total}. In series table: ${inSeries ? `yes ("${inSeries.title}")` : 'no'}` + ); + error(404, 'Game not found'); + } + if (game.library === 'private' && !loggedIn) error(403, 'Login required'); + + const files = db + .prepare('SELECT * FROM game_files WHERE game_id = ? ORDER BY platform, filename') + .all(game.id) as GameFile[]; + + const screenshots = db + .prepare('SELECT * FROM screenshots WHERE game_id = ? ORDER BY sort_order') + .all(game.id) as Screenshot[]; + + const tags = db + .prepare( + `SELECT t.id, t.name FROM tags t + JOIN game_tags gt ON gt.tag_id = t.id + WHERE gt.game_id = ? + ORDER BY t.name` + ) + .all(game.id) as Tag[]; + + return { game, files, screenshots, tags }; +}; + +export const actions: Actions = { + updateMeta: async ({ request, params, cookies }) => { + if (!getSession(cookies)) error(403, 'Login required'); + const db = getDb(); + const data = await request.formData(); + const description = (data.get('description') as string) ?? ''; + const genre = (data.get('genre') as string) ?? ''; + db.prepare('UPDATE games SET description = ?, genre = ? WHERE slug = ?').run( + description, + genre, + params.slug + ); + return { success: true }; + }, + + addTag: async ({ request, params, cookies }) => { + if (!getSession(cookies)) error(403, 'Login required'); + const db = getDb(); + const data = await request.formData(); + const name = ((data.get('tag') as string) ?? '').trim(); + if (!name) return fail(400, { tagError: 'Tag name required' }); + + db.prepare('INSERT OR IGNORE INTO tags (name) VALUES (?)').run(name); + const tag = db.prepare('SELECT id FROM tags WHERE name = ?').get(name) as { id: number }; + const game = db.prepare('SELECT id FROM games WHERE slug = ?').get(params.slug) as { + id: number; + }; + db.prepare('INSERT OR IGNORE INTO game_tags (game_id, tag_id) VALUES (?, ?)').run( + game.id, + tag.id + ); + return { success: true }; + }, + + removeTag: async ({ request, params, cookies }) => { + if (!getSession(cookies)) error(403, 'Login required'); + const db = getDb(); + const data = await request.formData(); + const tagId = Number(data.get('tagId')); + const game = db.prepare('SELECT id FROM games WHERE slug = ?').get(params.slug) as { + id: number; + }; + db.prepare('DELETE FROM game_tags WHERE game_id = ? AND tag_id = ?').run(game.id, tagId); + return { success: true }; + } +}; diff --git a/src/routes/games/[slug]/+page.svelte b/src/routes/games/[slug]/+page.svelte new file mode 100644 index 0000000..e7d62a2 --- /dev/null +++ b/src/routes/games/[slug]/+page.svelte @@ -0,0 +1,71 @@ + + + + {game.title} — Game Grid + + +
+ + {#if game.has_wide || game.has_cover} +
+ {game.title} +
+ {/if} + +
+ + {#if game.has_cover} +
+
+ {game.title} +
+
+ {/if} + +
+

{game.title}

+ + {#if game.genre} +

{game.genre}

+ {/if} + + + +
+ +
+
+
+ +
+ +
+ + {#if data.screenshots.length > 0} +
+

Screenshots

+ +
+ {/if} + +
+ ← Back to library +
+