morozovka-portal/app/templates/admin_schedule.html
2026-10-20 03:27:14 +03:00

200 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.

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Управление расписанием — Morozovka Portal</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/themes/dark.css">
<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
<script src="https://cdn.jsdelivr.net/npm/flatpickr/dist/l10n/ru.js"></script>
<style>
body { background: #0d1117; color: #e6edf3; font-family: sans-serif; padding: 40px; }
.container { max-width: 1000px; margin: 0 auto; }
.header-actions { display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid #30363d; padding-bottom: 10px; margin-bottom: 20px; }
h2 { color: #58a6ff; margin: 0; }
h3 { color: #8b949e; margin-top: 30px; }
.card { background: #161b22; border: 1px solid #30363d; border-radius: 8px; padding: 20px; margin-bottom: 20px; }
.form-row { display: flex; gap: 15px; margin-bottom: 15px; align-items: flex-end; flex-wrap: wrap; }
.form-group { display: flex; flex-direction: column; flex: 1; min-width: 200px; }
.form-group label { margin-bottom: 5px; font-size: 0.85rem; color: #8b949e; }
input, select, textarea { padding: 8px; background: #0d1117; color: white; border: 1px solid #30363d; border-radius: 5px; font-family: inherit; }
textarea { resize: vertical; min-height: 60px; }
.quick-btns { display: flex; gap: 10px; margin-bottom: 15px; flex-wrap: wrap; }
.quick-btn { padding: 8px 15px; border-radius: 5px; border: none; cursor: pointer; font-weight: bold; font-size: 0.85rem; color: white; transition: opacity 0.2s; }
.quick-btn:hover { opacity: 0.8; }
.btn-green { background: #238636; }
.btn-yellow { background: #d29922; }
.btn-red { background: #da3633; }
.btn-grey { background: #30363d; }
button[type="submit"] { padding: 10px 15px; background: #238636; color: white; border: none; border-radius: 5px; cursor: pointer; font-weight: bold; height: 38px; }
button[type="submit"]:hover { background: #2ea043; }
button.danger { background: #da3633; padding: 6px 10px; font-size: 0.8rem; height: auto; }
button.danger:hover { background: #f85149; }
button.edit-btn { background: #1f6feb; padding: 6px 10px; font-size: 0.8rem; height: auto; text-decoration: none; color: white; border-radius: 5px; margin-right: 5px; }
button.edit-btn:hover { background: #388bfd; }
table { width: 100%; border-collapse: collapse; margin-top: 20px; }
th, td { padding: 10px; text-align: left; border-bottom: 1px solid #30363d; }
th { background: #21262d; color: #8b949e; font-size: 0.85rem; }
.back-link { display: inline-block; margin-bottom: 20px; color: #8b949e; text-decoration: none; }
.back-link:hover { color: #58a6ff; }
.action-buttons a { display: inline-block; padding: 8px 15px; border-radius: 5px; text-decoration: none; font-weight: bold; font-size: 0.85rem; margin-left: 10px; color: white; }
.btn-import { background: #a371f7; }
.btn-export { background: #21262d; border: 1px solid #30363d; }
.btn-export:hover { background: #30363d; }
</style>
</head>
<body>
<div class="container">
<a href="/" class="back-link">← На главную</a>
<div class="header-actions">
<h2>Управление расписанием</h2>
<div class="action-buttons">
<a href="/admin/schedule/import" class="btn-import">📥 Импорт (.ics)</a>
<a href="/schedule/export.ics" class="btn-export">📤 Экспорт (.ics)</a>
</div>
</div>
<div class="card">
<h3>Текущий статус</h3>
<div class="quick-btns">
<button type="button" class="quick-btn btn-green" onclick="setFastStatus('on_place', 0, 'На месте')">✅ Я на месте</button>
<button type="button" class="quick-btn btn-yellow" onclick="setFastStatus('delayed', 5, 'Задерживаюсь на 5 мин')">⏳ Опоздаю на 5 мин</button>
<button type="button" class="quick-btn btn-yellow" onclick="setFastStatus('delayed', 15, 'Задерживаюсь на 15 мин')">⏳ Опоздаю на 15 мин</button>
<button type="button" class="quick-btn btn-yellow" onclick="setFastStatus('delayed', 30, 'Задерживаюсь на 30 мин')">⏳ Опоздаю на 30 мин</button>
<button type="button" class="quick-btn btn-grey" onclick="setFastStatus('away', 0, 'Вне вуза')">🚶 Вне вуза</button>
</div>
<form action="/admin/schedule/status" method="POST" id="status-form">
<div class="form-row">
<div class="form-group">
<label>Статус (вручную)</label>
<select name="status" id="status-select">
<option value="free" {% if status.status == 'free' %}selected{% endif %}>Свободен / Вне расписания</option>
<option value="on_place" {% if status.status == 'on_place' %}selected{% endif %}>На месте</option>
<option value="delayed" {% if status.status == 'delayed' %}selected{% endif %}>Опаздываю</option>
<option value="away" {% if status.status == 'away' %}selected{% endif %}>Вне вуза</option>
<option value="cancelled" {% if status.status == 'cancelled' %}selected{% endif %}>Отменено</option>
</select>
</div>
<div class="form-group" style="flex: 0.5;">
<label>Опоздание (мин)</label>
<input type="number" name="delay_minutes" id="delay-input" value="{{ status.delay_minutes or 0 }}" min="0">
</div>
<div class="form-group">
<label>Сообщение для студентов</label>
<input type="text" name="message" id="message-input" value="{{ status.message or '' }}" placeholder="Например: задерживаюсь на 15 минут">
</div>
<button type="submit">Обновить</button>
</div>
</form>
</div>
<div class="card">
<h3>Добавить новое событие</h3>
<form action="/admin/schedule/event/add" method="POST">
<div class="form-row">
<div class="form-group" style="flex: 2;">
<label>Название</label>
<input type="text" name="title" required>
</div>
<div class="form-group">
<label>Тип</label>
<select name="event_type">
<option value="lecture">Лекция</option>
<option value="workshop">Мастер-класс</option>
<option value="meeting">Встреча</option>
<option value="personal">Личное</option>
</select>
</div>
<div class="form-group">
<label>Место</label>
<input type="text" name="location">
</div>
</div>
<div class="form-row">
<div class="form-group">
<label>Начало</label>
<input type="text" class="flatpickr" name="start_time" required placeholder="Выберите дату и время">
</div>
<div class="form-group">
<label>Конец</label>
<input type="text" class="flatpickr" name="end_time" required placeholder="Выберите дату и время">
</div>
<div class="form-group" style="flex: 0.5; flex-direction: row; align-items: center; gap: 10px;">
<input type="checkbox" name="is_public" checked id="is_public">
<label for="is_public" style="margin: 0; cursor: pointer;">Публичное</label>
</div>
</div>
<div class="form-row">
<div class="form-group">
<label>Описание</label>
<textarea name="description"></textarea>
</div>
<button type="submit" style="height: 60px;">Добавить</button>
</div>
</form>
</div>
<div class="card">
<h3>Последние 50 событий</h3>
<table>
<thead>
<tr>
<th>Дата и время</th>
<th>Название</th>
<th>Тип</th>
<th>Публичное</th>
<th>Действие</th>
</tr>
</thead>
<tbody>
{% for event in events %}
<tr>
<td>{{ event.start_time|msk_strftime('%d.%m.%Y %H:%M') }}<br><small style="color:#8b949e">до {{ event.end_time|msk_strftime('%H:%M') }}</small></td>
<td><strong>{{ event.title }}</strong><br><small style="color:#8b949e">{{ event.location or '' }}</small></td>
<td>{{ event.event_type }}</td>
<td>{{ 'Да' if event.is_public else 'Нет' }}</td>
<td style="display:flex; gap: 5px;">
<a href="/admin/schedule/event/{{ event.id }}/edit" class="edit-btn">✎ Ред.</a>
<form action="/admin/schedule/event/{{ event.id }}/delete" method="POST" onsubmit="return confirm('Удалить событие?');">
<button type="submit" class="danger">✕ Удалить</button>
</form>
</td>
</tr>
{% else %}
<tr><td colspan="5" style="text-align: center; color: #8b949e;">Нет событий</td></tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<script>
flatpickr(".flatpickr", {
enableTime: true,
dateFormat: "Y-m-d H:i",
time_24hr: true,
locale: "ru",
minuteIncrement: 15,
defaultDate: "today"
});
function setFastStatus(status, minutes, message) {
document.getElementById('status-select').value = status;
document.getElementById('delay-input').value = minutes;
document.getElementById('message-input').value = message;
document.getElementById('status-form').submit();
}
</script>
</body>
</html>