import { getContext, setContext } from 'svelte' import { api } from './pocketbase.svelte' import { auth } from './pocketbase.svelte' import { getTeamContext } from './teams.svelte' import type { TrailsResponse } from '$lib/types' const KEY = Symbol('trail') export class TrailStore { records = $state([]) loading = $state(false) error = $state(null) private unsubscribe: (() => void) | null = null private teams = getTeamContext() /** Records gefiltert nach aktivem Team */ get scoped(): TrailsResponse[] { const teamId = this.teams.activeId if (!teamId) return [] return this.records.filter((r) => r.team === teamId) } getById(id: string): TrailsResponse | undefined { return this.records.find((r) => r.id === id) } /** * Bearbeiten dürfen Trail-Paten sowie Owner und Admins des Teams — * dieselbe Regel wie in der updateRule der Collection. Die Prüfung hier * blendet nur UI aus; durchgesetzt wird sie serverseitig. */ canEdit(trail: TrailsResponse): boolean { const uid = auth.user?.id if (!uid) return false const team = this.teams.records.find((t) => t.id === trail.team) const stewards = (trail.stewards ?? []) as string[] return ( stewards.includes(uid) || team?.owner === uid || ((team?.admins ?? []) as string[]).includes(uid) ) } async load() { this.loading = true this.error = null try { this.records = await api.collection('trails').getFullList({ sort: 'name', requestKey: null, }) } catch (e: any) { this.error = e.message ?? 'Fehler beim Laden der Trails' console.error(e) } finally { this.loading = false } } subscribe() { if (this.unsubscribe) return api.collection('trails').subscribe('*', (e) => { const idx = this.records.findIndex((r) => r.id === e.record.id) if (e.action === 'create' && idx === -1) this.records = [...this.records, e.record] 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('trails subscribe failed:', e)) } async create(data: { name: string; description?: string; status?: string }) { const teamId = this.teams.activeId if (!teamId) throw new Error('Kein aktives Team') const uid = auth.user?.id // Wer anlegt, wird automatisch erster Pate — sonst könnte niemand // den frisch angelegten Trail bearbeiten. return await api.collection('trails').create({ ...data, status: data.status ?? 'offen', team: teamId, created_by: uid, stewards: uid ? [uid] : [], }) } async edit(id: string, data: Partial) { return await api.collection('trails').update(id, data) } /** * Status melden. Wann und von wem kommt gleich mit — ohne das ließe sich * einer Sperrung nicht ansehen, ob sie von heute oder vom letzten Jahr ist. */ async setStatus(id: string, status: string) { return await api.collection('trails').update(id, { status, status_changed: new Date().toISOString(), status_by: auth.user?.id ?? '', }) } async setStewards(id: string, userIds: string[]) { return await api.collection('trails').update(id, { stewards: userIds }) } async remove(id: string) { await api.collection('trails').delete(id) } destroy() { if (this.unsubscribe) { this.unsubscribe() this.unsubscribe = null } } } export function setTrailContext() { const store = new TrailStore() setContext(KEY, store) return store } export function getTrailContext(): TrailStore { return getContext(KEY) }