Hide department KPI card, "Загрузка по сотрудникам" card, and the assignee filter for non-director sessions. The tasks table title swaps to "Мои поручения" for employees. Calendar dots and the upcoming-tasks widget now show only the current user's tasks when not director. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
299 lines
14 KiB
HTML
299 lines
14 KiB
HTML
<!doctype html>
|
||
<html lang="ru">
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||
<meta http-equiv="Cache-Control" content="no-store, no-cache, must-revalidate" />
|
||
<meta http-equiv="Pragma" content="no-cache" />
|
||
<meta http-equiv="Expires" content="0" />
|
||
<title>ДВГО — Помощник руководителя</title>
|
||
<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=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr@4.6.13/dist/flatpickr.min.css">
|
||
<link rel="stylesheet" href="styles.css?v=33" />
|
||
</head>
|
||
<body>
|
||
<header class="topbar">
|
||
<div class="topbar-left">
|
||
<div class="menu-host">
|
||
<button id="menuBtn" class="menu-btn" aria-label="Открыть меню" aria-haspopup="true" aria-expanded="false">
|
||
<span></span><span></span><span></span>
|
||
</button>
|
||
<div id="menuPanel" class="menu-panel" role="menu" hidden>
|
||
<a href="#/home" class="menu-item" data-view="home" role="menuitem">
|
||
<span class="menu-icon">🏠</span>
|
||
<span class="menu-text">
|
||
<span class="menu-title">Главная</span>
|
||
<span class="menu-sub">Время, погода, новости отрасли</span>
|
||
</span>
|
||
</a>
|
||
<a href="#/create" class="menu-item director-only" data-view="create" role="menuitem">
|
||
<span class="menu-icon">+</span>
|
||
<span class="menu-text">
|
||
<span class="menu-title">Создать поручение</span>
|
||
<span class="menu-sub">Форма ввода нового поручения</span>
|
||
</span>
|
||
</a>
|
||
<a href="#/analytics" class="menu-item" data-view="analytics" role="menuitem">
|
||
<span class="menu-icon">📊</span>
|
||
<span class="menu-text">
|
||
<span class="menu-title">Аналитика</span>
|
||
<span class="menu-sub">Сводка, фильтры, графики</span>
|
||
</span>
|
||
</a>
|
||
</div>
|
||
</div>
|
||
<a href="#/home" class="brand" id="brandHome" title="На главную">
|
||
<img src="icon.jpg" alt="" class="logo" />
|
||
<span class="brand-mark">
|
||
<span class="brand-mark-primary">GR</span>
|
||
<span class="brand-mark-divider" aria-hidden="true"></span>
|
||
<span class="brand-mark-secondary">Department</span>
|
||
</span>
|
||
</a>
|
||
</div>
|
||
<div class="who">
|
||
<div id="userChip" class="user-chip" hidden>
|
||
<button id="profileBtn" class="user-chip-main" type="button" title="Профиль">
|
||
<span class="user-chip-avatar" id="userChipAvatar">—</span>
|
||
<span class="user-chip-text">
|
||
<span class="user-chip-name" id="userChipName">—</span>
|
||
<span class="user-chip-role" id="userChipRole">—</span>
|
||
</span>
|
||
</button>
|
||
<button id="logoutBtn" class="btn btn-ghost" type="button" title="Выйти">Выйти</button>
|
||
</div>
|
||
<button id="resetDemo" class="btn btn-ghost" title="Очистить данные и пересоздать демо">↺ Сброс демо</button>
|
||
</div>
|
||
</header>
|
||
|
||
<!-- Профиль / смена пароля -->
|
||
<div id="profileModal" class="modal" hidden>
|
||
<div class="modal-backdrop" id="profileBackdrop"></div>
|
||
<div class="modal-card" role="dialog" aria-modal="true" aria-labelledby="profileTitle">
|
||
<button id="profileClose" class="modal-close" type="button" aria-label="Закрыть">×</button>
|
||
<h2 id="profileTitle" class="modal-title">Личный кабинет</h2>
|
||
<div class="profile-head">
|
||
<div class="profile-name" id="profileName">—</div>
|
||
<div class="profile-role" id="profileRole">—</div>
|
||
</div>
|
||
<h3 class="modal-sub">Смена пароля</h3>
|
||
<form id="profileForm" class="login-form">
|
||
<label>Текущий пароль
|
||
<input id="pwdCurrent" type="password" autocomplete="current-password" required />
|
||
</label>
|
||
<label>Новый пароль
|
||
<input id="pwdNew" type="password" autocomplete="new-password" minlength="4" required />
|
||
</label>
|
||
<label>Подтвердите новый
|
||
<input id="pwdConfirm" type="password" autocomplete="new-password" minlength="4" required />
|
||
</label>
|
||
<div id="profileError" class="login-error" hidden></div>
|
||
<div id="profileSuccess" class="login-success" hidden>Пароль обновлён.</div>
|
||
<button type="submit" class="btn btn-primary">Сохранить</button>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Логин -->
|
||
<div id="loginOverlay" class="login-overlay" hidden>
|
||
<div class="login-card">
|
||
<div class="login-brand">
|
||
<img src="icon.jpg" alt="" class="login-logo" />
|
||
<div>
|
||
<div class="login-title">GR Department</div>
|
||
<div class="login-sub">Помощник руководителя · ДВГО</div>
|
||
</div>
|
||
</div>
|
||
<h1 class="login-h1">Вход</h1>
|
||
<form id="loginForm" class="login-form">
|
||
<label>Сотрудник
|
||
<select id="loginUser" required></select>
|
||
</label>
|
||
<label id="loginPwdLabel" hidden>Пароль
|
||
<input id="loginPwd" type="password" autocomplete="current-password" placeholder="Введите пароль" />
|
||
</label>
|
||
<div id="loginError" class="login-error" hidden>Неверный пароль.</div>
|
||
<button type="submit" class="btn btn-primary">Войти</button>
|
||
<p class="login-hint">Если забыли пароль — попросите Абделазиза сбросить через личный кабинет.</p>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<main>
|
||
|
||
<!-- Главная -->
|
||
<div id="view-home" class="view">
|
||
<div class="home-grid">
|
||
<section class="card home-clock">
|
||
<div class="lbl">Сегодня</div>
|
||
<div class="clock-date" id="clockDate">—</div>
|
||
<div class="clock-time" id="clockTime">—</div>
|
||
<div class="clock-tz">Время в Астане · UTC+5</div>
|
||
</section>
|
||
|
||
<section class="card home-weather">
|
||
<div class="lbl">Погода · Астана</div>
|
||
<div id="weatherBox" class="weather-box">
|
||
<div class="weather-loading">Загружаем данные…</div>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
|
||
<div class="home-row2">
|
||
<section class="card home-calendar">
|
||
<div class="cal-head">
|
||
<h2>Календарь</h2>
|
||
<div class="cal-nav">
|
||
<button class="cal-btn" id="calPrev" type="button" aria-label="Предыдущий месяц">‹</button>
|
||
<span class="cal-title" id="calTitle">—</span>
|
||
<button class="cal-btn" id="calNext" type="button" aria-label="Следующий месяц">›</button>
|
||
</div>
|
||
</div>
|
||
<div class="cal-weekdays" aria-hidden="true">
|
||
<span>Пн</span><span>Вт</span><span>Ср</span><span>Чт</span><span>Пт</span><span>Сб</span><span>Вс</span>
|
||
</div>
|
||
<div class="cal-grid" id="calGrid"></div>
|
||
<p class="hint cal-hint">Точки — задачи с дедлайнами. Нажмите день, чтобы перейти в аналитику.</p>
|
||
</section>
|
||
|
||
<section class="card home-tasks">
|
||
<div class="tasks-head">
|
||
<h2>Ближайшие задачи</h2>
|
||
<a href="#/analytics" class="tasks-all">Все →</a>
|
||
</div>
|
||
<ul id="upcomingList" class="upcoming-list">
|
||
<li class="upcoming-empty">Загружаем…</li>
|
||
</ul>
|
||
</section>
|
||
</div>
|
||
|
||
<section class="card">
|
||
<div class="news-header">
|
||
<h2>Новости отрасли</h2>
|
||
<button id="refreshNews" class="btn btn-ghost" title="Обновить">↻ Обновить</button>
|
||
</div>
|
||
<ul id="newsList" class="news-list">
|
||
<li class="news-loading">Загружаем заголовки…</li>
|
||
</ul>
|
||
<p class="hint" id="newsSource">—</p>
|
||
</section>
|
||
</div>
|
||
|
||
<!-- Создать поручение -->
|
||
<div id="view-create" class="view" hidden>
|
||
<section class="card">
|
||
<h2>Новое поручение</h2>
|
||
<form id="taskForm" class="grid">
|
||
<label>Заголовок<input type="text" name="title" required placeholder="Подготовить позицию по проекту НПА" /></label>
|
||
<label>Дедлайн<input type="date" name="deadline" required /></label>
|
||
|
||
<label>Исполнитель<select name="assignee" required></select></label>
|
||
<label>Направление<select name="direction"></select></label>
|
||
|
||
<label class="full">Описание<textarea name="description" rows="3" placeholder="Краткая суть, контекст, ожидаемый результат"></textarea></label>
|
||
|
||
<div class="actions full">
|
||
<button type="submit" class="btn btn-primary">+ Создать поручение</button>
|
||
<span class="hint">Приоритет назначится автоматически. Можно изменить вручную в аналитике.</span>
|
||
</div>
|
||
</form>
|
||
</section>
|
||
</div>
|
||
|
||
<!-- Аналитика -->
|
||
<div id="view-analytics" class="view" hidden>
|
||
<section class="card director-only">
|
||
<h2>Сводка по департаменту</h2>
|
||
<div class="kpis">
|
||
<div class="kpi"><div class="kpi-num" id="kpiActive">0</div><div class="kpi-lbl">Активных задач</div></div>
|
||
<div class="kpi"><div class="kpi-num" id="kpiOverdue">0</div><div class="kpi-lbl">Просрочено</div></div>
|
||
<div class="kpi"><div class="kpi-num" id="kpiSoon">0</div><div class="kpi-lbl">Дедлайн ≤ 3 дн</div></div>
|
||
<div class="kpi"><div class="kpi-num" id="kpiDone">0</div><div class="kpi-lbl">Выполнено</div></div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="card director-only">
|
||
<h2>Загрузка по сотрудникам</h2>
|
||
<div class="load" id="loadByAssignee"></div>
|
||
<p class="hint">Нажмите на сотрудника, чтобы отфильтровать таблицу.</p>
|
||
</section>
|
||
|
||
<section class="card">
|
||
<h2 class="director-only">Все поручения</h2>
|
||
<h2 class="employee-only">Мои поручения</h2>
|
||
<div class="filters">
|
||
<select id="fAssignee" class="director-only"><option value="">Все исполнители</option></select>
|
||
<select id="fStatus">
|
||
<option value="">Все статусы</option>
|
||
<option value="new">Новая</option>
|
||
<option value="in_progress">В работе</option>
|
||
<option value="done">Выполнена</option>
|
||
<option value="overdue">Просрочена</option>
|
||
</select>
|
||
<select id="fDirection"><option value="">Все направления</option></select>
|
||
<select id="fPriority">
|
||
<option value="">Все приоритеты</option>
|
||
<option value="high">Высокий</option>
|
||
<option value="medium">Средний</option>
|
||
<option value="low">Низкий</option>
|
||
</select>
|
||
<button id="clearFilters" class="btn btn-ghost">Сбросить фильтры</button>
|
||
</div>
|
||
|
||
<table id="tasksTable">
|
||
<thead>
|
||
<tr>
|
||
<th>Заголовок</th>
|
||
<th>Исполнитель</th>
|
||
<th>Направление</th>
|
||
<th>Дедлайн</th>
|
||
<th>Приоритет</th>
|
||
<th>Статус</th>
|
||
<th>Действия</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="tasksBody"></tbody>
|
||
</table>
|
||
<p id="emptyHint" class="hint" hidden>Нет поручений по текущим фильтрам.</p>
|
||
</section>
|
||
|
||
<section class="card">
|
||
<h2>Задачи по сотрудникам (по статусу)</h2>
|
||
<div class="chart-wrap"><canvas id="chartStatus"></canvas></div>
|
||
</section>
|
||
|
||
<section class="card">
|
||
<h2>Задачи по сотрудникам (по приоритету)</h2>
|
||
<div class="chart-wrap"><canvas id="chartPriority"></canvas></div>
|
||
</section>
|
||
|
||
<div class="charts-row">
|
||
<section class="card">
|
||
<h2>Распределение по дедлайнам</h2>
|
||
<div class="chart-wrap small"><canvas id="chartDeadlines"></canvas></div>
|
||
</section>
|
||
<section class="card">
|
||
<h2>Задачи по направлениям</h2>
|
||
<div class="chart-wrap small"><canvas id="chartDirections"></canvas></div>
|
||
</section>
|
||
</div>
|
||
|
||
<section class="card">
|
||
<h2>Поступление задач в ближайшие 14 дней</h2>
|
||
<div class="chart-wrap"><canvas id="chartTimeline"></canvas></div>
|
||
</section>
|
||
</div>
|
||
|
||
</main>
|
||
|
||
<div id="toast" class="toast" role="status" aria-live="polite" hidden></div>
|
||
|
||
<script src="https://cdn.jsdelivr.net/npm/flatpickr@4.6.13/dist/flatpickr.min.js"></script>
|
||
<script src="https://cdn.jsdelivr.net/npm/flatpickr@4.6.13/dist/l10n/ru.js"></script>
|
||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>
|
||
<script src="app.js?v=30"></script>
|
||
</body>
|
||
</html>
|