fix: подключил KT AI DS правильными путями
This commit is contained in:
parent
556c257c44
commit
afb6bd88ea
228
index.html
228
index.html
@ -1,104 +1,95 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="ru">
|
<html lang="ru" data-theme="light">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>Топ услуг B2C по регионам</title>
|
<title>Топ услуг B2C по регионам</title>
|
||||||
<link rel="stylesheet" href="./design-system/fonts.css">
|
<link rel="stylesheet" href="./design-system/kt-ai-fonts.css">
|
||||||
<link rel="stylesheet" href="./design-system/variables.css">
|
<link rel="stylesheet" href="./design-system/kt-ai-tokens.css">
|
||||||
<link rel="stylesheet" href="./design-system/base.css">
|
<link rel="stylesheet" href="./design-system/kt-ai-components.css">
|
||||||
<link rel="stylesheet" href="./design-system/components.css">
|
<link rel="stylesheet" href="./design-system/kt-ai-page.css">
|
||||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
|
||||||
<style>
|
<style>
|
||||||
* { margin: 0; box-sizing: border-box; }
|
.dashboard-header {
|
||||||
body {
|
|
||||||
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
||||||
background: var(--kt-bg-secondary, #f5f5f7);
|
|
||||||
color: var(--kt-text-primary, #1a1a1a);
|
|
||||||
padding: 24px;
|
|
||||||
}
|
|
||||||
.container { max-width: 1400px; margin: 0 auto; }
|
|
||||||
|
|
||||||
.header {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
margin-bottom: 32px;
|
margin-bottom: 32px;
|
||||||
padding: 20px 24px;
|
padding: 20px 24px;
|
||||||
background: var(--kt-bg-primary, #ffffff);
|
background: var(--kt-ai-card-bg);
|
||||||
border-radius: 12px;
|
border-radius: var(--kt-ai-radius-xl);
|
||||||
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
|
border: 1px solid var(--kt-ai-border);
|
||||||
}
|
}
|
||||||
.header img { height: 48px; }
|
.dashboard-header img { height: 48px; }
|
||||||
.header h1 {
|
.dashboard-header h1 {
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: var(--kt-text-primary, #1a1a1a);
|
color: var(--kt-ai-fg);
|
||||||
}
|
}
|
||||||
.header-meta {
|
.header-meta {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: var(--kt-text-secondary, #6b7280);
|
color: var(--kt-ai-fg-muted);
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
.summary {
|
.summary-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
|
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
margin-bottom: 32px;
|
margin-bottom: 32px;
|
||||||
}
|
}
|
||||||
.card {
|
.kpi-card {
|
||||||
background: var(--kt-bg-primary, #ffffff);
|
background: var(--kt-ai-card-bg);
|
||||||
border-radius: 12px;
|
border-radius: var(--kt-ai-radius-xl);
|
||||||
padding: 24px;
|
padding: 24px;
|
||||||
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
|
border: 1px solid var(--kt-ai-border);
|
||||||
}
|
}
|
||||||
.card-label {
|
.kpi-label {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: var(--kt-text-secondary, #6b7280);
|
color: var(--kt-ai-fg-muted);
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
.card-value {
|
.kpi-value {
|
||||||
font-size: 32px;
|
font-size: 32px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: var(--kt-primary, #0096D7);
|
color: var(--kt-ai-primary);
|
||||||
}
|
}
|
||||||
.card-sub {
|
.kpi-sub {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
color: var(--kt-text-secondary, #6b7280);
|
color: var(--kt-ai-fg-faint);
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.charts {
|
.charts-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(2, 1fr);
|
grid-template-columns: repeat(2, 1fr);
|
||||||
gap: 24px;
|
gap: 24px;
|
||||||
margin-bottom: 32px;
|
margin-bottom: 32px;
|
||||||
}
|
}
|
||||||
@media (max-width: 1024px) {
|
@media (max-width: 1024px) {
|
||||||
.charts { grid-template-columns: 1fr; }
|
.charts-grid { grid-template-columns: 1fr; }
|
||||||
}
|
}
|
||||||
.chart-container {
|
.chart-card {
|
||||||
background: var(--kt-bg-primary, #ffffff);
|
background: var(--kt-ai-card-bg);
|
||||||
border-radius: 12px;
|
border-radius: var(--kt-ai-radius-xl);
|
||||||
padding: 24px;
|
padding: 24px;
|
||||||
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
|
border: 1px solid var(--kt-ai-border);
|
||||||
}
|
}
|
||||||
.chart-title {
|
.chart-title {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
color: var(--kt-text-primary, #1a1a1a);
|
color: var(--kt-ai-fg);
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-section {
|
.table-card {
|
||||||
background: var(--kt-bg-primary, #ffffff);
|
background: var(--kt-ai-card-bg);
|
||||||
border-radius: 12px;
|
border-radius: var(--kt-ai-radius-xl);
|
||||||
padding: 24px;
|
padding: 24px;
|
||||||
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
|
border: 1px solid var(--kt-ai-border);
|
||||||
}
|
}
|
||||||
.table-header {
|
.table-toolbar {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -109,7 +100,7 @@
|
|||||||
.table-title {
|
.table-title {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: var(--kt-text-primary, #1a1a1a);
|
color: var(--kt-ai-fg);
|
||||||
}
|
}
|
||||||
.filter-group {
|
.filter-group {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -118,81 +109,81 @@
|
|||||||
}
|
}
|
||||||
.filter-label {
|
.filter-label {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: var(--kt-text-secondary, #6b7280);
|
color: var(--kt-ai-fg-muted);
|
||||||
}
|
}
|
||||||
.filter-select {
|
.filter-select {
|
||||||
padding: 8px 12px;
|
padding: 8px 12px;
|
||||||
border: 1px solid var(--kt-border, #e5e7eb);
|
border: 1px solid var(--kt-ai-border);
|
||||||
border-radius: 8px;
|
border-radius: var(--kt-ai-radius-md);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
background: var(--kt-bg-primary, #ffffff);
|
background: var(--kt-ai-card-bg);
|
||||||
color: var(--kt-text-primary, #1a1a1a);
|
color: var(--kt-ai-fg);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.filter-select:focus {
|
.filter-select:focus {
|
||||||
outline: 2px solid var(--kt-primary, #0096D7);
|
outline: 2px solid var(--kt-ai-primary);
|
||||||
border-color: transparent;
|
border-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-wrapper {
|
.table-wrapper {
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
}
|
}
|
||||||
table {
|
.data-table {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
th {
|
.data-table th {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
padding: 12px 16px;
|
padding: 12px 16px;
|
||||||
background: var(--kt-bg-secondary, #f5f5f7);
|
background: var(--kt-ai-bg-soft);
|
||||||
color: var(--kt-text-secondary, #6b7280);
|
color: var(--kt-ai-fg-muted);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
border-bottom: 2px solid var(--kt-border, #e5e7eb);
|
border-bottom: 2px solid var(--kt-ai-border);
|
||||||
}
|
}
|
||||||
td {
|
.data-table td {
|
||||||
padding: 14px 16px;
|
padding: 14px 16px;
|
||||||
border-bottom: 1px solid var(--kt-border, #e5e7eb);
|
border-bottom: 1px solid var(--kt-ai-border);
|
||||||
color: var(--kt-text-primary, #1a1a1a);
|
color: var(--kt-ai-fg);
|
||||||
}
|
}
|
||||||
tr:hover {
|
.data-table tr:hover {
|
||||||
background: var(--kt-bg-secondary, #f5f5f7);
|
background: var(--kt-ai-bg-soft);
|
||||||
}
|
}
|
||||||
.rank {
|
.rank-badge {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
width: 28px;
|
width: 28px;
|
||||||
height: 28px;
|
height: 28px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background: var(--kt-primary, #0096D7);
|
background: var(--kt-ai-primary);
|
||||||
color: white;
|
color: white;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
.amount {
|
.amount-cell {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: var(--kt-text-primary, #1a1a1a);
|
color: var(--kt-ai-fg);
|
||||||
}
|
}
|
||||||
.region-tag {
|
.region-chip {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 4px 10px;
|
padding: 4px 10px;
|
||||||
background: var(--kt-bg-secondary, #f5f5f7);
|
background: var(--kt-ai-bg-soft);
|
||||||
border-radius: 6px;
|
border-radius: var(--kt-ai-radius-md);
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
color: var(--kt-text-primary, #1a1a1a);
|
color: var(--kt-ai-fg);
|
||||||
}
|
}
|
||||||
|
|
||||||
.empty-state {
|
.empty-state {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 48px 24px;
|
padding: 48px 24px;
|
||||||
color: var(--kt-text-secondary, #6b7280);
|
color: var(--kt-ai-fg-muted);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="kt-ai-wrap">
|
||||||
<header class="header">
|
<header class="dashboard-header">
|
||||||
<img src="./kt-logo.svg" alt="Казахтелеком" height="48">
|
<img src="./kt-logo.svg" alt="Казахтелеком" height="48">
|
||||||
<h1>Топ услуг B2C по регионам</h1>
|
<h1>Топ услуг B2C по регионам</h1>
|
||||||
<div class="header-meta">
|
<div class="header-meta">
|
||||||
@ -201,21 +192,21 @@
|
|||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<section class="summary" id="summary"></section>
|
<section class="summary-grid" id="summary"></section>
|
||||||
|
|
||||||
<section class="charts">
|
<section class="charts-grid">
|
||||||
<div class="chart-container">
|
<div class="chart-card">
|
||||||
<h2 class="chart-title">Топ-10 регионов по количеству покупок</h2>
|
<h2 class="chart-title">Топ-10 регионов по количеству покупок</h2>
|
||||||
<canvas id="regionChart"></canvas>
|
<canvas id="regionChart"></canvas>
|
||||||
</div>
|
</div>
|
||||||
<div class="chart-container">
|
<div class="chart-card">
|
||||||
<h2 class="chart-title">Топ-10 услуг по количеству покупок</h2>
|
<h2 class="chart-title">Топ-10 услуг по количеству покупок</h2>
|
||||||
<canvas id="serviceChart"></canvas>
|
<canvas id="serviceChart"></canvas>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="table-section">
|
<section class="table-card">
|
||||||
<div class="table-header">
|
<div class="table-toolbar">
|
||||||
<h2 class="table-title">Детализация по услугам</h2>
|
<h2 class="table-title">Детализация по услугам</h2>
|
||||||
<div class="filter-group">
|
<div class="filter-group">
|
||||||
<label class="filter-label" for="regionFilter">Регион:</label>
|
<label class="filter-label" for="regionFilter">Регион:</label>
|
||||||
@ -225,7 +216,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="table-wrapper">
|
<div class="table-wrapper">
|
||||||
<table>
|
<table class="data-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>#</th>
|
<th>#</th>
|
||||||
@ -242,7 +233,6 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Исходные данные из брифа
|
|
||||||
const RAW_DATA = [
|
const RAW_DATA = [
|
||||||
{ region: "Астана", service: "B2C Абонплата ШПД по FTTx ГТС (New)", qty: 37372, amount: 238463786.09 },
|
{ region: "Астана", service: "B2C Абонплата ШПД по FTTx ГТС (New)", qty: 37372, amount: 238463786.09 },
|
||||||
{ region: "г.Алматы", service: "B2C Абонплата ШПД по FTTx ГТС (New)", qty: 39671, amount: 237005698.16 },
|
{ region: "г.Алматы", service: "B2C Абонплата ШПД по FTTx ГТС (New)", qty: 39671, amount: 237005698.16 },
|
||||||
@ -296,7 +286,6 @@
|
|||||||
{ region: "г.Караганда", service: "2022 B2C Абонплата за мобильный номер MT-C GSM закр.", qty: 15714, amount: 28837871.98 }
|
{ region: "г.Караганда", service: "2022 B2C Абонплата за мобильный номер MT-C GSM закр.", qty: 15714, amount: 28837871.98 }
|
||||||
];
|
];
|
||||||
|
|
||||||
// Форматирование чисел
|
|
||||||
function fmtNum(n) {
|
function fmtNum(n) {
|
||||||
return n.toString().replace(/\D/g, '').replace(/\B(?=(\d{3})+(?!\d))/g, " ");
|
return n.toString().replace(/\D/g, '').replace(/\B(?=(\d{3})+(?!\d))/g, " ");
|
||||||
}
|
}
|
||||||
@ -304,7 +293,6 @@
|
|||||||
return n.toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$& ') + ' ₸';
|
return n.toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$& ') + ' ₸';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Агрегация данных
|
|
||||||
function aggregate() {
|
function aggregate() {
|
||||||
const byRegion = {};
|
const byRegion = {};
|
||||||
const byService = {};
|
const byService = {};
|
||||||
@ -329,35 +317,33 @@
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Рендер сводных плиток
|
|
||||||
function renderSummary() {
|
function renderSummary() {
|
||||||
const agg = aggregate();
|
const agg = aggregate();
|
||||||
const container = document.getElementById('summary');
|
const container = document.getElementById('summary');
|
||||||
container.innerHTML = `
|
container.innerHTML = `
|
||||||
<div class="card">
|
<div class="kpi-card">
|
||||||
<div class="card-label">Всего покупок</div>
|
<div class="kpi-label">Всего покупок</div>
|
||||||
<div class="card-value">${fmtNum(agg.totalQty)}</div>
|
<div class="kpi-value">${fmtNum(agg.totalQty)}</div>
|
||||||
<div class="card-sub">за июль 2026</div>
|
<div class="kpi-sub">за июль 2026</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card">
|
<div class="kpi-card">
|
||||||
<div class="card-label">Всего регионов</div>
|
<div class="kpi-label">Всего регионов</div>
|
||||||
<div class="card-value">${agg.totalRegions}</div>
|
<div class="kpi-value">${agg.totalRegions}</div>
|
||||||
<div class="card-sub">в топ-50</div>
|
<div class="kpi-sub">в топ-50</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card">
|
<div class="kpi-card">
|
||||||
<div class="card-label">Услуга-лидер</div>
|
<div class="kpi-label">Услуга-лидер</div>
|
||||||
<div class="card-value" style="font-size:18px;line-height:1.4">${agg.topService}</div>
|
<div class="kpi-value" style="font-size:18px;line-height:1.4">${agg.topService}</div>
|
||||||
<div class="card-sub">по количеству покупок</div>
|
<div class="kpi-sub">по количеству покупок</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card">
|
<div class="kpi-card">
|
||||||
<div class="card-label">Регион-лидер</div>
|
<div class="kpi-label">Регион-лидер</div>
|
||||||
<div class="card-value">${agg.topRegion}</div>
|
<div class="kpi-value">${agg.topRegion}</div>
|
||||||
<div class="card-sub">больше всего покупок</div>
|
<div class="kpi-sub">больше всего покупок</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Графики
|
|
||||||
let regionChartInstance = null;
|
let regionChartInstance = null;
|
||||||
let serviceChartInstance = null;
|
let serviceChartInstance = null;
|
||||||
|
|
||||||
@ -367,11 +353,10 @@
|
|||||||
const top10Services = agg.services.slice(0, 10);
|
const top10Services = agg.services.slice(0, 10);
|
||||||
|
|
||||||
const colors = [
|
const colors = [
|
||||||
'#0096D7', '#0077A8', '#005F87', '#004A6B', '#003852',
|
'var(--kt-ai-primary)', '#0077A8', '#005F87', '#004A6B', '#003852',
|
||||||
'#00C7E3', '#00A3C7', '#0087B0', '#006B94', '#005278'
|
'#00C7E3', '#00A3C7', '#0087B0', '#006B94', '#005278'
|
||||||
];
|
];
|
||||||
|
|
||||||
// Регионы
|
|
||||||
const ctx1 = document.getElementById('regionChart').getContext('2d');
|
const ctx1 = document.getElementById('regionChart').getContext('2d');
|
||||||
if (regionChartInstance) regionChartInstance.destroy();
|
if (regionChartInstance) regionChartInstance.destroy();
|
||||||
regionChartInstance = new Chart(ctx1, {
|
regionChartInstance = new Chart(ctx1, {
|
||||||
@ -387,22 +372,14 @@
|
|||||||
},
|
},
|
||||||
options: {
|
options: {
|
||||||
responsive: true,
|
responsive: true,
|
||||||
plugins: {
|
plugins: { legend: { display: false } },
|
||||||
legend: { display: false }
|
|
||||||
},
|
|
||||||
scales: {
|
scales: {
|
||||||
y: {
|
y: { beginAtZero: true, grid: { color: 'rgba(0,0,0,0.05)' } },
|
||||||
beginAtZero: true,
|
x: { grid: { display: false } }
|
||||||
grid: { color: '#f0f0f0' }
|
|
||||||
},
|
|
||||||
x: {
|
|
||||||
grid: { display: false }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Услуги
|
|
||||||
const ctx2 = document.getElementById('serviceChart').getContext('2d');
|
const ctx2 = document.getElementById('serviceChart').getContext('2d');
|
||||||
if (serviceChartInstance) serviceChartInstance.destroy();
|
if (serviceChartInstance) serviceChartInstance.destroy();
|
||||||
serviceChartInstance = new Chart(ctx2, {
|
serviceChartInstance = new Chart(ctx2, {
|
||||||
@ -419,23 +396,15 @@
|
|||||||
options: {
|
options: {
|
||||||
indexAxis: 'y',
|
indexAxis: 'y',
|
||||||
responsive: true,
|
responsive: true,
|
||||||
plugins: {
|
plugins: { legend: { display: false } },
|
||||||
legend: { display: false }
|
|
||||||
},
|
|
||||||
scales: {
|
scales: {
|
||||||
x: {
|
x: { beginAtZero: true, grid: { color: 'rgba(0,0,0,0.05)' } },
|
||||||
beginAtZero: true,
|
y: { grid: { display: false } }
|
||||||
grid: { color: '#f0f0f0' }
|
|
||||||
},
|
|
||||||
y: {
|
|
||||||
grid: { display: false }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Таблица
|
|
||||||
function renderTable(filterRegion = '') {
|
function renderTable(filterRegion = '') {
|
||||||
const tbody = document.getElementById('tableBody');
|
const tbody = document.getElementById('tableBody');
|
||||||
let filtered = RAW_DATA;
|
let filtered = RAW_DATA;
|
||||||
@ -451,16 +420,15 @@
|
|||||||
|
|
||||||
tbody.innerHTML = filtered.map((r, i) => `
|
tbody.innerHTML = filtered.map((r, i) => `
|
||||||
<tr>
|
<tr>
|
||||||
<td><span class="rank">${i + 1}</span></td>
|
<td><span class="rank-badge">${i + 1}</span></td>
|
||||||
<td><span class="region-tag">${r.region}</span></td>
|
<td><span class="region-chip">${r.region}</span></td>
|
||||||
<td>${r.service}</td>
|
<td>${r.service}</td>
|
||||||
<td>${fmtNum(r.qty)}</td>
|
<td>${fmtNum(r.qty)}</td>
|
||||||
<td class="amount">${fmtAmount(r.amount)}</td>
|
<td class="amount-cell">${fmtAmount(r.amount)}</td>
|
||||||
</tr>
|
</tr>
|
||||||
`).join('');
|
`).join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Заполнение фильтра регионов
|
|
||||||
function initFilter() {
|
function initFilter() {
|
||||||
const select = document.getElementById('regionFilter');
|
const select = document.getElementById('regionFilter');
|
||||||
const regions = [...new Set(RAW_DATA.map(r => r.region))].sort();
|
const regions = [...new Set(RAW_DATA.map(r => r.region))].sort();
|
||||||
@ -477,13 +445,11 @@
|
|||||||
localStorage.setItem('b2c_region_filter', e.target.value);
|
localStorage.setItem('b2c_region_filter', e.target.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Восстановление из localStorage
|
|
||||||
const saved = localStorage.getItem('b2c_region_filter') || '';
|
const saved = localStorage.getItem('b2c_region_filter') || '';
|
||||||
select.value = saved;
|
select.value = saved;
|
||||||
renderTable(saved);
|
renderTable(saved);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Инициализация
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
renderSummary();
|
renderSummary();
|
||||||
renderCharts();
|
renderCharts();
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user