Tickets: Hooks useWorkorder, Zaehler und Zeitsummen; useWorkorders verwirft veraltete Antworten

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Opus 5.5 committed 2026-10-06 06:02:55 +00:00
1 parent 0b53fc825a
commit ab42918bbc
4 files changed
+206 -2

No files matched your search

+58
View File
@@ -0,0 +1,58 @@
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 }
}