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 / Talkytimes | Chat icebreakers мають moods Hot Talks, Real Love і Friendship та запускаються групою; Mail запускається окремо. Додавання фотографії залежить від права TU. |
| Chathouse | Окремий запуск Chat і Mail; до Mail можна додати фотографії та відео. Відхилені елементи показуються разом з причиною модерації. |
Golden використовує окремі Sender-фічі й не входить до цієї сторінки.
Логіка
- Після відкриття завантажується доступна для ролі структура TU та їхні статуси.
- Після вибору TU завантажуються її approved, hidden, in progress та on moderation icebreakers.
- Перемикач Chat / Mail фільтрує всі колонки за каналом, а заголовки колонок перемикають approved / hidden та in progress / on moderation.
- Після успішного створення, приховування або запуску поточний список TU оновлюється.
- Якщо запит завершився помилкою, сторінка зберігає доступний стан, показує повідомлення сервера або frontend fallback і дає повторити завантаження.
Обмеження
| Тип | Мінімум | Максимум |
|---|---|---|
| Chat | 1 символ | 300 символів |
| 150 символів | 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 не додають дозволів. Statushiddenвизначає лише напрямок 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 titleIcebreakers. 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 видалено. Історичний опис вище залишено лише для контексту й документації.
Зв’язки нового етапу
- Бек: getAllows у test Swagger, getIcebreakerList у test Swagger.
- Медіадозволи TU: getAllowsByTu у test Swagger.
- Not-found state: getNotFound у test Swagger, getNotFoundByTu у test Swagger.
- Створення: createIcebreaker у test Swagger, getMediaList у test Swagger.
- Дії картки: activateIcebreaker у test Swagger, hideIcebreaker у test Swagger, resolveSuggestedIcebreaker у test Swagger, remoderateIcebreaker у test Swagger.
- Group Launch: activateIcebreakerGroup у test Swagger.