Extract admin dashboard from ghabilee-frontend2 into a dedicated Next.js app for backoffice.ghabilee.ir (no SEO indexing / Clarity).
118 lines
3.8 KiB
TypeScript
118 lines
3.8 KiB
TypeScript
import type { UserBlockResponseDto } from '@/api/generated/models'
|
|
import {
|
|
createServiceError,
|
|
errorResult,
|
|
handleServiceError,
|
|
type ServiceCallOptions,
|
|
type ServiceResult,
|
|
shouldBubbleErrorToParent,
|
|
successResult,
|
|
} from '@/services/errorHandler'
|
|
import { unwrapApiData } from '@/services/apiResponse'
|
|
import { getUserBlocks } from '@/api/generated/user-blocks/user-blocks'
|
|
import { texts } from '@/texts'
|
|
import { parseRemittanceList } from '@/helpers/listResponse'
|
|
|
|
// docs/workflows/fa/user-blocking-reporting.md, Flow A — a directed block
|
|
// record (`blocker_id` = current user, `blocked_id` = the other user).
|
|
// Effect is mutual: once either side has a row against the other, new
|
|
// *direct* messages between them are rejected in both directions. Event
|
|
// group chats are never affected.
|
|
|
|
export type UserBlock = UserBlockResponseDto
|
|
|
|
const userBlocksApi = getUserBlocks()
|
|
|
|
export const BLOCK_USER = async (blockedId: string, options?: ServiceCallOptions): Promise<ServiceResult<UserBlock>> => {
|
|
try {
|
|
const res = await userBlocksApi.userBlocksControllerCreate({ blockedId })
|
|
const payload = res.data
|
|
|
|
if (!payload.success) {
|
|
throw createServiceError(payload.message || texts.chats.blockUserFailed, payload.code)
|
|
}
|
|
|
|
const block = unwrapApiData(payload)
|
|
|
|
if (!block?.id) {
|
|
throw createServiceError(texts.common.invalidServerResponse)
|
|
}
|
|
|
|
return successResult(block)
|
|
} catch (error) {
|
|
const normalizedError = handleServiceError(error, options)
|
|
|
|
if (shouldBubbleErrorToParent(options)) {
|
|
throw normalizedError
|
|
}
|
|
|
|
return errorResult(normalizedError)
|
|
}
|
|
}
|
|
|
|
export const UNBLOCK_USER = async (blockedId: string, options?: ServiceCallOptions): Promise<ServiceResult<UserBlock>> => {
|
|
try {
|
|
const res = await userBlocksApi.userBlocksControllerUnblock(blockedId)
|
|
const payload = res.data
|
|
|
|
if (!payload.success) {
|
|
throw createServiceError(payload.message || texts.chats.unblockUserFailed, payload.code)
|
|
}
|
|
|
|
const block = unwrapApiData(payload)
|
|
|
|
if (!block?.id) {
|
|
throw createServiceError(texts.common.invalidServerResponse)
|
|
}
|
|
|
|
return successResult(block)
|
|
} catch (error) {
|
|
const normalizedError = handleServiceError(error, options)
|
|
|
|
if (shouldBubbleErrorToParent(options)) {
|
|
throw normalizedError
|
|
}
|
|
|
|
return errorResult(normalizedError)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Checks whether the current user has an active block row against
|
|
* `otherUserId`. Used to toggle the header menu between «مسدود کردن» and
|
|
* «رفع مسدودیت» — there's no dedicated "is blocked" endpoint, so this
|
|
* reuses `GET /user-blocks/me?filters[blockedId]=...` (paginated, so a
|
|
* single-row page is enough to answer a yes/no question).
|
|
*
|
|
* Note: this only reflects blocks *I* created (`blocker_id = me`), not
|
|
* ones the other person may have created against me — matching the known
|
|
* gap documented in user-blocking-reporting.md ("هیچ endpoint «چه کسی مرا
|
|
* مسدود کرده» وجود ندارد").
|
|
*/
|
|
export const GET_MY_BLOCK_STATUS = async (
|
|
otherUserId: string,
|
|
options?: ServiceCallOptions
|
|
): Promise<ServiceResult<{ isBlocked: boolean }>> => {
|
|
try {
|
|
const res = await userBlocksApi.userBlocksControllerListMine({ page: 1, pageSize: 1, 'filters[blockedId]': otherUserId })
|
|
|
|
const payload = res.data
|
|
|
|
if (!payload.success) {
|
|
throw createServiceError(payload.message || texts.chats.blockStatusFailed)
|
|
}
|
|
|
|
const parsed = parseRemittanceList<UserBlock>(unwrapApiData(payload) ?? {}, 'items')
|
|
|
|
return successResult({ isBlocked: parsed.items.length > 0 })
|
|
} catch (error) {
|
|
const normalizedError = handleServiceError(error, options)
|
|
|
|
if (shouldBubbleErrorToParent(options)) {
|
|
throw normalizedError
|
|
}
|
|
|
|
return errorResult(normalizedError)
|
|
}
|
|
}
|