feat: global platform v2 update

This commit is contained in:
ivannoskov
2025-12-29 10:12:13 +03:00
parent 8e6a1fa83f
commit f64cf02100
84 changed files with 11023 additions and 11486 deletions

View File

@@ -1,5 +1,5 @@
// ============================================================================
// API Types - Generated from API_DOCUMENTATION.md
// API Types - Based on actual API responses
// ============================================================================
// ----------------------------------------------------------------------------
@@ -12,148 +12,220 @@ export interface User {
username: string | null;
}
export interface AuthInitResponse {
bot_username: string;
start_param: string; // "login"
}
export interface AuthCompleteRequest {
token: string; // one-time token from bot
}
export interface AuthCompleteResponse {
access_token: string;
refresh_token: string;
user: User;
}
export interface AuthRefreshRequest {
refresh_token: string;
}
export interface AuthRefreshResponse {
access_token: string;
}
// ----------------------------------------------------------------------------
// Target Channel
// Pagination
// ----------------------------------------------------------------------------
// Основная структура как возвращает API
export interface TargetChannel {
export interface PaginatedResponse<T> {
items: T[];
total: number;
page: number;
size: number;
pages: number;
}
export interface PaginationParams {
page?: number;
size?: number;
}
// ----------------------------------------------------------------------------
// Workspaces
// ----------------------------------------------------------------------------
export interface Workspace {
id: string; // UUID
name: string;
}
export interface WorkspaceCreateRequest {
name: string;
}
export interface WorkspaceUpdateRequest {
name?: string;
}
// ----------------------------------------------------------------------------
// Workspace Members & Permissions
// ----------------------------------------------------------------------------
export type WorkspaceUserStatus = "active" | "invited";
export type PermissionKey =
| "admin_full"
| "projects_read"
| "projects_write"
| "placements_read"
| "placements_write"
| "analytics_read";
export type PermissionScopeType = "project";
export interface PermissionScope {
type: PermissionScopeType;
id: string; // UUID
}
export interface Permission {
key: PermissionKey;
scopes?: PermissionScope[];
}
export interface WorkspaceMemberUser {
id: string; // user_id
telegram_id: number;
username: string | null;
}
export interface WorkspaceMember {
id: string; // member record id
status: WorkspaceUserStatus;
user: WorkspaceMemberUser;
permissions: Permission[];
}
export interface UpdatePermissionsRequest {
permissions: Permission[];
}
// ----------------------------------------------------------------------------
// Workspace Invites
// ----------------------------------------------------------------------------
export type WorkspaceInviteStatus = "pending" | "accepted" | "rejected";
export interface WorkspaceInvite {
id: string; // UUID
username: string;
status: WorkspaceInviteStatus;
created_at: string;
}
export interface WorkspaceInviteCreateRequest {
username: string; // без @
}
// ----------------------------------------------------------------------------
// Projects (Target Channels)
// ----------------------------------------------------------------------------
export type ProjectStatus = "active" | "inactive" | "archived";
export interface Project {
id: string; // UUID
telegram_id: number;
title: string;
username: string | null;
is_active: boolean;
}
// Расширенная версия с дополнительными полями (пока не реализовано на бекенде)
export interface TargetChannelDetail extends TargetChannel {
// В будущем можно добавить статистику
}
export interface TargetChannelUpdateRequest {
is_active?: boolean;
}
export interface TargetChannelsListResponse {
target_channels: TargetChannel[];
status: ProjectStatus;
}
// ----------------------------------------------------------------------------
// External Channel
// Channels (Catalog for Placements)
// ----------------------------------------------------------------------------
// Основная структура как возвращает API
export interface ExternalChannel {
export type ChannelStatus = "active" | "inactive" | "archived";
export interface Channel {
id: string; // UUID
telegram_id: number;
title: string;
username: string | null;
description: string | null;
subscribers_count: number | null;
}
export interface ExternalChannelCreateRequest {
telegram_id: number;
title: string;
username?: string | null;
description?: string | null;
subscribers_count?: number | null;
target_channel_ids: string[]; // UUID[]
subscribers_count?: number;
}
export interface ExternalChannelUpdateRequest {
title?: string;
username?: string | null;
description?: string | null;
subscribers_count?: number | null;
}
export interface ExternalChannelLinksUpdateRequest {
add_target_channel_ids?: string[];
remove_target_channel_ids?: string[];
}
export interface ExternalChannelsListResponse {
external_channels: ExternalChannel[];
export interface ChannelsQueryParams extends PaginationParams {
username?: string;
}
// ----------------------------------------------------------------------------
// Creative
// Purchase Plan
// ----------------------------------------------------------------------------
export type PurchasePlanStatus = "planned" | "completed" | "cancelled";
export interface PurchasePlanChannel {
id: string; // UUID
status: PurchasePlanStatus;
planned_cost: number | null;
comment: string | null;
channel: {
id: string;
telegram_id: number;
title: string;
username: string | null;
};
}
export interface PurchasePlanChannelCreateRequest {
channel_id: string;
planned_cost?: number;
comment?: string;
}
export interface PurchasePlanChannelUpdateRequest {
planned_cost?: number;
comment?: string;
}
// ----------------------------------------------------------------------------
// Creatives
// ----------------------------------------------------------------------------
export type CreativeStatus = "active" | "archived";
export interface Creative {
id: string;
id: string; // UUID
name: string;
text: string;
target_channel_id: string;
target_channel_title: string;
text: string; // Contains {invite_link} placeholder
project_id: string;
project_channel_title: string;
created_at: string;
status: CreativeStatus;
placements_count: number;
}
export interface CreativesListResponse {
creatives: Creative[];
}
export interface CreativeCreateRequest {
name: string;
text: string;
target_channel_id: string;
}
export interface CreativeUpdateRequest {
name?: string;
text?: string;
status?: CreativeStatus;
}
export interface CreativesQueryParams extends PaginationParams {
project_id?: string;
include_archived?: boolean;
}
// ----------------------------------------------------------------------------
// Placement (Purchase)
// Placements
// ----------------------------------------------------------------------------
export type InviteLinkType = "public" | "approval";
export type PlacementStatus = "active" | "archived";
export type ViewsAvailability =
export type InviteLinkType = "public" | "approval";
export type PostViewsAvailability =
| "unknown"
| "available"
| "unavailable"
| "manual";
export interface Placement {
id: string;
target_channel_id: string;
target_channel_title: string;
external_channel_id: string;
external_channel_title: string;
id: string; // UUID
project_id: string;
project_channel_title: string;
placement_channel_id: string;
placement_channel_title: string;
creative_id: string;
creative_name: string;
placement_date: string;
placement_date: string; // ISO 8601
cost: number | null;
comment: string | null;
ad_post_url: string | null;
@@ -161,84 +233,96 @@ export interface Placement {
invite_link: string;
status: PlacementStatus;
subscriptions_count: number;
views_count: number | null;
views_availability: ViewsAvailability;
last_views_fetch_at: string | null;
views_count?: number | null;
views_availability?: PostViewsAvailability;
last_views_fetch_at?: string | null;
created_at: string;
}
export interface PlacementsListResponse {
placements: Placement[];
}
export interface PlacementCreateRequest {
target_channel_id: string;
external_channel_id: string;
project_id: string;
placement_channel_id: string;
creative_id: string;
placement_date: string;
cost?: number | null;
comment?: string | null;
ad_post_url?: string | null;
invite_link_type?: InviteLinkType;
placement_date: string; // ISO 8601
cost?: number;
comment?: string;
ad_post_url?: string;
invite_link_type: InviteLinkType;
}
export interface PlacementUpdateRequest {
placement_date?: string;
cost?: number | null;
comment?: string | null;
ad_post_url?: string | null;
status?: PlacementStatus;
cost?: number;
comment?: string;
ad_post_url?: string;
}
// Legacy aliases for backwards compatibility
export type Purchase = Placement;
export type PurchaseCreateRequest = PlacementCreateRequest;
export type PurchaseUpdateRequest = PlacementUpdateRequest;
export interface ViewsFetchResponse {
placement_id: string;
views_count: number | null;
views_availability: ViewsAvailability;
fetched_at: string;
error_message: string | null;
}
export interface ViewsHistoryResponse {
histories: ViewsSnapshot[];
export interface PlacementsQueryParams extends PaginationParams {
project_id?: string;
placement_channel_id?: string;
creative_id?: string;
include_archived?: boolean;
}
// ----------------------------------------------------------------------------
// Subscription
// Views History
// ----------------------------------------------------------------------------
export interface Subscription {
id: string;
purchase_id: string;
telegram_user_id: number;
user_first_name: string;
user_last_name: string | null;
user_username: string | null;
subscribed_at: string; // ISO 8601
is_active: boolean;
event_type: "chat_member" | "join_request";
}
// ----------------------------------------------------------------------------
// Views Snapshot
// ----------------------------------------------------------------------------
export interface ViewsSnapshot {
id: string;
purchase_id: string;
views: number;
export interface ViewsHistoryItem {
id: string; // UUID
views_count: number;
fetched_at: string; // ISO 8601
}
export interface ViewsHistoryQueryParams extends PaginationParams {
from_date?: string;
to_date?: string;
}
// ----------------------------------------------------------------------------
// Analytics
// ----------------------------------------------------------------------------
export type DateGrouping = "day" | "week" | "month" | "quarter" | "year";
export type DateGrouping = "day" | "week" | "month" | "DAY" | "WEEK" | "MONTH";
// Placements Analytics
export interface PlacementAnalyticsItem {
placement_id: string;
placement_channel_title: string;
placement_channel_username: string | null;
creative_name: string;
placement_date: string;
cost: number | null;
subscriptions_count: number;
views_count: number | null;
cps: number | null; // cost per subscription
cpm: number | null; // cost per mille views
}
// Creatives Analytics (matches actual API response)
export interface CreativeAnalyticsItem {
id: string;
name: string;
placements_count: number;
total_cost: number;
total_subscriptions: number;
total_views: number;
avg_cpf: number | null; // cost per follower (same as CPS)
avg_cpm: number | null;
}
// Channels Analytics
export interface ChannelAnalyticsItem {
channel_id: string;
channel_title: string;
channel_username: string | null;
placements_count: number;
total_cost: number;
total_subscriptions: number;
total_views: number;
avg_cps: number | null;
avg_cpm: number | null;
}
// Spending Analytics
export interface SpendingDataPoint {
@@ -251,40 +335,7 @@ export interface SpendingDataPoint {
}
export interface SpendingAnalytics {
total_cost: number;
total_subscriptions: number;
total_views: number;
avg_cpf: number | null;
avg_cpm: number | null;
chart_data: SpendingDataPoint[];
}
// Placements Analytics
export interface PlacementAnalytics {
id: string;
target_channel_id: string;
target_channel_title: string;
external_channel_id: string;
external_channel_title: string;
creative_id: string;
creative_name: string;
placement_date: string;
cost: number | null;
subscriptions_count: number;
views_count: number | null;
cpf: number | null;
cpm: number | null;
}
export interface PlacementsAnalytics {
placements: PlacementAnalytics[];
}
// Creatives Analytics
export interface CreativeAnalytics {
id: string;
name: string;
placements_count: number;
total_cost: number;
total_subscriptions: number;
total_views: number;
@@ -292,99 +343,34 @@ export interface CreativeAnalytics {
avg_cpm: number | null;
}
export interface CreativesAnalytics {
creatives: CreativeAnalytics[];
}
// External Channels Analytics
export interface ExternalChannelAnalytics {
id: string;
title: string;
username: string | null;
placements_count: number;
total_cost: number;
total_subscriptions: number;
total_views: number;
avg_cpf: number | null;
avg_cpm: number | null;
}
export interface ExternalChannelsAnalytics {
external_channels: ExternalChannelAnalytics[];
}
// Analytics Configuration Types
export type AnalyticsMetric = "cost" | "subscriptions" | "views" | "cpf" | "cpm";
export interface ChartConfig {
id: string;
targetChannelIds: string[]; // Multiple selection
metrics: AnalyticsMetric[];
dateFrom: Date | null;
dateTo: Date | null;
grouping: DateGrouping;
export interface AnalyticsQueryParams extends PaginationParams {
project_id?: string;
}
export interface SpendingAnalyticsQueryParams {
target_channel_id?: string;
project_id?: string;
date_from?: string;
date_to?: string;
grouping?: DateGrouping;
}
// ----------------------------------------------------------------------------
// Common API Responses
// Common Types
// ----------------------------------------------------------------------------
export interface ListResponse<T> {
data: T[];
total: number;
}
export interface SuccessResponse {
success: boolean;
}
export interface ApiError {
error: {
code: string;
message: string;
details?: any;
};
detail: string;
}
// ----------------------------------------------------------------------------
// Query Parameters
// Legacy Aliases (for backwards compatibility during migration)
// ----------------------------------------------------------------------------
export interface TargetChannelQueryParams {
is_active?: boolean;
}
/** @deprecated Use Project instead */
export type TargetChannel = Project;
export interface ExternalChannelQueryParams {
target_channel_id?: string;
search?: string;
}
export interface CreativeQueryParams {
target_channel_id?: string;
is_archived?: boolean;
}
export interface PlacementQueryParams {
target_channel_id?: string;
external_channel_id?: string;
creative_id?: string;
is_archived?: boolean;
date_from?: string; // ISO 8601
date_to?: string; // ISO 8601
sort?: "date" | "cost" | "cpf" | "subscriptions";
order?: "asc" | "desc";
}
export interface AnalyticsOverviewQueryParams {
target_channel_id?: string;
date_from?: string;
date_to?: string;
}
/** @deprecated Use Channel instead */
export type ExternalChannel = Channel;
/** @deprecated Use PlacementCreateRequest with new fields */
export type PurchaseCreateRequest = PlacementCreateRequest;