import { useState, useEffect, useRef } from 'react' import { databases, DATABASE_ID, COLLECTIONS, Query } from '../lib/appwrite' import { planTimeLoad, blockMinutes, mapLimit, TIME_PARALLEL, TIME_QUERY_LIMIT } from '../lib/ticketTimes' // Spalte "Zeit" der Ticketliste: Arbeitszeit je woid, in Bloecken nachgeladen (nur Lesen). // byWoid ist eine Map woid -> Minuten (null = nicht zu ermitteln). Sie wird an Ort und Stelle // ergaenzt, `version` zaehlt hoch, wenn sich etwas geaendert hat (fuer useMemo-Abhaengigkeiten). // Der Zwischenspeicher gilt nur fuer die Lebensdauer der Seite: wer von einer Ticketseite // zurueckkehrt, sieht frische Zahlen. export function useTicketMinutes(tickets) { const cache = useRef(new Map()) const inFlight = useRef(new Set()) const mounted = useRef(true) const [version, setVersion] = useState(0) const [capped, setCapped] = useState(false) useEffect(() => { mounted.current = true return () => { mounted.current = false } }, []) useEffect(() => { const byWoid = cache.current const running = inFlight.current // Ein woid, dessen Abfrage noch laeuft, gilt als bekannt (kein Block doppelt anfragen) const known = { has: (woid) => byWoid.has(woid) || running.has(woid) } const plan = planTimeLoad(tickets, known) setCapped(plan.capped) if (plan.blocks.length === 0) return for (const block of plan.blocks) { for (const woid of block) running.add(woid) } // Auch wenn sich `tickets` inzwischen geaendert hat, wird das Ergebnis eingetragen: // sonst bliebe das woid ungeladen und ohne Abfrage. mapLimit(plan.blocks, TIME_PARALLEL, async (block) => { const response = await databases.listDocuments(DATABASE_ID, COLLECTIONS.WORKSHEETS, [ Query.equal('woid', block), Query.select(['woid', 'totalTime', 'supporters', 'isComment']), Query.limit(TIME_QUERY_LIMIT), ]) return blockMinutes(block, response.documents, response.total) }).then((results) => { results.forEach((result, index) => { const sums = result.ok ? result.value : null if (!sums) console.warn('Zeitsummen nicht geladen:', result.ok ? 'Antwort abgeschnitten' : result.error) for (const woid of plan.blocks[index]) { byWoid.set(woid, sums ? sums[woid] ?? null : null) running.delete(woid) } }) if (mounted.current) setVersion((v) => v + 1) }) }, [tickets]) return { byWoid: cache.current, capped, version } }