This repository has been archived on 2025-03-02. You can view files and clone it, but cannot push or open issues or pull requests.
identity/identity-web/src/routes/dashboard/Entries.svelte

146 lines
No EOL
5.2 KiB
Svelte

<script lang="ts">
import type { Entry as EntryType, EntryKind, KnownFeeling } from "$lib/entry";
import ExternalLink from "./utils/ExternalLink.svelte";
import FeelingPill from "./utils/FeelingPill.svelte";
import Entry from "./utils/Entry.svelte";
import EntryDescription from "./utils/EntryDescription.svelte";
import AssetPreview from "./utils/AssetPreview.svelte";
import { createEventDispatcher } from "svelte";
import Fuse from "fuse.js";
let dispatch = createEventDispatcher()
export let entries: EntryType[]
let filteredEntries = entries
export let filters: {
fromDate: null | Date,
toDate: null | Date,
kind: null | EntryKind[],
feelings: null | {
exclusive: boolean,
feelings: KnownFeeling[],
},
searchQuery: null | string,
}
let extended: string[] = []
function applyFilters(filters: {
fromDate: null | Date,
toDate: null | Date,
kind: null | EntryKind[],
feelings: null | {
exclusive: boolean,
feelings: KnownFeeling[],
},
searchQuery: null | string,
}) {
filteredEntries = entries
if (filters.fromDate != null) {
filteredEntries = entries.filter((v) => new Date(v.creationDate) >= filters.fromDate!);
}
if (filters.toDate != null) {
filteredEntries = entries.filter((v) => new Date(v.creationDate) <= filters.toDate!);
}
if (filters.kind != null) {
filteredEntries = entries.filter((v) => filters.kind!.includes(v.base.kind));
}
if (filters.feelings != null) {
let feelings = filters.feelings!.feelings
if (filters.feelings.exclusive) {
filteredEntries = entries.filter((v) => {
let v1 = v.feelings.filter((f) => typeof f === "string" && feelings.includes(f))
return v.feelings.length === v1.length;
})
} else {
filteredEntries = entries.filter((v) => {
let includes = false
feelings.forEach((f) => {
if (v.feelings.includes(f)) {
includes = true
}
})
return includes
})
}
}
if (filters.searchQuery != null) {
let fuse = new Fuse(entries, {
keys: [
"title",
"description",
],
});
let results = fuse.search(filters.searchQuery!);
filteredEntries = results.map((v) => v.item);
}
if (filteredEntries.length !== entries.length) {
dispatch('updatedFilterStatus', true)
} else {
dispatch('updatedFilterStatus', false)
}
}
$: applyFilters(filters)
</script>
{#each filteredEntries as entry (entry.id)}
<Entry
on:extended={(e) => extended = [e.detail.id, ...extended]}
on:contracted={(e) => extended = extended.filter(v => v !== e.detail.id)}
on:deleted={(e) => { dispatch('deleted', e.detail) }}
id={entry.id}
kind={entry.base.kind}
creationDate={new Date(entry.creationDate)}
title={entry.base.kind === "date" ? new Date(entry.base.referencedDate).toLocaleDateString() : entry.title}
isExtended={extended.includes(entry.id)}
>
<div slot="contracted">
{#if entry.base.kind === "song" || entry.base.kind === "album"}
<ExternalLink href={entry.base.link[0]}>{entry.base.artist} &dash; {entry.base.title}</ExternalLink>
{/if}
{#if entry.base.kind === "feeling"}
<div class="flex gap-1">
{#each entry.feelings as feeling}
{#if typeof feeling === "string"}
<FeelingPill feeling={feeling}/>
{:else}
<FeelingPill feeling={feeling.identifier} bgColor={feeling.backgroundColor} textColor={feeling.textColor}/>
{/if}
{/each}
</div>
{/if}
</div>
<div slot="extended">
<div class="flex gap-1 mb-2">
{#each entry.feelings as feeling}
{#if typeof feeling === "string"}
<FeelingPill feeling={feeling}/>
{:else}
<FeelingPill feeling={feeling.identifier} bgColor={feeling.backgroundColor} textColor={feeling.textColor}/>
{/if}
{/each}
</div>
{#if entry.base.kind === "song" || entry.base.kind === "album"}
<ExternalLink href={entry.base.link[0]}>{entry.base.artist} &dash; {entry.base.title}</ExternalLink>
{/if}
{#if entry.description != null}
<EntryDescription>{entry.description}</EntryDescription>
{/if}
<div class="flex gap-1 mt-2">
{#each entry.assets as asset}
<AssetPreview asset_id={asset}/>
{/each}
</div>
</div>
</Entry>
{/each}