Ka-Note/ka-note/client/src/lib/stores/agenda.ts

121 lines
3.0 KiB
TypeScript

import { writable, derived } from 'svelte/store';
import { liveQuery } from 'dexie';
import { db } from '$lib/db/schema';
import type { AgendaContext, Topic, HistoryEntry, ContextType } from '@ka-note/shared';
// --- Writable UI state ---
export const currentContextId = writable<string>('daily-log');
export const currentMode = writable<'prep' | 'meeting'>('prep');
export const currentView = writable<string>('agenda');
// --- Session-only state (resets on tab close) ---
const isBrowser = typeof sessionStorage !== 'undefined';
function createSessionSet(key: string) {
const stored = isBrowser ? sessionStorage.getItem(key) : null;
const initial = stored ? new Set<string>(JSON.parse(stored)) : new Set<string>();
const { subscribe, set, update } = writable(initial);
return {
subscribe,
add(id: string) {
update(s => {
s.add(id);
if (isBrowser) sessionStorage.setItem(key, JSON.stringify([...s]));
return new Set(s);
});
},
remove(id: string) {
update(s => {
s.delete(id);
if (isBrowser) sessionStorage.setItem(key, JSON.stringify([...s]));
return new Set(s);
});
},
clear() {
set(new Set());
if (isBrowser) sessionStorage.removeItem(key);
}
};
}
export const processedTopicIds = createSessionSet('ka-note-processed');
// --- UI-only state ---
export const collapsedTopicIds = writable(new Set<string>());
// --- Reactive Dexie queries ---
export function contextsByType(type: ContextType) {
return liveQuery(() =>
db.contexts
.where('type').equals(type)
.filter(c => !c.deletedAt)
.sortBy('sortOrder')
);
}
export function allActiveContexts() {
return liveQuery(() =>
db.contexts.filter(c => !c.deletedAt).sortBy('sortOrder')
);
}
export function contextById(id: string) {
return liveQuery(() => db.contexts.get(id));
}
export function topicsForContext(contextId: string) {
return liveQuery(() =>
db.topics
.where('contextId').equals(contextId)
.filter(t => !t.deletedAt)
.sortBy('sortOrder')
);
}
export function historyForTopic(topicId: string) {
return liveQuery(() =>
db.historyEntries
.where('topicId').equals(topicId)
.filter(h => !h.deletedAt)
.sortBy('sortOrder')
);
}
export function allHistoryForContext(contextId: string) {
return liveQuery(async () => {
const topics = await db.topics
.where('contextId').equals(contextId)
.filter(t => !t.deletedAt)
.toArray();
const topicIds = topics.map(t => t.id);
const entries = await db.historyEntries
.where('topicId').anyOf(topicIds)
.filter(h => !h.deletedAt)
.toArray();
return entries.map(e => ({
...e,
topicTitle: topics.find(t => t.id === e.topicId)?.title ?? ''
}));
});
}
export function ratingsForHistoryEntry(historyEntryId: string) {
return liveQuery(() =>
db.ratings
.where('historyEntryId').equals(historyEntryId)
.filter(r => !r.deletedAt)
.toArray()
);
}
export function ratingsForPerson(personName: string) {
return liveQuery(() =>
db.ratings
.where('personName').equals(personName)
.filter(r => !r.deletedAt)
.toArray()
);
}