195 lines
12 KiB
HTML
195 lines
12 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 Platform</title>
|
||
<style>
|
||
* { box-sizing: border-box; }
|
||
body { background: #0d1117; color: #e6edf3; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; margin: 0; font-size: 14px; line-height: 1.5; min-height: 100vh; display: flex; flex-direction: column; }
|
||
a { color: #58a6ff; text-decoration: none; }
|
||
a:hover { text-decoration: underline; }
|
||
.topnav { background: #161b22; border-bottom: 1px solid #30363d; padding: 12px 32px; display: flex; align-items: center; gap: 24px; position: sticky; top: 0; z-index: 100; }
|
||
.topnav-logo { display: flex; align-items: center; gap: 8px; color: #e6edf3; font-weight: 600; font-size: 15px; }
|
||
.topnav-logo:hover { text-decoration: none; color: #e6edf3; }
|
||
.topnav-logo svg { color: #58a6ff; }
|
||
.topnav-links { display: flex; gap: 20px; flex: 1; }
|
||
.topnav-links a { color: #c9d1d9; font-weight: 500; font-size: 14px; }
|
||
.topnav-links a:hover { color: #58a6ff; text-decoration: none; }
|
||
.topnav-actions { display: flex; gap: 12px; align-items: center; padding-right: 80px; }
|
||
.btn { display: inline-flex; align-items: center; gap: 6px; padding: 5px 16px; border-radius: 6px; font-size: 14px; font-weight: 500; line-height: 20px; border: 1px solid rgba(240,246,252,0.1); cursor: pointer; text-decoration: none; transition: all .15s; white-space: nowrap; }
|
||
.btn:hover { text-decoration: none; }
|
||
.btn-primary { background: #238636; color: #fff; }
|
||
.btn-primary:hover { background: #2ea043; color: #fff; }
|
||
.btn-default { background: #21262d; color: #c9d1d9; }
|
||
.btn-default:hover { background: #30363d; color: #c9d1d9; }
|
||
.btn-outline { background: transparent; color: #c9d1d9; border-color: #30363d; }
|
||
.btn-outline:hover { background: #21262d; color: #e6edf3; border-color: #8b949e; }
|
||
.btn-lg { padding: 10px 24px; font-size: 15px; }
|
||
.container { max-width: 1200px; margin: 0 auto; padding: 32px; flex: 1; width: 100%; }
|
||
.hero { display: grid; grid-template-columns: 2fr 1fr; gap: 32px; margin-bottom: 32px; }
|
||
.hero-main { padding: 32px; background: linear-gradient(135deg, #161b22 0%, #1c2128 100%); border: 1px solid #30363d; border-radius: 6px; position: relative; overflow: hidden; }
|
||
.hero-main::before { content: ''; position: absolute; top: -50%; right: -20%; width: 400px; height: 400px; background: radial-gradient(circle, rgba(88,166,255,0.08) 0%, transparent 70%); pointer-events: none; }
|
||
.hero-title { font-size: 32px; font-weight: 700; margin: 0 0 12px; background: linear-gradient(90deg, #58a6ff, #a371f7); -webkit-background-clip: text; background-clip: text; color: transparent; line-height: 1.2; }
|
||
.hero-subtitle { color: #8b949e; font-size: 16px; margin: 0 0 24px; line-height: 1.6; max-width: 500px; }
|
||
.hero-actions { display: flex; gap: 12px; flex-wrap: wrap; }
|
||
.hero-side { display: flex; flex-direction: column; gap: 16px; }
|
||
.status-card { padding: 20px; border: 1px solid #30363d; border-radius: 6px; background: #161b22; }
|
||
.status-label { color: #8b949e; font-size: 12px; text-transform: uppercase; font-weight: 600; margin-bottom: 8px; }
|
||
.status-value { font-size: 18px; font-weight: 600; margin-bottom: 4px; display: flex; align-items: center; gap: 8px; }
|
||
.status-dot { width: 10px; height: 10px; border-radius: 50%; display: inline-block; }
|
||
.status-dot-green { background: #3fb950; box-shadow: 0 0 0 3px rgba(63,185,80,0.2); }
|
||
.status-dot-yellow { background: #d29922; box-shadow: 0 0 0 3px rgba(210,153,34,0.2); }
|
||
.status-dot-red { background: #f85149; box-shadow: 0 0 0 3px rgba(248,81,73,0.2); }
|
||
.status-dot-grey { background: #8b949e; box-shadow: 0 0 0 3px rgba(139,148,158,0.2); }
|
||
.status-meta { color: #8b949e; font-size: 13px; }
|
||
.status-link { display: inline-flex; align-items: center; gap: 4px; margin-top: 12px; font-size: 13px; font-weight: 500; }
|
||
.section-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; margin-top: 32px; }
|
||
.section-title { font-size: 18px; font-weight: 600; color: #e6edf3; margin: 0; }
|
||
.cards-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 16px; }
|
||
.feature-card { padding: 20px; border: 1px solid #30363d; border-radius: 6px; background: #161b22; transition: all .15s; display: flex; flex-direction: column; text-decoration: none; color: inherit; }
|
||
.feature-card:hover { border-color: #58a6ff; transform: translateY(-2px); text-decoration: none; }
|
||
.feature-icon { font-size: 32px; margin-bottom: 12px; }
|
||
.feature-title { font-size: 16px; font-weight: 600; color: #e6edf3; margin: 0 0 6px; }
|
||
.feature-desc { color: #8b949e; font-size: 13px; line-height: 1.5; margin: 0; flex: 1; }
|
||
.feature-badge { display: inline-block; margin-top: 12px; padding: 0 8px; border-radius: 2em; font-size: 11px; font-weight: 500; line-height: 18px; border: 1px solid; }
|
||
.feature-badge-new { background: rgba(63,185,80,0.15); color: #3fb950; border-color: rgba(63,185,80,0.4); }
|
||
.footer { border-top: 1px solid #30363d; padding: 24px 32px; text-align: center; color: #8b949e; font-size: 13px; }
|
||
.footer a { color: #8b949e; }
|
||
.footer a:hover { color: #58a6ff; }
|
||
@media (max-width: 900px) { .hero { grid-template-columns: 1fr; } .hero-side { flex-direction: row; flex-wrap: wrap; } .hero-side > * { flex: 1; min-width: 200px; } }
|
||
@media (max-width: 768px) { .topnav { padding: 12px 16px; gap: 12px; } .topnav-links { display: none; } .topnav-actions { padding-right: 60px; } .container { padding: 16px; } .hero-main { padding: 20px; } .hero-title { font-size: 24px; } .section-header { flex-direction: column; align-items: flex-start; gap: 8px; } }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<nav class="topnav">
|
||
<a href="/" class="topnav-logo">
|
||
<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 15h-2v-6h2v6zm0-8h-2V7h2v2zm4 8h-2v-6h2v6zm0-8h-2V7h2v2z"/></svg>
|
||
Morozovka Platform
|
||
</a>
|
||
<div class="topnav-links">
|
||
<a href="/schedule">Расписание</a>
|
||
<a href="/projects">Проекты</a>
|
||
<a href="/workshops">Мастер-классы</a>
|
||
<a href="/files">Файлы</a>
|
||
</div>
|
||
<div class="topnav-actions">
|
||
{% if username %}
|
||
<a href="/profile" class="btn btn-default">{{ username }}</a>
|
||
{% if session.get('role') == 'admin' %}<a href="/admin/users" class="btn btn-outline">Админ</a>{% endif %}
|
||
<a href="/logout" class="btn btn-outline">Выйти</a>
|
||
{% else %}
|
||
<a href="/login" class="btn btn-default">Войти</a>
|
||
<a href="/register" class="btn btn-primary">Регистрация</a>
|
||
{% endif %}
|
||
</div>
|
||
</nav>
|
||
|
||
<div class="container">
|
||
<div class="hero">
|
||
<div class="hero-main">
|
||
{% if username %}
|
||
<h1 class="hero-title">Привет, {{ username }}!</h1>
|
||
<p class="hero-subtitle">Добро пожаловать на платформу команды Морозовки. Расписание, проекты, мастер-классы и файлы — всё в одном месте.</p>
|
||
{% else %}
|
||
<h1 class="hero-title">Morozovka Platform</h1>
|
||
<p class="hero-subtitle">Единая платформа команды: расписание, проекты, мастер-классы и файлы. Войдите, чтобы получить полный доступ.</p>
|
||
{% endif %}
|
||
<div class="hero-actions">
|
||
<a href="/schedule" class="btn btn-primary btn-lg">
|
||
<svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor"><path d="M3.75 1.5a.75.75 0 0 1 .75.75V3h7V2.25a.75.75 0 0 1 1.5 0V3h.5A1.75 1.75 0 0 1 15 4.75v9A1.75 1.75 0 0 1 13.5 15.5h-11A1.75 1.75 0 0 1 1 13.75v-9A1.75 1.75 0 0 1 2.5 3H3V2.25a.75.75 0 0 1 .75-.75Zm10.75 5.5h-13v6.75c0 .138.112.25.25.25h11a.25.25 0 0 0 .25-.25Z"/></svg>
|
||
Расписание
|
||
</a>
|
||
<a href="/projects" class="btn btn-outline btn-lg">Проекты</a>
|
||
<a href="/workshops" class="btn btn-outline btn-lg">Мастер-классы</a>
|
||
</div>
|
||
</div>
|
||
<div class="hero-side">
|
||
<div class="status-card">
|
||
<div class="status-label">Статус Никиты Сергеевича</div>
|
||
<div class="status-value" id="status-value"><span class="status-dot status-dot-grey"></span><span>Загрузка...</span></div>
|
||
<div class="status-meta" id="status-meta">Проверяем расписание...</div>
|
||
<a href="/schedule" class="status-link">Открыть расписание →</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="section-header">
|
||
<h2 class="section-title">Разделы платформы</h2>
|
||
</div>
|
||
|
||
<div class="cards-grid">
|
||
<a href="/schedule" class="feature-card">
|
||
<div class="feature-icon">📅</div>
|
||
<h3 class="feature-title">Расписание</h3>
|
||
<p class="feature-desc">Календарь событий, статус преподавателя, встроенный ассистент</p>
|
||
</a>
|
||
<a href="/projects" class="feature-card">
|
||
<div class="feature-icon">🗂</div>
|
||
<h3 class="feature-title">Проекты</h3>
|
||
<p class="feature-desc">Каталог проектов команды, канбан-доски, участники и роли</p>
|
||
</a>
|
||
<a href="/workshops" class="feature-card">
|
||
<div class="feature-icon">🎓</div>
|
||
<h3 class="feature-title">Мастер-классы</h3>
|
||
<p class="feature-desc">Пайка, embedded, Linux и творческие занятия. Регистрация и материалы</p>
|
||
<span class="feature-badge feature-badge-new">NEW</span>
|
||
</a>
|
||
<a href="/files" class="feature-card">
|
||
<div class="feature-icon">📁</div>
|
||
<h3 class="feature-title">Файлы</h3>
|
||
<p class="feature-desc">Единое хранилище документов, схем и материалов</p>
|
||
</a>
|
||
{% if session.get('role') in ['admin', 'professor'] %}
|
||
<a href="/admin/schedule" class="feature-card">
|
||
<div class="feature-icon">⚙️</div>
|
||
<h3 class="feature-title">Управление расписанием</h3>
|
||
<p class="feature-desc">Быстрые действия, события, импорт/экспорт .ics</p>
|
||
</a>
|
||
{% endif %}
|
||
{% if session.get('role') == 'admin' %}
|
||
<a href="/admin/users" class="feature-card">
|
||
<div class="feature-icon">👥</div>
|
||
<h3 class="feature-title">Пользователи</h3>
|
||
<p class="feature-desc">Управление ролями и доступом</p>
|
||
</a>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
|
||
<div class="footer">
|
||
Morozovka Platform · <a href="/schedule">Расписание</a> · <a href="/projects">Проекты</a> · <a href="/workshops">Мастер-классы</a> · <a href="/files">Файлы</a>
|
||
</div>
|
||
|
||
<script>
|
||
(function() {
|
||
fetch('/api/public-status')
|
||
.then(r => r.ok ? r.json() : null)
|
||
.then(data => {
|
||
const valEl = document.getElementById('status-value');
|
||
const metaEl = document.getElementById('status-meta');
|
||
if (!data || !data.status) {
|
||
valEl.innerHTML = '<span class="status-dot status-dot-grey"></span><span>Нет данных</span>';
|
||
metaEl.textContent = '';
|
||
return;
|
||
}
|
||
const map = {
|
||
'on_place': { text: 'На месте', dot: 'green' },
|
||
'delayed': { text: 'Опаздывает на ' + (data.delay_minutes || 0) + ' мин', dot: 'yellow' },
|
||
'away': { text: 'Вне вуза', dot: 'red' },
|
||
'cancelled': { text: 'Отменено', dot: 'red' },
|
||
'free': { text: 'Вне расписания', dot: 'grey' }
|
||
};
|
||
const info = map[data.status] || map.free;
|
||
valEl.innerHTML = '<span class="status-dot status-dot-' + info.dot + '"></span><span>' + info.text + '</span>';
|
||
metaEl.textContent = data.message || '';
|
||
})
|
||
.catch(() => {
|
||
document.getElementById('status-value').innerHTML = '<span class="status-dot status-dot-grey"></span><span>Нет данных</span>';
|
||
});
|
||
})();
|
||
</script>
|
||
<script src="/static/notif_bell.js"></script>
|
||
</body>
|
||
</html>
|