Files
portal/app/resources/js/utils/prospectContacts.ts
T
Дмитрий 68428f16c6 @
feat(sales): карточка кандидата — девять полей владельца + правка контактных лиц

Владелец задал список полей карточки и попросил дать менеджеру записывать
контактных лиц прямо в карточке: поиск отдаёт 5-7 ПРЕДПОЛАГАЕМЫХ номеров
директора, живой из них выясняется обзвоном; а если директор перенаправил
к маркетологу — менеджер фиксирует и его, людей может быть 2-3.

- Карточка показывает РОВНО девять полей в его порядке: Юрлицо, Сайт, ИНН фирмы,
  Адрес, Телефон общий, Каналы, Бюджет, Директор, Тел. директора (предполагаемый).
  Убраны Оценка, Достоверность, Реклама, Запросы в Директе, ОГРН, Статус юрлица,
  Личный ИНН директора, Почта директора — данные остаются в payload.
- PATCH /api/sales/prospects/{id}/contacts — список заменяется целиком, пустой
  стирает всех; права как у update() (менеджер свои, начальник любые); главный
  телефон карточки из поиска не трогается.
- ProspectContactsEditor.vue + utils/prospectContacts.ts — один редактор контактов
  на диалог создания и карточку; диалог создания переведён на него.
- Закрывает хвост §16: у 24 живых карточек из поиска контактных лиц не было,
  теперь дозаполняются руками.

Спека §18. Гейты: Pest 223/223 sales, Vitest 196 файлов / 1397 тестов,
vue-tsc чисто, Larastan 0 в своих файлах. TDD RED→GREEN на каждом шаге.

LEFTHOOK_EXCLUDE: larastan/cspell падают на файлах параллельной сессии
tests/Feature/Admin/*Balances*, свои файлы проверены отдельно и чисты.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@
2026-07-18 12:29:04 +03:00

42 lines
1.8 KiB
TypeScript

import type { ProspectContact } from '../api/sales';
/**
* Контактное лицо в форме: те же поля, но position всегда строка (v-model не любит null),
* а телефоны — редактируемый список с пустыми заготовками.
*/
export interface ContactForm {
name: string;
position: string;
phones: string[];
}
export function emptyContact(): ContactForm {
return { name: '', position: '', phones: [''] };
}
/** Из сохранённых контактов делаем форму. Пусто → одна пустая строка, чтобы было куда писать. */
export function toForm(contacts: ProspectContact[] | null | undefined): ContactForm[] {
if (!contacts || contacts.length === 0) return [emptyContact()];
return contacts.map((c) => ({
name: c.name ?? '',
position: c.position ?? '',
phones: c.phones && c.phones.length > 0 ? [...c.phones] : [''],
}));
}
/**
* Форма → то, что уходит на сервер: пустые телефоны выброшены, люди без имени
* и без телефонов не отправляются. Сервер делает то же самое — здесь это чтобы
* не гонять по сети заведомый мусор.
*/
export function cleanContacts(list: ContactForm[]): ProspectContact[] {
const out: ProspectContact[] = [];
for (const c of list) {
const name = c.name.trim();
const phones = c.phones.map((p) => p.trim()).filter((p) => p !== '');
if (name === '' && phones.length === 0) continue;
out.push({ name, position: c.position.trim() === '' ? null : c.position.trim(), phones });
}
return out;
}