admin/services/discountCodes.ts
alisaza 82593dc18c refactor(events): update event management components and remove unused files
- Replaced `LIST_PUBLIC_CATEGORIES` with `LIST_ADMIN_CATEGORIES_FLAT` in `ArticleFormModal.tsx`.
- Removed the "Add Event" button from the dashboard page.
- Simplified the `EventsPage` by removing the button and adjusting the layout.
- Cleaned up the `AdminEventEditPage` by removing unnecessary props.
- Deleted unused layout and page files related to event creation.
- Updated `AdminAuthContent` to use `useAdminCitiesQuery` instead of `useDiscoveryCitiesQuery`.
- Refactored `EventGuestListAccessPanel` to remove the `accessMode` prop and adjust API calls accordingly.
- Removed several unused components and tests related to event creation, enhancing project maintainability.
2026-09-07 18:09:55 +03:30

172 lines
5.2 KiB
TypeScript

import type {
BulkCreateDiscountCodesResponseDto,
CreateDiscountCodesDto,
DiscountCodeResponseDto,
DiscountRedemptionResponseDto,
DiscountReportSummaryDto,
} from '@/api/generated/models'
import { getDiscountCodes } from '@/api/generated/discount-codes/discount-codes'
import axiosInstance from '@/config/axios'
import { parseRemittanceList, unwrapApiPayload } from '@/helpers/listResponse'
import { texts } from '@/texts'
import {
createServiceError,
errorResult,
handleServiceError,
type ServiceCallOptions,
type ServiceResult,
shouldBubbleErrorToParent,
successResult,
} from '@/services/errorHandler'
export type DiscountCode = DiscountCodeResponseDto
export type DiscountRedemption = DiscountRedemptionResponseDto
export type DiscountReport = DiscountReportSummaryDto
export type DiscountBulkResult = BulkCreateDiscountCodesResponseDto
export type DiscountType = CreateDiscountCodesDto['type']
export type DiscountBearer = NonNullable<CreateDiscountCodesDto['bearer']>
export interface DiscountCodesPage {
items: DiscountCode[]
totalItemsCount: number
totalPages: number
}
export interface DiscountRedemptionsPage {
items: DiscountRedemption[]
totalItemsCount: number
totalPages: number
}
export interface DiscountManagementBootstrap {
codes: { items: DiscountCode[] }
report: DiscountReport
redemptions: { items: DiscountRedemption[] }
}
export interface BulkCreateDiscountInput {
type: DiscountType
value: number
quantity: number
maxUses?: number
maxUsesPerUser?: number
validFrom?: string
validUntil?: string
bearer?: DiscountBearer
}
const discountApi = getDiscountCodes()
const wrap = async <T>(run: () => Promise<T>, options?: ServiceCallOptions): Promise<ServiceResult<T>> => {
try {
return successResult(await run())
} catch (error) {
const normalizedError = handleServiceError(error, options)
if (shouldBubbleErrorToParent(options)) {
throw normalizedError
}
return errorResult(normalizedError)
}
}
export const GET_DISCOUNT_MANAGEMENT_BOOTSTRAP = (
eventId: string,
options?: ServiceCallOptions
): Promise<ServiceResult<DiscountManagementBootstrap>> =>
wrap(async () => {
const response = await axiosInstance.get(`events/${eventId}/discount-codes/management-bootstrap`)
return unwrapApiPayload<DiscountManagementBootstrap>(response.data)
}, options)
export const LIST_DISCOUNT_CODES = (
eventId: string,
params: { page?: number; pageSize?: number } = {},
options?: ServiceCallOptions
): Promise<ServiceResult<DiscountCodesPage>> =>
wrap(async () => {
const res = await discountApi.discountCodesControllerList(eventId, {
page: params.page ?? 1,
pageSize: params.pageSize ?? 50,
sort: '-createdAt',
})
const parsed = parseRemittanceList<DiscountCode>(res.data)
return {
items: parsed.items,
totalItemsCount: parsed.pagination.totalItemsCount,
totalPages: parsed.pagination.totalPages ?? 0,
}
}, options)
export const LIST_DISCOUNT_REDEMPTIONS = (
eventId: string,
params: { page?: number; pageSize?: number } = {},
options?: ServiceCallOptions
): Promise<ServiceResult<DiscountRedemptionsPage>> =>
wrap(async () => {
const res = await discountApi.discountCodesControllerRedemptions(eventId, {
page: params.page ?? 1,
pageSize: params.pageSize ?? 50,
sort: '-createdAt',
})
const parsed = parseRemittanceList<DiscountRedemption>(res.data)
return {
items: parsed.items,
totalItemsCount: parsed.pagination.totalItemsCount,
totalPages: parsed.pagination.totalPages ?? 0,
}
}, options)
export const GET_DISCOUNT_REPORT = (eventId: string, options?: ServiceCallOptions): Promise<ServiceResult<DiscountReport>> =>
wrap(async () => {
const res = await discountApi.discountCodesControllerReport(eventId)
return unwrapApiPayload<DiscountReport>(res.data)
}, options)
export const BULK_CREATE_DISCOUNT_CODES = (
eventId: string,
input: BulkCreateDiscountInput,
options?: ServiceCallOptions
): Promise<ServiceResult<DiscountBulkResult>> =>
wrap(async () => {
const res = await discountApi.discountCodesControllerCreate(eventId, {
type: input.type,
value: input.value,
quantity: input.quantity,
maxUses: input.maxUses,
maxUsesPerUser: input.maxUsesPerUser,
validFrom: input.validFrom,
validUntil: input.validUntil,
bearer: input.bearer,
})
const data = unwrapApiPayload<DiscountBulkResult>(res.data)
if (!data?.codes) throw createServiceError(texts.events.discountCreateFailed)
return data
}, options)
export const SET_DISCOUNT_CODE_ACTIVE = (
codeId: string,
isActive: boolean,
options?: ServiceCallOptions
): Promise<ServiceResult<DiscountCode>> =>
wrap(async () => {
const res = await discountApi.discountCodesControllerUpdate(codeId, { isActive })
const data = unwrapApiPayload<DiscountCode>(res.data)
if (!data?.id) throw createServiceError(texts.events.discountUpdateFailed)
return data
}, options)
export const DELETE_DISCOUNT_CODE = (codeId: string, options?: ServiceCallOptions): Promise<ServiceResult<void>> =>
wrap(async () => {
await discountApi.discountCodesControllerRemove(codeId)
}, options)