feat: all project setup

This commit is contained in:
ivannoskov
2025-11-10 12:07:24 +03:00
parent fbfd7719bb
commit b0a9934220
99 changed files with 19597 additions and 0 deletions

277
lib/mocks/data/analytics.ts Normal file
View File

@@ -0,0 +1,277 @@
import type {
AnalyticsOverview,
CostsReport,
AnalyticsChannelData,
AnalyticsCreativeData,
} from "@/lib/types/api";
// ============================================================================
// Mock Analytics Data
// ============================================================================
export const mockAnalyticsOverview: AnalyticsOverview = {
totalPurchases: 25,
purchasesChange: 5,
totalFollowers: 2500,
followersChange: 320,
averageCpf: 50.0,
cpfChange: -5.2,
averageCpm: 450.0,
cpmChange: -3.8,
topChannelsByCpf: [
{
channel_id: "ec3",
channel_name: "IT и Технологии",
total_purchases: 3,
avg_cpf: 38.2,
},
{
channel_id: "ec1",
channel_name: "Канал о Маркетинге",
total_purchases: 5,
avg_cpf: 40.0,
},
{
channel_id: "ec5",
channel_name: "Продажи и Переговоры",
total_purchases: 4,
avg_cpf: 45.0,
},
{
channel_id: "ec2",
channel_name: "Бизнес и Стартапы",
total_purchases: 8,
avg_cpf: 55.8,
},
{
channel_id: "ec4",
channel_name: "Крипто Инвестиции",
total_purchases: 2,
avg_cpf: 68.5,
},
],
topCreativesByCpf: [
{
creative_id: "cr1",
creative_name: 'Креатив "Присоединяйся"',
total_subscriptions: 1180,
avg_cpf: 42.4,
},
{
creative_id: "cr2",
creative_name: 'Креатив "Эксклюзив"',
total_subscriptions: 577,
avg_cpf: 48.5,
},
{
creative_id: "cr3",
creative_name: 'Креатив "Обучение"',
total_subscriptions: 803,
avg_cpf: 52.3,
},
],
};
// Mock data for costs report
export const mockCostsReportByDay: CostsReport = {
totalCost: 76500,
averageCost: 7650,
periods: [
{
date: "2024-02-20",
total_cost: 5000,
purchases_count: 1,
avg_cost: 5000,
},
{
date: "2024-02-22",
total_cost: 3500,
purchases_count: 1,
avg_cost: 3500,
},
{
date: "2024-02-25",
total_cost: 7000,
purchases_count: 2,
avg_cost: 3500,
},
{
date: "2024-02-28",
total_cost: 4500,
purchases_count: 1,
avg_cost: 4500,
},
{
date: "2024-03-02",
total_cost: 8500,
purchases_count: 2,
avg_cost: 4250,
},
{
date: "2024-03-05",
total_cost: 6000,
purchases_count: 1,
avg_cost: 6000,
},
{
date: "2024-03-08",
total_cost: 12000,
purchases_count: 3,
avg_cost: 4000,
},
{
date: "2024-03-12",
total_cost: 5500,
purchases_count: 1,
avg_cost: 5500,
},
{
date: "2024-03-15",
total_cost: 15000,
purchases_count: 3,
avg_cost: 5000,
},
{
date: "2024-03-18",
total_cost: 9500,
purchases_count: 2,
avg_cost: 4750,
},
],
};
export const mockCostsReportByWeek: CostsReport = {
totalCost: 125000,
averageCost: 15625,
periods: [
{
date: "2024-02-19",
total_cost: 15500,
purchases_count: 4,
avg_cost: 3875,
},
{
date: "2024-02-26",
total_cost: 13000,
purchases_count: 3,
avg_cost: 4333,
},
{
date: "2024-03-04",
total_cost: 26500,
purchases_count: 6,
avg_cost: 4417,
},
{
date: "2024-03-11",
total_cost: 33000,
purchases_count: 7,
avg_cost: 4714,
},
{
date: "2024-03-18",
total_cost: 24500,
purchases_count: 5,
avg_cost: 4900,
},
],
};
export const mockCostsReportByMonth: CostsReport = {
totalCost: 125000,
averageCost: 62500,
periods: [
{
date: "2024-02-01",
total_cost: 20000,
purchases_count: 5,
avg_cost: 4000,
},
{
date: "2024-03-01",
total_cost: 105000,
purchases_count: 20,
avg_cost: 5250,
},
],
};
// Mock data for channels analytics
export const mockAnalyticsChannelsData: AnalyticsChannelData[] = [
{
channel_id: "ec1",
channel_name: "Канал о Маркетинге",
purchases_count: 5,
total_cost: 25000,
total_subscriptions: 625,
avg_cpf: 40.0,
avg_cpm: 380.0,
},
{
channel_id: "ec2",
channel_name: "Бизнес и Стартапы",
purchases_count: 8,
total_cost: 48000,
total_subscriptions: 860,
avg_cpf: 55.8,
avg_cpm: 450.0,
},
{
channel_id: "ec3",
channel_name: "IT и Технологии",
purchases_count: 3,
total_cost: 12000,
total_subscriptions: 314,
avg_cpf: 38.2,
avg_cpm: 360.0,
},
{
channel_id: "ec4",
channel_name: "Крипто Инвестиции",
purchases_count: 2,
total_cost: 18000,
total_subscriptions: 263,
avg_cpf: 68.5,
avg_cpm: 520.0,
},
{
channel_id: "ec5",
channel_name: "Продажи и Переговоры",
purchases_count: 4,
total_cost: 16000,
total_subscriptions: 356,
avg_cpf: 45.0,
avg_cpm: 410.0,
},
];
// Mock data for creatives analytics
export const mockAnalyticsCreativesData: AnalyticsCreativeData[] = [
{
creative_id: "cr1",
creative_name: 'Креатив "Присоединяйся"',
purchases_count: 10,
total_cost: 50000,
total_subscriptions: 1180,
avg_cpf: 42.4,
conversion_rate: 0.95,
},
{
creative_id: "cr2",
creative_name: 'Креатив "Эксклюзив"',
purchases_count: 5,
total_cost: 28000,
total_subscriptions: 577,
avg_cpf: 48.5,
conversion_rate: 0.88,
},
{
creative_id: "cr3",
creative_name: 'Креатив "Обучение"',
purchases_count: 8,
total_cost: 42000,
total_subscriptions: 803,
avg_cpf: 52.3,
conversion_rate: 0.92,
},
];

View File

@@ -0,0 +1,79 @@
import { TargetChannel, TargetChannelDetail } from "@/lib/types/api";
// ============================================================================
// Mock Target Channels Data
// ============================================================================
export const mockTargetChannels: TargetChannel[] = [
{
id: "tc1",
telegram_id: -1001234567890,
title: "Мой Главный Канал",
username: "my_main_channel",
description: "Основной канал для продвижения продукта",
is_active: true,
created_at: "2024-01-10T10:00:00.000Z",
updated_at: "2024-01-10T10:00:00.000Z",
total_purchases: 15,
total_subscriptions: 1250,
avg_cpf: 45.5,
},
{
id: "tc2",
telegram_id: -1009876543210,
title: "Тестовый Канал",
username: "test_channel_promo",
description: "Канал для тестирования рекламных креативов",
is_active: true,
created_at: "2024-02-15T12:00:00.000Z",
updated_at: "2024-02-15T12:00:00.000Z",
total_purchases: 8,
total_subscriptions: 450,
avg_cpf: 52.3,
},
{
id: "tc3",
telegram_id: -1005555555555,
title: "Новости и Обновления",
username: null,
description: "Приватный канал для новостей",
is_active: false,
created_at: "2024-03-01T08:00:00.000Z",
updated_at: "2024-03-20T14:30:00.000Z",
total_purchases: 3,
total_subscriptions: 120,
avg_cpf: 67.8,
},
];
export const getMockTargetChannelDetail = (
id: string
): TargetChannelDetail | null => {
const channel = mockTargetChannels.find((c) => c.id === id);
if (!channel) return null;
return {
...channel,
recent_purchases: [], // Will be populated from purchases mock
stats_by_period: [
{
period: "day",
subscriptions: 25,
cost: 1200,
cpf: 48.0,
},
{
period: "week",
subscriptions: 180,
cost: 8500,
cpf: 47.2,
},
{
period: "month",
subscriptions: 750,
cost: 35000,
cpf: 46.7,
},
],
};
};

View File

@@ -0,0 +1,71 @@
import { Creative, CreativeDetail } from "@/lib/types/api";
import { mockTargetChannels } from "./channels";
// ============================================================================
// Mock Creatives Data
// ============================================================================
export const mockCreatives: Creative[] = [
{
id: "cr1",
name: 'Креатив "Присоединяйся"',
text: "🔥 Присоединяйся к нашему сообществу!\n\nУзнавай первым о новых возможностях и фишках.\n\n👉 {link}",
target_channel_id: "tc1",
is_archived: false,
created_at: "2024-01-15T10:00:00.000Z",
updated_at: "2024-01-15T10:00:00.000Z",
target_channel: mockTargetChannels[0],
total_purchases: 10,
total_subscriptions: 850,
avg_cpf: 42.3,
},
{
id: "cr2",
name: 'Креатив "Эксклюзив"',
text: "⭐ Эксклюзивный контент только для подписчиков!\n\nНе упусти возможность быть в курсе всех трендов.\n\nПереходи: {link}",
target_channel_id: "tc1",
is_archived: false,
created_at: "2024-01-20T12:00:00.000Z",
updated_at: "2024-01-20T12:00:00.000Z",
target_channel: mockTargetChannels[0],
total_purchases: 5,
total_subscriptions: 400,
avg_cpf: 48.5,
},
{
id: "cr3",
name: 'Креатив "Обучение"',
text: "📚 Хочешь научиться зарабатывать больше?\n\nПодписывайся на канал с проверенными методиками!\n\n{link}",
target_channel_id: "tc2",
is_archived: false,
created_at: "2024-02-05T09:00:00.000Z",
updated_at: "2024-02-05T09:00:00.000Z",
target_channel: mockTargetChannels[1],
total_purchases: 8,
total_subscriptions: 450,
avg_cpf: 52.3,
},
{
id: "cr4",
name: "Старый креатив (архив)",
text: "Устаревший текст с предложением. {link}",
target_channel_id: "tc1",
is_archived: true,
created_at: "2023-12-01T10:00:00.000Z",
updated_at: "2024-01-10T15:00:00.000Z",
target_channel: mockTargetChannels[0],
total_purchases: 2,
total_subscriptions: 80,
avg_cpf: 75.0,
},
];
export const getMockCreativeDetail = (id: string): CreativeDetail | null => {
const creative = mockCreatives.find((c) => c.id === id);
if (!creative) return null;
return {
...creative,
purchases: [], // Will be populated from purchases mock
};
};

View File

@@ -0,0 +1,95 @@
import { ExternalChannel, ExternalChannelDetail } from "@/lib/types/api";
// ============================================================================
// Mock External Channels Data
// ============================================================================
export const mockExternalChannels: ExternalChannel[] = [
{
id: "ec1",
telegram_id: -1001111111111,
title: "Канал о Маркетинге",
username: "marketing_pro",
link: "https://t.me/marketing_pro",
subscribers_count: 50000,
description: "Лучшие практики маркетинга",
created_at: "2024-01-05T10:00:00.000Z",
updated_at: "2024-01-05T10:00:00.000Z",
target_channels: ["tc1", "tc2"],
total_purchases: 5,
avg_cpf: 42.5,
avg_cpm: 850.0,
},
{
id: "ec2",
telegram_id: -1002222222222,
title: "Бизнес и Стартапы",
username: "business_startups",
link: "https://t.me/business_startups",
subscribers_count: 120000,
description: "Новости мира бизнеса",
created_at: "2024-01-08T11:00:00.000Z",
updated_at: "2024-01-08T11:00:00.000Z",
target_channels: ["tc1"],
total_purchases: 8,
avg_cpf: 55.8,
avg_cpm: 1200.0,
},
{
id: "ec3",
telegram_id: -1003333333333,
title: "IT и Технологии",
username: "it_tech_news",
link: "https://t.me/it_tech_news",
subscribers_count: 85000,
description: "Все о новых технологиях",
created_at: "2024-01-12T09:00:00.000Z",
updated_at: "2024-01-12T09:00:00.000Z",
target_channels: ["tc1", "tc2"],
total_purchases: 3,
avg_cpf: 38.2,
avg_cpm: 750.0,
},
{
id: "ec4",
telegram_id: null,
title: "Крипто Инвестиции",
username: "crypto_invest",
link: "https://t.me/crypto_invest",
subscribers_count: 200000,
description: null,
created_at: "2024-02-01T10:00:00.000Z",
updated_at: "2024-02-01T10:00:00.000Z",
target_channels: ["tc2"],
total_purchases: 2,
avg_cpf: 68.5,
avg_cpm: 1500.0,
},
{
id: "ec5",
telegram_id: -1005555555555,
title: "Продажи и Переговоры",
username: "sales_expert",
link: "https://t.me/sales_expert",
subscribers_count: 35000,
description: "Экспертиза в продажах",
created_at: "2024-02-10T14:00:00.000Z",
updated_at: "2024-02-10T14:00:00.000Z",
target_channels: ["tc1"],
total_purchases: 4,
avg_cpf: 45.0,
avg_cpm: 900.0,
},
];
export const getMockExternalChannelDetail = (
id: string
): ExternalChannelDetail | null => {
const channel = mockExternalChannels.find((c) => c.id === id);
if (!channel) return null;
return {
...channel,
purchases: [], // Will be populated from purchases mock
};
};

264
lib/mocks/data/purchases.ts Normal file
View File

@@ -0,0 +1,264 @@
import {
Purchase,
PurchaseDetail,
Subscription,
ViewsSnapshot,
} from "@/lib/types/api";
import { mockTargetChannels } from "./channels";
import { mockExternalChannels } from "./external-channels";
import { mockCreatives } from "./creatives";
// ============================================================================
// Mock Purchases Data
// ============================================================================
export const mockPurchases: Purchase[] = [
{
id: "p1",
target_channel_id: "tc1",
external_channel_id: "ec1",
creative_id: "cr1",
scheduled_date: "2024-03-15T10:00:00.000Z",
actual_date: "2024-03-15T11:30:00.000Z",
cost: 5000,
comment: "Тестовая закупка на утро",
post_link: "https://t.me/marketing_pro/1234",
invite_link: "https://t.me/+AbCdEfGhIjKlMnOp",
invite_link_type: "public",
is_archived: false,
created_at: "2024-03-14T15:00:00.000Z",
updated_at: "2024-03-15T11:30:00.000Z",
target_channel: mockTargetChannels[0],
external_channel: mockExternalChannels[0],
creative: mockCreatives[0],
subscriptions_count: 125,
views_count: 12500,
cpf: 40.0,
cpm: 400.0,
conversion_rate: 1.0,
},
{
id: "p2",
target_channel_id: "tc1",
external_channel_id: "ec2",
creative_id: "cr2",
scheduled_date: "2024-03-18T14:00:00.000Z",
actual_date: "2024-03-18T14:15:00.000Z",
cost: 12000,
comment: "Большой канал, ожидаем хороших результатов",
post_link: "https://t.me/business_startups/5678",
invite_link: "https://t.me/+QrStUvWxYzAbCdEf",
invite_link_type: "public",
is_archived: false,
created_at: "2024-03-17T10:00:00.000Z",
updated_at: "2024-03-18T14:15:00.000Z",
target_channel: mockTargetChannels[0],
external_channel: mockExternalChannels[1],
creative: mockCreatives[1],
subscriptions_count: 210,
views_count: 28000,
cpf: 57.1,
cpm: 428.6,
conversion_rate: 0.75,
},
{
id: "p3",
target_channel_id: "tc2",
external_channel_id: "ec3",
creative_id: "cr3",
scheduled_date: "2024-03-20T16:00:00.000Z",
actual_date: null,
cost: 3500,
comment: null,
post_link: "https://t.me/it_tech_news/9101",
invite_link: "https://t.me/+GhIjKlMnOpQrStUv",
invite_link_type: "private",
is_archived: false,
created_at: "2024-03-19T12:00:00.000Z",
updated_at: "2024-03-19T12:00:00.000Z",
target_channel: mockTargetChannels[1],
external_channel: mockExternalChannels[2],
creative: mockCreatives[2],
subscriptions_count: 85,
views_count: 8500,
cpf: 41.2,
cpm: 411.8,
conversion_rate: 1.0,
},
{
id: "p4",
target_channel_id: "tc1",
external_channel_id: "ec5",
creative_id: "cr1",
scheduled_date: "2024-03-22T12:00:00.000Z",
actual_date: null,
cost: 4500,
comment: "Повторная закупка в том же канале",
post_link: null,
invite_link: "https://t.me/+WxYzAbCdEfGhIjKl",
invite_link_type: "public",
is_archived: false,
created_at: "2024-03-21T09:00:00.000Z",
updated_at: "2024-03-21T09:00:00.000Z",
target_channel: mockTargetChannels[0],
external_channel: mockExternalChannels[4],
creative: mockCreatives[0],
subscriptions_count: 95,
views_count: null,
cpf: 47.4,
cpm: null,
conversion_rate: null,
},
{
id: "p5",
target_channel_id: "tc1",
external_channel_id: "ec1",
creative_id: "cr1",
scheduled_date: "2024-02-10T10:00:00.000Z",
actual_date: "2024-02-10T10:30:00.000Z",
cost: 5500,
comment: "Старая закупка для истории",
post_link: "https://t.me/marketing_pro/1100",
invite_link: "https://t.me/+OldInviteLink123",
invite_link_type: "public",
is_archived: true,
created_at: "2024-02-09T15:00:00.000Z",
updated_at: "2024-02-20T10:00:00.000Z",
target_channel: mockTargetChannels[0],
external_channel: mockExternalChannels[0],
creative: mockCreatives[0],
subscriptions_count: 140,
views_count: 15000,
cpf: 39.3,
cpm: 366.7,
conversion_rate: 0.93,
},
];
// Mock Subscriptions
export const mockSubscriptions: Subscription[] = [
{
id: "s1",
purchase_id: "p1",
telegram_user_id: 111111111,
user_first_name: "Иван",
user_last_name: "Петров",
user_username: "user1",
subscribed_at: "2024-03-15T11:35:00.000Z",
is_active: true,
event_type: "chat_member",
},
{
id: "s2",
purchase_id: "p1",
telegram_user_id: 222222222,
user_first_name: "Мария",
user_last_name: "Сидорова",
user_username: "user2",
subscribed_at: "2024-03-15T11:40:00.000Z",
is_active: true,
event_type: "chat_member",
},
{
id: "s3",
purchase_id: "p1",
telegram_user_id: 333333333,
user_first_name: "Алексей",
user_last_name: null,
user_username: null,
subscribed_at: "2024-03-15T12:00:00.000Z",
is_active: false,
event_type: "join_request",
},
{
id: "s4",
purchase_id: "p2",
telegram_user_id: 444444444,
user_first_name: "Елена",
user_last_name: "Кузнецова",
user_username: "user4",
subscribed_at: "2024-03-18T14:20:00.000Z",
is_active: true,
event_type: "chat_member",
},
{
id: "s5",
purchase_id: "p2",
telegram_user_id: 555555555,
user_first_name: "Дмитрий",
user_last_name: "Смирнов",
user_username: "user5",
subscribed_at: "2024-03-18T14:25:00.000Z",
is_active: true,
event_type: "chat_member",
},
];
// Mock Views Snapshots
export const mockViewsSnapshots: ViewsSnapshot[] = [
{
id: "v1",
purchase_id: "p1",
views: 5000,
fetched_at: "2024-03-15T12:00:00.000Z",
},
{
id: "v2",
purchase_id: "p1",
views: 8500,
fetched_at: "2024-03-15T18:00:00.000Z",
},
{
id: "v3",
purchase_id: "p1",
views: 10200,
fetched_at: "2024-03-16T09:00:00.000Z",
},
{
id: "v4",
purchase_id: "p1",
views: 11800,
fetched_at: "2024-03-16T18:00:00.000Z",
},
{
id: "v5",
purchase_id: "p1",
views: 12500,
fetched_at: "2024-03-17T12:00:00.000Z",
},
{
id: "v6",
purchase_id: "p2",
views: 15000,
fetched_at: "2024-03-18T15:00:00.000Z",
},
{
id: "v7",
purchase_id: "p2",
views: 22000,
fetched_at: "2024-03-18T20:00:00.000Z",
},
{
id: "v8",
purchase_id: "p2",
views: 26500,
fetched_at: "2024-03-19T09:00:00.000Z",
},
{
id: "v9",
purchase_id: "p2",
views: 28000,
fetched_at: "2024-03-19T18:00:00.000Z",
},
];
export const getMockPurchaseDetail = (id: string): PurchaseDetail | null => {
const purchase = mockPurchases.find((p) => p.id === id);
if (!purchase) return null;
return {
...purchase,
subscriptions: mockSubscriptions.filter((s) => s.purchase_id === id),
views_history: mockViewsSnapshots.filter((v) => v.purchase_id === id),
};
};

32
lib/mocks/data/users.ts Normal file
View File

@@ -0,0 +1,32 @@
import { User } from "@/lib/types/api";
// ============================================================================
// Mock Users Data
// ============================================================================
export const mockUsers: User[] = [
{
id: "1",
telegram_id: 123456789,
username: "ivan_test",
first_name: "Иван",
last_name: "Иванов",
created_at: "2024-01-15T10:00:00.000Z",
},
{
id: "2",
telegram_id: 987654321,
username: "maria_test",
first_name: "Мария",
last_name: "Петрова",
created_at: "2024-02-01T10:00:00.000Z",
},
];
export const mockCurrentUser = mockUsers[0];
// Mock tokens
export const mockTokens = {
access_token: "mock_access_token_123456789",
refresh_token: "mock_refresh_token_123456789",
};