90 lines
3.0 KiB
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ür {selectedDate}.</div>
|
|
{/each}
|