<script lang="ts">
import { browser } from "$app/env";
import { resolve } from "$app/paths";
import ArrowRight from "$icon/arrow-right";
import Bell from "$icon/bell";
import BellOff from "$icon/bell-off";
import Inbox from "$icon/inbox";
import { createLoad } from "#lib/action.svelte.ts";
import NotificationList from "#lib/components/notifications/NotificationList.svelte";
import type { NotificationSummary } from "#lib/components/notifications/types.ts";
import { getNotifications, type Notifications } from "#lib/notifications.svelte.ts";
import PreviewCard from "#lib/components/timeline/PreviewCard.svelte";
import PreviewEmpty from "#lib/components/timeline/PreviewEmpty.svelte";
import timelineNotificationspreviewSkeletonFixture from "#lib/bones/timeline-notificationspreview--skeleton-fixture.bones.json";
import Bones from "#lib/components/ui/Bones.svelte";
import Button from "#lib/components/ui/Button.svelte";
const PREVIEW_LIMIT = 5;
let {
signedIn = false,
notifications: fixtures
}: {
signedIn?: boolean;
notifications?: NotificationSummary[] | Promise<NotificationSummary[]>;
} = $props();
const context = getNotifications() as Notifications | undefined;
const path = "/notifications";
const fixturePreview = $derived.by(() => {
if (!fixtures) return undefined;
if (fixtures instanceof Promise) return fixtures;
return { notifications: fixtures, totalUnread: fixtures.filter((n) => !n.read).length };
});
const previewLoad = createLoad(async (): Promise<NotificationSummary[] | null> => {
if (!browser || !signedIn || !context) return null;
return context.list({ limit: PREVIEW_LIMIT });
});
const live = $derived(
previewLoad.data ? (context?.overlay(previewLoad.data) ?? previewLoad.data) : null
);
const loading = $derived(
signedIn &&
fixtures === undefined &&
(previewLoad.loading || previewLoad.data === undefined)
);
</script>
{#snippet content(items: NotificationSummary[], totalUnread: number | null)}
{#if items.length > 0}
<NotificationList notifications={items} border={false} onToggleRead={context?.setRead} />
{:else if totalUnread === 0}
<PreviewEmpty icon={Inbox}>
<p>All caught up!</p>
</PreviewEmpty>
{:else}
<PreviewEmpty icon={Bell}>
<a href={resolve(path as "/")}>Open your inbox</a>
</PreviewEmpty>
{/if}
{/snippet}
<PreviewCard title="Notifications" icon={Bell} href={path}>
{#snippet action()}
<Button
href={resolve(path as "/")}
variant="ghost"
size="small"
class="self-stretch [--btn-radius:var(--radius-md)]"
>
View all
<ArrowRight class="size-3.5" aria-hidden="true" />
</Button>
{/snippet}
{#if !signedIn}
<PreviewEmpty icon={BellOff}>
<a href={resolve("/login" as "/")}>Sign in</a> to view your inbox
</PreviewEmpty>
{:else if loading}
<Bones capture={timelineNotificationspreviewSkeletonFixture} />
{:else if fixturePreview}
{#if fixturePreview instanceof Promise}
{#await fixturePreview}
<Bones capture={timelineNotificationspreviewSkeletonFixture} />
{:then resolved}
{@render content(resolved, null)}
{/await}
{:else}
{@render content(fixturePreview.notifications, fixturePreview.totalUnread)}
{/if}
{:else if live}
{@render content(live, context?.unread ?? null)}
{:else}
<PreviewEmpty icon={Bell}>
<a href={resolve(path as "/")}>Open your inbox</a>
</PreviewEmpty>
{/if}
</PreviewCard>