Files
portal/app/resources/js/api/adminLeads.ts
T
Дмитрий 6536c19c96 feat(дашборд): Этап A — сквозная вложенность Лиды до источника
Экран «Лиды» (/admin/leads): серверный список с фильтрами (дата/канал/поставщик/
статус/поиск) + пагинация (масштаб 10⁴+ лидов). Карточка лида (/admin/leads/{id}):
полная цепочка — ОТКУДА (поставщик B1/B2/B3 + канал + источник + регион) → КОМУ
(сделки клиентов через deals.source_crm_id = supplier_leads.vid). Дашборд: drill
Лиды +топ-10 последних + «Открыть все лиды →». Nav-пункт «Лиды». ПДн-телефон
маскируется (152-ФЗ). Тесты: backend 3 + FE 5 (38 FE всего зелёные).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 10:14:47 +03:00

82 lines
2.1 KiB
TypeScript

import { apiClient } from './client';
/**
* SaaS-admin «Лиды» (L3) — сквозная вложенность дашборда до источника.
* Серверная пагинация/фильтры. Backend: AdminLeadsController.
* Spec: docs/superpowers/specs/2026-06-28-dashboard-drilldown-scale-design.md
*/
export type LeadStatus = 'delivered' | 'no_match' | 'pending' | 'stuck' | 'error';
export interface LeadRow {
id: number;
received_at: string;
platform: string;
channel: string | null;
source: string | null;
region_code: number | null;
phone_masked: string;
deals_created_count: number;
status: string;
}
export interface LeadsPage {
data: LeadRow[];
total: number;
page: number;
per_page: number;
}
export interface LeadsFilters {
page?: number;
per_page?: number;
date_from?: string;
date_to?: string;
channel?: string;
platform?: string;
status?: string;
tenant_id?: number;
search?: string;
}
export interface LeadDetail {
lead: {
id: number;
platform: string;
phone_masked: string;
received_at: string;
processed_at: string | null;
error: string | null;
region_code: number | null;
region_source: string | null;
phone_operator: string | null;
deals_created_count: number;
status: string;
};
source: {
platform: string;
channel: string | null;
identifier: string | null;
supplier_project_id: number | null;
};
deals: Array<{
id: number;
tenant_id: number;
tenant_name: string;
subdomain: string;
status: string;
project_id: number | null;
received_at: string;
}>;
}
export async function getLeads(filters: LeadsFilters): Promise<LeadsPage> {
const { data } = await apiClient.get<LeadsPage>('/api/admin/leads', { params: filters });
return data;
}
export async function getLead(id: number | string): Promise<LeadDetail> {
const { data } = await apiClient.get<LeadDetail>(`/api/admin/leads/${id}`);
return data;
}