feat: all project setup
This commit is contained in:
410
lib/types/api.ts
Normal file
410
lib/types/api.ts
Normal file
@@ -0,0 +1,410 @@
|
||||
// ============================================================================
|
||||
// API Types - Generated from API_DOCUMENTATION.md
|
||||
// ============================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// User & Auth
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
export interface User {
|
||||
id: string;
|
||||
telegram_id: number;
|
||||
username: string | null;
|
||||
first_name: string;
|
||||
last_name: string | null;
|
||||
created_at: string; // ISO 8601
|
||||
}
|
||||
|
||||
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
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
export interface TargetChannel {
|
||||
id: string;
|
||||
telegram_id: number;
|
||||
title: string;
|
||||
username: string | null; // @channel_name
|
||||
description: string | null;
|
||||
is_active: boolean;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
// Stats
|
||||
total_purchases: number;
|
||||
total_subscriptions: number;
|
||||
avg_cpf: number | null; // Average Cost Per Follower
|
||||
}
|
||||
|
||||
export interface TargetChannelDetail extends TargetChannel {
|
||||
recent_purchases: Purchase[]; // last 5
|
||||
stats_by_period: {
|
||||
period: "day" | "week" | "month";
|
||||
subscriptions: number;
|
||||
cost: number;
|
||||
cpf: number;
|
||||
}[];
|
||||
}
|
||||
|
||||
export interface TargetChannelUpdateRequest {
|
||||
is_active: boolean;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// External Channel
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
export interface ExternalChannel {
|
||||
id: string;
|
||||
telegram_id: number | null;
|
||||
title: string;
|
||||
username: string | null;
|
||||
link: string; // t.me link or custom
|
||||
subscribers_count: number | null;
|
||||
description: string | null;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
// Relations
|
||||
target_channels: string[]; // IDs of target channels
|
||||
// Stats
|
||||
total_purchases: number;
|
||||
avg_cpf: number | null;
|
||||
avg_cpm: number | null;
|
||||
}
|
||||
|
||||
export interface ExternalChannelDetail extends ExternalChannel {
|
||||
purchases: Purchase[];
|
||||
}
|
||||
|
||||
export interface ExternalChannelCreateRequest {
|
||||
title: string;
|
||||
username?: string;
|
||||
link: string;
|
||||
subscribers_count?: number;
|
||||
description?: string;
|
||||
target_channel_ids: string[]; // Привязка к целевым каналам
|
||||
}
|
||||
|
||||
export interface ExternalChannelUpdateRequest {
|
||||
title?: string;
|
||||
username?: string;
|
||||
link?: string;
|
||||
subscribers_count?: number;
|
||||
description?: string;
|
||||
target_channel_ids?: string[];
|
||||
}
|
||||
|
||||
export interface ExternalChannelImportResponse {
|
||||
imported: number;
|
||||
skipped: number;
|
||||
errors: string[];
|
||||
channels: ExternalChannel[];
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Creative
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
export interface Creative {
|
||||
id: string;
|
||||
name: string;
|
||||
text: string; // Template with {link} placeholder
|
||||
target_channel_id: string;
|
||||
is_archived: boolean;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
// Relations
|
||||
target_channel: TargetChannel;
|
||||
// Stats
|
||||
total_purchases: number;
|
||||
total_subscriptions: number;
|
||||
avg_cpf: number | null;
|
||||
}
|
||||
|
||||
export interface CreativeDetail extends Creative {
|
||||
purchases: Purchase[];
|
||||
}
|
||||
|
||||
export interface CreativeCreateRequest {
|
||||
name: string;
|
||||
text: string; // Must contain {link} placeholder
|
||||
target_channel_id: string;
|
||||
}
|
||||
|
||||
export interface CreativeUpdateRequest {
|
||||
name?: string;
|
||||
text?: string;
|
||||
is_archived?: boolean;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Purchase
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
export type InviteLinkType = "public" | "private";
|
||||
|
||||
export interface Purchase {
|
||||
id: string;
|
||||
target_channel_id: string;
|
||||
external_channel_id: string;
|
||||
creative_id: string;
|
||||
// Purchase details
|
||||
scheduled_date: string | null; // ISO 8601
|
||||
actual_date: string | null;
|
||||
cost: number | null; // in rubles
|
||||
comment: string | null;
|
||||
post_link: string | null; // Link to ad post in external channel
|
||||
invite_link: string; // Generated invite link
|
||||
invite_link_type: InviteLinkType; // with bot approval or not
|
||||
is_archived: boolean;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
// Relations
|
||||
target_channel: TargetChannel;
|
||||
external_channel: ExternalChannel;
|
||||
creative: Creative;
|
||||
// Stats
|
||||
subscriptions_count: number;
|
||||
views_count: number | null;
|
||||
cpf: number | null; // Cost Per Follower
|
||||
cpm: number | null; // Cost Per Mile (1000 views)
|
||||
conversion_rate: number | null; // subscriptions / views * 100
|
||||
}
|
||||
|
||||
export interface PurchaseDetail extends Purchase {
|
||||
subscriptions: Subscription[];
|
||||
views_history: ViewsSnapshot[];
|
||||
}
|
||||
|
||||
export interface PurchaseCreateRequest {
|
||||
target_channel_id: string;
|
||||
external_channel_id: string;
|
||||
creative_id: string;
|
||||
scheduled_date?: string;
|
||||
actual_date?: string;
|
||||
cost?: number;
|
||||
comment?: string;
|
||||
post_link?: string;
|
||||
invite_link_type: InviteLinkType;
|
||||
}
|
||||
|
||||
export interface PurchaseCreateResponse extends Purchase {
|
||||
formatted_message: string; // Creative text with invite_link inserted
|
||||
}
|
||||
|
||||
export interface PurchaseUpdateRequest {
|
||||
scheduled_date?: string;
|
||||
actual_date?: string;
|
||||
cost?: number;
|
||||
comment?: string;
|
||||
post_link?: string;
|
||||
is_archived?: boolean;
|
||||
}
|
||||
|
||||
export interface PurchaseRefreshViewsResponse {
|
||||
views: number;
|
||||
fetched_at: string;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Subscription
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
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;
|
||||
fetched_at: string; // ISO 8601
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Analytics
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
export interface AnalyticsOverview {
|
||||
totalPurchases: number;
|
||||
purchasesChange: number;
|
||||
totalFollowers: number;
|
||||
followersChange: number;
|
||||
averageCpf: number;
|
||||
cpfChange: number;
|
||||
averageCpm: number;
|
||||
cpmChange: number;
|
||||
topChannelsByCpf: {
|
||||
channel_id: string;
|
||||
channel_name: string;
|
||||
total_purchases: number;
|
||||
avg_cpf: number;
|
||||
}[];
|
||||
topCreativesByCpf: {
|
||||
creative_id: string;
|
||||
creative_name: string;
|
||||
total_subscriptions: number;
|
||||
avg_cpf: number;
|
||||
}[];
|
||||
}
|
||||
|
||||
export type GroupByPeriod = "day" | "week" | "month" | "quarter" | "year";
|
||||
|
||||
export interface AnalyticsCostsDataPoint {
|
||||
period: string; // ISO 8601 date (start of period)
|
||||
cost: number;
|
||||
purchases_count: number;
|
||||
subscriptions: number;
|
||||
}
|
||||
|
||||
export interface AnalyticsCostsResponse {
|
||||
data: AnalyticsCostsDataPoint[];
|
||||
}
|
||||
|
||||
export interface CostsReport {
|
||||
totalCost: number;
|
||||
averageCost: number;
|
||||
periods: {
|
||||
date: string;
|
||||
total_cost: number;
|
||||
purchases_count: number;
|
||||
avg_cost: number;
|
||||
}[];
|
||||
}
|
||||
|
||||
export interface AnalyticsChannelData {
|
||||
channel_id: string;
|
||||
channel_name: string;
|
||||
purchases_count: number;
|
||||
total_cost: number;
|
||||
total_subscriptions: number;
|
||||
avg_cpf: number;
|
||||
avg_cpm: number;
|
||||
}
|
||||
|
||||
export interface AnalyticsChannelsResponse {
|
||||
data: AnalyticsChannelData[];
|
||||
}
|
||||
|
||||
export interface AnalyticsCreativeData {
|
||||
creative_id: string;
|
||||
creative_name: string;
|
||||
purchases_count: number;
|
||||
total_cost: number;
|
||||
total_subscriptions: number;
|
||||
avg_cpf: number;
|
||||
conversion_rate: number;
|
||||
}
|
||||
|
||||
export interface AnalyticsCreativesResponse {
|
||||
data: AnalyticsCreativeData[];
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Common API Responses
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
export interface ListResponse<T> {
|
||||
data: T[];
|
||||
total: number;
|
||||
}
|
||||
|
||||
export interface SuccessResponse {
|
||||
success: boolean;
|
||||
}
|
||||
|
||||
export interface ApiError {
|
||||
error: {
|
||||
code: string;
|
||||
message: string;
|
||||
details?: any;
|
||||
};
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Query Parameters
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
export interface TargetChannelQueryParams {
|
||||
is_active?: boolean;
|
||||
}
|
||||
|
||||
export interface ExternalChannelQueryParams {
|
||||
target_channel_id?: string;
|
||||
search?: string;
|
||||
}
|
||||
|
||||
export interface CreativeQueryParams {
|
||||
target_channel_id?: string;
|
||||
is_archived?: boolean;
|
||||
}
|
||||
|
||||
export interface PurchaseQueryParams {
|
||||
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;
|
||||
}
|
||||
|
||||
export interface AnalyticsCostsQueryParams {
|
||||
target_channel_id?: string;
|
||||
date_from: string; // required
|
||||
date_to: string; // required
|
||||
group_by: GroupByPeriod;
|
||||
}
|
||||
|
||||
export interface AnalyticsChannelsQueryParams {
|
||||
target_channel_id?: string;
|
||||
date_from?: string;
|
||||
date_to?: string;
|
||||
type: "external" | "target";
|
||||
}
|
||||
|
||||
export interface AnalyticsCreativesQueryParams {
|
||||
target_channel_id?: string;
|
||||
date_from?: string;
|
||||
date_to?: string;
|
||||
}
|
||||
21
lib/types/common.ts
Normal file
21
lib/types/common.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
// ============================================================================
|
||||
// Common Types
|
||||
// ============================================================================
|
||||
|
||||
export type LoadingState = "idle" | "loading" | "success" | "error";
|
||||
|
||||
export interface AsyncState<T> {
|
||||
data: T | null;
|
||||
loading: boolean;
|
||||
error: string | null;
|
||||
}
|
||||
|
||||
export interface PaginationParams {
|
||||
page?: number;
|
||||
limit?: number;
|
||||
}
|
||||
|
||||
export interface SortParams {
|
||||
sort_by?: string;
|
||||
order?: "asc" | "desc";
|
||||
}
|
||||
Reference in New Issue
Block a user