Ka-Note/ka-note/client/src/lib/components/PersonsView.svelte

90 lines
3.0 KiB
Svelte

<script lang="ts">
import { liveQuery } from 'dexie';
import { db } from '$lib/db/schema';
import { extractAssignments, extractMentions } from '$lib/utils/extractors';
import { today } from '$lib/db/helpers';
import { JOURNAL_TOPIC_ID } from '$lib/db/repositories';
import HistoryEntryText from './HistoryEntryText.svelte';
import DateNavigator from './DateNavigator.svelte';
import type { EventMeta } from '@ka-note/shared';
interface Props {
contextId: string;
}
let { contextId }: Props = $props();
const isDailyLog = $derived(contextId === 'daily-log');
let selectedDate = $state(today());
const personData = liveQuery(async () => {
const topics = await db.topics
.where('contextId').equals(contextId)
.filter(t => !t.deletedAt)
.toArray();
// For daily-log: also include the journal topic
const journalTopic = isDailyLog ? await db.topics.get(JOURNAL_TOPIC_ID) : null;
const allTopics = journalTopic ? [...topics, journalTopic] : topics;
const history = allTopics.length > 0
? await db.historyEntries
.where('topicId').anyOf(allTopics.map(t => t.id))
.filter(h => !h.deletedAt)
.toArray()
: [];
const byPerson = new Map<string, { id: string; topicId: string; title: string; date: string; text: string }[]>();
for (const h of history) {
const topic = allTopics.find(t => t.id === h.topicId);
const names = new Set([...extractAssignments(h.text), ...extractMentions(h.text)]);
for (const name of names) {
const list = byPerson.get(name) ?? [];
list.push({ id: h.id, topicId: h.topicId, title: topic?.title ?? '', date: h.date, text: h.text });
byPerson.set(name, list);
}
}
// For daily-log: also collect participants from events
if (isDailyLog) {
const events = await db.contexts
.filter(c => !c.deletedAt && c.type === 'event')
.toArray();
for (const ev of events) {
const meta = ev.meta as EventMeta | null;
if (!meta) continue;
for (const name of meta.participants ?? []) {
const list = byPerson.get(name) ?? [];
list.push({ id: '', topicId: '', title: ev.name, date: meta.date, text: '' });
byPerson.set(name, list);
}
}
}
return [...byPerson.entries()].sort((a, b) => a[0].localeCompare(b[0]));
});
const filteredData = $derived(
($personData ?? [])
.map(([person, tasks]) => [person, tasks.filter(t => t.date === selectedDate)] as const)
.filter(([, tasks]) => tasks.length > 0)
);
</script>
<DateNavigator {selectedDate} onchange={(d) => selectedDate = d} />
{#each filteredData as [person, tasks]}
<div class="mb-5 rounded-lg border-l-[5px] border-l-info bg-card-bg p-4">
<div class="mb-2.5 border-b border-[#444] pb-1 text-xl font-bold text-info">{person}</div>
{#each tasks as task}
<div class="mb-2.5 border-l-2 border-[#444] pl-2.5">
<div class="mb-0.5 text-xs text-[#aaa]">{task.title}</div>
<HistoryEntryText entry={task} />
</div>
{/each}
</div>
{:else}
<div class="text-center text-muted">Keine Personen-Referenzen f&uuml;r {selectedDate}.</div>
{/each}