Files
tgex-frontend/lib/api/placements.ts
2026-02-02 21:49:57 +03:00

157 lines
4.4 KiB
TypeScript

// ============================================================================
// Placements API
// ============================================================================
import { api } from "./client";
import type {
Placement,
PlacementWithStats,
PlacementCreateRequest,
PlacementUpdateRequest,
PlacementsQueryParams,
ViewsHistoryItem,
ViewsHistoryQueryParams,
PaginatedResponse,
UpdatePlacementInProjectRequest,
} from "@/lib/types/api";
export const placementsApi = {
/**
* Get list of placements for workspace
*/
list: (workspaceId: string, params?: PlacementsQueryParams) =>
api.get<PaginatedResponse<Placement>>(
`/workspaces/${workspaceId}/placements`,
{ params }
),
/**
* Get placements for a specific project (grouped by channel UI)
*/
getByProject: (workspaceId: string, projectId: string) =>
api.get<PaginatedResponse<Placement>>(`/workspaces/${workspaceId}/projects/${projectId}/placements`)
.then((response) => response.items),
/**
* 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
*/
create: (workspaceId: string, data: PlacementCreateRequest) =>
api.post<Placement>(`/workspaces/${workspaceId}/placements`, data),
/**
* Create placements for multiple channels (bulk creation)
*/
createBulk: (
workspaceId: string,
projectId: string,
data: {
creative_id?: string;
channels: Array<{
channel_id: string;
status?: string;
comment?: string;
details?: {
placement_at?: string;
payment_at?: string;
cost?: { type: string; value: number };
cost_before_bargain?: number;
placement_type?: string;
format?: string;
comment?: string;
creative_id?: string;
};
}>;
details?: {
placement_at?: string;
payment_at?: string;
cost?: { type: string; value: number };
cost_before_bargain?: number;
placement_type?: string;
format?: string;
comment?: string;
creative_id?: string;
};
}
) =>
api.post<{ placements: Placement[] }>(
`/workspaces/${workspaceId}/projects/${projectId}/placements`,
data
),
/**
* Update placement
*/
update: (
workspaceId: string,
placementId: string,
data: PlacementUpdateRequest
) =>
api.patch<Placement>(
`/workspaces/${workspaceId}/placements/${placementId}`,
data
),
/**
* Update placement within project (Purchase Plans UI)
* PATCH /workspaces/{workspace_id}/projects/{project_id}/placements/{placement_id}
*/
updateInProject: (
workspaceId: string,
projectId: string,
placementId: string,
data: UpdatePlacementInProjectRequest
) =>
api.patch<Placement>(
`/workspaces/${workspaceId}/projects/${projectId}/placements/${placementId}`,
data
),
/**
* Delete placement within project
* DELETE /workspaces/{workspace_id}/projects/{project_id}/placements/{placement_id}
*/
deleteInProject: (workspaceId: string, projectId: string, placementId: string) =>
api.delete<void>(
`/workspaces/${workspaceId}/projects/${projectId}/placements/${placementId}`
),
/**
* Get views history for placement
*/
getViewsHistory: (
workspaceId: string,
placementId: string,
params?: ViewsHistoryQueryParams
) =>
api.get<PaginatedResponse<ViewsHistoryItem>>(
`/workspaces/${workspaceId}/placements/${placementId}/views/history`,
{ params }
),
/**
* Build creative for placement (generate invite link and send to user via bot)
* POST /workspaces/{workspace_id}/projects/{project_id}/placements/{placement_id}/creative
*/
sendCreative: (
workspaceId: string,
projectId: string,
placementId: string
) =>
api.post<{ id: string; name: string; text: string }>(
`/workspaces/${workspaceId}/projects/${projectId}/placements/${placementId}/creative`
),
};