flnxi-Wu/app/admin/_hooks/useDepartmentOperations.ts
2025-11-22 17:56:24 +08:00

146 lines
4.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* useDepartmentOperations Hook
*
* 部门操作Hook
* 统一管理部门相关的操作(创建、删除、重命名等)
* 包括数据验证、错误处理、Toast通知
*
* @created 2025-01-XX(从 page.tsx 提取)
* @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>