mirror of
https://github.com/BradNut/boredgame
synced 2025-09-08 17:40:22 +00:00
Adding dialog just to the game collection for now and using a custom event for removing.
This commit is contained in:
parent
7b9e1cdaa2
commit
5236ac5c2b
8 changed files with 108 additions and 65 deletions
|
|
@ -1,4 +1,5 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { createEventDispatcher } from 'svelte';
|
||||||
import { fade } from 'svelte/transition';
|
import { fade } from 'svelte/transition';
|
||||||
import { MinusCircleIcon, PlusCircleIcon } from '@rgossiaux/svelte-heroicons/outline';
|
import { MinusCircleIcon, PlusCircleIcon } from '@rgossiaux/svelte-heroicons/outline';
|
||||||
import type { GameType, SavedGameType } from '$lib/types';
|
import type { GameType, SavedGameType } from '$lib/types';
|
||||||
|
|
@ -8,6 +9,13 @@
|
||||||
export let game: GameType | SavedGameType;
|
export let game: GameType | SavedGameType;
|
||||||
export let minimal: boolean = false;
|
export let minimal: boolean = false;
|
||||||
export let detailed: boolean = false;
|
export let detailed: boolean = false;
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
|
function removeGame() {
|
||||||
|
dispatch('removeGameEvent', game);
|
||||||
|
}
|
||||||
|
|
||||||
$: existsInCollection = $collectionStore.find((item: SavedGameType) => item.id === game.id);
|
$: existsInCollection = $collectionStore.find((item: SavedGameType) => item.id === game.id);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
@ -36,8 +44,7 @@
|
||||||
aria-label="Remove from collection"
|
aria-label="Remove from collection"
|
||||||
class="btn"
|
class="btn"
|
||||||
type="button"
|
type="button"
|
||||||
on:click={() => removeFromCollection(game)}
|
on:click={() => removeGame()}>Remove <MinusCircleIcon width="24" height="24" /></button
|
||||||
>Remove <MinusCircleIcon width="24" height="24" /></button
|
|
||||||
>
|
>
|
||||||
{:else}
|
{:else}
|
||||||
<button
|
<button
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
async function getRandomCollectionGame() {
|
async function getRandomCollectionGame() {
|
||||||
if ($collectionStore.length > 0) {
|
if ($collectionStore.length > 0) {
|
||||||
boredState.set({ loading: true, dialogOpen: false });
|
boredState.set({ 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();
|
||||||
|
|
@ -19,11 +19,11 @@
|
||||||
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.set({ loading: false, dialogOpen: false });
|
boredState.set({ loading: false });
|
||||||
} else {
|
} else {
|
||||||
toast.send('Error!', { duration: 3000, type: ToastType.ERROR, dismissible: true });
|
toast.send('Error!', { duration: 3000, type: ToastType.ERROR, dismissible: true });
|
||||||
}
|
}
|
||||||
boredState.set({ loading: false, dialogOpen: false });
|
boredState.set({ loading: false });
|
||||||
} else {
|
} else {
|
||||||
toast.send('No items in your collection!', {
|
toast.send('No items in your collection!', {
|
||||||
duration: 3000,
|
duration: 3000,
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
async function handleSubmit(event: SubmitEvent) {
|
async function handleSubmit(event: SubmitEvent) {
|
||||||
// submitting = true;
|
// submitting = true;
|
||||||
boredState.set({ loading: true, dialogOpen: false });
|
boredState.set({ loading: true });
|
||||||
const form = event.target as HTMLFormElement;
|
const form = event.target as HTMLFormElement;
|
||||||
console.log('form', form);
|
console.log('form', form);
|
||||||
const response = await fetch('/api/games', {
|
const response = await fetch('/api/games', {
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
});
|
});
|
||||||
const responseData = await response.json();
|
const responseData = await response.json();
|
||||||
// submitting = false;
|
// submitting = false;
|
||||||
boredState.set({ loading: false, dialogOpen: false });
|
boredState.set({ loading: false });
|
||||||
gameStore.removeAll();
|
gameStore.removeAll();
|
||||||
gameStore.addAll(responseData?.games);
|
gameStore.addAll(responseData?.games);
|
||||||
// games = responseData?.games;
|
// games = responseData?.games;
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { writable } from 'svelte/store';
|
||||||
|
|
||||||
// Custom store
|
// Custom store
|
||||||
const state = () => {
|
const state = () => {
|
||||||
const { subscribe, set, update } = writable<BoredStore>({ loading: false, dialogOpen: false });
|
const { subscribe, set, update } = writable<BoredStore>({ loading: false });
|
||||||
|
|
||||||
// function remove(id: string) {
|
// function remove(id: string) {
|
||||||
// update((store) => {
|
// update((store) => {
|
||||||
|
|
@ -20,7 +20,7 @@ const state = () => {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
function clear() {
|
function clear() {
|
||||||
set({ loading: false, dialogOpen: false });
|
set({ loading: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
return { subscribe, set, update, clear };
|
return { subscribe, set, update, clear };
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
export type BoredStore = {
|
export type BoredStore = {
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
dialogOpen: boolean;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export enum ToastType {
|
export enum ToastType {
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,8 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { browser } from '$app/environment';
|
import { browser } from '$app/environment';
|
||||||
import { fade } from 'svelte/transition';
|
|
||||||
import { navigating } from '$app/stores';
|
import { navigating } from '$app/stores';
|
||||||
import debounce from 'just-debounce-it';
|
import debounce from 'just-debounce-it';
|
||||||
import { Toy } from '@leveluptuts/svelte-toy';
|
import { Toy } from '@leveluptuts/svelte-toy';
|
||||||
import {
|
|
||||||
Dialog,
|
|
||||||
DialogOverlay,
|
|
||||||
DialogTitle,
|
|
||||||
DialogDescription
|
|
||||||
} from '@rgossiaux/svelte-headlessui';
|
|
||||||
import Header from '$lib/components/header/Header.svelte';
|
import Header from '$lib/components/header/Header.svelte';
|
||||||
import Loading from '$lib/components/loading.svelte';
|
import Loading from '$lib/components/loading.svelte';
|
||||||
import Transition from '$lib/components/transition/index.svelte';
|
import Transition from '$lib/components/transition/index.svelte';
|
||||||
|
|
@ -24,11 +17,11 @@
|
||||||
$: {
|
$: {
|
||||||
if ($navigating) {
|
if ($navigating) {
|
||||||
debounce(() => {
|
debounce(() => {
|
||||||
boredState.set({ loading: true, dialogOpen: false });
|
boredState.set({ loading: true });
|
||||||
}, 250);
|
}, 250);
|
||||||
}
|
}
|
||||||
if (!$navigating) {
|
if (!$navigating) {
|
||||||
boredState.set({ loading: false, dialogOpen: false });
|
boredState.set({ loading: false });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -81,51 +74,10 @@
|
||||||
<div class="background" />
|
<div class="background" />
|
||||||
</Portal>
|
</Portal>
|
||||||
{/if}
|
{/if}
|
||||||
{#if $boredState?.dialogOpen}
|
|
||||||
<div transition:fade>
|
|
||||||
<Dialog
|
|
||||||
open={$boredState?.dialogOpen}
|
|
||||||
on:close={() => boredState.set({ loading: false, dialogOpen: false })}
|
|
||||||
static
|
|
||||||
>
|
|
||||||
<DialogOverlay
|
|
||||||
style={'position: fixed; inset: 0; z-index: 100; background-color: rgb(0 0 0); opacity: 0.3;'}
|
|
||||||
/>
|
|
||||||
<div class="dialog">
|
|
||||||
<DialogTitle>Deactivate account</DialogTitle>
|
|
||||||
<DialogDescription>This will permanently deactivate your account</DialogDescription>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Are you sure you want to deactivate your account? All of your data will be permanently
|
|
||||||
removed. This action cannot be undone.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<button on:click={() => boredState.set({ loading: false, dialogOpen: false })}
|
|
||||||
>Deactivate</button
|
|
||||||
>
|
|
||||||
<button on:click={() => boredState.set({ loading: false, dialogOpen: false })}
|
|
||||||
>Cancel</button
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</Dialog>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
<Toast />
|
<Toast />
|
||||||
</Transition>
|
</Transition>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
:global(.dialog) {
|
|
||||||
position: fixed;
|
|
||||||
top: 25%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
z-index: 101;
|
|
||||||
border-radius: 10px;
|
|
||||||
background-color: var(--primary);
|
|
||||||
padding: 2rem;
|
|
||||||
/* max-width: 400px; */
|
|
||||||
}
|
|
||||||
|
|
||||||
.loading {
|
.loading {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
import { boredState } from '$root/lib/stores/boredState';
|
import { boredState } from '$root/lib/stores/boredState';
|
||||||
|
|
||||||
async function handleSearch(event: SubmitEvent) {
|
async function handleSearch(event: SubmitEvent) {
|
||||||
boredState.set({ loading: true, dialogOpen: false });
|
boredState.set({ loading: true });
|
||||||
const form = event.target as HTMLFormElement;
|
const form = event.target as HTMLFormElement;
|
||||||
console.log('form', form);
|
console.log('form', form);
|
||||||
const response = await fetch('/api/game', {
|
const response = await fetch('/api/game', {
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
body: new FormData(form)
|
body: new FormData(form)
|
||||||
});
|
});
|
||||||
const responseData = await response.json();
|
const responseData = await response.json();
|
||||||
boredState.set({ loading: false, dialogOpen: false });
|
boredState.set({ loading: false });
|
||||||
gameStore.removeAll();
|
gameStore.removeAll();
|
||||||
gameStore.addAll(responseData?.games);
|
gameStore.addAll(responseData?.games);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,30 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { fade } from 'svelte/transition';
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogDescription,
|
||||||
|
DialogOverlay,
|
||||||
|
DialogTitle
|
||||||
|
} from '@rgossiaux/svelte-headlessui';
|
||||||
import Game from '$lib/components/game/index.svelte';
|
import Game from '$lib/components/game/index.svelte';
|
||||||
import { collectionStore } from '$lib/stores/collectionStore';
|
import { collectionStore } from '$lib/stores/collectionStore';
|
||||||
|
import type { GameType, SavedGameType } from '$root/lib/types';
|
||||||
|
import { removeFromCollection } from '$root/lib/util/manipulateCollection';
|
||||||
|
|
||||||
|
let isOpen: boolean = false;
|
||||||
|
let gameToRemove: GameType | SavedGameType;
|
||||||
|
console.log('isOpen', isOpen);
|
||||||
|
|
||||||
|
function handleRemoveGame(event: Event) {
|
||||||
|
console.log('event', event);
|
||||||
|
gameToRemove = event?.detail;
|
||||||
|
isOpen = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeGame() {
|
||||||
|
removeFromCollection(gameToRemove);
|
||||||
|
isOpen = false;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
|
|
@ -11,11 +35,37 @@
|
||||||
|
|
||||||
<div class="games">
|
<div class="games">
|
||||||
<div class="games-list">
|
<div class="games-list">
|
||||||
{#each $collectionStore as game}
|
{#if $collectionStore.length === 0}
|
||||||
<Game minimal {game} />
|
<h2>No games in your collection</h2>
|
||||||
{/each}
|
{:else}
|
||||||
|
{#each $collectionStore as game}
|
||||||
|
<Game on:removeGameEvent={handleRemoveGame} minimal {game} />
|
||||||
|
{/each}
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{#if isOpen}
|
||||||
|
<!-- <div class="container"> -->
|
||||||
|
<div transition:fade>
|
||||||
|
<Dialog open={isOpen} on:close={() => (isOpen = false)} static>
|
||||||
|
<div transition:fade>
|
||||||
|
<DialogOverlay class="dialog-overlay" />
|
||||||
|
<div class="dialog">
|
||||||
|
<DialogTitle>Remove from collection</DialogTitle>
|
||||||
|
<DialogDescription
|
||||||
|
>Are you sure you want to remove from your collection?</DialogDescription
|
||||||
|
>
|
||||||
|
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<button on:click={() => removeGame()}>Remove</button>
|
||||||
|
<button on:click={() => (isOpen = false)}>Cancel</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Dialog>
|
||||||
|
</div>
|
||||||
|
<!-- </div> -->
|
||||||
|
{/if}
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
h1 {
|
h1 {
|
||||||
|
|
@ -39,4 +89,39 @@
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dialog) {
|
||||||
|
display: grid;
|
||||||
|
gap: 1.5rem;
|
||||||
|
position: fixed;
|
||||||
|
top: 25%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
z-index: 101;
|
||||||
|
border-radius: 10px;
|
||||||
|
background-color: var(--primary);
|
||||||
|
padding: 2rem;
|
||||||
|
max-width: 500px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.dialog-overlay) {
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
z-index: 100;
|
||||||
|
background-color: rgb(0 0 0);
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.dialog-footer) {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 2rem;
|
||||||
|
margin: 1rem 0;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
.container > .button {
|
||||||
|
display: grid;
|
||||||
|
justify-content: center;
|
||||||
|
background-color: var(--primary);
|
||||||
|
} */
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue