mirror of
https://github.com/BradNut/boredgame
synced 2025-09-08 17:40:22 +00:00
Update toast to be in the bottom middle, error for fetching game data, fixing random from collection.
This commit is contained in:
parent
226c9454c7
commit
49464d3fba
10 changed files with 174 additions and 127 deletions
|
|
@ -14,6 +14,8 @@
|
||||||
--background-without-opacity: rgba(255, 255, 255, 0.7);
|
--background-without-opacity: rgba(255, 255, 255, 0.7);
|
||||||
--column-width: 42rem;
|
--column-width: 42rem;
|
||||||
--column-margin-top: 4rem;
|
--column-margin-top: 4rem;
|
||||||
|
--z-highest: 100;
|
||||||
|
--cardBorderRadius: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
|
|
||||||
|
|
@ -24,11 +24,11 @@
|
||||||
<div class="game-info">
|
<div class="game-info">
|
||||||
<h2>{game.name}</h2>
|
<h2>{game.name}</h2>
|
||||||
<a class="thumbnail" href={`/game/${game.id}`}>
|
<a class="thumbnail" href={`/game/${game.id}`}>
|
||||||
<img width="140" height="140" src={game.thumb_url} alt={`Image of ${game.name}`} />
|
<img src={game.thumb_url} alt={`Image of ${game.name}`} />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if !minimal}
|
{#if !minimal && game?.players && game?.playtime}
|
||||||
<div class="game-details">
|
<div class="game-details">
|
||||||
{#if game.year_published}
|
{#if game.year_published}
|
||||||
<p>{game.year_published}</p>
|
<p>{game.year_published}</p>
|
||||||
|
|
@ -36,7 +36,7 @@
|
||||||
<p>{game.players} {game.max_players === 1 ? 'player' : 'players'}</p>
|
<p>{game.players} {game.max_players === 1 ? 'player' : 'players'}</p>
|
||||||
<p>{game.playtime} minutes</p>
|
<p>{game.playtime} minutes</p>
|
||||||
<p>Minimum Age: {game.min_age}</p>
|
<p>Minimum Age: {game.min_age}</p>
|
||||||
<a href={`/game/${game.id}`}>View Game</a>
|
<!-- <a href={`/game/${game.id}`}>View Game</a> -->
|
||||||
{#if detailed}
|
{#if detailed}
|
||||||
<div class="description">{@html game.description}</div>
|
<div class="description">{@html game.description}</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
@ -68,7 +68,7 @@
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
img {
|
img {
|
||||||
border-radius: 10px;
|
max-height: 200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
|
|
@ -84,6 +84,7 @@
|
||||||
|
|
||||||
.game-container {
|
.game-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
place-content: center;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|
||||||
@media (max-width: 650px) {
|
@media (max-width: 650px) {
|
||||||
|
|
@ -101,7 +102,8 @@
|
||||||
|
|
||||||
.game-info {
|
.game-info {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 0.5rem;
|
place-items: center;
|
||||||
|
gap: 0.75rem;
|
||||||
margin: 0.2rem;
|
margin: 0.2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,46 +1,48 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { boredState } from '$lib/stores/boredState';
|
import { boredState } from '$lib/stores/boredState';
|
||||||
import { gameStore } from '$lib/stores/gameSearchStore';
|
import { gameStore } from '$lib/stores/gameSearchStore';
|
||||||
import { collectionStore } from '$lib/stores/collectionStore';
|
import { collectionStore } from '$lib/stores/collectionStore';
|
||||||
import { toast } from '$lib/components/toast/toast';
|
import { toast } from '$lib/components/toast/toast';
|
||||||
import { ToastType, type SavedGameType } from '$lib/types';
|
import { ToastType, type SavedGameType } from '$lib/types';
|
||||||
|
import { mapSavedGameToGame } from '$root/lib/util/gameMapper';
|
||||||
|
|
||||||
async function getRandomCollectionGame() {
|
async function getRandomCollectionGame() {
|
||||||
if ($collectionStore.length > 0) {
|
if ($collectionStore.length > 0) {
|
||||||
boredState.update((n) => ({ ...n, loading: true }));
|
boredState.update((n) => ({ ...n, loading: true }));
|
||||||
let randomNumber: number = Math.round(Math.random() * $collectionStore.length - 1);
|
let randomNumber: number = Math.round(Math.random() * $collectionStore.length - 1);
|
||||||
if ($collectionStore.at(randomNumber)) {
|
if ($collectionStore.at(randomNumber)) {
|
||||||
gameStore.removeAll();
|
gameStore.removeAll();
|
||||||
const randomGame: SavedGameType = $collectionStore.at(randomNumber)!;
|
const randomGame: SavedGameType = $collectionStore.at(randomNumber)!;
|
||||||
const response = await fetch(`/api/game/${randomGame?.id}`, {
|
// const response = await fetch(`/api/game/${randomGame?.id}`, {
|
||||||
method: 'GET',
|
// method: 'GET',
|
||||||
headers: { accept: 'application/json' }
|
// headers: { accept: 'application/json' }
|
||||||
});
|
// });
|
||||||
const responseData = await response.json();
|
// const responseData = await response.json();
|
||||||
console.log('responseData', responseData);
|
// console.log('responseData', responseData);
|
||||||
gameStore.add(responseData?.game);
|
// gameStore.add(responseData?.game);
|
||||||
boredState.update((n) => ({ ...n, loading: false }));
|
const game = gameStore.add(mapSavedGameToGame(randomGame));
|
||||||
} else {
|
boredState.update((n) => ({ ...n, loading: false }));
|
||||||
toast.send('Error!', { duration: 3000, type: ToastType.ERROR, dismissible: true });
|
} else {
|
||||||
}
|
toast.send('Error!', { duration: 3000, type: ToastType.ERROR, dismissible: true });
|
||||||
boredState.update((n) => ({ ...n, loading: false }));
|
}
|
||||||
} else {
|
boredState.update((n) => ({ ...n, loading: false }));
|
||||||
toast.send('No items in your collection!', {
|
} else {
|
||||||
duration: 3000,
|
toast.send('No items in your collection!', {
|
||||||
type: ToastType.ERROR,
|
duration: 3000,
|
||||||
dismissible: true
|
type: ToastType.ERROR,
|
||||||
});
|
dismissible: true
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<button class="btn" type="button" on:click={() => getRandomCollectionGame()}
|
<button class="btn" type="button" on:click={() => getRandomCollectionGame()}
|
||||||
>Random from collection 🎲</button
|
>Random from collection 🎲</button
|
||||||
>
|
>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
button {
|
button {
|
||||||
max-width: 450px;
|
max-width: 450px;
|
||||||
padding: var(--spacing-8) var(--spacing-16);
|
padding: var(--spacing-8) var(--spacing-16);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,11 @@
|
||||||
console.log('In success');
|
console.log('In success');
|
||||||
const resultGames = result?.data?.games;
|
const resultGames = result?.data?.games;
|
||||||
if (resultGames?.length <= 0) {
|
if (resultGames?.length <= 0) {
|
||||||
toast.send('No results!', { duration: 3000, type: ToastType.INFO, dismissible: true });
|
toast.send('No results found 😿', {
|
||||||
|
duration: 3000,
|
||||||
|
type: ToastType.INFO,
|
||||||
|
dismissible: true
|
||||||
|
});
|
||||||
}
|
}
|
||||||
gameStore.addAll(resultGames);
|
gameStore.addAll(resultGames);
|
||||||
console.log(`Frontend result: ${JSON.stringify(result)}`);
|
console.log(`Frontend result: ${JSON.stringify(result)}`);
|
||||||
|
|
|
||||||
|
|
@ -1,87 +1,94 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { fly, fade } from 'svelte/transition';
|
import { fly, fade } from 'svelte/transition';
|
||||||
import { flip } from 'svelte/animate';
|
import { flip } from 'svelte/animate';
|
||||||
import Portal from '../../Portal.svelte';
|
import Portal from '../../Portal.svelte';
|
||||||
import ToastMessage from './ToastMessage.svelte';
|
import ToastMessage from './ToastMessage.svelte';
|
||||||
import { toast } from './toast';
|
import { toast } from './toast';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Portal>
|
<Portal>
|
||||||
<div class="toast-wrapper">
|
<div class="toast-wrapper">
|
||||||
{#each $toast as toastData (toastData.id)}
|
{#each $toast as toastData (toastData.id)}
|
||||||
<div
|
<div
|
||||||
aria-label={toastData.dismissible ? 'Click to dismiss' : `${toastData.message}`}
|
aria-label={toastData.dismissible ? 'Click to dismiss' : `${toastData.message}`}
|
||||||
on:click={() => toastData.dismissible && toast.remove(toastData.id)}
|
on:click={() => toastData.dismissible && toast.remove(toastData.id)}
|
||||||
in:fly={{ opacity: 0, x: 100 }}
|
on:keydown={() => toastData.dismissible && toast.remove(toastData.id)}
|
||||||
out:fade
|
in:fly={{ opacity: 0, x: 100 }}
|
||||||
animate:flip
|
out:fade
|
||||||
class={`toast ${toastData.type.toLowerCase()}`}
|
animate:flip
|
||||||
>
|
class={`toast ${toastData.type.toLowerCase()}`}
|
||||||
<ToastMessage {toastData} />
|
>
|
||||||
{#if toastData.dismissible && toastData.showButton}
|
<ToastMessage {toastData} />
|
||||||
<button
|
{#if toastData.dismissible && toastData.showButton}
|
||||||
type="button"
|
<button
|
||||||
aria-label="Click to dismiss"
|
type="button"
|
||||||
on:click={() => toastData.dismissible && toast.remove(toastData.id)}
|
aria-label="Click to dismiss"
|
||||||
class="close"
|
on:click={() => toastData.dismissible && toast.remove(toastData.id)}
|
||||||
>
|
class="close"
|
||||||
<svg
|
>
|
||||||
viewBox="0 0 15 15"
|
<svg
|
||||||
fill="none"
|
viewBox="0 0 15 15"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
fill="none"
|
||||||
width="16"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
height="16"
|
width="16"
|
||||||
><path
|
height="16"
|
||||||
d="M11.7816 4.03157C12.0062 3.80702 12.0062 3.44295 11.7816 3.2184C11.5571 2.99385 11.193 2.99385 10.9685 3.2184L7.50005 6.68682L4.03164 3.2184C3.80708 2.99385 3.44301 2.99385 3.21846 3.2184C2.99391 3.44295 2.99391 3.80702 3.21846 4.03157L6.68688 7.49999L3.21846 10.9684C2.99391 11.193 2.99391 11.557 3.21846 11.7816C3.44301 12.0061 3.80708 12.0061 4.03164 11.7816L7.50005 8.31316L10.9685 11.7816C11.193 12.0061 11.5571 12.0061 11.7816 11.7816C12.0062 11.557 12.0062 11.193 11.7816 10.9684L8.31322 7.49999L11.7816 4.03157Z"
|
><path
|
||||||
fill="currentColor"
|
d="M11.7816 4.03157C12.0062 3.80702 12.0062 3.44295 11.7816 3.2184C11.5571 2.99385 11.193 2.99385 10.9685 3.2184L7.50005 6.68682L4.03164 3.2184C3.80708 2.99385 3.44301 2.99385 3.21846 3.2184C2.99391 3.44295 2.99391 3.80702 3.21846 4.03157L6.68688 7.49999L3.21846 10.9684C2.99391 11.193 2.99391 11.557 3.21846 11.7816C3.44301 12.0061 3.80708 12.0061 4.03164 11.7816L7.50005 8.31316L10.9685 11.7816C11.193 12.0061 11.5571 12.0061 11.7816 11.7816C12.0062 11.557 12.0062 11.193 11.7816 10.9684L8.31322 7.49999L11.7816 4.03157Z"
|
||||||
fill-rule="evenodd"
|
fill="currentColor"
|
||||||
clip-rule="evenodd"
|
fill-rule="evenodd"
|
||||||
/></svg
|
clip-rule="evenodd"
|
||||||
>
|
/></svg
|
||||||
</button>
|
>
|
||||||
{/if}
|
</button>
|
||||||
</div>
|
{/if}
|
||||||
{/each}
|
</div>
|
||||||
</div>
|
{/each}
|
||||||
|
</div>
|
||||||
</Portal>
|
</Portal>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.toast-wrapper {
|
.toast-wrapper {
|
||||||
position: fixed;
|
display: flex;
|
||||||
bottom: 5px;
|
flex-flow: column;
|
||||||
right: 25px;
|
align-items: center;
|
||||||
}
|
justify-content: center;
|
||||||
|
position: fixed;
|
||||||
|
bottom: 5vh;
|
||||||
|
width: 100vw;
|
||||||
|
z-index: calc(var(--z-highest) + 10);
|
||||||
|
}
|
||||||
|
|
||||||
.toast {
|
.toast {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 1rem;
|
justify-content: center;
|
||||||
place-items: center;
|
gap: 1rem;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
margin: 1rem 1rem 0;
|
||||||
|
min-width: 460px;
|
||||||
|
color: white;
|
||||||
|
background: var(--toast-background, #625df5);
|
||||||
|
padding: 1.5rem;
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.3);
|
||||||
|
width: 30rem;
|
||||||
|
|
||||||
overflow: hidden;
|
.close {
|
||||||
position: relative;
|
padding: 5px;
|
||||||
margin-bottom: 1rem;
|
border-radius: 5px;
|
||||||
color: white;
|
opacity: 1;
|
||||||
background: var(--toast-background, #625df5);
|
transition: ease 0.3s;
|
||||||
padding: 20px;
|
|
||||||
border-radius: 15px;
|
|
||||||
box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.3);
|
|
||||||
|
|
||||||
.close {
|
&:hover,
|
||||||
padding: 5px;
|
&:focus {
|
||||||
border-radius: 5px;
|
transition: ease 0.3s;
|
||||||
opacity: 1;
|
background-color: #625df5;
|
||||||
transition: ease 0.3s;
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&:hover,
|
.toast.error {
|
||||||
&:focus {
|
background: var(--toast-error-background, #e54b4b);
|
||||||
transition: ease 0.3s;
|
color: black;
|
||||||
background-color: #625df5;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.toast.error {
|
|
||||||
background: var(--toast-error-background, #e54b4b);
|
|
||||||
color: black;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,14 @@
|
||||||
import type { GameType } from '$lib/types';
|
import type { GameType, SavedGameType } from '$lib/types';
|
||||||
|
|
||||||
|
export function mapSavedGameToGame(game: SavedGameType): GameType {
|
||||||
|
const { id, name, thumb_url } = game;
|
||||||
|
|
||||||
|
return {
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
thumb_url
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function mapAPIGameToBoredGame(game): GameType {
|
export function mapAPIGameToBoredGame(game): GameType {
|
||||||
const {
|
const {
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
<h1>The page you requested doesn't exist!</h1>
|
<h1>The page you requested doesn't exist! 🤷♂️</h1>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
h1 {
|
h1 {
|
||||||
margin-top: var(--spacing-64);
|
margin-top: var(--spacing-64);
|
||||||
font-family: var(--font-sans);
|
font-family: var(--font-sans);
|
||||||
font-size: var(--font-32);
|
font-size: var(--font-32);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,11 @@
|
||||||
console.log('In success');
|
console.log('In success');
|
||||||
const resultGames = result?.data?.games;
|
const resultGames = result?.data?.games;
|
||||||
if (resultGames?.length <= 0) {
|
if (resultGames?.length <= 0) {
|
||||||
toast.send('No results!', { duration: 3000, type: ToastType.INFO, dismissible: true });
|
toast.send('No results found 😿', {
|
||||||
|
duration: 3000,
|
||||||
|
type: ToastType.ERROR,
|
||||||
|
dismissible: true
|
||||||
|
});
|
||||||
}
|
}
|
||||||
gameStore.addAll(resultGames);
|
gameStore.addAll(resultGames);
|
||||||
totalItems = result?.data?.totalCount;
|
totalItems = result?.data?.totalCount;
|
||||||
|
|
|
||||||
12
src/routes/game/[id]/+error.svelte
Normal file
12
src/routes/game/[id]/+error.svelte
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
<h1>Unable to load board game info! 🤦♂️</h1>
|
||||||
|
<h2>Please try again later. 🙇🏼</h2>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: var(--spacing-64);
|
||||||
|
font-family: var(--font-sans);
|
||||||
|
font-size: var(--font-32);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -127,6 +127,10 @@
|
||||||
margin-bottom: 3rem;
|
margin-bottom: 3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
max-width: 500px;
|
||||||
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue