Files
call-center/ui/operator/index.html
T

763 lines
46 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="ru">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>KonturCC Оператор</title>
<link rel="icon" href="/operator/assets/favicon.svg" type="image/svg+xml" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Manrope:wght@500;600;700;800&family=IBM+Plex+Sans:wght@400;500;600&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="/operator/assets/styles.css?v=track25-messenger-polish1" />
</head>
<body>
<div class="app-shell">
<aside class="sidebar">
<div class="brand">
<div class="brand-mark">K</div>
<div>
<div class="brand-title">KonturCC</div>
<div class="brand-sub">Омниканальный контур</div>
</div>
</div>
<nav class="nav-menu">
<div class="nav-group">
<div class="nav-label">Рабочие зоны</div>
<a class="nav-link" data-shell="supervisor" data-roles="admin,supervisor" href="/supervisor"><span class="nav-bullet"></span>Супервизор</a>
<a class="nav-link" data-shell="analyst" data-roles="admin,supervisor,analyst" href="/analyst"><span class="nav-bullet"></span>Аналитика</a>
<a class="nav-link" data-shell="admin" data-roles="admin" href="/admin"><span class="nav-bullet"></span>Администрирование</a>
<a class="nav-link" data-shell="sales" data-roles="admin,supervisor,operator,analyst" href="/sales"><span class="nav-bullet"></span>Продажи</a>
</div>
<div class="nav-group">
<div class="nav-label">Страницы</div>
<a class="nav-link active" data-operator-view-link="workspace" href="#workspace"><span class="nav-bullet"></span>Рабочий стол</a>
<a class="nav-link" data-operator-view-link="messages" href="#messages"><span class="nav-bullet"></span>Сообщения</a>
<a class="nav-link" data-operator-view-link="customers" href="#customers-page"><span class="nav-bullet"></span>Клиенты</a>
<a class="nav-link" data-debug-channel="telegram" href="#telegram-page" hidden><span class="nav-bullet"></span>Telegram</a>
<a class="nav-link" data-debug-channel="whatsapp" href="#whatsapp-page" hidden><span class="nav-bullet"></span>WhatsApp</a>
<a class="nav-link" data-operator-view-link="calls" data-roles="admin,operator" href="#calls"><span class="nav-bullet"></span>Звонки</a>
</div>
</nav>
<div class="sidebar-footer">
<strong>Операторский экран</strong>
<p>Показывает единый контур: клиент, обращение, каналы, база знаний и voice lifecycle.</p>
<button id="logoutBtn" class="btn ghost" type="button">Выйти</button>
</div>
</aside>
<section class="workspace">
<header class="workspace-topbar reveal">
<div class="search-box">
<input class="app-search" placeholder="Найти клиента, обращение или канал..." />
</div>
<div class="topbar-actions">
<div class="status-pill" id="gatewayStatus">Шлюз: проверка...</div>
<div class="phone-entrypoint">
<button id="browserPhoneStatusBtn" class="phone-chip" type="button" aria-label="Состояние браузерного телефона" aria-expanded="false" data-state="offline">
<span class="phone-chip-dot" id="browserPhoneStatusDot"></span>
<span class="phone-chip-copy">
<span class="phone-chip-title">Телефон</span>
<span class="phone-chip-status" id="browserPhoneStatusLabel">Не подключен</span>
</span>
</button>
<div id="browserPhoneSettingsPanel" class="phone-settings hidden">
<div class="softphone-summary compact">
<div class="softphone-status-block">
<div class="softphone-status-label">Регистрация</div>
<div class="softphone-status-value" id="browserPhoneRegistrationState">Не настроен</div>
</div>
<div class="softphone-status-block">
<div class="softphone-status-label">Внутренний номер оператора</div>
<div class="softphone-status-value" id="browserPhoneOperatorExtension"></div>
</div>
<div class="softphone-status-block">
<div class="softphone-status-label">WSS</div>
<div class="softphone-status-value" id="browserPhoneWsUrl"></div>
</div>
</div>
<div class="inline-form compact phone-settings-actions">
<button id="browserPhoneConnectBtn" class="btn" type="button">Подключить телефон</button>
<button id="browserPhoneDisconnectBtn" class="btn ghost" type="button">Отключить</button>
</div>
<div class="inline-form split-two">
<div class="row stacked">
<label for="browserPhoneMicSelect">Микрофон</label>
<select id="browserPhoneMicSelect"></select>
</div>
<div class="row stacked">
<label for="browserPhoneSpeakerSelect">Динамик</label>
<select id="browserPhoneSpeakerSelect"></select>
</div>
</div>
<p class="hint" id="browserPhoneHint">Браузерный телефон выключен или не настроен.</p>
</div>
</div>
<button class="icon-button" type="button" aria-label="Уведомления"></button>
<div class="profile-chip">
<div class="avatar-badge">OP</div>
<div class="profile-meta">
<div class="profile-name" id="profileName">Экран оператора</div>
<div class="profile-role" id="profileRole">Основной сценарий</div>
</div>
</div>
</div>
</header>
<main class="layout">
<section id="workspaceView" class="operator-view" data-operator-view="workspace">
<section class="page-hero reveal">
<h1>Операторский пульт v2</h1>
</section>
<section class="panel auth reveal" id="authPanel">
<h2>Сессия</h2>
<div class="row">
<label>Пользователь</label>
<input id="sessionUser" value="admin" />
</div>
<div class="row">
<label>Роль</label>
<select id="sessionRole">
<option value="admin" selected>Администратор</option>
<option value="supervisor">Супервизор</option>
<option value="operator">Оператор</option>
<option value="analyst">Аналитик</option>
</select>
</div>
<div class="row">
<label>Пароль</label>
<input id="sessionPassword" type="password" value="admin123" />
</div>
<div class="actions">
<button id="loginBtn" class="btn">Войти</button>
<button id="corporateLoginBtn" class="btn ghost" type="button">Корпоративный вход</button>
<button id="refreshBtn" class="btn ghost">Обновить всё</button>
</div>
<p class="hint" id="sessionInfo">Токен: отсутствует</p>
</section>
<section class="grid">
<article class="panel reveal panel-span-full unified-inbox-panel" id="unifiedInbox">
<div class="unified-inbox-head">
<div>
<h2>Единая очередь</h2>
<p class="hint">Новые задачи, мои диалоги, AI handoff, эскалации и живые звонки в одном месте.</p>
</div>
<button id="refreshUnifiedInboxBtn" class="btn ghost" type="button">Обновить очередь</button>
</div>
<div id="unifiedInboxSummary" class="summary-grid"></div>
<div id="unifiedInboxBoard" class="unified-inbox-scroll"></div>
</article>
<article class="panel reveal panel-span-full" id="interactions">
<h2>Обращения</h2>
<div class="inline-form">
<select id="interactionChannel">
<option value="voice">Голос</option>
<option value="telegram">Telegram</option>
<option value="whatsapp" data-feature-option="whatsapp" hidden disabled>WhatsApp</option>
<option value="webchat">Веб-чат</option>
<option value="email">Электронная почта</option>
</select>
<input id="interactionSubject" placeholder="Тема обращения" />
<input id="interactionCustomerId" placeholder="ID клиента" />
<button id="createInteractionBtn" class="btn">Создать</button>
</div>
<div class="inline-form split-two">
<input id="defaultAssignee" value="operator_a" placeholder="Исполнитель по умолчанию" />
<input id="defaultEscalationQueue" value="line2" placeholder="Очередь 2 линии" />
</div>
<div class="inline-form compact">
<button id="loadInteractionsBtn" class="btn ghost">Загрузить список</button>
</div>
<div id="interactionTable" class="table"></div>
</article>
</section>
</section>
<section id="messagesView" class="operator-view hidden" data-operator-view="messages">
<article class="panel reveal panel-span-full messenger-panel" id="messengerWorkspace">
<div class="messenger-layout">
<aside class="messenger-list-pane">
<div class="messenger-pane-head">
<div>
<p class="eyebrow">Unified messenger</p>
<h2>Сообщения</h2>
<p class="hint">Единое окно для Telegram сейчас и WhatsApp позже.</p>
</div>
<button id="messengerRefreshBtn" class="btn ghost" type="button">Повторить</button>
</div>
<div class="messenger-filters" aria-label="Фильтры сообщений">
<button class="messenger-filter active" data-messenger-filter="all" type="button">Все</button>
<button class="messenger-filter" data-messenger-filter="new" type="button">Новые</button>
<button class="messenger-filter" data-messenger-filter="mine" type="button">Мои</button>
<button class="messenger-filter" data-messenger-filter="ai" type="button">AI handoff</button>
</div>
<div id="messengerConversationList" class="messenger-conversation-list"></div>
</aside>
<section class="messenger-chat-pane">
<header class="messenger-chat-header">
<div class="messenger-chat-identity">
<div id="messengerConversationAvatar" class="telegram-thread-avatar">TG</div>
<div class="messenger-chat-copy">
<div id="messengerConversationTitle" class="messenger-chat-title">Выберите диалог</div>
<div id="messengerConversationMeta" class="messenger-chat-meta">Выберите диалог слева.</div>
</div>
</div>
<div class="messenger-chat-actions">
<span id="messengerChannelBadge" class="messenger-channel-badge">Telegram</span>
<button id="messengerClaimBtn" class="btn ghost" type="button">Взять в работу</button>
<button id="messengerCloseBtn" class="btn ghost" type="button">Закрыть</button>
</div>
</header>
<section id="messengerAiSummaryCard" class="telegram-ai-summary messenger-ai-summary hidden">
<div class="telegram-ai-summary-head">
<div>
<div class="telegram-ai-summary-title">AI summary</div>
<div class="telegram-ai-summary-caption">Короткий контекст перед ручным ответом.</div>
</div>
<div class="telegram-ai-summary-side">
<div id="messengerAiSummaryStatus"></div>
<div id="messengerAiSummaryMeta" class="telegram-ai-summary-meta"></div>
</div>
</div>
<div id="messengerAiSummaryContent" class="telegram-ai-summary-grid"></div>
</section>
<div id="messengerBackendError" class="messenger-error hidden">
<span>Backend сообщений недоступен.</span>
<button id="messengerRetryBtn" class="btn ghost" type="button">Повторить</button>
</div>
<div class="messenger-chat-surface">
<div id="messengerMessagesTimeline" class="telegram-message-timeline messenger-message-timeline"></div>
</div>
<footer class="messenger-composer-wrap">
<div class="telegram-composer-shell messenger-composer-shell">
<textarea id="messengerReplyText" placeholder="Написать ответ клиенту..."></textarea>
<button id="messengerSendReplyBtn" class="telegram-send-btn" type="button" aria-label="Отправить">
<svg viewBox="0 0 24 24" aria-hidden="true">
<path d="M21 3 3.9 10.09a1 1 0 0 0 .06 1.87l6.5 2.27 2.27 6.5a1 1 0 0 0 1.87.06L21 3Z" />
<path d="M10.5 14.5 21 3" />
</svg>
</button>
</div>
<div id="messengerComposerHint" class="telegram-composer-hint">Ответ доступен после выбора и принятия диалога в работу.</div>
</footer>
</section>
<aside class="messenger-context-pane">
<div class="messenger-context-card">
<p class="eyebrow">Клиент</p>
<h3 id="messengerContextName">Диалог не выбран</h3>
<dl class="messenger-context-list">
<div>
<dt>Канал</dt>
<dd id="messengerContextChannel">Telegram</dd>
</div>
<div>
<dt>Статус</dt>
<dd id="messengerContextStatus"></dd>
</div>
<div>
<dt>Клиент</dt>
<dd id="messengerContextCustomer"></dd>
</div>
<div>
<dt>Обращение</dt>
<dd id="messengerContextInteraction"></dd>
</div>
</dl>
<button id="messengerOpenProfileBtn" class="btn" type="button">Открыть профиль</button>
</div>
<div class="messenger-context-card compact">
<p class="eyebrow">Последнее сообщение</p>
<p id="messengerContextPreview" class="messenger-context-preview">Выберите диалог слева.</p>
</div>
<div class="messenger-context-card compact">
<p class="eyebrow">AI summary</p>
<p id="messengerContextAiSummary" class="messenger-context-preview">Сводка появится после AI handoff.</p>
</div>
<div class="messenger-context-card compact">
<p class="eyebrow">Быстрые действия</p>
<button id="messengerContextOpenProfileBtn" class="btn ghost" type="button">Профиль клиента</button>
</div>
</aside>
</div>
</article>
</section>
<section id="customersView" class="operator-view hidden" data-operator-view="customers">
<section class="page-hero reveal customers-page-hero">
<h1>Список лидов</h1>
<p class="hint">База всех входящих и активных лидов.</p>
</section>
<article class="panel reveal panel-span-full customers-panel" id="customers">
<div class="customers-toolbar">
<div class="customers-toolbar-left">
<div class="customers-search">
<span class="customers-search-icon"></span>
<input id="customerQuery" placeholder="Поиск по имени или телефону..." />
</div>
</div>
<div class="customers-toolbar-right">
<button id="exportCustomersBtn" class="btn ghost" type="button">⇩ Экспорт CSV</button>
<button id="toggleCustomerLeadFormBtn" class="btn" type="button"> Добавить лид</button>
</div>
</div>
<div id="customerLeadForm" class="customer-lead-form hidden">
<div class="inline-form">
<input id="customerName" placeholder="Имя контакта" />
<input id="customerPhone" placeholder="Телефон" />
<button id="createCustomerBtn" class="btn" type="button">Сохранить лид</button>
<button id="customerCancelBtn" class="btn ghost" type="button">Отмена</button>
</div>
</div>
<div id="customerList" class="lead-table-shell"></div>
<div class="customers-footer">
<div id="customerPageSummary" class="customers-summary">Пока нет лидов.</div>
<div class="customers-pager">
<button id="customerPrevPageBtn" class="icon-button" type="button" aria-label="Предыдущая страница"></button>
<button id="customerNextPageBtn" class="icon-button" type="button" aria-label="Следующая страница"></button>
</div>
</div>
</article>
</section>
<section id="customerProfileView" class="operator-view hidden" data-operator-view="customer-profile">
<section class="page-hero reveal customers-page-hero customer-profile-page-hero">
<div class="page-hero-actions">
<button id="customerProfileBackBtn" class="btn ghost" type="button">&larr; К списку клиентов</button>
</div>
<h1 id="customerProfileTitle">Профиль клиента</h1>
<p id="customerProfileHint" class="hint">Единый профиль клиента и вся история его контактов в одном месте.</p>
</section>
<article class="panel reveal panel-span-full customer-profile-page-panel">
<section id="customerProfileContent" class="customer-spotlight-shell customer-spotlight-page">
<div class="customer-spotlight-empty">
<strong>Выберите клиента</strong>
<p>Откройте карточку из списка клиентов, чтобы увидеть профиль и историю.</p>
</div>
</section>
</article>
</section>
<section id="telegramView" class="operator-view hidden" data-operator-view="telegram">
<article class="panel reveal panel-span-full telegram-panel" id="telegramWorkspace">
<div class="telegram-layout">
<aside class="telegram-threads-pane">
<div class="telegram-pane-head">
<button class="telegram-pane-icon-btn" type="button" aria-label="Меню" disabled>
<svg viewBox="0 0 24 24" aria-hidden="true">
<path d="M4 7.25h16M4 12h16M4 16.75h16" />
</svg>
</button>
<div class="telegram-thread-search">
<span class="telegram-thread-search-icon" aria-hidden="true">
<svg viewBox="0 0 24 24">
<circle cx="11" cy="11" r="6.5" />
<path d="m16 16 4.5 4.5" />
</svg>
</span>
<input id="telegramThreadSearch" placeholder="Поиск" />
</div>
<button id="loadTelegramThreadsBtn" class="telegram-pane-icon-btn" type="button" aria-label="Обновить">
<svg viewBox="0 0 24 24" aria-hidden="true">
<path d="M20 12a8 8 0 1 1-2.34-5.66M20 4v6h-6" />
</svg>
</button>
</div>
<div id="telegramThreadsList" class="telegram-thread-list"></div>
</aside>
<section class="telegram-chat-pane">
<header class="telegram-chat-header">
<div class="telegram-thread-identity">
<div id="telegramThreadAvatar" class="telegram-thread-avatar">TG</div>
<div class="telegram-thread-copy">
<div id="telegramThreadDisplayName" class="telegram-thread-title">Выберите диалог</div>
<div class="telegram-thread-meta-row">
<div id="telegramThreadMeta" class="telegram-thread-meta">Выберите диалог слева.</div>
<span id="telegramThreadAiChip" class="telegram-thread-ai-chip hidden">AI активен</span>
</div>
</div>
</div>
<div class="telegram-chat-actions">
<button id="telegramHeaderSearchBtn" class="telegram-chat-icon-btn" type="button" aria-label="Поиск">
<svg viewBox="0 0 24 24" aria-hidden="true">
<circle cx="11" cy="11" r="6.5" />
<path d="m16 16 4.5 4.5" />
</svg>
</button>
<button id="telegramHeaderCallBtn" class="telegram-chat-icon-btn" type="button" aria-label="Звонок">
<svg viewBox="0 0 24 24" aria-hidden="true">
<path d="M5.5 4.5h3l1.4 3.6-1.7 1.7a15.4 15.4 0 0 0 6 6l1.7-1.7 3.6 1.4v3a1.5 1.5 0 0 1-1.5 1.5A15.5 15.5 0 0 1 4 6A1.5 1.5 0 0 1 5.5 4.5Z" />
</svg>
</button>
<button id="telegramHeaderMenuBtn" class="telegram-chat-icon-btn" type="button" aria-label="Действия">
<svg viewBox="0 0 24 24" aria-hidden="true">
<circle cx="12" cy="5" r="1.5" />
<circle cx="12" cy="12" r="1.5" />
<circle cx="12" cy="19" r="1.5" />
</svg>
</button>
</div>
</header>
<div id="telegramMessageSearchBar" class="telegram-message-search hidden">
<div class="telegram-message-search-field">
<span class="telegram-thread-search-icon" aria-hidden="true">
<svg viewBox="0 0 24 24">
<circle cx="11" cy="11" r="6.5" />
<path d="m16 16 4.5 4.5" />
</svg>
</span>
<input id="telegramMessageSearch" placeholder="Поиск по чату" />
</div>
<div id="telegramMessageSearchMeta" class="telegram-message-search-meta">Поиск по текущему чату</div>
<button id="telegramMessageSearchClearBtn" class="telegram-message-search-clear" type="button">Закрыть</button>
</div>
<div id="telegramOperatorTray" class="telegram-operator-tray hidden">
<div class="telegram-operator-meta">
<span id="telegramThreadPresenceChip" class="telegram-operator-chip free">свободен</span>
<span id="telegramThreadOwnerChip" class="telegram-operator-chip subtle">владелец —</span>
</div>
<div class="telegram-operator-controls">
<button id="telegramClaimThreadBtn" class="telegram-operator-action" type="button">В работу</button>
<button id="telegramReturnToAiBtn" class="telegram-operator-action subtle" type="button">Вернуть AI</button>
<button id="telegramCloseThreadBtn" class="telegram-operator-action subtle" type="button">Закрыть</button>
<input id="telegramEscalationQueue" class="telegram-operator-input" placeholder="line2" />
<button id="telegramEscalateThreadBtn" class="telegram-operator-action subtle" type="button">Эскалация</button>
</div>
</div>
<section id="telegramAiSummaryCard" class="telegram-ai-summary hidden">
<div class="telegram-ai-summary-head">
<div>
<div class="telegram-ai-summary-title">Сводка AI</div>
<div class="telegram-ai-summary-caption">Краткая сводка для оператора перед ручным ответом.</div>
</div>
<div class="telegram-ai-summary-side">
<div id="telegramAiSummaryStatus"></div>
<div id="telegramAiSummaryMeta" class="telegram-ai-summary-meta"></div>
</div>
</div>
<div id="telegramAiSummaryContent" class="telegram-ai-summary-grid"></div>
</section>
<div class="telegram-chat-surface">
<div id="telegramMessagesTimeline" class="telegram-message-timeline"></div>
</div>
<footer class="telegram-composer-wrap">
<div class="telegram-composer-shell">
<button class="telegram-composer-icon-btn" type="button" aria-label="Вложение" disabled>
<svg viewBox="0 0 24 24" aria-hidden="true">
<path d="m9.5 12.5 5.94-5.94a3 3 0 1 1 4.24 4.24l-8.48 8.48a5 5 0 0 1-7.07-7.07l8.13-8.13" />
</svg>
</button>
<textarea id="telegramReplyText" placeholder="Написать сообщение..."></textarea>
<button class="telegram-composer-icon-btn" type="button" aria-label="Эмодзи">
<svg viewBox="0 0 24 24" aria-hidden="true">
<circle cx="12" cy="12" r="9" />
<path d="M8.5 14.5c.8 1.2 2 2 3.5 2s2.7-.8 3.5-2" />
<circle cx="9" cy="10" r="1" />
<circle cx="15" cy="10" r="1" />
</svg>
</button>
<button id="telegramSendReplyBtn" class="telegram-send-btn" type="button" aria-label="Отправить">
<svg viewBox="0 0 24 24" aria-hidden="true">
<path d="M21 3 3.9 10.09a1 1 0 0 0 .06 1.87l6.5 2.27 2.27 6.5a1 1 0 0 0 1.87.06L21 3Z" />
<path d="M10.5 14.5 21 3" />
</svg>
</button>
</div>
<div id="telegramComposerHint" class="telegram-composer-hint">Ответ доступен после принятия в работу или для admin/supervisor.</div>
</footer>
</section>
</div>
</article>
</section>
<section id="whatsappView" class="operator-view hidden" data-operator-view="whatsapp" data-feature="whatsapp" hidden>
<article class="panel reveal panel-span-full whatsapp-panel" id="whatsappWorkspace">
<div class="whatsapp-shell">
<aside class="whatsapp-nav-rail" aria-label="WhatsApp navigation">
<div class="whatsapp-rail-group">
<button class="whatsapp-rail-btn active" type="button" aria-label="Чаты" data-whatsapp-ui-action="chats">
<svg viewBox="0 0 24 24" aria-hidden="true">
<path d="M5.5 6.5h13a2 2 0 0 1 2 2v7a2 2 0 0 1-2 2H10l-4.5 3v-3H5.5a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2Z" />
</svg>
</button>
<button class="whatsapp-rail-btn" type="button" aria-label="Статус" data-whatsapp-ui-action="status">
<svg viewBox="0 0 24 24" aria-hidden="true">
<circle cx="12" cy="12" r="8.25" />
<path d="M12 7.75v4.5l3 1.75" />
</svg>
</button>
<button class="whatsapp-rail-btn" type="button" aria-label="Channels" data-whatsapp-ui-action="channels">
<svg viewBox="0 0 24 24" aria-hidden="true">
<path d="M4.5 8.5a7.5 7.5 0 0 1 15 0" />
<path d="M7 12a5 5 0 0 1 10 0" />
<path d="M9.5 15.5a2.5 2.5 0 0 1 5 0" />
</svg>
</button>
</div>
<div class="whatsapp-rail-footer">
<button class="whatsapp-rail-btn" type="button" aria-label="Настройки" data-whatsapp-ui-action="settings">
<svg viewBox="0 0 24 24" aria-hidden="true">
<path d="M12 8.5a3.5 3.5 0 1 1 0 7 3.5 3.5 0 0 1 0-7Z" />
<path d="M19.4 13.5a1 1 0 0 0 .2 1.1l.1.1a1 1 0 0 1 0 1.4l-1 1a1 1 0 0 1-1.4 0l-.1-.1a1 1 0 0 0-1.1-.2 1 1 0 0 0-.6.9V19a1 1 0 0 1-1 1h-1.4a1 1 0 0 1-1-1v-.1a1 1 0 0 0-.7-.9 1 1 0 0 0-1 .2l-.1.1a1 1 0 0 1-1.4 0l-1-1a1 1 0 0 1 0-1.4l.1-.1a1 1 0 0 0 .2-1.1 1 1 0 0 0-.9-.6H5a1 1 0 0 1-1-1v-1.4a1 1 0 0 1 1-1h.1a1 1 0 0 0 .9-.7 1 1 0 0 0-.2-1l-.1-.1a1 1 0 0 1 0-1.4l1-1a1 1 0 0 1 1.4 0l.1.1a1 1 0 0 0 1 .2 1 1 0 0 0 .6-.9V5a1 1 0 0 1 1-1h1.4a1 1 0 0 1 1 1v.1a1 1 0 0 0 .7.9 1 1 0 0 0 1.1-.2l.1-.1a1 1 0 0 1 1.4 0l1 1a1 1 0 0 1 0 1.4l-.1.1a1 1 0 0 0-.2 1 1 1 0 0 0 .9.6H19a1 1 0 0 1 1 1v1.4a1 1 0 0 1-1 1h-.1a1 1 0 0 0-.9.7Z" />
</svg>
</button>
<div class="whatsapp-rail-avatar" aria-hidden="true">OP</div>
</div>
</aside>
<aside class="whatsapp-list-pane">
<header class="whatsapp-list-head">
<div class="whatsapp-pane-title-wrap">
<div class="whatsapp-pane-title">WhatsApp</div>
<div id="whatsappPaneCaption" class="whatsapp-pane-caption">Держите телефон подключённым</div>
</div>
<div class="whatsapp-list-actions">
<button class="whatsapp-icon-btn" type="button" aria-label="Новый чат" data-whatsapp-ui-action="new-chat">
<svg viewBox="0 0 24 24" aria-hidden="true">
<path d="M12 5v14M5 12h14" />
</svg>
</button>
<button class="whatsapp-icon-btn" type="button" aria-label="Меню" data-whatsapp-ui-action="menu">
<svg viewBox="0 0 24 24" aria-hidden="true">
<circle cx="12" cy="5" r="1.5" />
<circle cx="12" cy="12" r="1.5" />
<circle cx="12" cy="19" r="1.5" />
</svg>
</button>
</div>
</header>
<div class="whatsapp-search-wrap">
<div class="whatsapp-search-field">
<span class="whatsapp-search-icon" aria-hidden="true">
<svg viewBox="0 0 24 24">
<circle cx="11" cy="11" r="6.5" />
<path d="m16 16 4.5 4.5" />
</svg>
</span>
<input id="whatsappSearchInput" type="search" placeholder="Поиск или новый чат" />
</div>
<div id="whatsappFilterBar" class="whatsapp-filter-bar" role="tablist" aria-label="Фильтры чатов">
<button class="whatsapp-filter-chip active" type="button" data-whatsapp-filter="all">Все</button>
<button class="whatsapp-filter-chip" type="button" data-whatsapp-filter="unread">Непрочитанные</button>
<button class="whatsapp-filter-chip" type="button" data-whatsapp-filter="groups">Группы</button>
</div>
</div>
<div id="whatsappChatList" class="whatsapp-chat-list"></div>
</aside>
<section class="whatsapp-chat-pane">
<header class="whatsapp-chat-head">
<div class="whatsapp-chat-identity">
<div id="whatsappChatAvatar" class="whatsapp-chat-avatar">WA</div>
<div class="whatsapp-chat-copy">
<div id="whatsappChatTitle" class="whatsapp-chat-title">WhatsApp</div>
<div id="whatsappChatMeta" class="whatsapp-chat-meta">Выберите чат для начала переписки.</div>
</div>
</div>
<div class="whatsapp-chat-actions">
<button class="whatsapp-icon-btn" type="button" aria-label="Голосовой звонок" data-whatsapp-ui-action="voice-call">
<svg viewBox="0 0 24 24" aria-hidden="true">
<path d="M5.5 4.5h3l1.4 3.6-1.7 1.7a15.4 15.4 0 0 0 6 6l1.7-1.7 3.6 1.4v3a1.5 1.5 0 0 1-1.5 1.5A15.5 15.5 0 0 1 4 6 1.5 1.5 0 0 1 5.5 4.5Z" />
</svg>
</button>
<button class="whatsapp-icon-btn" type="button" aria-label="Видеозвонок" data-whatsapp-ui-action="video-call">
<svg viewBox="0 0 24 24" aria-hidden="true">
<rect x="3.75" y="6.5" width="10.5" height="11" rx="2.5" />
<path d="m14.75 10.5 5.5-3v9l-5.5-3" />
</svg>
</button>
<button class="whatsapp-icon-btn" type="button" aria-label="Поиск по чату" data-whatsapp-ui-action="search-chat">
<svg viewBox="0 0 24 24" aria-hidden="true">
<circle cx="11" cy="11" r="6.5" />
<path d="m16 16 4.5 4.5" />
</svg>
</button>
<button class="whatsapp-icon-btn" type="button" aria-label="Меню чата" data-whatsapp-ui-action="chat-menu">
<svg viewBox="0 0 24 24" aria-hidden="true">
<circle cx="12" cy="5" r="1.5" />
<circle cx="12" cy="12" r="1.5" />
<circle cx="12" cy="19" r="1.5" />
</svg>
</button>
</div>
</header>
<section id="whatsappContextPanel" class="whatsapp-context-panel hidden" aria-live="polite">
<div class="whatsapp-context-bar">
<div class="whatsapp-context-pills">
<span id="whatsappAiStateChip" class="whatsapp-state-chip hidden"></span>
<span id="whatsappOwnerChip" class="whatsapp-state-chip subtle hidden"></span>
</div>
<div class="whatsapp-context-actions">
<button id="whatsappClaimBtn" class="whatsapp-context-btn" type="button">Взять в работу</button>
<button id="whatsappReturnToAiBtn" class="whatsapp-context-btn secondary" type="button">Вернуть AI</button>
</div>
</div>
<article id="whatsappAiSummaryCard" class="whatsapp-ai-summary hidden">
<div class="whatsapp-ai-summary-head">
<div>
<div class="whatsapp-ai-summary-kicker">Передача от AI</div>
<h3>Контекст для оператора</h3>
</div>
<div class="whatsapp-ai-summary-side">
<div id="whatsappAiSummaryStatus"></div>
<div id="whatsappAiSummaryMeta" class="whatsapp-ai-summary-meta"></div>
</div>
</div>
<div id="whatsappAiSummaryContent" class="whatsapp-ai-summary-grid"></div>
</article>
</section>
<div class="whatsapp-chat-surface">
<div id="whatsappMessageTimeline" class="whatsapp-message-timeline"></div>
</div>
<footer class="whatsapp-composer-wrap">
<div class="whatsapp-composer-shell">
<button class="whatsapp-composer-btn" type="button" aria-label="Вложение" data-whatsapp-ui-action="attach">
<svg viewBox="0 0 24 24" aria-hidden="true">
<path d="m9.5 12.5 5.94-5.94a3 3 0 1 1 4.24 4.24l-8.48 8.48a5 5 0 0 1-7.07-7.07l8.13-8.13" />
</svg>
</button>
<textarea id="whatsappComposerInput" placeholder="Написать сообщение"></textarea>
<button class="whatsapp-composer-btn" type="button" aria-label="Эмодзи" data-whatsapp-ui-action="emoji">
<svg viewBox="0 0 24 24" aria-hidden="true">
<circle cx="12" cy="12" r="9" />
<path d="M8.5 14.5c.8 1.2 2 2 3.5 2s2.7-.8 3.5-2" />
<circle cx="9" cy="10" r="1" />
<circle cx="15" cy="10" r="1" />
</svg>
</button>
<button id="whatsappSendBtn" class="whatsapp-send-btn" type="button" aria-label="Отправить">
<svg viewBox="0 0 24 24" aria-hidden="true">
<path d="M21 3 3.9 10.09a1 1 0 0 0 .06 1.87l6.5 2.27 2.27 6.5a1 1 0 0 0 1.87.06L21 3Z" />
<path d="M10.5 14.5 21 3" />
</svg>
</button>
</div>
</footer>
</section>
</div>
</article>
</section>
<section id="callsView" class="operator-view hidden" data-operator-view="calls">
<section class="page-hero reveal customers-page-hero">
<h1>Звонки</h1>
<p class="hint">Живые и недавние звонки, AI-handoff и журнал действий в одном месте. Основной take over остаётся во всплывающем окне браузерного телефона.</p>
</section>
<article class="panel reveal panel-span-full technical-panel" id="liveCalls">
<h2>Мониторинг звонков</h2>
<p class="hint">Здесь видны текущий статус, недавние вызовы и трассировка действий. Ответ, перевод и завершение звонка остаются во всплывающем окне.</p>
<div class="inline-form compact">
<button id="loadLiveCallsBtn" class="btn ghost">Обновить звонки</button>
<button id="loadLiveCallActionsBtn" class="btn ghost">Действия по звонку</button>
</div>
<div class="inline-form compact live-call-inspector">
<select id="liveCallIdSelect"></select>
</div>
<div id="liveCallNameEditor" class="live-call-name-editor hidden">
<div class="live-call-name-editor-head">
<div class="live-call-name-editor-title">Исправить имя клиента</div>
<p id="liveCallNameEditorMeta" class="hint">Выберите звонок, связанный с клиентом, чтобы исправить имя.</p>
</div>
<div class="live-call-name-editor-form">
<input id="liveCallNameInput" type="text" placeholder="Введите имя клиента" />
<button id="liveCallNameSaveBtn" class="btn" type="button">Сохранить имя</button>
<button id="liveCallNameCancelBtn" class="btn ghost" type="button">Отмена</button>
</div>
<p id="liveCallNameStatus" class="hint"></p>
</div>
<p class="hint">Здесь остаются живые и недавние звонки, а оперативные действия по ним вынесены во всплывающее окно.</p>
<p class="hint" id="liveCallStatusHint">Пока нет активных звонков.</p>
<div id="liveCallsTable" class="table"></div>
<details class="details-block">
<summary>Лог действий по звонку</summary>
<pre id="liveCallActionsOutput" class="output"></pre>
</details>
</article>
</section>
</main>
</section>
</div>
<div id="browserPhoneCallOverlay" class="call-window-overlay hidden" aria-live="polite">
<div class="call-window">
<div class="call-window-head">
<div>
<div id="browserPhoneCallState" class="call-window-status">Входящий звонок</div>
<h2 id="browserPhoneCallTitle" class="call-window-title">Неизвестный абонент</h2>
<p id="browserPhoneIncomingText" class="call-window-meta">SIP-приглашение ещё не поступало.</p>
<p id="browserPhoneCallMeta" class="call-window-meta subtle">Ждём входящий звонок в браузере.</p>
</div>
<button id="browserPhoneCallSettingsBtn" class="icon-button" type="button" aria-label="Настройки телефона"></button>
</div>
<div class="call-window-body">
<div class="call-window-avatar"></div>
<div id="browserPhoneCallTimer" class="call-window-timer">00:00</div>
<p id="browserPhoneCallWarning" class="call-window-warning hidden"></p>
</div>
<div id="browserPhoneAiSummary" class="call-window-ai-summary hidden"></div>
<div id="browserPhoneNameEditor" class="call-window-name-editor hidden">
<div class="call-window-name-head">
<div class="voice-summary-label">Исправить имя клиента</div>
<p id="browserPhoneNameHint" class="call-window-meta subtle">Имя сохранится в профиле клиента и voice-контуре.</p>
</div>
<div class="call-window-name-form">
<input id="browserPhoneNameInput" type="text" placeholder="Введите имя клиента" />
<button id="browserPhoneNameSaveBtn" class="btn" type="button">Сохранить имя</button>
<button id="browserPhoneNameCancelBtn" class="btn ghost" type="button">Отмена</button>
</div>
<p id="browserPhoneNameStatus" class="call-window-meta subtle hidden"></p>
</div>
<div class="call-window-transfer">
<select id="browserPhoneTransferTargetType">
<option value="extension">внутренний номер</option>
<option value="queue_code">код очереди</option>
</select>
<input id="browserPhoneTransferTargetValue" placeholder="2002 или voice_lab" />
</div>
<div class="call-window-actions">
<button id="browserPhoneAnswerBtn" class="btn" type="button">Ответить</button>
<button id="browserPhoneRejectBtn" class="btn ghost" type="button">Отклонить</button>
<button id="browserPhoneCallClaimBtn" class="btn ghost" type="button">Принять в работу</button>
<button id="browserPhoneEditNameBtn" class="btn ghost" type="button">Исправить имя</button>
<button id="browserPhoneMuteBtn" class="btn ghost" type="button">Выключить микрофон</button>
<button id="browserPhoneCallTransferBtn" class="btn ghost" type="button">Передать</button>
<button id="browserPhoneCallHangupBtn" class="btn danger" type="button">Завершить</button>
</div>
</div>
</div>
<audio id="browserPhoneRemoteAudio" autoplay playsinline></audio>
<script src="/operator/assets/access-guards.js?v=track16-voice-transcript1"></script>
<script src="/operator/assets/sip-0.21.2.min.js?v=track16-voice-transcript1"></script>
<script src="/operator/assets/app.js?v=track44-messenger-polish1"></script>
</body>
</html>