fix(governance): keep event history filter responses ordered
All checks were successful
Code Review / ai-code-review (push) Successful in 11s
CD Pipeline / tests (push) Successful in 3m56s
CD Pipeline / build-and-deploy (push) Successful in 4m35s
CD Pipeline / post-deploy-checks (push) Successful in 1m46s

This commit is contained in:
Your Name
2026-05-20 11:23:21 +08:00
parent 55e642eeaf
commit 93070600b4

View File

@@ -12,7 +12,7 @@
* @updated 2026-05-02 Claude Sonnet 4.6 — governance PR 3-5 填入真實內容
*/
import { useEffect, useState, useCallback } from 'react'
import { useEffect, useState, useCallback, useRef } from 'react'
import { useSearchParams } from 'next/navigation'
import { EventsFilterBar, type EventsFilter } from '@/components/governance/events-filter-bar'
import {
@@ -117,20 +117,27 @@ const DEFAULT_FILTER: EventsFilter = {
export function EventsTab() {
const searchParams = useSearchParams()
const eventIdFromUrl = searchParams.get('event_id')?.trim() ?? ''
const [filter, setFilter] = useState<EventsFilter>(DEFAULT_FILTER)
const [filter, setFilter] = useState<EventsFilter>(() => ({
...DEFAULT_FILTER,
eventId: eventIdFromUrl,
}))
const [page, setPage] = useState(1)
const [events, setEvents] = useState<GovernanceEvent[]>([])
const [total, setTotal] = useState(0)
const [availableEventTypes, setAvailableEventTypes] = useState<string[]>([])
const [loading, setLoading] = useState(true)
const [error, setError] = useState(false)
const requestSeq = useRef(0)
const fetchEvents = useCallback(() => {
const requestId = requestSeq.current + 1
requestSeq.current = requestId
setLoading(true)
const qs = buildQueryString(filter, page)
fetch(`${API_BASE}/api/v1/ai/governance/events?${qs}`)
.then(r => r.ok ? r.json() : Promise.reject(r.status))
.then((d: EventsApiResponse) => {
if (requestId !== requestSeq.current) return
setEvents((d.items ?? []).map(toGovernanceEvent))
setTotal(d.total ?? 0)
if (d.event_types && d.event_types.length > 0) {
@@ -138,8 +145,14 @@ export function EventsTab() {
}
setError(false)
})
.catch(() => setError(true))
.finally(() => setLoading(false))
.catch(() => {
if (requestId !== requestSeq.current) return
setError(true)
})
.finally(() => {
if (requestId !== requestSeq.current) return
setLoading(false)
})
}, [filter, page])
// Re-fetch when filter or page changes