Files
geointel/frontend/src/hooks/useSourceFreshness.ts
T
Codex eed6ee796e
GeoIntel CI / docs-smoke (push) Canceled after 0s
GeoIntel CI / contract-smoke (push) Canceled after 0s
Add governed GRB refresh workflow
2026-07-16 17:59:00 +02:00

123 lines
3.9 KiB
TypeScript

import { useCallback, useEffect, useRef, useState } from 'react'
import { datasetsApi } from '../services/api'
import type { GrbRefreshPlan, SourceCatalogProbeReport, SourceFreshnessReport } from '../types'
export function useSourceFreshness(selectedProjectId: string | null) {
const [report, setReport] = useState<SourceFreshnessReport | null>(null)
const [loading, setLoading] = useState(false)
const [error, setError] = useState<string | null>(null)
const requestSequence = useRef(0)
const catalogRequestSequence = useRef(0)
const [catalogReport, setCatalogReport] = useState<SourceCatalogProbeReport | null>(null)
const [catalogLoading, setCatalogLoading] = useState(false)
const [catalogError, setCatalogError] = useState<string | null>(null)
const [grbRefreshPlan, setGrbRefreshPlan] = useState<GrbRefreshPlan | null>(null)
const [grbRefreshPlanLoading, setGrbRefreshPlanLoading] = useState(false)
const [grbRefreshPlanError, setGrbRefreshPlanError] = useState<string | null>(null)
const refresh = useCallback(async () => {
const requestId = ++requestSequence.current
if (!selectedProjectId) {
setReport(null)
setError(null)
setLoading(false)
return
}
setLoading(true)
setError(null)
try {
const nextReport = await datasetsApi.sourceFreshness(selectedProjectId)
if (requestSequence.current === requestId) {
setReport(nextReport)
}
} catch (caught) {
if (requestSequence.current === requestId) {
setError(caught instanceof Error ? caught.message : 'De broncontrole kon niet worden geladen.')
}
} finally {
if (requestSequence.current === requestId) {
setLoading(false)
}
}
}, [selectedProjectId])
const probeCatalogs = useCallback(async (force = false) => {
const requestId = ++catalogRequestSequence.current
if (!selectedProjectId) {
setCatalogReport(null)
setCatalogError(null)
setCatalogLoading(false)
setGrbRefreshPlan(null)
setGrbRefreshPlanError(null)
setGrbRefreshPlanLoading(false)
return
}
setCatalogLoading(true)
setCatalogError(null)
setGrbRefreshPlanLoading(true)
setGrbRefreshPlanError(null)
try {
const nextReport = await datasetsApi.sourceCatalogProbes(selectedProjectId, force)
if (catalogRequestSequence.current === requestId) {
setCatalogReport(nextReport)
}
} catch (caught) {
if (catalogRequestSequence.current === requestId) {
setCatalogError(caught instanceof Error ? caught.message : 'De officiële broncatalogi konden niet worden gecontroleerd.')
}
if (catalogRequestSequence.current === requestId) {
setCatalogLoading(false)
setGrbRefreshPlanLoading(false)
}
return
}
try {
const nextPlan = await datasetsApi.grbRefreshPlan(selectedProjectId)
if (catalogRequestSequence.current === requestId) {
setGrbRefreshPlan(nextPlan)
}
} catch (caught) {
if (catalogRequestSequence.current === requestId) {
setGrbRefreshPlanError(caught instanceof Error ? caught.message : 'Het veilige GRB-vernieuwingsplan kon niet worden opgebouwd.')
}
} finally {
if (catalogRequestSequence.current === requestId) {
setCatalogLoading(false)
setGrbRefreshPlanLoading(false)
}
}
}, [selectedProjectId])
useEffect(() => {
void refresh()
return () => {
requestSequence.current += 1
}
}, [refresh])
useEffect(() => {
catalogRequestSequence.current += 1
setCatalogReport(null)
setCatalogError(null)
setCatalogLoading(false)
setGrbRefreshPlan(null)
setGrbRefreshPlanError(null)
setGrbRefreshPlanLoading(false)
}, [selectedProjectId])
return {
report,
loading,
error,
refresh,
catalogReport,
catalogLoading,
catalogError,
probeCatalogs,
grbRefreshPlan,
grbRefreshPlanLoading,
grbRefreshPlanError,
}
}