feat: apply new Мои Товары design system across all templates

Replace Pico CSS with custom design: dark sidebar layout, Golos Text +
JetBrains Mono fonts, orange accent (#FF5500), new component classes
(cards, tables, buttons, tags, toggles, alerts, tabs, login split-panel).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
mguschin
2026-05-18 12:43:08 +03:00
parent 75513e647d
commit eb4165e48b
25 changed files with 2201 additions and 1889 deletions

View File

@@ -1,121 +1,155 @@
<!DOCTYPE html>
<html lang="ru" data-theme="light">
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}ЭВОСИНК{% endblock %}</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
<link rel="stylesheet" href="/static/style.css">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}Мои Товары{% endblock %}</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Golos+Text:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
<link rel="stylesheet" href="/static/style.css">
</head>
<body>
<header class="site-header">
<nav class="container">
<ul>
<li><a href="/" class="brand-logo">ЭВОСИНК</a></li>
</ul>
<ul class="nav-links">
{% if user %}
{% if user.role not in ('admin', 'system') or viewed_user %}
<li><a href="/connections">Подключения</a></li>
<li><a href="/catalog">Каталог Эвотор</a></li>
<li><a href="/vk-catalog/albums">Каталог ВК</a></li>
<li><a href="/sync">Синхронизация</a></li>
{% endif %}
{% if user.role in ('admin', 'system') %}
<li><a href="/admin/users"><i class="bi bi-shield-lock"></i> Админ</a></li>
<li><a href="/admin/logs"><i class="bi bi-journal-text"></i> Логи</a></li>
{% endif %}
<li><a href="/profile"><i class="bi bi-person-circle"></i> Личный кабинет</a></li>
<li><a href="/logout" class="secondary">Выход</a></li>
{% else %}
<li><a href="/login">Вход</a></li>
{% endif %}
</ul>
{% if user %}
<details class="mobile-menu">
<summary role="button" class="outline secondary icon-btn"><i class="bi bi-list"></i></summary>
<ul>
{% if user.role not in ('admin', 'system') or viewed_user %}
<li><a href="/connections">Подключения</a></li>
<li><a href="/catalog">Каталог Эвотор</a></li>
<li><a href="/vk-catalog/albums">Каталог ВК</a></li>
<li><a href="/sync">Синхронизация</a></li>
{% endif %}
{% if user.role in ('admin', 'system') %}
<li><a href="/admin/users">Админ</a></li>
<li><a href="/admin/logs">Логи</a></li>
{% endif %}
<li><a href="/profile">Личный кабинет</a></li>
<li><a href="/logout">Выход</a></li>
</ul>
</details>
{% else %}
<details class="mobile-menu">
<summary role="button" class="outline secondary icon-btn"><i class="bi bi-list"></i></summary>
<ul>
<li><a href="/login">Вход</a></li>
</ul>
</details>
{% endif %}
</nav>
</header>
{% block body %}
<div class="shell">
<!-- ── Sidebar ── -->
<aside class="sidebar">
<div class="sb-logo">
<div class="sb-logo-icon">
<svg width="22" height="22" viewBox="0 0 28 28" fill="none">
<path d="M9 11h10l-1.5 9H10.5L9 11Z" fill="white" opacity="0.95"/>
<path d="M11.5 11V9a2.5 2.5 0 015 0v2" stroke="white" stroke-width="1.6" stroke-linecap="round" fill="none"/>
<line x1="12" y1="15" x2="16" y2="15" stroke="#FF5500" stroke-width="1.3" stroke-linecap="round"/>
</svg>
</div>
<div>
<div class="sb-logo-name">Мои Товары</div>
<div class="sb-logo-sub">мои-товары.рф</div>
</div>
</div>
<nav class="sb-nav">
{% if user %}
{% if user.role in ('admin', 'system') %}
<div class="sb-section">Управление</div>
<a href="/admin/users" class="sb-item {% if request.url.path.startswith('/admin/users') %}active{% endif %}">
<span class="sb-icon"><i class="bi bi-people"></i></span>
<span>Пользователи</span>
</a>
{% if user.role == 'system' %}
<a href="/admin/logs" class="sb-item {% if request.url.path.startswith('/admin/logs') %}active{% endif %}">
<span class="sb-icon"><i class="bi bi-journal-text"></i></span>
<span>Логи</span>
</a>
{% endif %}
{% else %}
<div class="sb-section">Главное</div>
<a href="/connections" class="sb-item {% if request.url.path == '/connections' %}active{% endif %}">
<span class="sb-icon"><i class="bi bi-plug"></i></span>
<span>Подключения</span>
</a>
<a href="/catalog/stores" class="sb-item {% if request.url.path.startswith('/catalog') %}active{% endif %}">
<span class="sb-icon"><i class="bi bi-shop"></i></span>
<span>Каталог Эвотор</span>
</a>
<a href="/vk-catalog/albums" class="sb-item {% if request.url.path.startswith('/vk-catalog') %}active{% endif %}">
<span class="sb-icon"><i class="bi bi-bag"></i></span>
<span>Каталог ВК</span>
</a>
<a href="/sync" class="sb-item {% if request.url.path == '/sync' %}active{% endif %}">
<span class="sb-icon"><i class="bi bi-arrow-repeat"></i></span>
<span>Синхронизация</span>
</a>
<div class="sb-section" style="margin-top:6px;">Аккаунт</div>
<a href="/profile" class="sb-item {% if request.url.path.startswith('/profile') %}active{% endif %}">
<span class="sb-icon"><i class="bi bi-person"></i></span>
<span>Профиль</span>
</a>
{% endif %}
{% endif %}
</nav>
{% if user %}
<a href="/profile" class="sb-user">
<div class="avatar {% if user.role in ('admin','system') %}admin{% endif %}">
{{ user.first_name[0] if user.first_name else '?' }}{{ user.last_name[0] if user.last_name else '' }}
</div>
<div style="flex:1; min-width:0;">
<div class="sb-user-name">{{ user.first_name }} {{ user.last_name }}</div>
<div class="sb-user-role">
<span class="role-chip {% if user.role in ('admin','system') %}admin{% else %}user{% endif %}">
{% if user.role == 'system' %}SYSTEM{% elif user.role == 'admin' %}ADMIN{% else %}USER{% endif %}
</span>
</div>
</div>
</a>
{% endif %}
</aside>
<!-- ── Main ── -->
<div class="main">
<!-- Topbar -->
<div class="topbar">
<div class="topbar-title">{% block page_title %}{% endblock %}</div>
{% block topbar_extras %}{% endblock %}
{% if user %}
<a href="/logout" class="btn btn-ghost btn-sm" style="margin-left:auto;" title="Выйти">
<i class="bi bi-box-arrow-right"></i>
</a>
{% endif %}
</div>
{% if viewed_user %}
<div style="background:#e65c00;color:#fff;text-align:center;padding:0.4rem 1rem;font-size:0.9rem;">
<i class="bi bi-eye me-1"></i>Просмотр от имени: <strong>{{ viewed_user.first_name }} {{ viewed_user.last_name }}</strong> ({{ viewed_user.email }})
<form method="post" action="/admin/view-as/stop" style="display:inline;margin-left:1rem;">
<button type="submit" style="background:none;border:1px solid #fff;color:#fff;padding:0.1rem 0.6rem;font-size:0.85rem;cursor:pointer;border-radius:4px;">Выйти</button>
</form>
<div class="view-as-bar">
<i class="bi bi-eye"></i> Просмотр от имени: <strong>{{ viewed_user.first_name }} {{ viewed_user.last_name }}</strong> ({{ viewed_user.email }})
<form method="post" action="/admin/view-as/stop" style="display:inline;margin-left:1rem;">
<button type="submit" style="background:none;border:1px solid rgba(255,255,255,0.6);color:#fff;padding:2px 10px;font-size:12px;cursor:pointer;border-radius:4px;font-family:inherit;">Выйти</button>
</form>
</div>
{% endif %}
<main class="container py-4">
{% if errors %}
<div role="alert" class="alert alert-danger">
{% for error in errors %}
<p>{{ error }}</p>
{% endfor %}
</div>
{% endif %}
<div class="content">
{% if errors %}
<div class="alert alert-rd" style="margin-bottom:16px;">
<span><i class="bi bi-x-circle"></i></span>
<div>{% for e in errors %}<div>{{ e }}</div>{% endfor %}</div>
</div>
{% endif %}
{% if success %}
<div class="alert alert-gr" style="margin-bottom:16px;">
<span><i class="bi bi-check-circle"></i></span>
<div>{{ success }}</div>
</div>
{% endif %}
{% block content %}{% endblock %}
</div>
{% if success %}
<div role="alert" class="alert alert-success">
<p>{{ success }}</p>
</div>
{% endif %}
</div>
</div>
{% endblock %}
{% block content %}{% endblock %}
</main>
{% if jivosite_widget_id %}
<script src="//code.jivosite.com/widget/{{ jivosite_widget_id }}" async></script>
{% endif %}
<script src="https://cdn.jsdelivr.net/npm/inputmask@5.0.9/dist/inputmask.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
var phoneInputs = document.querySelectorAll('input[name="phone"]');
if (phoneInputs.length) {
Inputmask('+7 (999) 999-99-99', {
placeholder: '_',
showMaskOnHover: false,
clearMaskOnLostFocus: false
}).mask(phoneInputs);
}
});
</script>
<script>
document.addEventListener('invalid', function(e) {
if (e.target.validity.valueMissing) {
e.target.setCustomValidity('Пожалуйста, заполните это поле');
} else if (e.target.validity.typeMismatch) {
e.target.setCustomValidity('Пожалуйста, введите корректное значение');
}
}, true);
document.addEventListener('input', function(e) {
if (e.target.required) e.target.setCustomValidity('');
}, true);
</script>
{% block scripts %}{% endblock %}
{% if jivosite_widget_id %}
<script src="//code.jivosite.com/widget/{{ jivosite_widget_id }}" async></script>
{% endif %}
<script src="https://cdn.jsdelivr.net/npm/inputmask@5.0.9/dist/inputmask.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
var phoneInputs = document.querySelectorAll('input[name="phone"]');
if (phoneInputs.length) {
Inputmask('+7 (999) 999-99-99', { placeholder: '_', showMaskOnHover: false, clearMaskOnLostFocus: false }).mask(phoneInputs);
}
});
document.addEventListener('invalid', function(e) {
if (e.target.validity.valueMissing) e.target.setCustomValidity('Пожалуйста, заполните это поле');
else if (e.target.validity.typeMismatch) e.target.setCustomValidity('Пожалуйста, введите корректное значение');
}, true);
document.addEventListener('input', function(e) {
if (e.target.required) e.target.setCustomValidity('');
}, true);
</script>
{% block scripts %}{% endblock %}
</body>
</html>