flnxi-Wu/app/admin/_hooks/useDepartmentOperations.ts
WuYongJie e4dcb6260a
Some checks failed
CI Check / check (push) Has been cancelled
feat: Admin页面重构 & UI三层架构系统
- 创建统一UI三层架构系统(基础层、颜色层、组合层)
- 拆分Admin页面为独立Tab组件(MonitorTab、UsersTab、DepartmentsTab等)
- 提取公共逻辑到Hooks(useToast、useDataFetch、useUserOperations等)
- 提取工具函数(validators、formatters、api等)
- 创建统一弹窗组件(Modal)和useModal Hook
- 添加错误边界和统一状态组件
- 完善类型定义和可访问性支持
- 更新文档(优化记录、优化计划、更新日志)
2025-11-22 15:17:10 +08:00

140 lines
3.9 KiB
TypeScript

/**
* 部门操作 Hook
* 统一管理部门相关的操作(创建、删除、重命名等)
*/
'use client'
import { useCallback } from 'react'
import type { Department } from '../_components/types'
import { parseErrorResponse } from '../_utils/api'
import { validateDepartmentName } from '../_utils/validators'
import type { ToastFn } from '../_components/types'
interface UseDepartmentOperationsOptions {
departments: Department[]
setDepartments: React.Dispatch<React.SetStateAction<Department[]>>
showToast: ToastFn
fetchDepartments: () => Promise<void>
loadUsersData: () => Promise<void>
}
export function useDepartmentOperations({
departments,
setDepartments,
showToast,
fetchDepartments,
loadUsersData,
}: UseDepartmentOperationsOptions) {
const createDepartment = useCallback(
async (name: string) => {
const nameValidation = validateDepartmentName(name)
if (!nameValidation.valid) {
showToast(nameValidation.error || '部门名称不能为空', 'error')
return false
}
const trimmed = name.trim()
try {
const response = await fetch('/api/departments', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ name: trimmed }),
})
if (response.ok) {
await fetchDepartments()
showToast('部门添加成功')
return true
}
const errorData = await parseErrorResponse(response)
showToast(errorData.error || '添加失败', 'error')
return false
} catch (error) {
console.error('Add department error:', error)
showToast('添加失败,请稍后重试', 'error')
return false
}
},
[fetchDepartments, showToast]
)
const deleteDepartment = useCallback(
async (id: string, name: string) => {
try {
const response = await fetch(`/api/departments?id=${id}`, {
method: 'DELETE',
})
if (response.ok) {
const result = await response.json().catch(() => ({})) as { message?: string }
await Promise.all([fetchDepartments(), loadUsersData()])
showToast(result.message || '部门删除成功')
return true
}
const errorData = await parseErrorResponse(response)
showToast(errorData.error || '删除失败', 'error')
return false
} catch (error) {
console.error('Delete department error:', error)
showToast('删除失败,请稍后重试', 'error')
return false
}
},
[fetchDepartments, loadUsersData, showToast]
)
const renameDepartment = useCallback(
async (deptId: string, newName: string) => {
const nameValidation = validateDepartmentName(newName)
if (!nameValidation.valid) {
showToast(nameValidation.error || '部门名称不能为空', 'error')
return false
}
if (!deptId) {
showToast('部门ID不能为空', 'error')
return false
}
const trimmed = newName.trim()
try {
const response = await fetch('/api/departments', {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ id: deptId, name: trimmed }),
})
if (response.ok) {
await fetchDepartments()
showToast('部门重命名成功')
return true
}
const errorData = await parseErrorResponse(response)
showToast(errorData.error || '重命名失败', 'error')
return false
} catch (error) {
console.error('Error renaming department:', error)
showToast('重命名失败', 'error')
return false
}
},
[fetchDepartments, showToast]
)
return {
createDepartment,
deleteDepartment,
renameDepartment,
}
}
export type UseDepartmentOperationsReturn = ReturnType<typeof useDepartmentOperations>