feat: purchase-plans global update
This commit is contained in:
@@ -12,20 +12,9 @@ import type {
|
||||
ViewsHistoryItem,
|
||||
ViewsHistoryQueryParams,
|
||||
PaginatedResponse,
|
||||
UpdatePlacementInProjectRequest,
|
||||
} from "@/lib/types/api";
|
||||
|
||||
type UpdatePlacementInProjectRequest = Partial<{
|
||||
status: string;
|
||||
comment: string | null;
|
||||
creative_id: string | null;
|
||||
placement_at: string | null;
|
||||
payment_at: string | null;
|
||||
cost: { type: "fixed"; value: number } | null;
|
||||
cost_before_bargain: number | null;
|
||||
placement_type: string | null;
|
||||
format: string | null;
|
||||
}>;
|
||||
|
||||
export const placementsApi = {
|
||||
/**
|
||||
* Get list of placements for workspace
|
||||
@@ -40,15 +29,22 @@ export const placementsApi = {
|
||||
* Get placements for a specific project (grouped by channel UI)
|
||||
*/
|
||||
getByProject: (workspaceId: string, projectId: string) =>
|
||||
api.get<{ placements: Placement[] }>(`/workspaces/${workspaceId}/projects/${projectId}/placements`)
|
||||
.then((response) => response.placements),
|
||||
api.get<PaginatedResponse<Placement>>(`/workspaces/${workspaceId}/projects/${projectId}/placements`)
|
||||
.then((response) => response.items),
|
||||
|
||||
/**
|
||||
* Get single placement
|
||||
* Get single placement (deprecated - use getInProject for project-specific data)
|
||||
*/
|
||||
get: (workspaceId: string, placementId: string) =>
|
||||
api.get<Placement>(`/workspaces/${workspaceId}/placements/${placementId}`),
|
||||
|
||||
/**
|
||||
* Get single placement within project
|
||||
* GET /workspaces/{workspace_id}/projects/{project_id}/placements/{placement_id}
|
||||
*/
|
||||
getInProject: (workspaceId: string, projectId: string, placementId: string) =>
|
||||
api.get<PlacementWithStats>(`/workspaces/${workspaceId}/projects/${projectId}/placements/${placementId}`),
|
||||
|
||||
/**
|
||||
* Create new placement
|
||||
*/
|
||||
@@ -124,10 +120,13 @@ export const placementsApi = {
|
||||
),
|
||||
|
||||
/**
|
||||
* Delete (archive) placement
|
||||
* Delete placement within project
|
||||
* DELETE /workspaces/{workspace_id}/projects/{project_id}/placements/{placement_id}
|
||||
*/
|
||||
delete: (workspaceId: string, placementId: string) =>
|
||||
api.delete<void>(`/workspaces/${workspaceId}/placements/${placementId}`),
|
||||
deleteInProject: (workspaceId: string, projectId: string, placementId: string) =>
|
||||
api.delete<void>(
|
||||
`/workspaces/${workspaceId}/projects/${projectId}/placements/${placementId}`
|
||||
),
|
||||
|
||||
/**
|
||||
* Get views history for placement
|
||||
|
||||
148
lib/config/placement-columns.ts
Normal file
148
lib/config/placement-columns.ts
Normal file
@@ -0,0 +1,148 @@
|
||||
import type { PlacementStatus, PlacementPostStatus, CostType, PlacementType, InviteLinkType } from "@/lib/types/api";
|
||||
|
||||
export interface ColumnConfig {
|
||||
id: string;
|
||||
label: string;
|
||||
group: string;
|
||||
editable: boolean;
|
||||
width?: string;
|
||||
required?: boolean;
|
||||
}
|
||||
|
||||
export const COLUMN_GROUPS = [
|
||||
{ id: "basic", label: "Основная информация" },
|
||||
{ id: "content", label: "Контент" },
|
||||
{ id: "finance", label: "Финансы" },
|
||||
{ id: "dates", label: "Даты и время" },
|
||||
{ id: "metrics", label: "Метрики" },
|
||||
{ id: "calculated", label: "Расчетные показатели" },
|
||||
{ id: "technical", label: "Технические детали" },
|
||||
] as const;
|
||||
|
||||
export const ALL_COLUMNS: ColumnConfig[] = [
|
||||
// Basic
|
||||
{ id: "checkbox", label: "", group: "basic", editable: false, required: true },
|
||||
{ id: "number", label: "№", group: "basic", editable: false, required: true },
|
||||
{ id: "status_deal", label: "Статус сделки", group: "basic", editable: true },
|
||||
{ id: "status_post", label: "Статус поста", group: "basic", editable: true },
|
||||
|
||||
// Content
|
||||
{ id: "creative", label: "Креатив", group: "content", editable: true },
|
||||
{ id: "invite_link", label: "Пригласительная ссылка", group: "content", editable: false },
|
||||
{ id: "post_link", label: "Ссылка на пост", group: "content", editable: false },
|
||||
|
||||
// Finance
|
||||
{ id: "cost", label: "Стоимость", group: "finance", editable: true },
|
||||
{ id: "cost_before", label: "Стоимость до торга", group: "finance", editable: true },
|
||||
{ id: "cost_format", label: "Формат оплаты", group: "finance", editable: true },
|
||||
{ id: "placement_type", label: "Тип закупа", group: "finance", editable: true },
|
||||
{ id: "discount", label: "% скидки", group: "finance", editable: false },
|
||||
{ id: "payment_date", label: "Дата оплаты", group: "finance", editable: true },
|
||||
|
||||
// Dates
|
||||
{ id: "planned_date", label: "Плановая дата", group: "dates", editable: true },
|
||||
{ id: "actual_date", label: "Фактическая дата", group: "dates", editable: false },
|
||||
{ id: "format", label: "Плановый формат", group: "dates", editable: true },
|
||||
{ id: "time_top", label: "Время в топе", group: "dates", editable: false },
|
||||
{ id: "time_in_feed", label: "Время в ленте", group: "dates", editable: false },
|
||||
{ id: "link_created", label: "Дата ссылки", group: "dates", editable: false },
|
||||
{ id: "post_deleted", label: "Дата удаления", group: "dates", editable: false },
|
||||
|
||||
// Metrics
|
||||
{ id: "subscriptions", label: "Всего подписок", group: "metrics", editable: false },
|
||||
{ id: "views", label: "Просмотры", group: "metrics", editable: false },
|
||||
|
||||
// Calculated
|
||||
{ id: "cpf", label: "CPF", group: "calculated", editable: false },
|
||||
{ id: "cpm", label: "CPM", group: "calculated", editable: false },
|
||||
{ id: "conversion_24h", label: "Конверсия 24ч", group: "calculated", editable: false },
|
||||
{ id: "conversion_48h", label: "Конверсия 48ч", group: "calculated", editable: false },
|
||||
{ id: "conversion_total", label: "Конверсия общ.", group: "calculated", editable: false },
|
||||
{ id: "total_unsubs", label: "Всего отписок", group: "calculated", editable: false },
|
||||
{ id: "unsub_percent", label: "% отписок", group: "calculated", editable: false },
|
||||
{ id: "total_active", label: "Итого подписок", group: "calculated", editable: false },
|
||||
|
||||
// Technical
|
||||
{ id: "invite_type", label: "Тип ссылки", group: "technical", editable: true },
|
||||
{ id: "comment", label: "Комментарий", group: "technical", editable: true },
|
||||
] as const;
|
||||
|
||||
// Default visible columns
|
||||
export const DEFAULT_VISIBLE_COLUMNS = new Set([
|
||||
"checkbox",
|
||||
"number",
|
||||
"status_deal",
|
||||
"status_post",
|
||||
"creative",
|
||||
"invite_link",
|
||||
"cost",
|
||||
"cost_before",
|
||||
"cost_format",
|
||||
"planned_date",
|
||||
"format",
|
||||
"subscriptions",
|
||||
"views",
|
||||
"cpf",
|
||||
"cpm",
|
||||
"comment",
|
||||
]);
|
||||
|
||||
// Status lists
|
||||
export const PLACEMENT_DEAL_STATUSES: PlacementStatus[] = [
|
||||
"Без статуса",
|
||||
"Написать",
|
||||
"Ждём ответа",
|
||||
"Согласование условий",
|
||||
"Оплатить",
|
||||
"Оплачено",
|
||||
"Отмена",
|
||||
"Не подходит цена",
|
||||
"Неактуально",
|
||||
"Не отвечает",
|
||||
];
|
||||
|
||||
export const PLACEMENT_POST_STATUSES: PlacementPostStatus[] = [
|
||||
"Без статуса",
|
||||
"Отправить пост",
|
||||
"Согласование поста",
|
||||
"Ожидание отложки",
|
||||
"Запланирован",
|
||||
"Пост вышел",
|
||||
"Размещение отработало - пост удалён",
|
||||
"Размещение отработало - пост не удалён",
|
||||
"Проверить - пост удалён раньше срока",
|
||||
"Проверить - пост не вышел",
|
||||
"Размещение отработало",
|
||||
];
|
||||
|
||||
export const COST_FORMATS: CostType[] = ["fixed", "cpm"];
|
||||
export const PLACEMENT_TYPES: PlacementType[] = ["self_promo", "standard"];
|
||||
export const INVITE_TYPES: InviteLinkType[] = ["public", "approval"];
|
||||
|
||||
// Manual post statuses (user can select before post is published)
|
||||
export const MANUAL_POST_STATUSES: Set<PlacementPostStatus> = new Set([
|
||||
"Без статуса",
|
||||
"Отправить пост",
|
||||
"Согласование поста",
|
||||
"Ожидание отложки",
|
||||
"Запланирован",
|
||||
]);
|
||||
|
||||
// Automatic post statuses (set by backend)
|
||||
export const AUTOMATIC_POST_STATUSES: Set<PlacementPostStatus> = new Set([
|
||||
"Пост вышел",
|
||||
"Размещение отработало - пост удалён",
|
||||
"Размещение отработало - пост не удалён",
|
||||
"Проверить - пост удалён раньше срока",
|
||||
"Проверить - пост не вышел",
|
||||
"Размещение отработало",
|
||||
]);
|
||||
|
||||
// Helper functions
|
||||
export const canEditPostStatus = (currentStatus: PlacementPostStatus): boolean => {
|
||||
return MANUAL_POST_STATUSES.has(currentStatus);
|
||||
};
|
||||
|
||||
export const isAutomaticPostStatus = (status: PlacementPostStatus): boolean => {
|
||||
return AUTOMATIC_POST_STATUSES.has(status);
|
||||
};
|
||||
@@ -312,15 +312,19 @@ export const demoPlacements: (Placement & { project_id: string })[] = [
|
||||
project_id: "proj-0001-0000-0000-000000000001",
|
||||
status: "Оплачено",
|
||||
creative_id: "crea-0001-0000-0000-000000000001",
|
||||
creative_name: "Креатив 1",
|
||||
comment: "crypto_jan",
|
||||
invite_link: "https://t.me/+abc123",
|
||||
invite_link_created_at: "2024-12-19T10:00:00Z",
|
||||
invite_link_type: "public",
|
||||
channel: demoPlacementChannels[0],
|
||||
project: demoProjects[0],
|
||||
short_id: "abc123",
|
||||
details: {
|
||||
placement_at: "2024-12-20T12:00:00Z",
|
||||
payment_at: "2024-12-19T10:00:00Z",
|
||||
cost: { type: "fixed", value: 5500 },
|
||||
cost_before_bargain: 6000,
|
||||
cost_before_bargain: { type: "fixed", value: 6000 },
|
||||
placement_type: "self_promo",
|
||||
format: "Стандарт",
|
||||
comment: null,
|
||||
@@ -329,6 +333,8 @@ export const demoPlacements: (Placement & { project_id: string })[] = [
|
||||
placement_post: {
|
||||
subscriptions_count: 156,
|
||||
views_count: 8500,
|
||||
status: "Пост вышел",
|
||||
time_on_top: null,
|
||||
created_at: "2024-12-20T12:00:00Z",
|
||||
post: {
|
||||
id: "post-0001-0000-0000-000000000001",
|
||||
@@ -336,6 +342,7 @@ export const demoPlacements: (Placement & { project_id: string })[] = [
|
||||
text: "Привет! Отличные новости...",
|
||||
url: "https://t.me/tech_future/12345",
|
||||
deleted_from_channel_at: null,
|
||||
published_at: null,
|
||||
created_at: "2024-12-20T12:00:00Z",
|
||||
updated_at: "2024-12-20T12:00:00Z",
|
||||
},
|
||||
@@ -347,15 +354,19 @@ export const demoPlacements: (Placement & { project_id: string })[] = [
|
||||
project_id: "proj-0001-0000-0000-000000000001",
|
||||
status: "Согласование условий",
|
||||
creative_id: "crea-0001-0000-0000-000000000001",
|
||||
creative_name: "Креатив 1",
|
||||
comment: "crypto_feb",
|
||||
invite_link: "https://t.me/+def456",
|
||||
invite_link_created_at: null,
|
||||
invite_link_type: "approval",
|
||||
channel: demoPlacementChannels[1],
|
||||
project: demoProjects[0],
|
||||
short_id: "def456",
|
||||
details: {
|
||||
placement_at: "2024-12-25T14:00:00Z",
|
||||
payment_at: null,
|
||||
cost: { type: "fixed", value: 3200 },
|
||||
cost_before_bargain: 3500,
|
||||
cost_before_bargain: { type: "fixed", value: 3500 },
|
||||
placement_type: "self_promo",
|
||||
format: "Стандарт",
|
||||
comment: null,
|
||||
@@ -369,15 +380,19 @@ export const demoPlacements: (Placement & { project_id: string })[] = [
|
||||
project_id: "proj-0001-0000-0000-000000000001",
|
||||
status: "Оплачено",
|
||||
creative_id: "crea-0001-0000-0000-000000000001",
|
||||
creative_name: "Креатив 1",
|
||||
comment: null,
|
||||
invite_link: "https://t.me/+ghi789",
|
||||
invite_link_created_at: "2024-12-14T16:00:00Z",
|
||||
invite_link_type: "public",
|
||||
channel: demoPlacementChannels[2],
|
||||
project: demoProjects[0],
|
||||
short_id: "ghi789",
|
||||
details: {
|
||||
placement_at: "2024-12-15T10:00:00Z",
|
||||
payment_at: "2024-12-14T16:00:00Z",
|
||||
cost: { type: "fixed", value: 4800 },
|
||||
cost_before_bargain: 5000,
|
||||
cost_before_bargain: { type: "fixed", value: 5000 },
|
||||
placement_type: "self_promo",
|
||||
format: "Стандарт",
|
||||
comment: null,
|
||||
@@ -386,6 +401,8 @@ export const demoPlacements: (Placement & { project_id: string })[] = [
|
||||
placement_post: {
|
||||
subscriptions_count: 234,
|
||||
views_count: 12000,
|
||||
status: "Пост вышел",
|
||||
time_on_top: null,
|
||||
created_at: "2024-12-15T10:00:00Z",
|
||||
post: {
|
||||
id: "post-0002-0000-0000-000000000002",
|
||||
@@ -393,6 +410,7 @@ export const demoPlacements: (Placement & { project_id: string })[] = [
|
||||
text: "Криптовалюты продолжают расти...",
|
||||
url: "https://t.me/programmers/67890",
|
||||
deleted_from_channel_at: null,
|
||||
published_at: null,
|
||||
created_at: "2024-12-15T10:00:00Z",
|
||||
updated_at: "2024-12-15T10:00:00Z",
|
||||
},
|
||||
@@ -404,66 +422,172 @@ export const demoPlacements: (Placement & { project_id: string })[] = [
|
||||
project_id: "proj-0001-0000-0000-000000000001",
|
||||
status: "Ждём ответа",
|
||||
creative_id: "crea-0001-0000-0000-000000000001",
|
||||
creative_name: "Креатив 1",
|
||||
comment: null,
|
||||
invite_link: "https://t.me/+jkl012",
|
||||
invite_link_type: "public",
|
||||
invite_link: null,
|
||||
invite_link_created_at: null,
|
||||
invite_link_type: "approval",
|
||||
channel: demoPlacementChannels[3],
|
||||
project: demoProjects[0],
|
||||
short_id: "jkl012",
|
||||
details: {
|
||||
placement_at: "2024-12-28T09:00:00Z",
|
||||
placement_at: "2024-12-30T11:00:00Z",
|
||||
payment_at: null,
|
||||
cost: { type: "fixed", value: 2500 },
|
||||
cost_before_bargain: 2800,
|
||||
cost: { type: "fixed", value: 6100 },
|
||||
cost_before_bargain: { type: "fixed", value: 6500 },
|
||||
placement_type: "self_promo",
|
||||
format: "Стандарт",
|
||||
comment: null,
|
||||
creative_id: "crea-0001-0000-0000-000000000001",
|
||||
},
|
||||
placement_post: null,
|
||||
created_at: "2024-12-24T14:00:00Z",
|
||||
created_at: "2024-12-27T08:00:00Z",
|
||||
},
|
||||
{
|
||||
id: "plac-0005-0000-0000-000000000005",
|
||||
project_id: "proj-0002-0000-0000-000000000002",
|
||||
status: "Написать",
|
||||
creative_id: "crea-0002-0000-0000-000000000002",
|
||||
comment: "Новый оффер",
|
||||
project_id: "proj-0001-0000-0000-000000000001",
|
||||
status: "Неактуально",
|
||||
creative_id: "crea-0001-0000-0000-000000000001",
|
||||
creative_name: "Креатив 1",
|
||||
comment: "Разобрались без рекламы",
|
||||
invite_link: null,
|
||||
invite_link_type: "approval",
|
||||
channel: demoPlacementChannels[0],
|
||||
invite_link_created_at: null,
|
||||
invite_link_type: "public",
|
||||
channel: demoPlacementChannels[4],
|
||||
project: demoProjects[0],
|
||||
short_id: "mno345",
|
||||
details: {
|
||||
placement_at: null,
|
||||
payment_at: null,
|
||||
cost: { type: "fixed", value: 6000 },
|
||||
cost_before_bargain: null,
|
||||
cost: { type: "fixed", value: 7300 },
|
||||
cost_before_bargain: { type: "fixed", value: 7800 },
|
||||
placement_type: "self_promo",
|
||||
format: "Спонсорский",
|
||||
format: "Стандарт",
|
||||
comment: null,
|
||||
creative_id: "crea-0002-0000-0000-000000000002",
|
||||
creative_id: "crea-0001-0000-0000-000000000001",
|
||||
},
|
||||
placement_post: null,
|
||||
created_at: "2024-12-26T08:00:00Z",
|
||||
created_at: "2024-12-25T14:00:00Z",
|
||||
},
|
||||
{
|
||||
id: "plac-0006-0000-0000-000000000006",
|
||||
project_id: "proj-0002-0000-0000-000000000002",
|
||||
status: "Отмена",
|
||||
creative_id: "crea-0001-0000-0000-000000000001",
|
||||
comment: "Неактуально",
|
||||
status: "Согласование условий",
|
||||
creative_id: "crea-0002-0000-0000-000000000002",
|
||||
creative_name: "Креатив 2",
|
||||
comment: null,
|
||||
invite_link: null,
|
||||
invite_link_type: "public",
|
||||
channel: demoPlacementChannels[1],
|
||||
invite_link_created_at: null,
|
||||
invite_link_type: "approval",
|
||||
channel: demoPlacementChannels[5],
|
||||
project: demoProjects[1],
|
||||
short_id: "pqr678",
|
||||
details: {
|
||||
placement_at: null,
|
||||
placement_at: "2025-01-05T15:00:00Z",
|
||||
payment_at: null,
|
||||
cost: null,
|
||||
cost_before_bargain: null,
|
||||
placement_type: null,
|
||||
format: null,
|
||||
comment: "Клиент отказался",
|
||||
creative_id: null,
|
||||
cost: { type: "fixed", value: 4100 },
|
||||
cost_before_bargain: { type: "fixed", value: 4500 },
|
||||
placement_type: "self_promo",
|
||||
format: "Стандарт",
|
||||
comment: null,
|
||||
creative_id: "crea-0002-0000-0000-000000000002",
|
||||
},
|
||||
placement_post: null,
|
||||
created_at: "2024-12-10T10:00:00Z",
|
||||
created_at: "2025-01-02T10:00:00Z",
|
||||
},
|
||||
{
|
||||
id: "plac-0007-0000-0000-000000000007",
|
||||
project_id: "proj-0002-0000-0000-000000000002",
|
||||
status: "Оплачено",
|
||||
creative_id: "crea-0002-0000-0000-000000000002",
|
||||
creative_name: "Креатив 2",
|
||||
comment: "finance_mar",
|
||||
invite_link: "https://t.me/+stu901",
|
||||
invite_link_created_at: "2025-01-06T12:00:00Z",
|
||||
invite_link_type: "public",
|
||||
channel: demoPlacementChannels[6],
|
||||
project: demoProjects[1],
|
||||
short_id: "stu901",
|
||||
details: {
|
||||
placement_at: "2025-01-07T09:00:00Z",
|
||||
payment_at: "2025-01-06T12:00:00Z",
|
||||
cost: { type: "fixed", value: 5700 },
|
||||
cost_before_bargain: { type: "fixed", value: 6100 },
|
||||
placement_type: "self_promo",
|
||||
format: "Стандарт",
|
||||
comment: null,
|
||||
creative_id: "crea-0002-0000-0000-000000000002",
|
||||
},
|
||||
placement_post: {
|
||||
subscriptions_count: 298,
|
||||
views_count: 15500,
|
||||
status: "Пост вышел",
|
||||
time_on_top: null,
|
||||
created_at: "2025-01-07T09:00:00Z",
|
||||
post: {
|
||||
id: "post-0003-0000-0000-000000000003",
|
||||
message_id: 11111,
|
||||
text: "Важное обновление в нашем продукте...",
|
||||
url: "https://t.me/product_updates/11111",
|
||||
deleted_from_channel_at: null,
|
||||
published_at: null,
|
||||
created_at: "2025-01-07T09:00:00Z",
|
||||
updated_at: "2025-01-07T09:00:00Z",
|
||||
},
|
||||
},
|
||||
created_at: "2025-01-04T11:00:00Z",
|
||||
},
|
||||
{
|
||||
id: "plac-0008-0000-0000-000000000008",
|
||||
project_id: "proj-0002-0000-0000-000000000002",
|
||||
status: "Ждём ответа",
|
||||
creative_id: "crea-0002-0000-0000-000000000002",
|
||||
creative_name: "Креатив 2",
|
||||
comment: null,
|
||||
invite_link: null,
|
||||
invite_link_created_at: null,
|
||||
invite_link_type: "approval",
|
||||
channel: demoPlacementChannels[7],
|
||||
project: demoProjects[1],
|
||||
short_id: "vwx234",
|
||||
details: {
|
||||
placement_at: "2025-01-12T16:00:00Z",
|
||||
payment_at: null,
|
||||
cost: { type: "fixed", value: 6900 },
|
||||
cost_before_bargain: { type: "fixed", value: 7400 },
|
||||
placement_type: "self_promo",
|
||||
format: "Стандарт",
|
||||
comment: null,
|
||||
creative_id: "crea-0002-0000-0000-000000000002",
|
||||
},
|
||||
placement_post: null,
|
||||
created_at: "2025-01-09T13:00:00Z",
|
||||
},
|
||||
{
|
||||
id: "plac-0009-0000-0000-000000000009",
|
||||
project_id: "proj-0003-0000-0000-000000000003",
|
||||
status: "Согласование условий",
|
||||
creative_id: "crea-0003-0000-0000-000000000003",
|
||||
creative_name: "Креатив 3",
|
||||
comment: null,
|
||||
invite_link: null,
|
||||
invite_link_created_at: null,
|
||||
invite_link_type: "approval",
|
||||
channel: demoPlacementChannels[8],
|
||||
project: demoProjects[2],
|
||||
short_id: "yza567",
|
||||
details: {
|
||||
placement_at: "2025-01-18T11:00:00Z",
|
||||
payment_at: null,
|
||||
cost: { type: "fixed", value: 3500 },
|
||||
cost_before_bargain: { type: "fixed", value: 3800 },
|
||||
placement_type: "self_promo",
|
||||
format: "Стандарт",
|
||||
comment: null,
|
||||
creative_id: "crea-0003-0000-0000-000000000003",
|
||||
},
|
||||
placement_post: null,
|
||||
created_at: "2025-01-15T09:00:00Z",
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@@ -245,12 +245,27 @@ export type PlacementStatus =
|
||||
| "Неактуально"
|
||||
| "Не отвечает";
|
||||
|
||||
export type InviteLinkType = "public" | "approval";
|
||||
export type PostViewsAvailability =
|
||||
| "unknown"
|
||||
| "available"
|
||||
| "unavailable"
|
||||
| "manual";
|
||||
export type PlacementPostStatus =
|
||||
| "Без статуса"
|
||||
| "Отправить пост"
|
||||
| "Согласование поста"
|
||||
| "Ожидание отложки"
|
||||
| "Запланирован"
|
||||
| "Пост вышел"
|
||||
| "Размещение отработало - пост удалён"
|
||||
| "Размещение отработало - пост не удалён"
|
||||
| "Проверить - пост удалён раньше срока"
|
||||
| "Проверить - пост не вышел"
|
||||
| "Размещение отработало";
|
||||
|
||||
export type InviteLinkType = "public" | "approval";
|
||||
export type PlacementType = "self_promo" | "standard";
|
||||
export type CostType = "fixed" | "cpm";
|
||||
export type PostViewsAvailability =
|
||||
| "unknown"
|
||||
| "available"
|
||||
| "unavailable"
|
||||
| "manual";
|
||||
|
||||
export interface PlacementChannel {
|
||||
id: string;
|
||||
@@ -261,7 +276,7 @@ export interface PlacementChannel {
|
||||
}
|
||||
|
||||
export interface PlacementCostInfo {
|
||||
type: "fixed" | "cpm";
|
||||
type: CostType;
|
||||
value: number;
|
||||
}
|
||||
|
||||
@@ -269,8 +284,8 @@ export interface PlacementDetails {
|
||||
placement_at: string | null; // ISO 8601
|
||||
payment_at: string | null; // ISO 8601
|
||||
cost: PlacementCostInfo | null;
|
||||
cost_before_bargain: number | null;
|
||||
placement_type: string | null;
|
||||
cost_before_bargain: PlacementCostInfo | null;
|
||||
placement_type: PlacementType | null;
|
||||
format: string | null;
|
||||
comment: string | null;
|
||||
creative_id: string | null;
|
||||
@@ -286,27 +301,44 @@ export interface PlacementPost {
|
||||
text: string;
|
||||
url: string | null;
|
||||
deleted_from_channel_at: string | null;
|
||||
published_at: string | null;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
} | null;
|
||||
}
|
||||
|
||||
export interface PlacementPostWithStatus extends PlacementPost {
|
||||
status: PlacementPostStatus;
|
||||
time_on_top: number | null;
|
||||
}
|
||||
|
||||
export interface Placement {
|
||||
id: string;
|
||||
status: PlacementStatus;
|
||||
creative_id: string | null;
|
||||
creative_name: string | null;
|
||||
comment: string | null;
|
||||
invite_link: string | null;
|
||||
invite_link_created_at: string | null;
|
||||
invite_link_type: InviteLinkType;
|
||||
channel: PlacementChannel;
|
||||
project: Project | null;
|
||||
short_id: string;
|
||||
details: PlacementDetails | null;
|
||||
placement_post: PlacementPost | null;
|
||||
placement_post: PlacementPostWithStatus | null;
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
export interface PlacementWithStats extends Placement {
|
||||
cpf: number | null;
|
||||
cpm: number | null;
|
||||
time_in_feed?: number | null;
|
||||
conversion_24h?: number | null;
|
||||
conversion_48h?: number | null;
|
||||
conversion_total?: number | null;
|
||||
total_unsubs?: number | null;
|
||||
unsub_percent?: number | null;
|
||||
total_active?: number | null;
|
||||
}
|
||||
|
||||
export interface PlacementsGroupedByChannel {
|
||||
@@ -345,6 +377,19 @@ export interface PlacementUpdateRequest {
|
||||
ad_post_url?: string;
|
||||
}
|
||||
|
||||
export interface UpdatePlacementInProjectRequest {
|
||||
status?: string;
|
||||
comment?: string | null;
|
||||
creative_id?: string | null;
|
||||
creative_name?: string | null;
|
||||
placement_at?: string | null;
|
||||
payment_at?: string | null;
|
||||
cost?: { type: CostType; value: number } | null;
|
||||
cost_before_bargain?: { type: CostType; value: number } | null;
|
||||
placement_type?: PlacementType | null;
|
||||
format?: string | null;
|
||||
}
|
||||
|
||||
export interface PlacementsQueryParams extends PaginationParams {
|
||||
project_id?: string;
|
||||
placement_channel_id?: string;
|
||||
|
||||
Reference in New Issue
Block a user