admin/hooks/useAdminMutation.ts
alisaza e1eaf5eff5 feat: initial ghabilee-admin backoffice app
Extract admin dashboard from ghabilee-frontend2 into a dedicated Next.js
app for backoffice.ghabilee.ir (no SEO indexing / Clarity).
2026-09-05 13:12:59 +03:30

63 lines
2.0 KiB
TypeScript

'use client'
import { useCallback, useState } from 'react'
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { getServiceErrorCopy } from '@/helpers/serviceErrorCopy'
import { addToast } from '@/lib/toast'
import { adminKeys } from '@/queries/admin/adminKeys'
import { handleServiceError, resolveServiceErrorDisplayMessage } from '@/services/errorHandler'
interface UseAdminMutationOptions {
errorMessage?: string
url: string
}
interface AdminMutationVariables {
action: () => Promise<unknown>
id: string
successMessage: string
}
export default function useAdminMutation({ errorMessage = 'عملیات با خطا مواجه شد', url }: UseAdminMutationOptions) {
const queryClient = useQueryClient()
const [pendingId, setPendingId] = useState<string | null>(null)
const { mutateAsync } = useMutation({
mutationFn: ({ action }: AdminMutationVariables) => action(),
onSuccess: async (_data, { successMessage }) => {
addToast({ title: successMessage, color: 'success' })
await queryClient.invalidateQueries({ queryKey: adminKeys.listByUrl(url) })
},
onError: (error: unknown) => {
const normalizedError = handleServiceError(error, { errorMode: 'silent' })
const copy = getServiceErrorCopy()
const serviceMessage = resolveServiceErrorDisplayMessage(normalizedError, {
apiError: errorMessage || copy.apiError,
networkError: copy.networkError,
})
addToast({ title: serviceMessage || errorMessage, color: 'danger' })
},
})
const runAction = useCallback(
async (id: string, action: () => Promise<unknown>, successMessage: string) => {
setPendingId(id)
try {
await mutateAsync({ action, id, successMessage })
return true
} catch {
// Error presentation is centralized in the mutation's onError.
return false
} finally {
setPendingId(null)
}
},
[mutateAsync]
)
return { pendingId, runAction }
}