266 lines
14 KiB
HTML
266 lines
14 KiB
HTML
{% extends "base.html" %}
|
||
{% block title %}Дни рождения{% endblock %}
|
||
|
||
{% block styles %}
|
||
<link href="/static/css/birthdate.css" rel="stylesheet">
|
||
{% endblock %}
|
||
|
||
{% block content %}
|
||
<!-- Заголовок -->
|
||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||
<div>
|
||
<h2 class="mb-1"><i class="bi bi-balloon-heart-fill text-pink me-2"></i>Дни рождения</h2>
|
||
<p class="text-muted mb-0">Управление поздравлениями сотрудников</p>
|
||
</div>
|
||
<div class="badge bg-pink fs-6 px-3 py-2">
|
||
<i class="bi bi-calendar-heart me-1"></i>Поздравления
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Основной контент -->
|
||
<div class="row g-4 mb-3">
|
||
<!-- Левая колонка: Список сотрудников -->
|
||
<div class="col-lg-7">
|
||
<div class="card h-100">
|
||
<div class="card-header d-flex justify-content-between align-items-center">
|
||
<h5 class="mb-0"><i class="bi bi-people-fill me-2"></i>Сотрудники (<span id="usersCount">0</span>)</h5>
|
||
<button type="button" class="btn btn-sm btn-outline-primary" onclick="refreshUsersList()">
|
||
<i class="bi bi-arrow-clockwise me-1"></i>Обновить список
|
||
</button>
|
||
</div>
|
||
<div class="card-body p-0">
|
||
<!-- Таблица сотрудников -->
|
||
<div class="table-responsive">
|
||
<table class="table table-hover mb-0" id="usersTable">
|
||
<thead class="table-light">
|
||
<tr>
|
||
<th width="120">Дата рождения</th>
|
||
<th>Имя</th>
|
||
<th>Короткое имя</th>
|
||
<th>Полная дата<br><small>(возраст)</small></th>
|
||
<th>Пол</th>
|
||
<th>Специальности</th>
|
||
<th width="100" class="text-center">Статус</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="usersTableBody">
|
||
<!-- Данные будут загружены через JS -->
|
||
<tr>
|
||
<td colspan="8" class="text-center py-5">
|
||
<div class="spinner-border text-primary" role="status">
|
||
<span class="visually-hidden">Загрузка...</span>
|
||
</div>
|
||
</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
<div class="card-footer">
|
||
<div class="row g-2">
|
||
<div class="col-md-6">
|
||
<button type="button" class="btn btn-sm btn-outline-success w-100" onclick="enableAllUsers()">
|
||
<i class="bi bi-check-circle me-1"></i>Поздравлять всех
|
||
</button>
|
||
</div>
|
||
<div class="col-md-6">
|
||
<button type="button" class="btn btn-sm btn-outline-secondary w-100"
|
||
onclick="disableAllUsers()">
|
||
<i class="bi bi-x-circle me-1"></i>Не поздравлять никого
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Правая колонка: Данные сотрудника и планировщик -->
|
||
<div class="col-lg-5">
|
||
<!-- Данные выбранного сотрудника -->
|
||
<div class="card mb-4">
|
||
<div class="card-header">
|
||
<h5 class="mb-0">
|
||
<i class="bi bi-person-badge me-2"></i>
|
||
<span id="selectedUserName">Выберите сотрудника</span>
|
||
</h5>
|
||
</div>
|
||
<div class="card-body">
|
||
<form id="userForm">
|
||
<input type="hidden" id="userId">
|
||
|
||
<!-- Переключатель enabled -->
|
||
<div class="mb-4">
|
||
<div class="form-check form-switch d-flex align-items-center gap-2 p-0">
|
||
<input class="form-check-input m-0" type="checkbox" role="switch" id="user_enabled"
|
||
onchange="markUserChanged()">
|
||
<label class="form-check-label fw-semibold mb-0" for="user_enabled">
|
||
Включить поздравление для этого сотрудника
|
||
</label>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Ссылка на фото -->
|
||
<div class="mb-4">
|
||
<label class="form-label fw-semibold">
|
||
<i class="bi bi-image me-2"></i>Ссылка на фото для поздравления
|
||
</label>
|
||
<input type="url" class="form-control" id="photo_link"
|
||
placeholder="https://vk.com/groupname?z=photo-27937673_457248154"
|
||
oninput="markUserChanged()">
|
||
<div class="form-text">
|
||
Ссылка на изображение для поздравления. Должна быть доступна для всех. Лишние символы в
|
||
ссылке будут удалены автоматически.
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Текст поздравления -->
|
||
<div class="mb-4">
|
||
<label class="form-label fw-semibold">
|
||
<i class="bi bi-chat-heart me-2"></i>Текст поздравления
|
||
</label>
|
||
<textarea class="form-control" id="congratulations" rows="5"
|
||
placeholder="Дорогой(ая) [Имя], поздравляем с днем рождения! 🎉"
|
||
oninput="markUserChanged()"></textarea>
|
||
<div class="form-text">
|
||
Не поддерживается никакая разметка. Только текст и эмоджи. Максимум 2000 символов.
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Информация о посте -->
|
||
<div id="postInfo" style="display: none;">
|
||
<div class="alert alert-info">
|
||
<h6 class="alert-heading"><i class="bi bi-info-circle me-2"></i>Информация о посте</h6>
|
||
<div class="mb-2" id="postLinkContainer">
|
||
<!-- Ссылка на пост будет здесь -->
|
||
</div>
|
||
<div class="small" id="publishTime">
|
||
<!-- Время публикации будет здесь -->
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Кнопка сохранения -->
|
||
<div class="d-flex gap-2 pt-3 border-top">
|
||
<button type="button" class="btn btn-outline-secondary" onclick="resetUserForm()">
|
||
<i class="bi bi-x-lg me-1"></i>Отмена
|
||
</button>
|
||
<button type="button" class="btn btn-primary" id="saveUserButton" onclick="saveUserData()"
|
||
disabled>
|
||
<i class="bi bi-save me-1"></i>Сохранить данные сотрудника
|
||
</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Настройки планировщика -->
|
||
<div class="card">
|
||
<div class="card-header d-flex justify-content-between align-items-center">
|
||
<h5 class="mb-0"><i class="bi bi-clock me-2"></i>Настройки планировщика</h5>
|
||
<span id="schedulerStatus" class="badge">
|
||
{% if data.schedulerStatus.scheduler %}
|
||
<span class="badge bg-success"><i class="bi bi-play-circle me-1"></i>Активен</span>
|
||
{% else %}
|
||
<span class="badge bg-secondary"><i class="bi bi-stop-circle me-1"></i>Неактивен</span>
|
||
{% endif %}
|
||
</span>
|
||
</div>
|
||
<div class="card-body">
|
||
<form id="schedulerForm">
|
||
<!-- Время запуска -->
|
||
<div class="row g-3 mb-3">
|
||
<div class="col-md-6">
|
||
<label class="form-label fw-semibold">Час запуска</label>
|
||
<input type="number" class="form-control" id="scheduler_hour" min="0" max="23"
|
||
placeholder="9"
|
||
value="{{ data.schedulerSettings.hour if data.schedulerSettings else 9 }}"
|
||
oninput="markSchedulerChanged()">
|
||
</div>
|
||
<div class="col-md-6">
|
||
<label class="form-label fw-semibold">Минута запуска</label>
|
||
<input type="number" class="form-control" id="scheduler_minute" min="0" max="59"
|
||
placeholder="0"
|
||
value="{{ data.schedulerSettings.minute if data.schedulerSettings else 0 }}"
|
||
oninput="markSchedulerChanged()">
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Включение планировщика -->
|
||
<div class="mb-4">
|
||
<div class="form-check form-switch d-flex align-items-center gap-2 p-0">
|
||
<input class="form-check-input m-0" type="checkbox" role="switch" id="scheduler_enabled" {%
|
||
if data.schedulerSettings and data.schedulerSettings.enabled %}checked{% endif %}
|
||
onchange="markSchedulerChanged()">
|
||
<label class="form-check-label fw-semibold mb-0" for="scheduler_enabled">
|
||
Включить автоматическую публикацию
|
||
</label>
|
||
</div>
|
||
<div class="form-text">
|
||
Планировщик будет проверять дни рождения и публиковать поздравления ежедневно в
|
||
указанное время.
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Информация о следующем запуске -->
|
||
{% if data.schedulerStatus.next_run_time %}
|
||
<div class="alert alert-success">
|
||
<div class="d-flex align-items-center">
|
||
<i class="bi bi-calendar-event fs-5 me-3"></i>
|
||
<div>
|
||
<h6 class="alert-heading mb-1">Следующий запуск</h6>
|
||
<p class="mb-0">{{ data.schedulerStatus.next_run_time }}</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{% endif %}
|
||
|
||
<!-- Кнопка сохранения -->
|
||
<div class="d-flex gap-2 pt-3 border-top">
|
||
<button type="button" class="btn btn-outline-secondary" onclick="resetSchedulerForm()">
|
||
<i class="bi bi-x-lg me-1"></i>Сбросить
|
||
</button>
|
||
<button type="button" class="btn btn-warning" id="saveSchedulerButton"
|
||
onclick="saveSchedulerSettings()" disabled>
|
||
<i class="bi bi-save me-1"></i>Сохранить настройки планировщика
|
||
</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Модальное окно для подтверждения сохранения -->
|
||
<div class="modal fade" id="confirmModal" tabindex="-1" aria-hidden="true">
|
||
<div class="modal-dialog">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h5 class="modal-title"><i class="bi bi-exclamation-triangle text-warning me-2"></i>Несохраненные
|
||
изменения</h5>
|
||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<p>У вас есть несохраненные изменения для сотрудника <span id="modalUserName"
|
||
class="fw-semibold"></span>.</p>
|
||
<p>Вы хотите сохранить изменения перед переходом к другому сотруднику?</p>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" onclick="cancelSwitchUser()">
|
||
<i class="bi bi-x-circle me-1"></i>Отмена
|
||
</button>
|
||
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal"
|
||
onclick="discardUserChanges()">
|
||
<i class="bi bi-trash me-1"></i>Не сохранять
|
||
</button>
|
||
<button type="button" class="btn btn-primary" data-bs-dismiss="modal" onclick="saveAndSwitchUser()">
|
||
<i class="bi bi-save me-1"></i>Сохранить и перейти
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{% endblock %}
|
||
|
||
{% block scripts %}
|
||
<script src="/static/js/birthdate.js"></script>
|
||
{% endblock %} |