import { getContext, setContext } from 'svelte' import { api, auth } from './pocketbase.svelte' import { getTeamContext } from './teams.svelte' import type { TrailMarkersResponse } from '$lib/types' const KEY = Symbol('trailMarker') export class TrailMarkerStore { records = $state([]) loading = $state(false) error = $state(null) private unsubscribe: (() => void) | null = null private teams = getTeamContext() /** Alle Marker eines Trails, jüngste zuerst */ byTrail(trailId: string): TrailMarkersResponse[] { return this.records .filter((r) => r.trail === trailId) .sort((a, b) => (a.created < b.created ? 1 : -1)) } /** Nur die offenen — was auf der Karte auffallen soll */ openByTrail(trailId: string): TrailMarkersResponse[] { return this.byTrail(trailId).filter((r) => !r.resolved) } /** * Ändern darf, wer den Marker angelegt hat, sowie Trail-Paten und * Team-Admins — dieselbe Regel wie in der updateRule der Collection. * Der Trail wird übergeben, weil der Store ihn nicht kennt. */ canEdit(marker: TrailMarkersResponse, stewards: string[], teamOwner?: string, teamAdmins: string[] = []): boolean { const uid = auth.user?.id if (!uid) return false return ( marker.created_by === uid || stewards.includes(uid) || teamOwner === uid || teamAdmins.includes(uid) ) } async load() { this.loading = true this.error = null try { this.records = await api.collection('trail_markers').getFullList({ sort: '-created', requestKey: null, }) } catch (e: any) { this.error = e.message ?? 'Fehler beim Laden der Marker' console.error(e) } finally { this.loading = false } } subscribe() { if (this.unsubscribe) return api.collection('trail_markers').subscribe('*', (e) => { const idx = this.records.findIndex((r) => r.id === e.record.id) if (e.action === 'create' && idx === -1) this.records = [e.record, ...this.records] else if (e.action === 'update' && idx !== -1) this.records[idx] = e.record else if (e.action === 'delete' && idx !== -1) this.records = this.records.filter((r) => r.id !== e.record.id) }).then((unsub) => { this.unsubscribe = unsub }).catch((e) => console.warn('trail_markers subscribe failed:', e)) } async create(data: { trail: string; flag: string; lat: number; lng: number; note?: string }) { const teamId = this.teams.activeId if (!teamId) throw new Error('Kein aktives Team') return await api.collection('trail_markers').create({ ...data, team: teamId, resolved: false, created_by: auth.user?.id, }) } async edit(id: string, data: Partial) { return await api.collection('trail_markers').update(id, data) } /** Erledigt statt gelöscht — die Meldung bleibt als Historie erhalten. */ async toggleResolved(id: string) { const marker = this.records.find((r) => r.id === id) if (!marker) throw new Error('Marker nicht gefunden') await api.collection('trail_markers').update(id, { resolved: !marker.resolved }) } async remove(id: string) { await api.collection('trail_markers').delete(id) } destroy() { if (this.unsubscribe) { this.unsubscribe() this.unsubscribe = null } } } export function setTrailMarkerContext() { const store = new TrailMarkerStore() setContext(KEY, store) return store } export function getTrailMarkerContext(): TrailMarkerStore { return getContext(KEY) }