Files
awoooi/apps/web/src/hooks/useIncidentStatusChains.ts
Your Name 0870cdf789
All checks were successful
Code Review / ai-code-review (push) Successful in 12s
CD Pipeline / tests (push) Successful in 3m55s
CD Pipeline / build-and-deploy (push) Successful in 3m29s
CD Pipeline / post-deploy-checks (push) Successful in 1m21s
fix(web): show status chain evidence on alerts
2026-05-20 14:25:45 +08:00

86 lines
2.6 KiB
TypeScript

'use client'
import { useEffect, useMemo, useState } from 'react'
import type { AwoooPStatusChain } from '@/components/awooop/status-chain'
import { API_V1_URL } from '@/lib/config'
interface UseIncidentStatusChainsOptions {
incidentIds: string[]
limit?: number
projectId?: string
refreshKey?: string | number | Date | null
timeoutMs?: number
}
interface UseIncidentStatusChainsResult {
statusChains: Record<string, AwoooPStatusChain | null>
requestedIncidentIds: string[]
isLoading: boolean
}
export function useIncidentStatusChains({
incidentIds,
limit = 25,
projectId = 'awoooi',
refreshKey = null,
timeoutMs = 12000,
}: UseIncidentStatusChainsOptions): UseIncidentStatusChainsResult {
const incidentIdsKey = incidentIds.filter(Boolean).join('|')
const requestedIncidentIds = useMemo(() => {
return Array.from(new Set(incidentIdsKey ? incidentIdsKey.split('|') : [])).slice(0, limit)
}, [incidentIdsKey, limit])
const incidentKey = requestedIncidentIds.join('|')
const [statusChains, setStatusChains] = useState<Record<string, AwoooPStatusChain | null>>({})
const [isLoading, setIsLoading] = useState(false)
useEffect(() => {
if (requestedIncidentIds.length === 0) {
setStatusChains({})
setIsLoading(false)
return
}
let active = true
const controller = new AbortController()
const timeout = window.setTimeout(() => controller.abort(), timeoutMs)
setIsLoading(true)
Promise.all(
requestedIncidentIds.map(async (incidentId): Promise<[string, AwoooPStatusChain | null]> => {
const params = new URLSearchParams({ project_id: projectId, incident_id: incidentId })
try {
const response = await fetch(`${API_V1_URL}/platform/status-chain?${params.toString()}`, {
cache: 'no-store',
signal: controller.signal,
})
if (!response.ok) return [incidentId, null]
return [incidentId, await response.json() as AwoooPStatusChain]
} catch {
return [incidentId, null]
}
})
)
.then(entries => {
if (active) setStatusChains(Object.fromEntries(entries))
})
.catch(() => {
if (active) setStatusChains({})
})
.finally(() => {
window.clearTimeout(timeout)
if (active) setIsLoading(false)
})
return () => {
active = false
window.clearTimeout(timeout)
controller.abort()
}
}, [incidentKey, projectId, requestedIncidentIds, refreshKey, timeoutMs])
return { statusChains, requestedIncidentIds, isLoading }
}
export type { UseIncidentStatusChainsOptions, UseIncidentStatusChainsResult }