mirror of
https://github.com/BradNut/boredgame
synced 2025-09-08 17:40:22 +00:00
Save and clear collection from storage. Load from user storage into collection store on page load.
This commit is contained in:
parent
213cb8ed74
commit
470c0b051e
6 changed files with 189 additions and 16 deletions
|
|
@ -15,8 +15,8 @@
|
|||
</div>
|
||||
|
||||
<nav>
|
||||
<div><Themes /></div>
|
||||
<!-- <div><Profile /></div> -->
|
||||
<!-- <div><Themes /></div> -->
|
||||
<div><Profile /></div>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
|
|
|
|||
43
src/lib/components/preferences/gameCollection.svelte
Normal file
43
src/lib/components/preferences/gameCollection.svelte
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
<script lang="ts">
|
||||
import { browser } from '$app/env';
|
||||
import { collectionStore } from '$root/lib/stores/collectionStore';
|
||||
import { ToastType } from '$root/lib/types';
|
||||
import { SaveIcon } from '@rgossiaux/svelte-heroicons/outline';
|
||||
import { toast } from '../toast/toast';
|
||||
|
||||
function saveCollection() {
|
||||
console.log('Saving collection');
|
||||
console.log('collectionStore', $collectionStore);
|
||||
if (!browser) return;
|
||||
localStorage.collection = JSON.stringify($collectionStore);
|
||||
toast.send("Saved collection", { duration: 3000, type: ToastType.INFO });
|
||||
}
|
||||
|
||||
function clearCollection() {
|
||||
if (!browser) return;
|
||||
localStorage.collection = [];
|
||||
toast.send("Cleared collection", { duration: 3000, type: ToastType.INFO });
|
||||
}
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<button type="button" on:click={() => saveCollection()}><SaveIcon class="preferences-icon" /> Save Collection</button>
|
||||
<button type="button" on:click={() => clearCollection()}><SaveIcon class="preferences-icon" /> Clear Collection</button>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
:global(.preferences-icon) {
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
}
|
||||
|
||||
div {
|
||||
display: grid;
|
||||
}
|
||||
|
||||
button {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,25 +1,141 @@
|
|||
<script lang="ts">
|
||||
import { fade } from 'svelte/transition';
|
||||
import { Popover, PopoverButton, PopoverPanel } from '@rgossiaux/svelte-headlessui';
|
||||
import { CogIcon } from '@rgossiaux/svelte-heroicons/outline'
|
||||
import Themes from './themes.svelte';
|
||||
import GameCollection from './gameCollection.svelte';
|
||||
</script>
|
||||
|
||||
<Popover style="position: relative;">
|
||||
<PopoverButton>Solutions</PopoverButton>
|
||||
<div class="container">
|
||||
<Popover let:open class="popover">
|
||||
<PopoverButton aria-label="Preferences">
|
||||
<CogIcon width="24" height="24" />
|
||||
</PopoverButton>
|
||||
|
||||
<PopoverPanel style="position: absolute; z-index: 10;">
|
||||
<div class="panel-contents">
|
||||
<a href="/analytics">Analytics</a>
|
||||
<a href="/engagement">Engagement</a>
|
||||
<a href="/security">Security</a>
|
||||
<a href="/integrations">Integrations</a>
|
||||
</div>
|
||||
{#if open}
|
||||
<div transition:fade={{ duration: 100 }}>
|
||||
<PopoverPanel class="popover-panel" static>
|
||||
<div class="preferences">
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
class="arrow"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
id="inside"
|
||||
d="M23 24H1L11.0909 1.98341C11.4474 1.20562 12.5526 1.20562 12.9091 1.98341L23 24Z"
|
||||
fill="none"
|
||||
/>
|
||||
<path
|
||||
id="outside"
|
||||
d="M12.8944 1.78885L24 24H23L12.9021 2.88628C12.5396 2.12822 11.4604 2.12822 11.0979 2.88628L1 24H0L11.1056 1.78885C11.4741 1.05181 12.5259 1.0518 12.8944 1.78885Z"
|
||||
fill="none"
|
||||
/>
|
||||
</svg>
|
||||
|
||||
<img src="/solutions.jpg" alt="" />
|
||||
</PopoverPanel>
|
||||
</Popover>
|
||||
<span class="title">Preferences</span>
|
||||
|
||||
<div class="options">
|
||||
<Themes />
|
||||
<GameCollection />
|
||||
</div>
|
||||
</div>
|
||||
</PopoverPanel>
|
||||
</div>
|
||||
{/if}
|
||||
</Popover>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.panel-contents {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.container :global(.popover) {
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.container :global(.popover-panel) {
|
||||
position: absolute;
|
||||
top: 48px;
|
||||
right: -22px;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.preferences {
|
||||
background-image: var(--clr-menu-bg);
|
||||
padding: var(--spacing-24);
|
||||
border: 1px solid var(--clr-menu-border);
|
||||
border-radius: var(--rounded-20);
|
||||
box-shadow: var(--shadow-lg);
|
||||
}
|
||||
|
||||
.preferences .arrow {
|
||||
position: absolute;
|
||||
top: -23px;
|
||||
right: 22px;
|
||||
}
|
||||
|
||||
.preferences .arrow #inside {
|
||||
fill: var(--clr-menu-arrow-bg);
|
||||
}
|
||||
|
||||
.preferences .arrow #outside {
|
||||
fill: var(--clr-menu-border);
|
||||
}
|
||||
|
||||
.preferences .title {
|
||||
display: block;
|
||||
padding-bottom: var(--spacing-8);
|
||||
font-size: var(--font-24);
|
||||
font-weight: 700;
|
||||
line-height: 32px;
|
||||
border-bottom: 1px solid var(--clr-menu-border);
|
||||
}
|
||||
|
||||
.preferences .options {
|
||||
font-weight: 500;
|
||||
color: var(--clr-menu-text);
|
||||
}
|
||||
|
||||
.preferences .options > :global(*) {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: var(--spacing-32);
|
||||
padding: var(--spacing-24) 0;
|
||||
}
|
||||
|
||||
.preferences .options > :global(*:not(:last-child)) {
|
||||
border-bottom: 1px solid var(--clr-menu-border);
|
||||
}
|
||||
|
||||
.preferences .options > :global(*:last-child) {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.preferences .options span {
|
||||
max-width: 180px;
|
||||
}
|
||||
|
||||
@media (min-width: 480px) {
|
||||
.preferences {
|
||||
width: 420px;
|
||||
}
|
||||
|
||||
.preferences .options > :global(*) {
|
||||
gap: var(--spacing-64);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,12 @@ import type { GameType } from '$lib/types';
|
|||
const state = () => {
|
||||
const { subscribe, set, update } = writable<GameType[]>([]);
|
||||
|
||||
function addAll(games: GameType[]) {
|
||||
for (const game of games) {
|
||||
add(game);
|
||||
}
|
||||
}
|
||||
|
||||
function add(game: GameType) {
|
||||
update((store) => [...store, game]);
|
||||
}
|
||||
|
|
@ -22,7 +28,7 @@ const state = () => {
|
|||
});
|
||||
}
|
||||
|
||||
return { subscribe, set, update, add, remove, removeAll };
|
||||
return { subscribe, set, update, add, addAll, remove, removeAll };
|
||||
};
|
||||
|
||||
export const collectionStore = state();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
<script lang="ts">
|
||||
import { browser } from '$app/env';
|
||||
import { Toy } from '@leveluptuts/svelte-toy';
|
||||
import Header from '$lib/components/header/Header.svelte';
|
||||
import Loading from '$lib/components/loading.svelte';
|
||||
|
|
@ -11,6 +12,14 @@
|
|||
import '$root/styles/styles.scss';
|
||||
import Toast from '$lib/components/toast/Toast.svelte';
|
||||
|
||||
if (browser) {
|
||||
const collection = JSON.parse(localStorage.collection);
|
||||
console.log('collection', collection);
|
||||
if (collection) {
|
||||
collectionStore.addAll(collection);
|
||||
}
|
||||
}
|
||||
|
||||
const dev = process.env.NODE_ENV !== 'production';
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -80,7 +80,6 @@
|
|||
}
|
||||
}
|
||||
.game-search {
|
||||
margin: 1rem;
|
||||
border-radius: 4px;
|
||||
box-shadow: var(--level-2);
|
||||
background: rgba(0, 0, 0, 0.02);
|
||||
|
|
|
|||
Loading…
Reference in a new issue