131 lines
9.7 KiB
HTML
131 lines
9.7 KiB
HTML
{% extends "base.html" %}
|
||
{% block title %}Мастер-классы — Morozovka Portal{% endblock %}
|
||
{% block main_class %}container{% endblock %}
|
||
|
||
{% block head %}
|
||
<style>
|
||
.page-header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 24px; gap: 16px; flex-wrap: wrap; }
|
||
.page-title { font-size: 24px; font-weight: 600; margin: 0 0 4px; color: #e6edf3; }
|
||
.page-subtitle { color: #8b949e; font-size: 14px; margin: 0; }
|
||
.filters { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 24px; padding: 16px; background: #161b22; border: 1px solid #30363d; border-radius: 6px; }
|
||
.filter-chip { display: inline-flex; align-items: center; padding: 4px 10px; font-size: 12px; font-weight: 500; border-radius: 2em; border: 1px solid #30363d; background: #21262d; color: #c9d1d9; cursor: pointer; text-decoration: none; }
|
||
.filter-chip:hover { background: #30363d; text-decoration: none; color: #e6edf3; }
|
||
.filter-chip.active { background: #1f6feb; border-color: #1f6feb; color: #fff; }
|
||
.filter-chip.active:hover { background: #388bfd; color: #fff; }
|
||
.filter-chip-clear { border-color: #f85149; color: #f85149; background: transparent; }
|
||
.filter-chip-clear:hover { background: rgba(248,81,73,0.1); color: #f85149; }
|
||
.filter-label { color: #8b949e; font-size: 12px; font-weight: 600; text-transform: uppercase; align-self: center; margin-right: 6px; }
|
||
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 16px; }
|
||
.ws-card { background: #161b22; border: 1px solid #30363d; border-radius: 6px; overflow: hidden; display: flex; flex-direction: column; transition: border-color .15s; }
|
||
.ws-card:hover { border-color: #58a6ff; }
|
||
.ws-card-cover { height: 120px; background: linear-gradient(135deg, #1f6feb 0%, #a371f7 100%); display: flex; align-items: center; justify-content: center; font-size: 2.5rem; position: relative; }
|
||
.ws-card-cover-partner { position: absolute; top: 8px; right: 10px; background: rgba(0,0,0,0.5); color: #fff; padding: 2px 8px; border-radius: 10px; font-size: 11px; font-weight: 600; }
|
||
.ws-card-cover-sub { position: absolute; top: 8px; left: 10px; background: rgba(88,166,255,0.9); color: #fff; padding: 2px 8px; border-radius: 10px; font-size: 11px; font-weight: 600; }
|
||
.ws-card-body { padding: 16px; flex: 1; display: flex; flex-direction: column; }
|
||
.ws-card h3 { color: #e6edf3; font-size: 16px; font-weight: 600; margin: 0 0 8px; line-height: 1.4; }
|
||
.ws-card h3 a { color: inherit; text-decoration: none; }
|
||
.ws-card h3 a:hover { color: #58a6ff; }
|
||
.ws-card-desc { color: #8b949e; font-size: 13px; line-height: 1.5; margin: 0 0 12px; flex: 1; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
|
||
.badges { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 12px; }
|
||
.badge { display: inline-block; padding: 0 7px; border-radius: 2em; font-size: 12px; font-weight: 500; line-height: 18px; border: 1px solid; white-space: nowrap; }
|
||
.badge-cat-soldering { background: rgba(88,166,255,0.15); color: #58a6ff; border-color: rgba(88,166,255,0.4); }
|
||
.badge-cat-embroidery { background: rgba(163,113,247,0.15); color: #a371f7; border-color: rgba(163,113,247,0.4); }
|
||
.badge-cat-embedded { background: rgba(63,185,80,0.15); color: #3fb950; border-color: rgba(63,185,80,0.4); }
|
||
.badge-cat-linux { background: rgba(210,153,34,0.15); color: #d29922; border-color: rgba(210,153,34,0.4); }
|
||
.badge-cat-other { background: rgba(139,148,158,0.15); color: #8b949e; border-color: rgba(139,148,158,0.4); }
|
||
.badge-status-draft { background: rgba(139,148,158,0.15); color: #8b949e; border-color: rgba(139,148,158,0.4); }
|
||
.badge-status-published { background: rgba(63,185,80,0.15); color: #3fb950; border-color: rgba(63,185,80,0.4); }
|
||
.badge-status-archived { background: rgba(210,153,34,0.15); color: #d29922; border-color: rgba(210,153,34,0.4); }
|
||
.badge-vis-internal { background: rgba(248,81,73,0.15); color: #f85149; border-color: rgba(248,81,73,0.4); }
|
||
.badge-difficulty-beginner { background: rgba(63,185,80,0.15); color: #3fb950; border-color: rgba(63,185,80,0.4); }
|
||
.badge-difficulty-intermediate { background: rgba(210,153,34,0.15); color: #d29922; border-color: rgba(210,153,34,0.4); }
|
||
.badge-difficulty-advanced { background: rgba(248,81,73,0.15); color: #f85149; border-color: rgba(248,81,73,0.4); }
|
||
.badge-recurrence { background: rgba(163,113,247,0.15); color: #a371f7; border-color: rgba(163,113,247,0.4); }
|
||
.ws-meta { display: flex; flex-wrap: wrap; gap: 12px; font-size: 12px; color: #8b949e; padding-top: 12px; border-top: 1px solid #30363d; margin-top: auto; }
|
||
.ws-meta-item { display: inline-flex; align-items: center; gap: 4px; }
|
||
.empty-state { padding: 64px 24px; text-align: center; color: #8b949e; background: #161b22; border: 1px dashed #30363d; border-radius: 6px; }
|
||
.empty-state h3 { color: #e6edf3; margin-bottom: 8px; font-size: 16px; }
|
||
.empty-state p { margin-bottom: 16px; }
|
||
</style>
|
||
{% endblock %}
|
||
|
||
{% block content %}
|
||
<div class="page-header">
|
||
<div>
|
||
<h1 class="page-title">Мастер-классы</h1>
|
||
<p class="page-subtitle">Практические занятия: пайка, embedded, Linux, творчество</p>
|
||
</div>
|
||
{% if can_create %}
|
||
<a href="/workshops/new" class="btn btn-primary">
|
||
<svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor"><path d="M8 2a.75.75 0 0 1 .75.75v4.5h4.5a.75.75 0 0 1 0 1.5h-4.5v4.5a.75.75 0 0 1-1.5 0v-4.5h-4.5a.75.75 0 0 1 0-1.5h4.5v-4.5A.75.75 0 0 1 8 2Z"/></svg>
|
||
Создать мастер-класс
|
||
</a>
|
||
{% endif %}
|
||
</div>
|
||
|
||
<div class="filters">
|
||
<span class="filter-label">Категория:</span>
|
||
<a href="?{% if current_status %}status={{ current_status }}&{% endif %}category=" class="filter-chip {% if not current_cat %}active{% endif %}">Все</a>
|
||
{% for cat in WORKSHOP_CATEGORIES %}
|
||
<a href="?{% if current_status %}status={{ current_status }}&{% endif %}category={{ cat }}" class="filter-chip {% if current_cat == cat %}active{% endif %}">{{ WORKSHOP_CATEGORY_LABELS[cat] }}</a>
|
||
{% endfor %}
|
||
<span style="width:16px;"></span>
|
||
<span class="filter-label">Статус:</span>
|
||
<a href="?{% if current_cat %}category={{ current_cat }}&{% endif %}status=" class="filter-chip {% if not current_status %}active{% endif %}">Все</a>
|
||
<a href="?{% if current_cat %}category={{ current_cat }}&{% endif %}status=published" class="filter-chip {% if current_status == 'published' %}active{% endif %}">Опубликован</a>
|
||
<a href="?{% if current_cat %}category={{ current_cat }}&{% endif %}status=archived" class="filter-chip {% if current_status == 'archived' %}active{% endif %}">В архиве</a>
|
||
{% if session.get('role') == 'admin' %}
|
||
<a href="?{% if current_cat %}category={{ current_cat }}&{% endif %}status=draft" class="filter-chip {% if current_status == 'draft' %}active{% endif %}">Черновик</a>
|
||
{% endif %}
|
||
{% if current_cat or current_status %}
|
||
<a href="/workshops" class="filter-chip filter-chip-clear">✕ Сбросить</a>
|
||
{% endif %}
|
||
</div>
|
||
|
||
{% if workshops %}
|
||
<div class="grid">
|
||
{% for ws in workshops %}
|
||
<div class="ws-card">
|
||
<div class="ws-card-cover">
|
||
{% if ws.category == 'soldering' %}🔥
|
||
{% elif ws.category == 'embroidery' %}🎨
|
||
{% elif ws.category == 'embedded' %}⚙️
|
||
{% elif ws.category == 'linux' %}🐧
|
||
{% else %}🎓{% endif %}
|
||
{% if ws.partner %}<span class="ws-card-cover-partner">{{ ws.partner }}</span>{% endif %}
|
||
{% if my_subs.get(ws.id) %}<span class="ws-card-cover-sub">🔔</span>{% endif %}
|
||
</div>
|
||
<div class="ws-card-body">
|
||
<div class="badges">
|
||
<span class="badge badge-cat-{{ ws.category }}">{{ WORKSHOP_CATEGORY_LABELS[ws.category] }}</span>
|
||
<span class="badge badge-difficulty-{{ ws.difficulty }}">{{ WORKSHOP_DIFFICULTY_LABELS[ws.difficulty] }}</span>
|
||
<span class="badge badge-status-{{ ws.status }}">{{ WORKSHOP_STATUS_LABELS[ws.status] }}</span>
|
||
{% if ws.visibility == 'internal' %}<span class="badge badge-vis-internal">Внутренний</span>{% endif %}
|
||
{% if ws.recurrence and RECURRENCE_LABELS.get(ws.recurrence) %}<span class="badge badge-recurrence">🔁 {{ RECURRENCE_LABELS[ws.recurrence] }}</span>{% endif %}
|
||
</div>
|
||
<h3><a href="/workshops/{{ ws.id }}">{{ ws.title }}</a></h3>
|
||
<p class="ws-card-desc">{{ ws.description or 'Без описания' }}</p>
|
||
<div class="ws-meta">
|
||
{% set lead = leads_map.get(ws.lead_id) %}
|
||
{% if lead %}<span class="ws-meta-item">👤 {{ lead.full_name or lead.username }}</span>{% endif %}
|
||
{% set sess = next_sessions.get(ws.id) %}
|
||
{% if sess %}
|
||
<span class="ws-meta-item">📅 {{ sess.start_time|msk_strftime('%d.%m %H:%M') }}–{{ sess.end_time|msk_strftime('%H:%M') }}</span>
|
||
{% endif %}
|
||
<span class="ws-meta-item">🎫 {{ reg_counts.get(ws.id, 0) }}{% if ws.max_participants %}/{{ ws.max_participants }}{% endif %}</span>
|
||
{% if ws.location %}<span class="ws-meta-item">📍 {{ ws.location }}</span>{% endif %}
|
||
{% if ws.has_certificate %}<span class="ws-meta-item">🏅 Сертификат</span>{% endif %}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{% endfor %}
|
||
</div>
|
||
{% else %}
|
||
<div class="empty-state">
|
||
<h3>Пока нет мастер-классов</h3>
|
||
<p>{% if can_create %}Создайте первый — он появится здесь.{% else %}Загляните позже.{% endif %}</p>
|
||
{% if can_create %}<a href="/workshops/new" class="btn btn-primary">Создать мастер-класс</a>{% endif %}
|
||
</div>
|
||
{% endif %}
|
||
{% endblock %}
|