icebreakers

Icebreakers

(UI-сторінка) — керування шаблонами першого контакту для TU у Family Udate, Prime/Talkytimes і Chathouse.

Меню Family → Icebreakers

Наведені нижче розділи до «TU Icebreakers» описують історичну legacy-поведінку лише для контексту. Після migration legacy implementation видалено; production routes використовують TU Icebreakers feature, описану наприкінці.

Суть

Сторінка показує TU з індикатором достатності icebreakers і дає переглядати, створювати, приховувати та запускати повідомлення для Chat і Mail. Списки розділені на approved, hidden, in progress та on moderation.

Use cases

  • supervisor (team lead) працює з TU своєї команди та контролює, чи достатньо для них активних icebreakers.
  • topManager переглядає TU через структуру team lead → operator → TU і виконує ті самі дії на рівні організації.

Family-відмінності

FamilyПоведінка
UdateОкремий запуск Chat і Mail; до Chat можна додати одну фотографію.
Prime / TalkytimesChat icebreakers мають moods Hot Talks, Real Love і Friendship та запускаються групою; Mail запускається окремо. Додавання фотографії залежить від права TU.
ChathouseОкремий запуск Chat і Mail; до Mail можна додати фотографії та відео. Відхилені елементи показуються разом з причиною модерації.

Golden використовує окремі Sender-фічі й не входить до цієї сторінки.

Логіка

  1. Після відкриття завантажується доступна для ролі структура TU та їхні статуси.
  2. Після вибору TU завантажуються її approved, hidden, in progress та on moderation icebreakers.
  3. Перемикач Chat / Mail фільтрує всі колонки за каналом, а заголовки колонок перемикають approved / hidden та in progress / on moderation.
  4. Після успішного створення, приховування або запуску поточний список TU оновлюється.
  5. Якщо запит завершився помилкою, сторінка зберігає доступний стан, показує повідомлення сервера або frontend fallback і дає повторити завантаження.

Обмеження

ТипМінімумМаксимум
Chat1 символ300 символів
Mail150 символів1000 символів
  • Створення недоступне, доки TU не вибрана.
  • Повторна дія блокується, доки попередній запит того самого типу не завершився.
  • Для Prime можливість додати фотографію визначається правами вибраної TU.

Стани

  • Під час першого завантаження показується loading state.
  • Без вибраної TU колонки пропонують вибрати TU.
  • Порожня колонка показує empty state для поточного каналу та режиму.
  • Після помилки завантаження доступна дія Retry.
  • Пізня відповідь для раніше вибраної TU не замінює дані поточної TU.

Нюанси

  • Усі шість комбінацій Family і ролі використовують одну реалізацію; family- та role-відмінності задаються конфігурацією, тому окремі role-specific копії не підтримуються.
  • Для Udate і Chathouse час останнього запуску зіставляється з активними icebreakers. У Chathouse береться найновіший запуск одного елемента.
  • Пошук на рівні top manager скидає поточний вибір TU; у team lead він лише фільтрує доступне дерево.

Зв’язки

TU Icebreakers

Shared feature src/features/tu_icebreakers підключена до production routes для Prime, Golden, Udate і Chathouse. Доступ обмежено ролями topManager і supervisor та доступними їм проєктами; приховані для top manager проєкти недоступні.

Use cases

  • Top manager або team lead вибирає TU зі спільної панелі, фільтрує icebreakers за каналом, типом і статусом та переглядає текст, moods, вкладення, статистику, причину відхилення й дати, які повернув сервер.
  • Повні тексти в Chat і Mail відображаються одразу, зі збереженням переносів рядків, без згортання та внутрішньої прокрутки тексту.
  • Користувач поступово завантажує наступні сторінки під час прокручування або кнопкою Load more; після локальної помилки може повторити запит.
  • Натискання на фото або відео в картці відкриває спільний переглядач медіа з вибраного вкладення. У ньому доступні всі вкладення айса, включно з прихованими за +N; для фото відкривається оригінал, якщо його URL доступний. Перемикання й закриття працюють через кнопки та клавіші зі стрілками й Escape.

Поведінка

  • Перша TU автоматично не вибирається. Зміна проєкту, Team lead або Operator скидає вибір TU; пошук лише фільтрує ліву панель.
  • Конфігурація каналів, типів і статусів завантажується один раз на відкриття проєкту. Помилка конфігурації показується праворуч із Retry; ліва панель залишається доступною.
  • Початково вибрані перші доступні канал, тип і статус. Зміна каналу скидає тип і статус; зміна типу зберігає статус, оскільки статуси належать каналу. Для проєкту без каналів перемикач Channel відсутній.
  • Аналітика картки показує Sent, Read і Replies за наявності даних. Conversion to answer та оцінка надходять із backend: фронт показує переданий відсоток без додаткового округлення, а текст статусу bad, normal або good відображає без змін, у регістрі backend. Формула, пороги й округлення належать backend; Sent, Read і Replies не використовуються для локального відновлення конверсії чи оцінки. Відсоток та оцінка відображаються незалежно за наявності валідних серверних значень, зокрема без лічильників; без обох значень показник відсутній. Для On moderation аналітика не відображається. Для Declined замість аналітики показується причина відмови; якщо причину не передано, відображається No decline reason provided.
  • Зміна TU або фільтра починає новий список. Завантаження наступної сторінки зберігає видимі картки, зокрема при помилці. Коротка або порожня сторінка не означає завершення списку: його визначає лише кінцевий cursor сервера.
  • Повторений cursor блокує подальший автоматичний запит; Retry починає завантаження списку заново. Пізні відповіді попереднього вибору ігноруються.

Проблемні TU: другий етап

  • Під час відкриття проєкту окремо завантажуються project-level not-found records. Вибір TU, зміна фільтрів і pagination не повторюють цей запит.
  • TU із records позначаються знаком оклику на аватарці та червоним підсвічуванням рядка у списку. При наведенні на рядок TU або фокусі з клавіатури спільний tooltip показує, яких типів айсбрікерів не вистачає, наприклад Not enough message icebreakers. Повторні повідомлення не дублюються; для невідомого типу показується Not enough icebreakers. Без records tooltip відсутній. Вибрана проблемна TU зберігає підсвічування та додатково позначається бічною смугою. Повні records зберігаються за TU ID; зміна проєкту очищає попередні дані й ігнорує пізні відповіді.
  • Помилка завантаження issues показується поруч зі списком із Retry та не блокує TU Directory, permissions або перегляд icebreakers.
  • Точковий refresh через getNotFoundByTu повністю замінює records однієї TU. Порожня відповідь прибирає badge; помилка зберігає попередні records. Після успішної mutation оновлюються records саме тієї TU, яку було змінено.

Створення: третій етап

  • Натискання на фото або відео в медіапікері відкриває спільний переглядач; для фото показується оригінал. Перегляд не змінює вибір вкладень: окрема позначка на плитці додає або прибирає медіа. Досягнення ліміту блокує лише додавання, а перегляд і зняття вибору залишаються доступними. Escape закриває перегляд і повертає до заповненої форми створення.

  • Create показується лише за getAllows.canCreate активного каналу й працює для вибраної TU та поточного Ice type. Status не визначає permission або target створення; Channel і Type у modal показуються без повторного вибору.

  • Текст нормалізується за правилами Golden Sender; валідація й payload використовують однаковий normalized text. Межі довжини беруться з getAllows для поточного Ice type і мають пріоритет над статичними межами DTO. Зміна Type застосовує нові межі незалежно від Channel. Відсутні чи некоректні межі блокують Create без frontend fallback.

  • Moods надходять із getAllows; для Prime Chat потрібен хоча б один mood. Без доступних moods відповідний UI відсутній.

  • Picker отримує лише approved media категорії default вибраної TU через shared TU Media v2 API, без перемикача категорій та upload. Attachment capability визначають permissions поточного Ice type; photo/video limits застосовуються окремо. Вибір зберігається при перемиканні media type та incremental pagination; media query errors показуються локально з Retry.

  • Під час submit повторний запит і випадкове закриття modal блокуються. Зміна TU, Channel або Type закриває та скидає форму.

  • Успішне створення закриває modal і показує success notification. Поточний Ice list оновлюється з першої сторінки без приховування старих карток; паралельно getNotFoundByTu оновлює badge конкретної TU. Помилки цих допоміжних запитів не змінюють успішний результат Create: list error має inline Retry, а попередній badge зберігається при помилці refresh.

Дії картки та countdown: четвертий етап

  • У Suggested відхилені moods сірі, причина невідповідності має жовте попередження, а запропоновані moods показані окремо з діями Assign new moods / Reject new moods за canSuggest.
  • Базові дії картки визначає ice.allows: canActivate показує Activate, canHide — Hide або Restore, canSuggest — Accept і Reject, canRemoderate — Remoderate. Додаткова перевірка медіадозволів TU може заборонити Activate для медіаайса, але не додає нових дозволів. Project, роль, Channel, Status і context-level permissions не додають дозволів. Status hidden визначає лише напрямок Hide/Restore. Без дозволених дій блок кнопок відсутній; Group Launch є окремою дією в header.
  • Activate запускає icebreaker; Hide приховує його, Restore повертає у відповідний список. Accept/Reject приймають або відхиляють suggestion; Remoderate надсилає icebreaker на повторну модерацію. Подальший стан картки визначає backend після оновлення списку.
  • Поки mutation виконується, усі action buttons відповідної картки недоступні; повторні й конфліктні запити цієї картки блокуються. Різні картки можуть виконувати mutations паралельно. Після виходу зі сторінки пізні відповіді не показують notifications.
  • Create та всі дії картки використовують спільне оновлення після успіху: success notification, reload поточного Ice list з першої сторінки та refresh not-found records зміненої TU. Якщо під час запиту змінено TU або Status, reload використовує актуальний вибір; refresh badges стосується TU, яку змінила mutation. Картки не переносяться між списками вручну.
  • Помилка mutation показує backend message або повне fallback-речення й не запускає reload чи refresh badges. Якщо mutation успішна, помилка подальшого reload не скасовує успіх: картки зберігаються, а inline error має Retry. Помилка refresh badges зберігає попередні records і також не змінює результат mutation.
  • Countdown з’являється лише для in_progress із валідним dateActivated. Для всіх projects строк становить рівно 24 години від активації; час оновлюється приблизно щосекунди й після завершення показує Time is up!. Відсутня, порожня чи некоректна дата не запускає countdown; дата створення й legacy timestamps не використовуються. Завершення countdown не запускає polling або автоматичний reload.

Group Launch: п’ятий етап

  • Group Launch розміщено в header actions поруч із Create. Кнопка доступна для вибраної TU й валідних Channel/Type лише за getAllows.canActivateGroup активного каналу. Назва проєкту, роль, поточний Status і наявність карток у main list не визначають capability; фактичну доступність вирішує backend.
  • Modal використовує поточні TU, Project, Channel і Type без нових selectors. Зміна TU, Channel, Type або Project закриває та скидає modal, скасовує candidate requests і незавершену group mutation. Пізні відповіді не показують notifications і не запускають refresh.
  • При відкритті modal завантажуються лише approved icebreakers, сторінками по 100 до кінця cursors. Помилка сторінки або повторення cursor блокує весь список кандидатів; доступний inline Retry.
  • Записи відповіді зберігаються без дедуплікації, зокрема однакові Ice ID з різними moods. Кандидати Group Launch мають ice.allows.canActivateGroup; їхній список завантажується окремо від main list.
  • Moods надходять із getAllows. Кожен блок показує лише Ice з відповідним mood. Для запуску потрібен один Ice на кожен mood; refresh скидає вибір, якщо Ice зник або більше не містить цього mood.
  • Кандидати показані в окремих блоках moods, які можна згортати без скидання вибору. Блоки спочатку згорнуті; їхні заголовки показують, чи вибрано Ice, та залишаються доступними під час прокрутки розгорнутого списку. У modal одна область прокрутки кандидатів, а шапка та кнопки Refresh candidates, Cancel і Launch залишаються поза нею.
  • Один Ice можна вибрати для кількох moods, якщо він містить кожен із них. Без кандидатів для mood показується порожній стан, Launch недоступний.
  • Якщо capability дозволена, але moods відсутні, modal показує configuration error й не дозволяє submit.
  • Launch відправляє одну group activation для TU з обраними парами Ice/mood. Під час submit повторний запит, зміна selections і випадкове закриття modal блокуються. Помилка mutation зберігає modal і selections, показує backend message або Failed to activate the icebreaker group. та не запускає допоміжних запитів.
  • Успіх закриває modal й показує Icebreaker group activated.; далі спільний post-success flow оновлює актуальний main query з першої сторінки та not-found records зміненої TU. Зміна Status під час group mutation не змінює candidates і враховується при main reload. Помилки reload, refresh badges або допоміжного success callback не скасовують mutation success і не створюють другого error toast.

Медіадозволи конкретної TU

  • Нова поведінка наразі призначена для Prime, але вмикається прапорцем backend без обмеження за Family. Якщо перевірка дозволів TU вимкнена або прапорець відсутній, зберігається попередня поведінка без додаткового запиту чи попередження.
  • При відкритті TU завантажуються її медіадозволи для всіх Ice type. Вони мають пріоритет над статичними медіадозволами проєкту; канали, типи, текстові ліміти, moods і базові можливості залишаються із загальної конфігурації. Зміна Type або Status не повторює запит. Зміна TU чи Project скидає попередні дозволи й ігнорує пізні відповіді.
  • Створення і відправка мають незалежні медіадозволи. Доступні вкладення визначають види медіа та окремі photo/video limits під час створення. Відсутній тип, відсутні вкладення або нульові ліміти не дозволяють додавати медіа: picker приховано, запит списку медіа не виконується. Текстове створення залишається доступним за чинними правилами.
  • Заборона відправки з медіа не заважає створенню з дозволеними вкладеннями. У шапці відкритої TU для поточного Ice type показується компактне попередження Sending icebreakers with media is unavailable. У звичайному списку медіаайси залишаються видимими, але Activate для них недоступний; інші дозволені дії збережено.
  • Group Launch виключає медіаайси за заборони відправки з медіа. Текстові кандидати зберігаються за чинними правилами. Недоступний вибір скидається й не може потрапити до запиту запуску; без кандидата для обов’язкового mood Launch недоступний. Якщо відправку медіа дозволено, ліміти створення не відсіюють уже створені айси.
  • Поки медіадозволи завантажуються або їх не вдалося отримати, перегляд і текстові дії доступні, а додавання та відправка медіа заблоковані без статичного fallback. У шапці показується стан перевірки або помилка з Retry; вони не позначаються як підтверджена заборона. Відсутній у відповіді Ice type не отримує медіадозволів.

Golden Icebreakers є окремою feature від Golden Sender.

Production integration

  • Існуючі Icebreakers routes і menu links Udate, Prime та Chathouse для top manager і team lead тепер відкривають TU Icebreakers. URL збережено: /top_manager/{udate|talkytimes|chathouse}/icebreakers та /teamlead/{udate|talkytimes|chathouse}/icebreakers; Prime продовжує використовувати сегмент talkytimes.
  • Golden отримав окремі /top_manager/golden/icebreakers і /teamlead/golden/icebreakers, menu item та page title Icebreakers. Golden Sender routes і menu items залишаються окремими та без змін.
  • Використовується одна shared page. Family visibility top manager, FamilyRouteGuard team lead та власна перевірка доступу page збережені; доступ для інших ролей не додано.
  • Production migration завершена; dead legacy Icebreakers implementation разом із його adapters, components, hooks, styles, tests і route wrappers видалено. Історичний опис вище залишено лише для контексту й документації.

Зв’язки нового етапу