import { getContext, setContext } from 'svelte' import { api, auth } from './pocketbase.svelte' import { getTeamContext } from './teams.svelte' import { isRecent } from '$lib/time' import type { TrailCommentsResponse, UsersResponse } from '$lib/types' const KEY = Symbol('trailComment') /** Kommentar samt Verfasser, sofern dessen Datensatz sichtbar ist. */ export type TrailComment = Omit & { expand?: { created_by?: UsersResponse } } /** * Kommentare lagen bisher direkt in der Trail-Seite — als es sie nur dort * gab, war das die einfachere Lösung. Die Trail-Liste zeigt jetzt ebenfalls * ihre Anzahl, und zwei Ladewege auf dieselben Daten wären einer zu viel. */ export class TrailCommentStore { records = $state([]) loading = $state(false) error = $state(null) private unsubscribe: (() => void) | null = null private teams = getTeamContext() get scoped(): TrailComment[] { const teamId = this.teams.activeId if (!teamId) return [] return this.records.filter((r) => r.team === teamId) } /** Kommentare eines Trails, jüngste zuerst */ byTrail(trailId: string): TrailComment[] { return this.scoped .filter((r) => r.trail === trailId) .sort((a, b) => (a.created < b.created ? 1 : -1)) } /** Gab es zuletzt Bewegung? Für die Hervorhebung in der Liste. */ hasRecent(trailId: string, days?: number): boolean { return this.byTrail(trailId).some((r) => isRecent(r.created, days)) } async load() { this.loading = true this.error = null try { this.records = (await api.collection('trail_comments').getFullList({ sort: '-created', expand: 'created_by', requestKey: null, })) as TrailComment[] } catch (e: any) { this.error = e.message ?? 'Fehler beim Laden der Kommentare' console.error(e) } finally { this.loading = false } } subscribe() { if (this.unsubscribe) return api.collection('trail_comments').subscribe('*', (e) => { const record = e.record as TrailComment const idx = this.records.findIndex((r) => r.id === record.id) if (e.action === 'create' && idx === -1) this.records = [record, ...this.records] else if (e.action === 'update' && idx !== -1) this.records[idx] = record else if (e.action === 'delete' && idx !== -1) this.records = this.records.filter((r) => r.id !== record.id) }, { expand: 'created_by' }).then((unsub) => { this.unsubscribe = unsub }).catch((e) => console.warn('trail_comments subscribe failed:', e)) } async create(trailId: string, teamId: string, text: string) { return await api.collection('trail_comments').create({ trail: trailId, team: teamId, text: text.trim(), created_by: auth.user?.id, }) } async remove(id: string) { await api.collection('trail_comments').delete(id) } destroy() { if (this.unsubscribe) { this.unsubscribe() this.unsubscribe = null } } } export function setTrailCommentContext() { const store = new TrailCommentStore() setContext(KEY, store) return store } export function getTrailCommentContext(): TrailCommentStore { return getContext(KEY) }