feat(web): #126 Frontend Replay UI 整合
All checks were successful
E2E Health Check / e2e-health (push) Successful in 18s
All checks were successful
E2E Health Check / e2e-health (push) Successful in 18s
- 新增 useUXAudit hook (5 分鐘自動刷新) - 新增 UXAuditCard 組件 (健康度 + Replay 連結) - 整合到錯誤追蹤頁面 - i18n: zh-TW + en 翻譯 功能: - UX 健康度評分 (good/moderate/poor) - 有錯誤的 Replay 連結 - 憤怒點擊/死亡點擊統計 - Replay Dashboard 快捷連結 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
81
apps/web/src/hooks/useUXAudit.ts
Normal file
81
apps/web/src/hooks/useUXAudit.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* useUXAudit - Sentry Session Replay / UX Audit Hook
|
||||
* ===================================================
|
||||
* Phase 19: #126 Frontend Replay UI Integration
|
||||
*
|
||||
* 提供 UX 審計數據的 React Hook:
|
||||
* - Session Replay 統計
|
||||
* - 憤怒點擊 / 死亡點擊
|
||||
* - 有錯誤的 Replay 連結
|
||||
*
|
||||
* 建立: 2026-03-31 (台北時區)
|
||||
* 建立者: Claude Code (#126 Replay UI)
|
||||
*/
|
||||
|
||||
import { useState, useEffect, useCallback } from 'react'
|
||||
import { apiClient, type UXAuditResponse } from '@/lib/api-client'
|
||||
|
||||
// =============================================================================
|
||||
// Types
|
||||
// =============================================================================
|
||||
|
||||
interface UseUXAuditState {
|
||||
data: UXAuditResponse | null
|
||||
loading: boolean
|
||||
error: string | null
|
||||
}
|
||||
|
||||
interface UseUXAuditReturn extends UseUXAuditState {
|
||||
refetch: () => Promise<void>
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Hook
|
||||
// =============================================================================
|
||||
|
||||
export function useUXAudit(): UseUXAuditReturn {
|
||||
const [state, setState] = useState<UseUXAuditState>({
|
||||
data: null,
|
||||
loading: true,
|
||||
error: null,
|
||||
})
|
||||
|
||||
const fetchData = useCallback(async () => {
|
||||
setState((prev) => ({ ...prev, loading: true, error: null }))
|
||||
|
||||
try {
|
||||
const result = await apiClient.getUXAudit()
|
||||
setState({
|
||||
data: result,
|
||||
loading: false,
|
||||
error: null,
|
||||
})
|
||||
} catch (err) {
|
||||
setState((prev) => ({
|
||||
...prev,
|
||||
loading: false,
|
||||
error: err instanceof Error ? err.message : 'Failed to fetch UX audit data',
|
||||
}))
|
||||
}
|
||||
}, [])
|
||||
|
||||
const refetch = useCallback(() => {
|
||||
return fetchData()
|
||||
}, [fetchData])
|
||||
|
||||
// Initial fetch
|
||||
useEffect(() => {
|
||||
fetchData()
|
||||
}, [fetchData])
|
||||
|
||||
// Auto-refresh every 5 minutes (Replay data changes less frequently)
|
||||
useEffect(() => {
|
||||
const interval = setInterval(fetchData, 300000)
|
||||
return () => clearInterval(interval)
|
||||
}, [fetchData])
|
||||
|
||||
return {
|
||||
...state,
|
||||
refetch,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user