mirror of
https://github.com/BradNut/boredgame
synced 2025-09-08 17:40:22 +00:00
feat: ✨ Game page linked from home page
This commit is contained in:
parent
3c1cd6e13d
commit
462b0b5310
6 changed files with 121 additions and 192 deletions
|
|
@ -9,7 +9,7 @@
|
||||||
<article class="game-container" transition:fade>
|
<article class="game-container" transition:fade>
|
||||||
<div class="game-info">
|
<div class="game-info">
|
||||||
<h2>{game.name}</h2>
|
<h2>{game.name}</h2>
|
||||||
<a class="thumbnail" href={game.url}>
|
<a class="thumbnail" href={`/game/${game.id}`}>
|
||||||
<img width="140" height="140" src={game.thumb_url} alt={`Image of ${game.name}`} />
|
<img width="140" height="140" src={game.thumb_url} alt={`Image of ${game.name}`} />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -50,5 +50,11 @@
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: hsla(222, 9%, 65%, 1);
|
background-color: hsla(222, 9%, 65%, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.game-info {
|
||||||
|
margin: 0.2rem;
|
||||||
|
display: grid;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ export const post: RequestHandler = async ({ request }) => {
|
||||||
client_id: import.meta.env.VITE_PUBLIC_CLIENT_ID
|
client_id: import.meta.env.VITE_PUBLIC_CLIENT_ID
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const id = form.get('id');
|
||||||
const minAge = form.get('minAge');
|
const minAge = form.get('minAge');
|
||||||
const minPlayers = form.get('minPlayers');
|
const minPlayers = form.get('minPlayers');
|
||||||
const maxPlayers = form.get('maxPlayers');
|
const maxPlayers = form.get('maxPlayers');
|
||||||
|
|
@ -58,6 +59,11 @@ export const post: RequestHandler = async ({ request }) => {
|
||||||
queryParams.lt_max_players = +maxPlayers + 1;
|
queryParams.lt_max_players = +maxPlayers + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (id) {
|
||||||
|
queryParams.ids = new Array(`${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
queryParams.random = random;
|
queryParams.random = random;
|
||||||
console.log('queryParams', queryParams);
|
console.log('queryParams', queryParams);
|
||||||
|
|
||||||
|
|
@ -70,9 +76,8 @@ export const post: RequestHandler = async ({ request }) => {
|
||||||
|
|
||||||
const urlQueryParams = new URLSearchParams(newQueryParams);
|
const urlQueryParams = new URLSearchParams(newQueryParams);
|
||||||
|
|
||||||
const url = `https://api.boardgameatlas.com/api/search${
|
const url = `https://api.boardgameatlas.com/api/search${urlQueryParams ? `?${urlQueryParams}` : ''
|
||||||
urlQueryParams ? `?${urlQueryParams}` : ''
|
}`;
|
||||||
}`;
|
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
method: 'get',
|
method: 'get',
|
||||||
headers: {
|
headers: {
|
||||||
|
|
|
||||||
72
src/routes/game/[id].svelte
Normal file
72
src/routes/game/[id].svelte
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import type { GameType } from '$lib/types';
|
||||||
|
import { Checkbox, NumberInput } from 'carbon-components-svelte';
|
||||||
|
// import { enhance } from "$lib/form";
|
||||||
|
|
||||||
|
export let game: GameType;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:head>
|
||||||
|
<title>{game?.name} | Bored Game</title>
|
||||||
|
</svelte:head>
|
||||||
|
|
||||||
|
<h2>{game?.name}</h2>
|
||||||
|
|
||||||
|
<section class="games">
|
||||||
|
<div>
|
||||||
|
<a class="thumbnail" href={game.url}>
|
||||||
|
<img src={game.image_url} alt={`Image of ${game.name}`} />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="description">
|
||||||
|
{@html game?.description}
|
||||||
|
<div>
|
||||||
|
<p>Price: {game?.price}</p>
|
||||||
|
<p>Year Published: {game?.year_published}</p>
|
||||||
|
<p>Players: {game.players} {game.max_players === 1 ? 'player' : 'players'}</p>
|
||||||
|
<p>Playtime: {game.playtime} minutes</p>
|
||||||
|
<p>Minimum Age: {game.min_age}</p>
|
||||||
|
<a href={game.url} rel="noreferrer">Board Game Atlas Link</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
h2 {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 2.5rem;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
border-radius: 4px;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0.2rem;
|
||||||
|
background-color: var(--color-btn-primary-active);
|
||||||
|
}
|
||||||
|
|
||||||
|
.games {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 2rem;
|
||||||
|
margin: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
display: grid;
|
||||||
|
gap: 1.5rem;
|
||||||
|
margin: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.game-form {
|
||||||
|
display: flex;
|
||||||
|
place-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.game-form fieldset {
|
||||||
|
display: grid;
|
||||||
|
gap: 1rem;
|
||||||
|
grid-template-columns: repeat(3, minmax(200px, 1fr));
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -1,39 +1,37 @@
|
||||||
import type { RequestHandler } from '@sveltejs/kit';
|
import type { RequestHandler } from '@sveltejs/kit';
|
||||||
import { boardGameApi } from '../_api';
|
import { boardGameApi } from '../_api';
|
||||||
|
|
||||||
// export const get: RequestHandler = async ({ params }) => {
|
export const get: RequestHandler = async ({ params }) => {
|
||||||
// const queryParams = {
|
// console.log('params', params);
|
||||||
// order_by: 'rank',
|
const queryParams = {
|
||||||
// ascending: 'false',
|
ids: `${params?.id}`,
|
||||||
// limit: '10',
|
}
|
||||||
// }
|
console.log('queryParams', queryParams);
|
||||||
// const response = await boardGameApi('get', `search`, queryParams);
|
const response = await boardGameApi('get', `search`, queryParams);
|
||||||
// console.log('response', response);
|
if (response.status === 404) {
|
||||||
// if (response.status === 404) {
|
return {
|
||||||
// // user hasn't created a todo list.
|
body: {
|
||||||
// // start with an empty array
|
games: []
|
||||||
// return {
|
}
|
||||||
// body: {
|
};
|
||||||
// games: []
|
}
|
||||||
// }
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
// const gameResponse = await response.json();
|
const gameResponse = await response.json();
|
||||||
// const games = gameResponse?.games;
|
// console.log('gameResponse', gameResponse);
|
||||||
// console.log('games', games);
|
// const games = gameResponse?.games;
|
||||||
// return {
|
console.log('game', gameResponse?.games[0]);
|
||||||
// body: {
|
return {
|
||||||
// games: gameResponse?.games,
|
body: {
|
||||||
// }
|
game: gameResponse?.games[0],
|
||||||
// };
|
}
|
||||||
// }
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// return {
|
return {
|
||||||
// status: response.status
|
status: response.status
|
||||||
// };
|
};
|
||||||
// }
|
}
|
||||||
|
|
||||||
// export const post: RequestHandler = async ({ request }) => {
|
// export const post: RequestHandler = async ({ request }) => {
|
||||||
// const form = await request.formData();
|
// const form = await request.formData();
|
||||||
|
|
@ -1,156 +0,0 @@
|
||||||
<script lang="ts">
|
|
||||||
import type { Game } from '$lib/types';
|
|
||||||
import { Checkbox, NumberInput } from 'carbon-components-svelte';
|
|
||||||
// import { enhance } from "$lib/form";
|
|
||||||
|
|
||||||
let games: Game[] = [];
|
|
||||||
let submitting = false;
|
|
||||||
|
|
||||||
async function handleSubmit(event: SubmitEvent) {
|
|
||||||
submitting = true;
|
|
||||||
const form = event.target as HTMLFormElement;
|
|
||||||
console.log('form', form);
|
|
||||||
const response = await fetch('/api/games', {
|
|
||||||
method: 'post',
|
|
||||||
headers: { accept: 'application/json' },
|
|
||||||
body: new FormData(form)
|
|
||||||
});
|
|
||||||
const responseData = await response.json();
|
|
||||||
submitting = false;
|
|
||||||
games = responseData?.games;
|
|
||||||
}
|
|
||||||
|
|
||||||
let minAge = 0;
|
|
||||||
let minPlayers = 1;
|
|
||||||
let maxPlayers = 1;
|
|
||||||
let exactMinAge = false;
|
|
||||||
let exactMinPlayers = false;
|
|
||||||
let exactMaxPlayers = false;
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<svelte:head>
|
|
||||||
<title>Games</title>
|
|
||||||
</svelte:head>
|
|
||||||
|
|
||||||
<h1>Search Boardgames!</h1>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<p>Input your requirements to search for board game that match your criteria</p>
|
|
||||||
</section>
|
|
||||||
<div class="game-form">
|
|
||||||
<form on:submit|preventDefault={handleSubmit} method="post">
|
|
||||||
<fieldset aria-busy={submitting} disabled={submitting}>
|
|
||||||
<div>
|
|
||||||
<NumberInput
|
|
||||||
name="minAge"
|
|
||||||
min={0}
|
|
||||||
max={120}
|
|
||||||
bind:value={minAge}
|
|
||||||
invalidText="Number must be between 0 and 120"
|
|
||||||
label="Min Age"
|
|
||||||
/>
|
|
||||||
<Checkbox
|
|
||||||
name="exactMinAge"
|
|
||||||
bind:value={exactMinAge}
|
|
||||||
labelText="Search exact?"
|
|
||||||
bind:checked={exactMinAge}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<NumberInput
|
|
||||||
name="minPlayers"
|
|
||||||
min={1}
|
|
||||||
max={50}
|
|
||||||
bind:value={minPlayers}
|
|
||||||
invalidText="Number must be between 1 and 50"
|
|
||||||
label="Min Players"
|
|
||||||
/>
|
|
||||||
<Checkbox
|
|
||||||
name="exactMinPlayers"
|
|
||||||
labelText="Search exact?"
|
|
||||||
bind:value={exactMinPlayers}
|
|
||||||
bind:checked={exactMinPlayers}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<NumberInput
|
|
||||||
name="maxPlayers"
|
|
||||||
min={1}
|
|
||||||
max={50}
|
|
||||||
bind:value={maxPlayers}
|
|
||||||
invalidText="Number must be between 1 and 50"
|
|
||||||
label="Max Players"
|
|
||||||
/>
|
|
||||||
<Checkbox
|
|
||||||
name="exactMaxPlayers"
|
|
||||||
labelText="Search exact?"
|
|
||||||
bind:value={exactMaxPlayers}
|
|
||||||
bind:checked={exactMaxPlayers}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
|
||||||
<button type="submit" disabled={submitting}>Submit</button>
|
|
||||||
</form>
|
|
||||||
<form on:submit|preventDefault={handleSubmit} method="post">
|
|
||||||
<fieldset aria-busy={submitting} disabled={submitting}>
|
|
||||||
<input type="checkbox" id="random" name="random" hidden checked />
|
|
||||||
<button type="submit" disabled={submitting}>🎲</button>
|
|
||||||
</fieldset>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="games">
|
|
||||||
<h1>Games</h1>
|
|
||||||
{#each games as game}
|
|
||||||
<section>
|
|
||||||
<div>
|
|
||||||
<h2>{game.name}</h2>
|
|
||||||
<p>price : {game.price}</p>
|
|
||||||
<p>year_published : {game.year_published}</p>
|
|
||||||
<p>min_players : {game.min_players}</p>
|
|
||||||
<p>max_players : {game.max_players}</p>
|
|
||||||
<p>min_playtime : {game.min_playtime}</p>
|
|
||||||
<p>max_playtime : {game.max_playtime}</p>
|
|
||||||
<p>min_age : {game.min_age}</p>
|
|
||||||
<p>players : {game.players}</p>
|
|
||||||
<p>playtime : {game.playtime}</p>
|
|
||||||
<div class="description">{@html game.description}</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
h2 {
|
|
||||||
text-align: center;
|
|
||||||
font-size: 2.5rem;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
border-radius: 4px;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0.2rem;
|
|
||||||
background-color: var(--color-btn-primary-active);
|
|
||||||
}
|
|
||||||
|
|
||||||
.games {
|
|
||||||
display: grid;
|
|
||||||
gap: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.description {
|
|
||||||
margin: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.game-form {
|
|
||||||
display: flex;
|
|
||||||
place-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.game-form fieldset {
|
|
||||||
display: grid;
|
|
||||||
gap: 1rem;
|
|
||||||
grid-template-columns: repeat(3, minmax(200px, 1fr));
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -184,7 +184,11 @@
|
||||||
grid-template-columns: repeat(3, 1fr);
|
grid-template-columns: repeat(3, 1fr);
|
||||||
gap: 2rem;
|
gap: 2rem;
|
||||||
|
|
||||||
@media(max-width: 580px) {
|
@media (max-width: 800px) {
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 550px) {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue