Save and clear collection from storage. Load from user storage into collection store on page load.

This commit is contained in:
Bradley Shellnut 2022-08-01 16:30:06 -07:00
parent 213cb8ed74
commit 470c0b051e
6 changed files with 189 additions and 16 deletions

View file

@ -15,8 +15,8 @@
</div>
<nav>
<div><Themes /></div>
<!-- <div><Profile /></div> -->
<!-- <div><Themes /></div> -->
<div><Profile /></div>
</nav>
</header>

View 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>

View file

@ -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>

View file

@ -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();

View file

@ -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>

View file

@ -80,7 +80,6 @@
}
}
.game-search {
margin: 1rem;
border-radius: 4px;
box-shadow: var(--level-2);
background: rgba(0, 0, 0, 0.02);