mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-28 09:33:46 +00:00
Add files via upload
This commit is contained in:
247
src/api/promoOffers.ts
Normal file
247
src/api/promoOffers.ts
Normal file
@@ -0,0 +1,247 @@
|
|||||||
|
import apiClient from './client'
|
||||||
|
|
||||||
|
// ============== Types ==============
|
||||||
|
|
||||||
|
export interface PromoOfferUserInfo {
|
||||||
|
id: number
|
||||||
|
telegram_id: number
|
||||||
|
username: string | null
|
||||||
|
first_name: string | null
|
||||||
|
last_name: string | null
|
||||||
|
full_name: string | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PromoOfferSubscriptionInfo {
|
||||||
|
id: number
|
||||||
|
status: string
|
||||||
|
is_trial: boolean
|
||||||
|
start_date: string
|
||||||
|
end_date: string
|
||||||
|
autopay_enabled: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PromoOffer {
|
||||||
|
id: number
|
||||||
|
user_id: number
|
||||||
|
subscription_id: number | null
|
||||||
|
notification_type: string
|
||||||
|
discount_percent: number
|
||||||
|
bonus_amount_kopeks: number
|
||||||
|
expires_at: string
|
||||||
|
claimed_at: string | null
|
||||||
|
is_active: boolean
|
||||||
|
effect_type: string
|
||||||
|
extra_data: Record<string, any>
|
||||||
|
created_at: string
|
||||||
|
updated_at: string
|
||||||
|
user: PromoOfferUserInfo | null
|
||||||
|
subscription: PromoOfferSubscriptionInfo | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PromoOfferListResponse {
|
||||||
|
items: PromoOffer[]
|
||||||
|
total: number
|
||||||
|
limit: number
|
||||||
|
offset: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PromoOfferCreateRequest {
|
||||||
|
user_id?: number
|
||||||
|
telegram_id?: number
|
||||||
|
notification_type: string
|
||||||
|
valid_hours: number
|
||||||
|
discount_percent?: number
|
||||||
|
bonus_amount_kopeks?: number
|
||||||
|
subscription_id?: number
|
||||||
|
effect_type?: string
|
||||||
|
extra_data?: Record<string, any>
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PromoOfferBroadcastRequest extends PromoOfferCreateRequest {
|
||||||
|
target?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PromoOfferBroadcastResponse {
|
||||||
|
created_offers: number
|
||||||
|
user_ids: number[]
|
||||||
|
target: string | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PromoOfferTemplate {
|
||||||
|
id: number
|
||||||
|
name: string
|
||||||
|
offer_type: string
|
||||||
|
message_text: string
|
||||||
|
button_text: string
|
||||||
|
valid_hours: number
|
||||||
|
discount_percent: number
|
||||||
|
bonus_amount_kopeks: number
|
||||||
|
active_discount_hours: number | null
|
||||||
|
test_duration_hours: number | null
|
||||||
|
test_squad_uuids: string[]
|
||||||
|
is_active: boolean
|
||||||
|
created_by: number | null
|
||||||
|
created_at: string
|
||||||
|
updated_at: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PromoOfferTemplateListResponse {
|
||||||
|
items: PromoOfferTemplate[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PromoOfferTemplateUpdateRequest {
|
||||||
|
name?: string
|
||||||
|
message_text?: string
|
||||||
|
button_text?: string
|
||||||
|
valid_hours?: number
|
||||||
|
discount_percent?: number
|
||||||
|
bonus_amount_kopeks?: number
|
||||||
|
active_discount_hours?: number
|
||||||
|
test_duration_hours?: number
|
||||||
|
test_squad_uuids?: string[]
|
||||||
|
is_active?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PromoOfferLogOfferInfo {
|
||||||
|
id: number
|
||||||
|
notification_type: string | null
|
||||||
|
discount_percent: number | null
|
||||||
|
bonus_amount_kopeks: number | null
|
||||||
|
effect_type: string | null
|
||||||
|
expires_at: string | null
|
||||||
|
claimed_at: string | null
|
||||||
|
is_active: boolean | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PromoOfferLog {
|
||||||
|
id: number
|
||||||
|
user_id: number | null
|
||||||
|
offer_id: number | null
|
||||||
|
action: string
|
||||||
|
source: string | null
|
||||||
|
percent: number | null
|
||||||
|
effect_type: string | null
|
||||||
|
details: Record<string, any>
|
||||||
|
created_at: string
|
||||||
|
user: PromoOfferUserInfo | null
|
||||||
|
offer: PromoOfferLogOfferInfo | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PromoOfferLogListResponse {
|
||||||
|
items: PromoOfferLog[]
|
||||||
|
total: number
|
||||||
|
limit: number
|
||||||
|
offset: number
|
||||||
|
}
|
||||||
|
|
||||||
|
// Target segments for broadcast
|
||||||
|
export const TARGET_SEGMENTS = {
|
||||||
|
all: 'Все пользователи',
|
||||||
|
active: 'Активные подписчики',
|
||||||
|
trial: 'Триал пользователи',
|
||||||
|
trial_ending: 'Заканчивается триал',
|
||||||
|
expiring: 'Заканчивается подписка',
|
||||||
|
expired: 'Истекшая подписка',
|
||||||
|
zero: 'Нулевой баланс',
|
||||||
|
autopay_failed: 'Ошибка автоплатежа',
|
||||||
|
low_balance: 'Низкий баланс',
|
||||||
|
inactive_30d: 'Неактивны 30 дней',
|
||||||
|
inactive_60d: 'Неактивны 60 дней',
|
||||||
|
inactive_90d: 'Неактивны 90 дней',
|
||||||
|
custom_today: 'Зарегистрированы сегодня',
|
||||||
|
custom_week: 'Зарегистрированы за неделю',
|
||||||
|
custom_month: 'Зарегистрированы за месяц',
|
||||||
|
custom_active_today: 'Активны сегодня',
|
||||||
|
} as const
|
||||||
|
|
||||||
|
export type TargetSegment = keyof typeof TARGET_SEGMENTS
|
||||||
|
|
||||||
|
// Offer type configurations
|
||||||
|
export const OFFER_TYPE_CONFIG = {
|
||||||
|
test_access: {
|
||||||
|
icon: '🧪',
|
||||||
|
label: 'Тестовый доступ',
|
||||||
|
effect: 'test_access',
|
||||||
|
description: 'Временный доступ к дополнительным серверам',
|
||||||
|
},
|
||||||
|
extend_discount: {
|
||||||
|
icon: '💎',
|
||||||
|
label: 'Скидка на продление',
|
||||||
|
effect: 'percent_discount',
|
||||||
|
description: 'Скидка для текущих подписчиков',
|
||||||
|
},
|
||||||
|
purchase_discount: {
|
||||||
|
icon: '🎯',
|
||||||
|
label: 'Скидка на покупку',
|
||||||
|
effect: 'percent_discount',
|
||||||
|
description: 'Скидка для новых пользователей',
|
||||||
|
},
|
||||||
|
} as const
|
||||||
|
|
||||||
|
export type OfferType = keyof typeof OFFER_TYPE_CONFIG
|
||||||
|
|
||||||
|
// ============== API ==============
|
||||||
|
|
||||||
|
export const promoOffersApi = {
|
||||||
|
// Get list of promo offers
|
||||||
|
getOffers: async (params?: {
|
||||||
|
limit?: number
|
||||||
|
offset?: number
|
||||||
|
user_id?: number
|
||||||
|
telegram_id?: number
|
||||||
|
notification_type?: string
|
||||||
|
is_active?: boolean
|
||||||
|
}): Promise<PromoOfferListResponse> => {
|
||||||
|
const response = await apiClient.get('/api/promo-offers', { params })
|
||||||
|
return response.data
|
||||||
|
},
|
||||||
|
|
||||||
|
// Get single offer
|
||||||
|
getOffer: async (id: number): Promise<PromoOffer> => {
|
||||||
|
const response = await apiClient.get(`/api/promo-offers/${id}`)
|
||||||
|
return response.data
|
||||||
|
},
|
||||||
|
|
||||||
|
// Create single offer
|
||||||
|
createOffer: async (data: PromoOfferCreateRequest): Promise<PromoOffer> => {
|
||||||
|
const response = await apiClient.post('/api/promo-offers', data)
|
||||||
|
return response.data
|
||||||
|
},
|
||||||
|
|
||||||
|
// Broadcast offer to multiple users
|
||||||
|
broadcastOffer: async (data: PromoOfferBroadcastRequest): Promise<PromoOfferBroadcastResponse> => {
|
||||||
|
const response = await apiClient.post('/api/promo-offers/broadcast', data)
|
||||||
|
return response.data
|
||||||
|
},
|
||||||
|
|
||||||
|
// Get promo offer logs
|
||||||
|
getLogs: async (params?: {
|
||||||
|
limit?: number
|
||||||
|
offset?: number
|
||||||
|
user_id?: number
|
||||||
|
offer_id?: number
|
||||||
|
action?: string
|
||||||
|
source?: string
|
||||||
|
}): Promise<PromoOfferLogListResponse> => {
|
||||||
|
const response = await apiClient.get('/api/promo-offers/logs', { params })
|
||||||
|
return response.data
|
||||||
|
},
|
||||||
|
|
||||||
|
// Get all templates
|
||||||
|
getTemplates: async (): Promise<PromoOfferTemplateListResponse> => {
|
||||||
|
const response = await apiClient.get('/api/promo-offers/templates')
|
||||||
|
return response.data
|
||||||
|
},
|
||||||
|
|
||||||
|
// Get single template
|
||||||
|
getTemplate: async (id: number): Promise<PromoOfferTemplate> => {
|
||||||
|
const response = await apiClient.get(`/api/promo-offers/templates/${id}`)
|
||||||
|
return response.data
|
||||||
|
},
|
||||||
|
|
||||||
|
// Update template
|
||||||
|
updateTemplate: async (id: number, data: PromoOfferTemplateUpdateRequest): Promise<PromoOfferTemplate> => {
|
||||||
|
const response = await apiClient.patch(`/api/promo-offers/templates/${id}`, data)
|
||||||
|
return response.data
|
||||||
|
},
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user