Skip to content

Commit

Permalink
feat: sidebar store for managing localstorage states
Browse files Browse the repository at this point in the history
  • Loading branch information
moonlitgrace committed Dec 22, 2024
1 parent a6990cd commit 5419b24
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 26 deletions.
57 changes: 32 additions & 25 deletions frontend/src/lib/components/sidebar.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
import Avatar from '$lib/components/ui/avatar.svelte';
import favorite_communities from '$lib/data/mock/favorites.json';

Check failure on line 4 in frontend/src/lib/components/sidebar.svelte

View workflow job for this annotation

GitHub Actions / lint

'favorite_communities' is defined but never used
import your_communities from '$lib/data/mock/your_communities.json';
import { createSidebarStore } from '$lib/stores/sidebar.svelte';
const sidebarStore = createSidebarStore();
$inspect(sidebarStore.state);
</script>

<div
Expand Down Expand Up @@ -30,31 +35,33 @@
<span class="text-xs font-medium">Create Quiblet</span>
</button>
</div>
<div class="collapse gap-2 rounded-none">
<input type="checkbox" checked={true} class="peer h-max min-h-full w-full" />
<div
class="collapse-title flex h-max min-h-max items-center justify-between p-0 text-sm font-medium text-base-content/75 peer-checked:[&>coreicons-shape-chevron]:rotate-180"
>
Recent
<coreicons-shape-chevron class="size-4 transition-transform" variant="down"
></coreicons-shape-chevron>
</div>
<div class="collapse-content flex flex-col gap-2 !p-0">
{#each favorite_communities as community}
<div class="flex items-center gap-2">
<a href="q/{community.name}" class="flex">
<Avatar src={community.avatar} />
</a>
<a href="q/{community.name}" class="text-sm font-medium">q/{community.name}</a>
<button class="ml-auto" aria-label="Star Community">
<coreicons-shape-star class="size-4" class:text-primary={community.starred}
></coreicons-shape-star>
</button>
</div>
{/each}
{#if sidebarStore.state.recent}
<div class="collapse gap-2 overflow-visible rounded-none">
<input type="checkbox" checked={true} class="peer h-max min-h-full w-full" />
<div
class="collapse-title flex h-max min-h-max items-center justify-between p-0 text-sm font-medium text-base-content/75 peer-checked:[&>coreicons-shape-chevron]:rotate-180"
>
Recent
<coreicons-shape-chevron class="size-4 transition-transform" variant="down"
></coreicons-shape-chevron>
</div>
<div class="collapse-content flex flex-col gap-2 !p-0">
{#each sidebarStore.state.recent as quiblet}
<div class="flex items-center gap-2">
<a href="/q/{quiblet.name}" class="flex">
<Avatar src={quiblet.avatar} />
</a>
<a href="/q/{quiblet.name}" class="text-sm font-medium">q/{quiblet.name}</a>
<button class="ml-auto" aria-label="Star Community">
<coreicons-shape-star class="size-4" class:text-primary={quiblet.starred}
></coreicons-shape-star>
</button>
</div>
{/each}
</div>
</div>
</div>
<div class="collapse gap-2 rounded-none">
{/if}
<div class="collapse gap-2 overflow-visible rounded-none">
<input type="checkbox" checked={true} class="peer h-max min-h-full w-full" />
<div
class="collapse-title flex h-max min-h-max items-center justify-between p-0 text-sm font-medium text-base-content/75 peer-checked:[&>coreicons-shape-chevron]:rotate-180"
Expand All @@ -78,7 +85,7 @@
{/each}
</div>
</div>
<div class="collapse gap-2 rounded-none">
<div class="collapse gap-2 overflow-visible rounded-none">
<input type="checkbox" checked={true} class="peer h-max min-h-full w-full" />
<div
class="collapse-title flex h-max min-h-max items-center justify-between p-0 text-sm font-medium text-base-content/75 peer-checked:[&>coreicons-shape-chevron]:rotate-180"
Expand Down
64 changes: 64 additions & 0 deletions frontend/src/lib/stores/sidebar.svelte.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { browser } from '$app/environment';

type ISidebarStore = Record<string, IQuiblets>;

type IQuiblets = {
avatar?: string | null | undefined;
name: string;
starred: boolean;
}[];

export function createSidebarStore() {
const stored_sidebar_store = browser ? localStorage.getItem('sidebar_store') : null;

const parsed_stored_quiblets: ISidebarStore = stored_sidebar_store
? JSON.parse(stored_sidebar_store)
: {};

let sidebar_state = $state<ISidebarStore>(parsed_stored_quiblets);

Check failure on line 18 in frontend/src/lib/stores/sidebar.svelte.ts

View workflow job for this annotation

GitHub Actions / lint

'sidebar_state' is never reassigned. Use 'const' instead

function sync_localstorage() {
if (browser) {
localStorage.setItem('sidebar_store', JSON.stringify(sidebar_state));
}
}

function sort_quiblets(quiblets: IQuiblets) {
return [...quiblets].sort((a, b) => {
if (a.starred !== b.starred) {
return b.starred ? 1 : -1;
}
return a.name.localeCompare(b.name);
});
}

return {
get state() {
return sidebar_state;
},
add_quiblet(quiblet: IQuiblets[number], type: string) {
// initialize empty array for type
if (!sidebar_state[type]) {
sidebar_state[type] = [];
}

const state = sidebar_state[type];
if (!state) return;

const exists = state.some((q) => q.name === quiblet.name);
if (exists) return;

sidebar_state[type] = sort_quiblets([...state, quiblet]);
sync_localstorage();
},
toggle_star(name: string, type: string) {
if (!sidebar_state[type]) return;

sidebar_state[type] = sort_quiblets(
sidebar_state[type].map((q) =>
q.name === name ? { ...q, starred: !q.starred } : q
)
);
}
};
}
16 changes: 15 additions & 1 deletion frontend/src/routes/(app)/q/[name]/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,32 @@
import type { PageData } from './$types';
import { FormatDate } from '$lib/functions/date';
import { createAuthStore } from '$lib/stores/auth.svelte';
import { onMount } from 'svelte';
import { createSidebarStore } from '$lib/stores/sidebar.svelte';
const { data }: { data: PageData } = $props();
const { quiblet, quibs, highlighted_quibs } = data;
const authStore = createAuthStore();
const authStore = createAuthStore(),
sidebarStore = createSidebarStore();
const is_joined = $derived.by(() => {
if (!authStore.state.is_authenticated) return false;
if (authStore.state.profile && quiblet) {
return quiblet.members?.includes(authStore.state.profile.id);
}
});
onMount(() => {
sidebarStore.add_quiblet(
{
avatar: quiblet.avatar,
name: quiblet.name,
starred: false
},
'recent'
);
});
</script>

<svelte:head>
Expand Down

0 comments on commit 5419b24

Please sign in to comment.