144 lines
7.5 KiB
HTML
144 lines
7.5 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="ru">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Расписание — Morozovka Portal</title>
|
||
<style>
|
||
body { background: #0d1117; color: #e6edf3; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; margin: 0; padding: 40px 20px; }
|
||
.container { max-width: 800px; margin: 0 auto; }
|
||
|
||
.status-banner { padding: 20px; border-radius: 10px; text-align: center; margin-bottom: 30px; }
|
||
.status-on_place { background: rgba(35, 134, 54, 0.2); border: 1px solid #238636; color: #3fb950; }
|
||
.status-delayed { background: rgba(210, 153, 34, 0.2); border: 1px solid #d29922; color: #d29922; }
|
||
.status-away, .status-cancelled { background: rgba(248, 81, 73, 0.2); border: 1px solid #f85149; color: #f85149; }
|
||
.status-free { background: rgba(139, 148, 158, 0.2); border: 1px solid #8b949e; color: #8b949e; }
|
||
.status-title { font-size: 1.5rem; font-weight: bold; margin-bottom: 5px; }
|
||
.status-message { font-size: 1.1rem; }
|
||
|
||
.event-card { background: #161b22; border: 1px solid #30363d; border-radius: 8px; padding: 20px; margin-bottom: 15px; display: flex; gap: 20px; }
|
||
.event-time { font-family: monospace; font-size: 1.1rem; color: #58a6ff; min-width: 120px; }
|
||
.event-details { flex: 1; }
|
||
.event-title { font-size: 1.2rem; font-weight: bold; margin: 0 0 5px 0; }
|
||
.event-meta { color: #8b949e; font-size: 0.9rem; margin-bottom: 5px; }
|
||
.event-type { display: inline-block; background: #21262d; padding: 2px 8px; border-radius: 4px; font-size: 0.8rem; text-transform: uppercase; }
|
||
.event-desc { font-size: 0.95rem; margin-top: 10px; }
|
||
|
||
.back-link { display: inline-block; margin-bottom: 20px; color: #8b949e; text-decoration: none; }
|
||
.back-link:hover { color: #58a6ff; }
|
||
|
||
/* Стили для чата */
|
||
.chat-container { background: #161b22; border: 1px solid #30363d; border-radius: 8px; margin-top: 40px; display: flex; flex-direction: column; height: 400px; }
|
||
.chat-header { padding: 15px; border-bottom: 1px solid #30363d; background: #21262d; border-radius: 8px 8px 0 0; font-weight: bold; }
|
||
.chat-messages { flex: 1; padding: 15px; overflow-y: auto; display: flex; flex-direction: column; gap: 10px; }
|
||
.msg { max-width: 80%; padding: 10px 15px; border-radius: 8px; font-size: 0.95rem; line-height: 1.4; white-space: pre-wrap; }
|
||
.msg.bot { background: #21262d; align-self: flex-start; border: 1px solid #30363d; }
|
||
.msg.user { background: #1f6feb; color: white; align-self: flex-end; }
|
||
.chat-input-area { padding: 15px; border-top: 1px solid #30363d; display: flex; gap: 10px; }
|
||
.chat-input-area input { flex: 1; padding: 10px; border-radius: 5px; border: 1px solid #30363d; background: #0d1117; color: white; outline: none; }
|
||
.chat-input-area button { padding: 10px 20px; background: #238636; color: white; border: none; border-radius: 5px; cursor: pointer; font-weight: bold; }
|
||
.chat-input-area button:hover { background: #2ea043; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="container">
|
||
<a href="/" class="back-link">← На главную</a>
|
||
<h1 style="margin-top: 0;">Расписание</h1>
|
||
|
||
{% if status %}
|
||
<div class="status-banner status-{{ status.status }}">
|
||
<div class="status-title">
|
||
{% if status.status == 'on_place' %}На месте
|
||
{% elif status.status == 'delayed' %}Опаздываю на {{ status.delay_minutes }} мин
|
||
{% elif status.status == 'away' %}Вне вуза
|
||
{% elif status.status == 'cancelled' %}Отменено
|
||
{% else %}Свободен / Вне расписания{% endif %}
|
||
</div>
|
||
{% if status.message %}
|
||
<div class="status-message">{{ status.message }}</div>
|
||
{% endif %}
|
||
</div>
|
||
{% endif %}
|
||
|
||
<h2 style="color: #8b949e; font-size: 1.2rem; border-bottom: 1px solid #30363d; padding-bottom: 10px;">Ближайшие события</h2>
|
||
|
||
{% for event in events %}
|
||
<div class="event-card">
|
||
<div class="event-time">
|
||
{{ event.start_time.strftime('%d.%m %H:%M') }}<br>
|
||
<span style="color: #8b949e; font-size: 0.9rem;">до {{ event.end_time.strftime('%H:%M') }}</span>
|
||
</div>
|
||
<div class="event-details">
|
||
<h3 class="event-title">{{ event.title }}</h3>
|
||
<div class="event-meta">
|
||
{% if event.location %}📍 {{ event.location }}{% endif %}
|
||
</div>
|
||
<span class="event-type">{{ event.event_type }}</span>
|
||
{% if event.description %}
|
||
<div class="event-desc">{{ event.description }}</div>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
{% else %}
|
||
<p style="color: #8b949e;">Пока нет запланированных событий.</p>
|
||
{% endfor %}
|
||
|
||
<!-- Блок Чат-бота -->
|
||
<div class="chat-container">
|
||
<div class="chat-header">🤖 Ассистент расписания</div>
|
||
<div class="chat-messages" id="chat-messages">
|
||
<div class="msg bot">Привет! Я могу подсказать статус Никиты Сергеевича, его расписание или контакты. Спроси меня о чем-нибудь.</div>
|
||
</div>
|
||
<form class="chat-input-area" id="chat-form">
|
||
<input type="text" id="chat-input" placeholder="Например: Где сейчас? Что на неделе?" autocomplete="off">
|
||
<button type="submit">Отправить</button>
|
||
</form>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<script>
|
||
const chatForm = document.getElementById('chat-form');
|
||
const chatInput = document.getElementById('chat-input');
|
||
const chatMessages = document.getElementById('chat-messages');
|
||
|
||
chatForm.addEventListener('submit', async (e) => {
|
||
e.preventDefault();
|
||
const text = chatInput.value.trim();
|
||
if (!text) return;
|
||
|
||
// Добавляем сообщение пользователя
|
||
addMessage(text, 'user');
|
||
chatInput.value = '';
|
||
|
||
// Добавляем индикатор загрузки
|
||
const loadingMsg = addMessage('...', 'bot');
|
||
|
||
try {
|
||
const response = await fetch('/api/assistant', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({ message: text })
|
||
});
|
||
|
||
const data = await response.json();
|
||
|
||
// Заменяем индикатор загрузки на ответ бота
|
||
loadingMsg.textContent = data.reply || 'Ошибка: пустой ответ';
|
||
} catch (err) {
|
||
loadingMsg.textContent = 'Ошибка соединения с сервером.';
|
||
}
|
||
});
|
||
|
||
function addMessage(text, sender) {
|
||
const div = document.createElement('div');
|
||
div.className = `msg ${sender}`;
|
||
div.textContent = text;
|
||
chatMessages.appendChild(div);
|
||
chatMessages.scrollTop = chatMessages.scrollHeight;
|
||
return div;
|
||
}
|
||
</script>
|
||
</body>
|
||
</html>
|