morozovka-portal/app/templates/workshops.html

131 lines
9.7 KiB
HTML
Raw Permalink 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.

{% 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 %}