otslezhivat-povtornye-obrasc/index.html

192 lines
11 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.

<!-- no-design-system: приложение с кастомной структурой (не лендинг) -->
<!DOCTYPE html>
<html lang="ru" data-theme="auto">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Повторные обращения</title>
<link rel="stylesheet" href="design-system/kt-ai-fonts.css">
<link rel="stylesheet" href="design-system/kt-ai-tokens.css">
<link rel="stylesheet" href="design-system/kt-ai-components.css">
<link rel="stylesheet" href="design-system/kt-ai-page.css">
<style>
.kt-ai-btn { text-decoration: none; }
.app-shell { display:flex; min-height:100vh; background:var(--kt-ai-bg); }
.sidebar { width:280px; background:var(--kt-ai-bg-soft); border-right:1px solid var(--kt-ai-border); padding:var(--kt-ai-space-4); display:flex; flex-direction:column; position:fixed; height:100vh; overflow:auto; }
.main-content { margin-left:280px; flex:1; display:flex; flex-direction:column; }
.topbar { display:flex; align-items:center; gap:var(--kt-ai-space-4); padding:var(--kt-ai-space-4) var(--kt-ai-space-6); border-bottom:1px solid var(--kt-ai-border); position:sticky; top:0; background:var(--kt-ai-bg); z-index:10; }
.topbar-title { font-size:var(--kt-ai-text-lg); font-weight:var(--kt-ai-weight-semibold); margin:0; }
.kpi-strip { display:flex; gap:var(--kt-ai-space-6); padding:var(--kt-ai-space-4) var(--kt-ai-space-6); border-bottom:1px solid var(--kt-ai-border); }
.kpi { padding:var(--kt-ai-space-3) var(--kt-ai-space-4); background:var(--kt-ai-card-bg); border:1px solid var(--kt-ai-card-border); border-radius:var(--kt-ai-radius-lg); }
.kpi-value { font-size:var(--kt-ai-text-2xl); font-weight:var(--kt-ai-weight-bold); color:var(--kt-ai-fg); }
.kpi-label { font-size:var(--kt-ai-text-sm); color:var(--kt-ai-fg-muted); margin-top:var(--kt-ai-space-1); }
.toolbar { padding:var(--kt-ai-space-4) var(--kt-ai-space-6); display:flex; gap:var(--kt-ai-space-4); align-items:center; }
.table-wrap { flex:1; overflow:auto; padding:0 var(--kt-ai-space-6) var(--kt-ai-space-6); }
.appeals-table { width:100%; border-collapse:collapse; }
.appeals-table th, .appeals-table td { padding:var(--kt-ai-space-3) var(--kt-ai-space-4); text-align:left; border-bottom:1px solid var(--kt-ai-divider); }
.appeals-table th { font-weight:var(--kt-ai-weight-semibold); color:var(--kt-ai-fg-muted); font-size:var(--kt-ai-text-sm); position:sticky; top:0; background:var(--kt-ai-bg); }
.appeals-table tr:hover { background:var(--kt-ai-bg-soft); }
.status-pill { display:inline-block; padding:var(--kt-ai-space-1) var(--kt-ai-space-2); border-radius:var(--kt-ai-radius-full); font-size:var(--kt-ai-text-xs); font-weight:var(--kt-ai-weight-medium); }
.status-new { background:var(--kt-ai-bg-soft); color:var(--kt-ai-primary); }
.status-duplicate { background:var(--kt-ai-bg-soft); color:var(--kt-ai-fg-muted); }
.status-resolved { background:var(--kt-ai-bg-soft); color:var(--kt-ai-fg); }
.drawer-overlay { position:fixed; inset:0; background:rgba(0,0,0,0.5); z-index:100; display:none; }
.drawer-overlay.open { display:block; }
.drawer { position:fixed; right:0; top:0; bottom:0; width:480px; background:var(--kt-ai-bg); box-shadow:-4px 0 24px rgba(0,0,0,0.15); z-index:101; transform:translateX(100%); transition:transform 0.3s; display:flex; flex-direction:column; }
.drawer.open { transform:translateX(0); }
.drawer-header { display:flex; align-items:center; justify-content:space-between; padding:var(--kt-ai-space-4) var(--kt-ai-space-6); border-bottom:1px solid var(--kt-ai-border); }
.drawer-title { font-size:var(--kt-ai-text-lg); font-weight:var(--kt-ai-weight-semibold); margin:0; }
.drawer-content { flex:1; overflow:auto; padding:var(--kt-ai-space-6); }
.drawer-actions { padding:var(--kt-ai-space-4) var(--kt-ai-space-6); border-top:1px solid var(--kt-ai-border); display:flex; gap:var(--kt-ai-space-3); justify-content:flex-end; }
.field { margin-bottom:var(--kt-ai-space-4); }
.field label { display:block; font-size:var(--kt-ai-text-sm); font-weight:var(--kt-ai-weight-medium); color:var(--kt-ai-fg); margin-bottom:var(--kt-ai-space-2); }
.toast-container { position:fixed; bottom:var(--kt-ai-space-6); right:var(--kt-ai-space-6); display:flex; flex-direction:column; gap:var(--kt-ai-space-3); z-index:200; }
.toast { background:var(--kt-ai-fg); color:var(--kt-ai-bg); padding:var(--kt-ai-space-3) var(--kt-ai-space-4); border-radius:var(--kt-ai-radius-lg); font-size:var(--kt-ai-text-sm); min-width:280px; }
.search-input { width:100%; padding:var(--kt-ai-space-2) var(--kt-ai-space-3); border:1px solid var(--kt-ai-border); border-radius:var(--kt-ai-radius-md); background:var(--kt-ai-bg); color:var(--kt-ai-fg); font-size:var(--kt-ai-text-sm); }
.search-input:focus { outline:none; border-color:var(--kt-ai-primary); }
.empty-state { text-align:center; padding:var(--kt-ai-space-12); color:var(--kt-ai-fg-muted); }
.icon-btn { background:none; border:none; cursor:pointer; padding:var(--kt-ai-space-1); color:var(--kt-ai-fg-muted); }
.icon-btn:hover { color:var(--kt-ai-fg); }
</style>
</head>
<body>
<div class="app-shell">
<aside class="sidebar">
<div class="kt-ai-brand" style="margin-bottom:var(--kt-ai-space-6)">
<img src="design-system/brand/kt-ai-logo.png" alt="KT AI" height="20">
<span>Повторные обращения</span>
</div>
<nav>
<div class="kt-ai-nav-group">
<a class="kt-ai-nav-item is-active" href="#" data-filter="all">Все обращения</a>
<a class="kt-ai-nav-item" href="#" data-filter="new">Новые</a>
<a class="kt-ai-nav-item" href="#" data-filter="duplicate">Повторные</a>
<a class="kt-ai-nav-item" href="#" data-filter="resolved">Решённые</a>
</div>
</nav>
<div style="margin-top:auto">
<button class="kt-ai-btn" data-variant="primary" style="width:100%" id="newAppealBtn">
<svg class="kt-icon kt-icon-sm" aria-hidden="true"><use href="#plus"></use></svg>
Новое обращение
</button>
</div>
</aside>
<main class="main-content">
<header class="topbar">
<h1 class="topbar-title">Реестр обращений</h1>
<div style="flex:1; max-width:500px">
<input class="search-input" type="search" placeholder="Поиск по тексту, автору, дате…" id="searchInput">
</div>
<button class="kt-ai-btn" data-variant="ghost" id="themeToggle">
<svg class="kt-icon" aria-hidden="true"><use href="#sun"></use></svg>
</button>
</header>
<div class="kpi-strip">
<div class="kpi">
<div class="kpi-value" id="kpiTotal">0</div>
<div class="kpi-label">Всего обращений</div>
</div>
<div class="kpi">
<div class="kpi-value" id="kpiNew">0</div>
<div class="kpi-label">Новых</div>
</div>
<div class="kpi">
<div class="kpi-value" id="kpiDuplicate">0</div>
<div class="kpi-label">Повторных</div>
</div>
<div class="kpi">
<div class="kpi-value" id="kpiResolved">0</div>
<div class="kpi-label">Решённых</div>
</div>
</div>
<div class="toolbar">
<div class="kt-ai-segmented">
<button class="kt-ai-segmented-item is-active" data-sort="date">По дате</button>
<button class="kt-ai-segmented-item" data-sort="author">По автору</button>
</div>
<select class="kt-ai-select" id="statusFilter">
<option value="">Все статусы</option>
<option value="new">Новое</option>
<option value="duplicate">Повторное</option>
<option value="resolved">Решено</option>
</select>
</div>
<div class="table-wrap">
<table class="appeals-table">
<thead>
<tr>
<th>Дата</th>
<th>Автор</th>
<th>Текст обращения</th>
<th>Статус</th>
<th>Действия</th>
</tr>
</thead>
<tbody id="appealsTable"></tbody>
</table>
<div class="empty-state" id="emptyState" hidden>
<svg class="kt-icon kt-icon-lg" aria-hidden="true" style="margin-bottom:var(--kt-ai-space-4)"><use href="#inbox"></use></svg>
<p>Обращений пока нет</p>
<button class="kt-ai-btn" data-variant="primary" id="emptyNewBtn" style="margin-top:var(--kt-ai-space-4)">Добавить первое обращение</button>
</div>
</div>
</main>
</div>
<div class="drawer-overlay" id="drawerOverlay"></div>
<aside class="drawer" id="appealDrawer">
<header class="drawer-header">
<h2 class="drawer-title" id="drawerTitle">Новое обращение</h2>
<button class="kt-ai-btn" data-variant="ghost" id="closeDrawer">
<svg class="kt-icon" aria-hidden="true"><use href="#x"></use></svg>
</button>
</header>
<div class="drawer-content">
<form id="appealForm">
<input type="hidden" id="appealId">
<div class="field">
<label>Автор обращения</label>
<input class="kt-ai-input" id="authorInput" required placeholder="ФИО или название организации">
</div>
<div class="field">
<label>Контакты</label>
<input class="kt-ai-input" id="contactInput" placeholder="Телефон, email">
</div>
<div class="field">
<label>Текст обращения</label>
<textarea class="kt-ai-textarea" id="textInput" required rows="5" placeholder="Опишите суть обращения"></textarea>
</div>
<div class="field">
<label>Категория</label>
<select class="kt-ai-select" id="categoryInput">
<option value="">Не выбрано</option>
<option value="technical">Технический вопрос</option>
<option value="billing">Биллинг и оплата</option>
<option value="service">Качество услуги</option>
<option value="other">Другое</option>
</select>
</div>
<div class="field">
<label>Комментарий</label>
<textarea class="kt-ai-textarea" id="commentInput" rows="3" placeholder="Внутренний комментарий"></textarea>
</div>
</form>
</div>
<div class="drawer-actions">
<button class="kt-ai-btn" data-variant="ghost" id="cancelBtn">Отмена</button>
<button class="kt-ai-btn" data-variant="primary" id="saveBtn">Сохранить</button>
</div>
</aside>
<div class="toast-container" id="toastContainer"></div>
<script src="design-system/icons/kt-ai-icons.js"></script>
<script src="script.js"></script>
</body>
</html>