128 lines
3.3 KiB
TypeScript
128 lines
3.3 KiB
TypeScript
/**
|
||
* useDashboardData Hook
|
||
*
|
||
* 仪表板数据获取Hook
|
||
* 统一管理监控仪表板的数据获取逻辑
|
||
* 包括数据加载、错误处理、刷新等功能
|
||
*
|
||
* @created 2025-01-XX(从 page.tsx 提取)
|
||
* @hook
|
||
*/
|
||
|
||
'use client'
|
||
|
||
import { useCallback, useState } from 'react'
|
||
import type { DashboardData, ToastFn } from '../_components/types'
|
||
|
||
type SystemSettingKey = 'registrationEnabled' | 'userActivationRequired'
|
||
|
||
interface UseDashboardDataOptions {
|
||
showToast?: ToastFn
|
||
}
|
||
|
||
interface RefreshOptions {
|
||
background?: boolean
|
||
}
|
||
|
||
export function useDashboardData({ showToast }: UseDashboardDataOptions = {}) {
|
||
const [data, setData] = useState<DashboardData | null>(null)
|
||
const [loading, setLoading] = useState(false)
|
||
const [error, setError] = useState<string | null>(null)
|
||
const [lastUpdated, setLastUpdated] = useState<number | null>(null)
|
||
const [refreshing, setRefreshing] = useState(false)
|
||
|
||
const refresh = useCallback(
|
||
async (options: RefreshOptions = {}) => {
|
||
const { background = false } = options
|
||
if (!background) {
|
||
setLoading(true)
|
||
}
|
||
setRefreshing(true)
|
||
setError(null)
|
||
try {
|
||
const response = await fetch('/api/admin/system-status', { credentials: 'include' })
|
||
if (!response.ok) {
|
||
throw new Error(`HTTP ${response.status}: ${response.statusText}`)
|
||
}
|
||
const payload: DashboardData = await response.json()
|
||
setData(payload)
|
||
setLastUpdated(Date.now())
|
||
} catch (err) {
|
||
console.error('Failed to fetch dashboard data:', err)
|
||
const message = err instanceof Error ? err.message : '获取数据失败'
|
||
setError(message)
|
||
} finally {
|
||
if (!background) {
|
||
setLoading(false)
|
||
}
|
||
setRefreshing(false)
|
||
}
|
||
},
|
||
[],
|
||
)
|
||
|
||
const updateSystemSetting = useCallback(
|
||
async (key: SystemSettingKey, value: boolean) => {
|
||
let previousValue: boolean | undefined
|
||
setData((prev) => {
|
||
if (!prev) return prev
|
||
previousValue = prev.systemInfo[key]
|
||
return {
|
||
...prev,
|
||
systemInfo: {
|
||
...prev.systemInfo,
|
||
[key]: value,
|
||
},
|
||
}
|
||
})
|
||
|
||
try {
|
||
const body =
|
||
key === 'registrationEnabled'
|
||
? { enableRegistration: value }
|
||
: { enableUserActivation: value }
|
||
|
||
const response = await fetch('/api/system-settings', {
|
||
method: 'PUT',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify(body),
|
||
})
|
||
|
||
if (!response.ok) {
|
||
throw new Error('更新失败')
|
||
}
|
||
|
||
showToast?.('设置已更新')
|
||
} catch (err) {
|
||
console.error('Update system setting error:', err)
|
||
setData((prev) => {
|
||
if (!prev) return prev
|
||
return {
|
||
...prev,
|
||
systemInfo: {
|
||
...prev.systemInfo,
|
||
[key]: previousValue ?? prev.systemInfo[key],
|
||
},
|
||
}
|
||
})
|
||
showToast?.('更新失败', 'error')
|
||
throw err
|
||
}
|
||
},
|
||
[showToast],
|
||
)
|
||
|
||
return {
|
||
data,
|
||
loading,
|
||
error,
|
||
refresh,
|
||
updateSystemSetting,
|
||
lastUpdated,
|
||
refreshing,
|
||
}
|
||
}
|
||
|
||
export type UseDashboardDataReturn = ReturnType<typeof useDashboardData>
|
||
|