sozdat-dashbord-iz-dannoy-gu/index.html

474 lines
36 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">
<title>Дашборд по устранению замечаний БиОТ</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; background: #f5f7fa; color: #1a1a1a; padding: 20px; }
.container { max-width: 1400px; margin: 0 auto; }
h1 { font-size: 28px; margin-bottom: 10px; color: #1e3a5f; }
.subtitle { color: #666; margin-bottom: 30px; }
.summary-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; margin-bottom: 30px; }
.card { background: white; border-radius: 12px; padding: 20px; box-shadow: 0 2px 8px rgba(0,0,0,0.08); }
.card-title { font-size: 14px; color: #666; margin-bottom: 8px; }
.card-value { font-size: 32px; font-weight: bold; color: #1e3a5f; }
.card-subtitle { font-size: 12px; color: #999; margin-top: 4px; }
.card.success .card-value { color: #10b981; }
.card.warning .card-value { color: #f59e0b; }
.card.danger .card-value { color: #ef4444; }
.region-selector { display: flex; gap: 10px; margin-bottom: 20px; }
.region-btn { padding: 10px 20px; border: 2px solid #e2e8f0; background: white; border-radius: 8px; cursor: pointer; font-size: 14px; font-weight: 500; transition: all 0.2s; }
.region-btn:hover { border-color: #1e3a5f; }
.region-btn.active { background: #1e3a5f; color: white; border-color: #1e3a5f; }
.dashboard { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-bottom: 30px; }
@media (max-width: 900px) { .dashboard { grid-template-columns: 1fr; } }
.chart-container { background: white; border-radius: 12px; padding: 20px; box-shadow: 0 2px 8px rgba(0,0,0,0.08); }
.chart-title { font-size: 18px; font-weight: 600; margin-bottom: 20px; color: #1e3a5f; }
.bar-chart { display: flex; flex-direction: column; gap: 12px; }
.bar-item { display: flex; align-items: center; gap: 10px; }
.bar-label { width: 180px; font-size: 13px; color: #333; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bar-wrapper { flex: 1; background: #e2e8f0; border-radius: 6px; height: 28px; overflow: hidden; }
.bar { height: 100%; border-radius: 6px; transition: width 0.5s ease; }
.bar.success { background: linear-gradient(90deg, #10b981, #34d399); }
.bar.warning { background: linear-gradient(90deg, #f59e0b, #fbbf24); }
.bar.danger { background: linear-gradient(90deg, #ef4444, #f87171); }
.bar-value { width: 60px; text-align: right; font-size: 13px; font-weight: 600; color: #333; }
.status-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 15px; margin-bottom: 20px; }
.status-box { padding: 15px; border-radius: 8px; text-align: center; }
.status-box.success { background: #d1fae5; }
.status-box.warning { background: #fef3c7; }
.status-box.danger { background: #fee2e2; }
.status-box .value { font-size: 24px; font-weight: bold; margin-bottom: 4px; }
.status-box .label { font-size: 12px; color: #666; }
.status-box.success .value { color: #059669; }
.status-box.warning .value { color: #d97706; }
.status-box.danger .value { color: #dc2626; }
.table-container { background: white; border-radius: 12px; padding: 20px; box-shadow: 0 2px 8px rgba(0,0,0,0.08); overflow-x: auto; }
.table-title { font-size: 18px; font-weight: 600; margin-bottom: 15px; color: #1e3a5f; }
table { width: 100%; border-collapse: collapse; }
th, td { padding: 12px; text-align: left; border-bottom: 1px solid #e2e8f0; }
th { background: #f8fafc; font-weight: 600; font-size: 13px; color: #333; position: sticky; top: 0; }
td { font-size: 13px; }
tr:hover { background: #f8fafc; }
.status-badge { padding: 4px 10px; border-radius: 12px; font-size: 12px; font-weight: 500; }
.status-badge.success { background: #d1fae5; color: #059669; }
.status-badge.warning { background: #fef3c7; color: #d97706; }
.status-badge.danger { background: #fee2e2; color: #dc2626; }
.filter-section { display: flex; gap: 15px; margin-bottom: 20px; flex-wrap: wrap; align-items: center; }
.filter-input { padding: 8px 12px; border: 1px solid #e2e8f0; border-radius: 6px; font-size: 14px; }
.filter-select { padding: 8px 12px; border: 1px solid #e2e8f0; border-radius: 6px; font-size: 14px; background: white; }
.progress-ring { width: 120px; height: 120px; margin: 0 auto 15px; }
.progress-ring circle { fill: none; stroke-width: 8; }
.progress-ring .bg { stroke: #e2e8f0; }
.progress-ring .progress { stroke: #1e3a5f; stroke-linecap: round; transform: rotate(-90deg); transform-origin: 50% 50%; transition: stroke-dashoffset 0.5s; }
.progress-text { font-size: 24px; font-weight: bold; fill: #1e3a5f; }
.progress-label { font-size: 12px; fill: #666; }
.charts-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin-bottom: 30px; }
</style>
</head>
<body>
<div class="container">
<h1>📊 Дашборд по устранению замечаний БиОТ</h1>
<p class="subtitle">Северный регион • 2026 год</p>
<div class="summary-cards">
<div class="card">
<div class="card-title">Всего замечаний</div>
<div class="card-value" id="total">0</div>
<div class="card-subtitle">по Северному региону</div>
</div>
<div class="card success">
<div class="card-title">Исполнено</div>
<div class="card-value" id="completed">0</div>
<div class="card-subtitle" id="completedPct">0%</div>
</div>
<div class="card warning">
<div class="card-title">На контроле</div>
<div class="card-value" id="inControl">0</div>
<div class="card-subtitle" id="inControlPct">0%</div>
</div>
<div class="card danger">
<div class="card-title">Просрочено</div>
<div class="card-value" id="overdue">0</div>
<div class="card-subtitle" id="overduePct">0%</div>
</div>
</div>
<div class="region-selector">
<button class="region-btn active" data-region="all">Все области</button>
<button class="region-btn" data-region="kostanay">Костанайская область</button>
<button class="region-btn" data-region="sko">Северо-Казахстанская область</button>
</div>
<div class="status-grid">
<div class="status-box success">
<div class="value" id="kostanayCompleted">0</div>
<div class="label">Костанай: Исполнено</div>
</div>
<div class="status-box success">
<div class="value" id="skoCompleted">0</div>
<div class="label">СКО: Исполнено</div>
</div>
<div class="status-box warning">
<div class="value" id="totalOnControl">0</div>
<div class="label">Всего на контроле</div>
</div>
</div>
<div class="dashboard">
<div class="chart-container">
<div class="chart-title">📈 Статус исполнения по областям</div>
<div class="bar-chart" id="regionChart"></div>
</div>
<div class="chart-container">
<div class="chart-title">🎯 Общий процент исполнения</div>
<div style="display: flex; justify-content: space-around; align-items: center; height: 200px;">
<div>
<svg class="progress-ring" viewBox="0 0 120 120">
<circle class="bg" cx="60" cy="60" r="52"></circle>
<circle class="progress" cx="60" cy="60" r="52" stroke-dasharray="326.73" stroke-dashoffset="0"></circle>
<text class="progress-text" x="60" y="65" text-anchor="middle" id="progressPercent">0%</text>
<text class="progress-label" x="60" y="80" text-anchor="middle">Исполнение</text>
</svg>
</div>
<div style="flex: 1;">
<div class="bar-item" style="margin-bottom: 10px;">
<div class="bar-label">Исполнено</div>
<div class="bar-wrapper"><div class="bar success" id="completedBar" style="width: 0%"></div></div>
<div class="bar-value" id="completedVal">0</div>
</div>
<div class="bar-item" style="margin-bottom: 10px;">
<div class="bar-label">На контроле</div>
<div class="bar-wrapper"><div class="bar warning" id="controlBar" style="width: 0%"></div></div>
<div class="bar-value" id="controlVal">0</div>
</div>
<div class="bar-item">
<div class="bar-label">Просрочено</div>
<div class="bar-wrapper"><div class="bar danger" id="overdueBar" style="width: 0%"></div></div>
<div class="bar-value" id="overdueVal">0</div>
</div>
</div>
</div>
</div>
</div>
<div class="charts-row">
<div class="chart-container">
<div class="chart-title">📍 По подразделениям (ОДС)</div>
<div class="bar-chart" id="odsChart"></div>
</div>
<div class="chart-container">
<div class="chart-title">📍 По подразделениям (СФ)</div>
<div class="bar-chart" id="sfChart"></div>
</div>
</div>
<div class="table-container">
<div class="table-title">📋 Детальная таблица по регионам</div>
<div class="filter-section">
<input type="text" class="filter-input" id="searchInput" placeholder="Поиск по населённому пункту..." style="min-width: 250px;">
<select class="filter-select" id="divisionFilter">
<option value="">Все подразделения</option>
<option value="ОДС">ОДС</option>
<option value="СФ">СФ</option>
<option value="ДРБ">ДРБ</option>
<option value="ДКБ">ДКБ</option>
<option value="ДЦБ">ДЦБ</option>
</select>
<select class="filter-select" id="statusFilter">
<option value="">Все статусы</option>
<option value="executed">Исполнено</option>
<option value="control">На контроле</option>
<option value="overdue">Просрочено</option>
</select>
</div>
<table>
<thead>
<tr>
<th>№</th>
<th>Подразделение</th>
<th>Населённый пункт</th>
<th>Область</th>
<th>Статус</th>
<th>Документ</th>
<th>Ответственный</th>
</tr>
</thead>
<tbody id="dataTable"></tbody>
</table>
</div>
</div>
<script>
const DATA = [
{"id":38,"division":"УИТР","location":"г.Аркалык","region":"Костанай","status":"executed","doc":"№21 от 30.01.2026","responsible":"Адырбаев Ж.А."},
{"id":39,"division":"ТУСМ-8","location":"г.Аркалык","region":"Костанай","status":"executed","doc":"32 от 18.02.2026/№49","responsible":"Адырбаев Ж.А./Нурманов К.А."},
{"id":40,"division":"ЛТУ, ЦТПСР, ЦЭиК","location":"с.Амангельды","region":"Костанай","status":"executed","doc":"54 от 27.02.2026","responsible":"Нурманов К.А."},
{"id":41,"division":"УТО, ЦПХО","location":"с.Амангельды","region":"Костанай","status":"executed","doc":"55 от 27.02.2026","responsible":"Нурманов К.А."},
{"id":42,"division":"ГП ЦРК","location":"с.Амангельды","region":"Костанай","status":"executed","doc":"56 от 27.02.2026","responsible":"Нурманов К.А."},
{"id":43,"division":"ЛТУ, ЦТПСР, ЦЭиК","location":"с.Торгай","region":"Костанай","status":"executed","doc":"51от 25.02.2026","responsible":"Нурманов К.А."},
{"id":44,"division":"УТО, ЦПХО","location":"с.Торгай","region":"Костанай","status":"executed","doc":"52 от 25.02.2026","responsible":"Нурманов К.А."},
{"id":45,"division":"ГП ЦРК","location":"с.Торгай","region":"Костанай","status":"executed","doc":"53 от 25.02.2026","responsible":"Нурманов К.А."},
{"id":46,"division":"ЛТЦ, ЦТПСР, ЦЭиК","location":"с.Аулиеколь","region":"Костанай","status":"executed","doc":"№ 92 от 30.03.2026","responsible":"Книга А.В."},
{"id":47,"division":"УТО, ЦПХО","location":"с.Аулиеколь","region":"Костанай","status":"executed","doc":"№ 93 от 30.03.2026","responsible":"Книга А.В."},
{"id":48,"division":"ГП ЦРК","location":"с.Аулиеколь","region":"Костанай","status":"executed","doc":"№ 184 от 29.05.2026","responsible":"Книга А.В."},
{"id":49,"division":"ТУСМ-8","location":"п.Кушмурун","region":"Костанай","status":"executed","doc":"№ 212 от 14.04.2026","responsible":"Книга А.В."},
{"id":50,"division":"ЛТЦ, ЦТПСР, ЦЭиК","location":"п.Карасу","region":"Костанай","status":"executed","doc":"№ 6 от 22.01 2026","responsible":"Книга А.В."},
{"id":51,"division":"УТО, ЦПХО","location":"п.Карасу","region":"Костанай","status":"executed","doc":"№ 5 от 22.01 2026","responsible":"Книга А.В."},
{"id":52,"division":"ГП ЦРК","location":"п.Карасу","region":"Костанай","status":"executed","doc":"№ 7 от 23.01 2026","responsible":"Книга А.В."},
{"id":53,"division":"ЛУ, ЦТПСР, ЦЭиК","location":"c.Октябрьcкое","region":"Костанай","status":"executed","doc":"№ 90 от 29.03.2026","responsible":"Книга А.В."},
{"id":54,"division":"УТО, ЦПХО","location":"c.Октябрьcкое","region":"Костанай","status":"executed","doc":"№ 91 от 29.03.2026","responsible":"Книга А.В."},
{"id":55,"division":"ЛТУ, ЦТПСР, ЦЭиК","location":"с.Караменды","region":"Костанай","status":"executed","doc":"№ 98 от 30.03.2026","responsible":"Книга А.В."},
{"id":56,"division":"УТО, ЦПХО","location":"с.Караменды","region":"Костанай","status":"executed","doc":"№ 97 от 30.03.2026","responsible":"Книга А.В."},
{"id":57,"division":"ЛТЦ, ЦТПСР, ЦЭиК","location":"п.Сарыколь","region":"Костанай","status":"executed","doc":"№ 72 от 14.03.2026","responsible":"Книга А.В."},
{"id":58,"division":"УТО, ЦПХО","location":"п.Сарыколь","region":"Костанай","status":"executed","doc":"№ 73 от 14.03.2026","responsible":"Книга А.В."},
{"id":59,"division":"ГП ЦРК","location":"п.Сарыколь","region":"Костанай","status":"executed","doc":"№ 259 от28.07.26","responsible":"Книга А.В."},
{"id":60,"division":"ТУСМ-8","location":"п.Сарыколь","region":"Костанай","status":"executed","doc":"№ 81 от 17.03.2026","responsible":"Книга А.В."},
{"id":61,"division":"ЛТУ, ЦТПСР, ЦЭиК","location":"с.Узунколь","region":"Костанай","status":"executed","doc":"№ 86 от 23.03.2026","responsible":"Книга А.В."},
{"id":62,"division":"УТО, ЦПХО","location":"с.Узунколь","region":"Костанай","status":"executed","doc":"№ 87 от 23.03.2026","responsible":"Книга А.В."},
{"id":63,"division":"ГП ЦРК","location":"с.Узунколь","region":"Костанай","status":"executed","doc":"№ 271 от29.07.26","responsible":"Книга А.В."},
{"id":64,"division":"ЛТУ, ЦТПСР, ЦЭиК","location":"с.Силантьевка","region":"Костанай","status":"executed","doc":"№ 47 от 27.02.2026","responsible":"Книга А.В."},
{"id":65,"division":"УТО, ЦПХО","location":"с.Силантьевка","region":"Костанай","status":"executed","doc":"№ 48 от 27.02.2026","responsible":"Книга А.В."},
{"id":66,"division":"ЛТУ, ЦТПСР, ЦЭиК","location":"с.Боровское","region":"Костанай","status":"executed","doc":"№ 100 от 30.03.2026","responsible":"Книга А.В."},
{"id":67,"division":"УТО, ЦПХО","location":"с.Боровское","region":"Костанай","status":"executed","doc":"№ 99 от 30.03.2026","responsible":"Книга А.В."},
{"id":68,"division":"ГП ЦРК","location":"с.Боровское","region":"Костанай","status":"executed","doc":"№ 177 от 26.05.2026","responsible":"Книга А.В."},
{"id":69,"division":"ЛТЦ, ЦТПСР, ЦЭиК","location":"г.Житикара","region":"Костанай","status":"executed","doc":"№ 23 от 02-03.02.2026","responsible":"Ляшенко А.Л."},
{"id":70,"division":"ЦЛКС-82 ТУСМ-8","location":"г.Житикара","region":"Костанай","status":"executed","doc":"№ 45 от 26.02.2026","responsible":"Ляшенко А.Л."},
{"id":71,"division":"ГП ЦРК, ДИР","location":"г.Житикара","region":"Костанай","status":"executed","doc":"№ 22 от 02.02.2026","responsible":"Ляшенко А.Л."},
{"id":72,"division":"УТО, ЦПХО","location":"г.Житикара","region":"Костанай","status":"executed","doc":"№ 46 от 26.02.2026","responsible":"Ляшенко А.Л."},
{"id":73,"division":"ЛТУ, ЦТПСР, ЦЭиК","location":"с.Денисовка","region":"Костанай","status":"executed","doc":"№ 66 от 03.03.2026","responsible":"Ляшенко А.Л."},
{"id":74,"division":"ГП ЦРК","location":"с.Денисовка","region":"Костанай","status":"executed","doc":"№ 65 от 03.03.2026","responsible":"Ляшенко А.Л."},
{"id":75,"division":"УТО, ЦПХО","location":"с.Денисовка","region":"Костанай","status":"executed","doc":"№ 67 от 03.03.2026","responsible":"Ляшенко А.Л."},
{"id":76,"division":"ЛТУ, ЦТПСР, ЦЭиК","location":"с.Камысты","region":"Костанай","status":"executed","doc":"№ 107 от 27.03.2026","responsible":"Ляшенко А.Л."},
{"id":77,"division":"ГП ЦРК, ДИР","location":"с.Камысты","region":"Костанай","status":"executed","doc":"№ 108 от 27.03.2026","responsible":"Ляшенко А.Л."},
{"id":78,"division":"УТО, ЦПХО","location":"с.Камысты","region":"Костанай","status":"executed","doc":"№ 109 от 27.03.2026","responsible":"Ляшенко А.Л."},
{"id":79,"division":"ЛТУ, ЦТПСР, ЦЭиК","location":"г.Лисаковск","region":"Костанай","status":"executed","doc":"№ 78 от 03.03.2026","responsible":"Ляшенко А.Л."},
{"id":80,"division":"ГП ЦРК","location":"г.Лисаковск","region":"Костанай","status":"executed","doc":"№ 77 от 03.03.2026","responsible":"Ляшенко А.Л."},
{"id":81,"division":"УТО, ЦПХО","location":"г.Лисаковск","region":"Костанай","status":"executed","doc":"№ 79 от 03.03.2026","responsible":"Ляшенко А.Л."},
{"id":102,"division":"ЦТО МС ДЭСД","location":"г.Петропавловск","region":"СКО","status":"executed","doc":"№37 от 20.02.2026","responsible":"Шаймарданов А.С."},
{"id":103,"division":"ЦЭиК ДЭСД","location":"г.Петропавловск","region":"СКО","status":"executed","doc":"№14 от 28.01.2026","responsible":"Шаймарданов А.С."},
{"id":104,"division":"ЦТПСР ДЭСД","location":"г.Петропавловск","region":"СКО","status":"executed","doc":"№13от 28.01.2026","responsible":"Шаймарданов А.С."},
{"id":105,"division":"СТУиП ДЭСД","location":"г.Петропавловск","region":"СКО","status":"executed","doc":"№9 от 23.01.2026","responsible":"Шаймарданов А.С."},
{"id":106,"division":"ТУСМ-8","location":"г.Петропавловск","region":"СКО","status":"executed","doc":"№38 от 20.02.2026","responsible":"Ванин М.М."},
{"id":107,"division":"СЭРСТ ДЭСД","location":"г.Петропавловск","region":"СКО","status":"executed","doc":"№34 от 18.02.2026","responsible":"Шаймарданов А.С."},
{"id":108,"division":"УОД ДЭСД","location":"г.Петропавловск","region":"СКО","status":"executed","doc":"№268 от 30.07.2026","responsible":"Платонова Е.В."},
{"id":110,"division":"ДИТ","location":"г.Петропавловск","region":"СКО","status":"executed","doc":"№10 от 23.01.2026","responsible":"Шаймарданов А.С."},
{"id":109,"division":"ДУП","location":"г.Петропавловск","region":"СКО","status":"executed","doc":"№11 от 23.01.2026","responsible":"Шаймарданов А.С."},
{"id":111,"division":"ЦТО","location":"г.Петропавловск","region":"СКО","status":"executed","doc":"№25 от 04.02.2026","responsible":"Шаймарданов А.С."},
{"id":112,"division":"ЦПХО","location":"г.Петропавловск","region":"СКО","status":"executed","doc":"№33 от 18.02.2026","responsible":"Шаймарданов А.С."},
{"id":113,"division":"ЦРУ ДИР","location":"г.Петропавловск","region":"СКО","status":"executed","doc":"№29 от 16.02.2026","responsible":"Шаймарданов А.С."},
{"id":114,"division":"ПСС","location":"г.Петропавловск","region":"СКО","status":"executed","doc":"№71 от 16.03.2026","responsible":"Ванин М.М."},
{"id":115,"division":"ЦАП","location":"г.Петропавловск","region":"СКО","status":"executed","doc":"№70 от 16.03.2026","responsible":"Ванин М.М."},
{"id":116,"division":"ЦКП","location":"г.Петропавловск","region":"СКО","status":"executed","doc":"№69 от 13.03.2026","responsible":"Ванин М.М."},
{"id":117,"division":"СТПКР (165)","location":"г.Петропавловск","region":"СКО","status":"executed","doc":"№68 от 13.03.2026","responsible":"Ванин М.М."},
{"id":118,"division":"ЦРСТ","location":"г.Петропавловск","region":"СКО","status":"executed","doc":"№28 от 16.02.2026","responsible":"Шаймарданов А.С."},
{"id":119,"division":"Data Analytics&BI","location":"г.Петропавловск","region":"СКО","status":"executed","doc":"№170 от 29.05.2026","responsible":"Платонова Е.В."},
{"id":120,"division":"ОКиСК","location":"г.Петропавловск","region":"СКО","status":"control","doc":"СЗ № MMVN-DUHFC6","responsible":"Шаймарданов А.С."},
{"id":121,"division":"ГВБ/СС","location":"г.Петропавловск","region":"СКО","status":"control","doc":"№171,172 от 28.05.2026","responsible":"Платонова Е.В."},
{"id":122,"division":"ЛТЦ, ЦТПСР, ЦЭиК","location":"г.Булаево","region":"СКО","status":"executed","doc":"№125 от 16.04.2026","responsible":"Шаймарданов А.С."},
{"id":123,"division":"УТО, ЦПХО","location":"г.Булаево","region":"СКО","status":"executed","doc":"№127 от 16.04.2026","responsible":"Шаймарданов А.С."},
{"id":124,"division":"ГП ЦРК","location":"г.Булаево","region":"СКО","status":"executed","doc":"№126 от 16.04.2028","responsible":"Шаймарданов А.С."},
{"id":125,"division":"ЛТУ, ЦТПСР, ЦЭиК","location":"с.Пресновка","region":"СКО","status":"executed","doc":"№147 от 27.04.2026","responsible":"Ванин М.М."},
{"id":126,"division":"УТО, ЦПХО","location":"с.Пресновка","region":"СКО","status":"executed","doc":"№149 от 27.04.2026","responsible":"Ванин М.М."},
{"id":127,"division":"ГП ЦРК","location":"с.Пресновка","region":"СКО","status":"executed","doc":"№148 от 27.04.2026","responsible":"Ванин М.М."},
{"id":128,"division":"ЛТУ, ЦТПСР, ЦЭиК","location":"г.Мамлютка","region":"СКО","status":"executed","doc":"№131 от 06.04.2026","responsible":"Шаймарданов А.С."},
{"id":129,"division":"УТО, ЦПХО","location":"г.Мамлютка","region":"СКО","status":"executed","doc":"№132 от 06.04.2026","responsible":"Шаймарданов А.С."},
{"id":130,"division":"ГП ЦРК","location":"г.Мамлютка","region":"СКО","status":"executed","doc":"№133 от 06.04.2026","responsible":"Шаймарданов А.С."},
{"id":131,"division":"ЛТУ, ЦТПСР, ЦЭиК","location":"г.Сергеевка","region":"СКО","status":"executed","doc":"№44 от 25.02.2026","responsible":"Шаймарданов А.С."},
{"id":132,"division":"УТО, ЦПХО","location":"г.Сергеевка","region":"СКО","status":"executed","doc":"№43 от 25.02.2026","responsible":"Шаймарданов А.С."},
{"id":133,"division":"ГП ЦРК","location":"г.Сергеевка","region":"СКО","status":"executed","doc":"№50 от 25.02.2026","responsible":"Шаймарданов А.С."},
{"id":134,"division":"ЛТУ, ЦТПСР, ЦЭиК","location":"с.Тимирязево","region":"СКО","status":"executed","doc":"№42 от 24.02.2026","responsible":"Шаймарданов А.С."},
{"id":135,"division":"УТО, ЦПХО","location":"с.Тимирязево","region":"СКО","status":"executed","doc":"№41 от 24.02.2026","responsible":"Шаймарданов А.С."},
{"id":136,"division":"ГП ЦРК","location":"с.Тимирязево","region":"СКО","status":"executed","doc":"№40 от 24.02.2026","responsible":"Шаймарданов А.С."},
{"id":137,"division":"ЛТУ, ЦТПСР, ЦЭиК","location":"с.Явленка","region":"СКО","status":"executed","doc":"№62 от 13.03.2026","responsible":"Шаймарданов А.С."},
{"id":138,"division":"УТО, ЦПХО","location":"с.Явленка","region":"СКО","status":"executed","doc":"№63 от 13.03.2026","responsible":"Шаймарданов А.С."},
{"id":139,"division":"ГП ЦРК","location":"с.Явленка","region":"СКО","status":"executed","doc":"№64 от 13.03.2026","responsible":"Шаймарданов А.С."},
{"id":140,"division":"ЛТЦ, ЦТПСР, ЦЭиК","location":"с.Бесколь","region":"СКО","status":"executed","doc":"№102 от 31.03.2026","responsible":"Ванин М.М."},
{"id":141,"division":"УТО, ЦПХО","location":"с.Бесколь","region":"СКО","status":"executed","doc":"№103 от 31.03.2026","responsible":"Ванин М.М."},
{"id":142,"division":"ГП ЦРК","location":"с.Бесколь","region":"СКО","status":"executed","doc":"№104 от 31.03.2026","responsible":"Ванин М.М."}
];
let currentRegion = 'all';
function getStatusLabel(status) {
if (status === 'executed') return { text: 'Исполнено', class: 'success' };
if (status === 'control') return { text: 'На контроле', class: 'warning' };
if (status === 'overdue') return { text: 'Просрочено', class: 'danger' };
return { text: status, class: '' };
}
function updateDashboard() {
const filtered = currentRegion === 'all' ? DATA : DATA.filter(d => d.region === currentRegion);
const stats = { executed: 0, control: 0, overdue: 0 };
const kostanayStats = { executed: 0, control: 0, overdue: 0 };
const skoStats = { executed: 0, control: 0, overdue: 0 };
DATA.forEach(d => {
stats[d.status]++;
if (d.region === 'Костанай') kostanayStats[d.status]++;
else if (d.region === 'СКО') skoStats[d.status]++;
});
const total = filtered.length;
const completedPct = total > 0 ? Math.round((stats.executed / total) * 100) : 0;
const controlPct = total > 0 ? Math.round((stats.control / total) * 100) : 0;
const overduePct = total > 0 ? Math.round((stats.overdue / total) * 100) : 0;
document.getElementById('total').textContent = total;
document.getElementById('completed').textContent = stats.executed;
document.getElementById('inControl').textContent = stats.control;
document.getElementById('overdue').textContent = stats.overdue;
document.getElementById('completedPct').textContent = completedPct + '%';
document.getElementById('inControlPct').textContent = controlPct + '%';
document.getElementById('overduePct').textContent = overduePct + '%';
document.getElementById('kostanayCompleted').textContent = kostanayStats.executed;
document.getElementById('skoCompleted').textContent = skoStats.executed;
document.getElementById('totalOnControl').textContent = stats.control;
const progressCircle = document.querySelector('.progress-ring .progress');
const circumference = 2 * Math.PI * 52;
const offset = circumference - (completedPct / 100) * circumference;
progressCircle.style.strokeDashoffset = offset;
document.getElementById('progressPercent').textContent = completedPct + '%';
document.getElementById('completedBar').style.width = completedPct + '%';
document.getElementById('controlBar').style.width = controlPct + '%';
document.getElementById('overdueBar').style.width = overduePct + '%';
document.getElementById('completedVal').textContent = stats.executed;
document.getElementById('controlVal').textContent = stats.control;
document.getElementById('overdueVal').textContent = stats.overdue;
renderRegionChart(kostanayStats, skoStats);
renderDivisionCharts(filtered);
renderTable(filtered);
}
function renderRegionChart(kostanay, sko) {
const html = `
<div class="bar-item">
<div class="bar-label">Костанай: Исполнено</div>
<div class="bar-wrapper"><div class="bar success" style="width: ${Math.min(100, kostanay.executed * 2)}%"></div></div>
<div class="bar-value">${kostanay.executed}</div>
</div>
<div class="bar-item">
<div class="bar-label">Костанай: На контроле</div>
<div class="bar-wrapper"><div class="bar warning" style="width: ${Math.min(100, kostanay.control * 2)}%"></div></div>
<div class="bar-value">${kostanay.control}</div>
</div>
<div class="bar-item">
<div class="bar-label">СКО: Исполнено</div>
<div class="bar-wrapper"><div class="bar success" style="width: ${Math.min(100, sko.executed * 2)}%"></div></div>
<div class="bar-value">${sko.executed}</div>
</div>
<div class="bar-item">
<div class="bar-label">СКО: На контроле</div>
<div class="bar-wrapper"><div class="bar warning" style="width: ${Math.min(100, sko.control * 2)}%"></div></div>
<div class="bar-value">${sko.control}</div>
</div>
`;
document.getElementById('regionChart').innerHTML = html;
}
function renderDivisionCharts(data) {
function countByDivision(div, status) {
return data.filter(d => d.division.includes(div) && d.status === status).length;
}
const odsDivisions = ['ОДС', 'ЛТУ', 'ЛТЦ', 'ТУСМ', 'ЦТПСР', 'ЦЭиК'];
const sfDivisions = ['СФ', 'УТО', 'ЦПХО'];
const odsExecuted = data.filter(d => odsDivisions.some(div => d.division.includes(div)) && d.status === 'executed').length;
const odsControl = data.filter(d => odsDivisions.some(div => d.division.includes(div)) && d.status === 'control').length;
const sfExecuted = data.filter(d => sfDivisions.some(div => d.division.includes(div)) && d.status === 'executed').length;
const sfControl = data.filter(d => sfDivisions.some(div => d.division.includes(div)) && d.status === 'control').length;
document.getElementById('odsChart').innerHTML = `
<div class="bar-item">
<div class="bar-label">Исполнено</div>
<div class="bar-wrapper"><div class="bar success" style="width: ${Math.min(100, odsExecuted * 3)}%"></div></div>
<div class="bar-value">${odsExecuted}</div>
</div>
<div class="bar-item">
<div class="bar-label">На контроле</div>
<div class="bar-wrapper"><div class="bar warning" style="width: ${Math.min(100, odsControl * 3)}%"></div></div>
<div class="bar-value">${odsControl}</div>
</div>
`;
document.getElementById('sfChart').innerHTML = `
<div class="bar-item">
<div class="bar-label">Исполнено</div>
<div class="bar-wrapper"><div class="bar success" style="width: ${Math.min(100, sfExecuted * 3)}%"></div></div>
<div class="bar-value">${sfExecuted}</div>
</div>
<div class="bar-item">
<div class="bar-label">На контроле</div>
<div class="bar-wrapper"><div class="bar warning" style="width: ${Math.min(100, sfControl * 3)}%"></div></div>
<div class="bar-value">${sfControl}</div>
</div>
`;
}
function renderTable(data) {
const search = document.getElementById('searchInput').value.toLowerCase();
const divisionFilter = document.getElementById('divisionFilter').value;
const statusFilter = document.getElementById('statusFilter').value;
const filtered = data.filter(d => {
if (search && !d.location.toLowerCase().includes(search)) return false;
if (divisionFilter && !d.division.includes(divisionFilter)) return false;
if (statusFilter && d.status !== statusFilter) return false;
return true;
});
const html = filtered.slice(0, 100).map(d => {
const status = getStatusLabel(d.status);
return `
<tr>
<td>${d.id}</td>
<td>${d.division}</td>
<td>${d.location}</td>
<td>${d.region === 'СКО' ? 'Северо-Казахстанская' : 'Костанайская'}</td>
<td><span class="status-badge ${status.class}">${status.text}</span></td>
<td>${d.doc}</td>
<td>${d.responsible}</td>
</tr>
`;
}).join('');
document.getElementById('dataTable').innerHTML = html || '<tr><td colspan="7" style="text-align: center; padding: 40px;">Нет данных</td></tr>';
}
document.querySelectorAll('.region-btn').forEach(btn => {
btn.addEventListener('click', () => {
document.querySelectorAll('.region-btn').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
currentRegion = btn.dataset.region;
updateDashboard();
});
});
document.getElementById('searchInput').addEventListener('input', () => updateDashboard());
document.getElementById('divisionFilter').addEventListener('change', () => updateDashboard());
document.getElementById('statusFilter').addEventListener('change', () => updateDashboard());
updateDashboard();
</script>
</body>
</html>