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,71 +1,63 @@
{% extends "base.html" %}
{% block title %}Группы — {{ store.name }} — ЭВОСИНК{% endblock %}
{% block title %}Группы — {{ store.name }} — Мои Товары{% endblock %}
{% block page_title %}Каталог Эвотор{% endblock %}
{% block content %}
<nav aria-label="breadcrumb" class="mb-3">
<ol class="breadcrumb">
<li><a href="/catalog/stores">Магазины</a></li>
<li>{{ store.name }}</li>
<li>Группы</li>
</ol>
</nav>
<ol class="breadcrumb">
<li><a href="/catalog/stores">Магазины</a></li>
<li>{{ store.name }}</li>
<li>Группы</li>
</ol>
<div class="d-flex justify-between align-center mb-3">
<h1 style="font-size:1.3rem; margin:0;"><i class="bi bi-folder me-2"></i>Группы товаров — {{ store.name }}</h1>
<span class="text-muted small">Всего: {{ groups | length }}</span>
<div class="pg-title">Группы товаров — {{ store.name }}</div>
<div class="pg-sub">Управление категориями · Всего: {{ groups | length }}</div>
<div class="card" style="padding:0;">
{% if groups %}
<div class="table-wrap">
<table class="tbl">
<thead>
<tr>
<th>Синхронизация</th>
<th>Группа</th>
<th>Товаров</th>
<th>ID</th>
<th>Обновлено</th>
<th></th>
</tr>
</thead>
<tbody>
{% for g in groups %}
{% set is_enabled = (enabled_ids is none) or (g.evotor_id in enabled_ids) %}
<tr>
<td>
<form method="post" action="/catalog/stores/{{ store.evotor_id }}/groups/{{ g.evotor_id }}/toggle" style="margin:0;">
<button type="submit" class="tog {% if is_enabled %}on{% endif %}"
title="{% if is_enabled %}Отключить синхронизацию{% else %}Включить синхронизацию{% endif %}"
style="border:none;background:none;padding:0;cursor:pointer;"></button>
</form>
</td>
<td>
<div class="tbl-name"><i class="bi bi-folder2" style="color:#9EA8BE;margin-right:6px;"></i>{{ g.name }}</div>
</td>
<td><span class="mono" style="font-size:12px;">{{ product_counts.get(g.evotor_id, 0) }}</span></td>
<td><span class="mono" style="font-size:11px;color:#9EA8BE;">{{ g.evotor_id }}</span></td>
<td><span class="mono" style="font-size:11px;color:#9EA8BE;">{{ g.fetched_at | datefmt }}</span></td>
<td>
<a href="/catalog/stores/{{ store.evotor_id }}/products?group={{ g.evotor_id }}" class="btn btn-outline btn-xs">
<i class="bi bi-box-seam"></i> Товары
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="empty-state">
<i class="bi bi-folder"></i>
<p>Группы для этого магазина ещё не загружены.</p>
</div>
{% endif %}
</div>
<article class="card">
{% if groups %}
<div class="table-scroll">
<table class="align-middle">
<thead>
<tr>
<th>Синхронизация</th>
<th>Название</th>
<th>Количество товаров</th>
<th>ID</th>
<th>Обновлено</th>
<th></th>
</tr>
</thead>
<tbody>
{% for g in groups %}
{% set is_enabled = (enabled_ids is none) or (g.evotor_id in enabled_ids) %}
<tr class="{% if not is_enabled %}text-muted{% endif %}">
<td>
<form method="post" action="/catalog/stores/{{ store.evotor_id }}/groups/{{ g.evotor_id }}/toggle" style="margin:0;">
<button type="submit"
class="outline sm {% if is_enabled %}success{% else %}secondary{% endif %}"
title="{% if is_enabled %}Отключить синхронизацию{% else %}Включить синхронизацию{% endif %}"
style="padding:0.2rem 0.6rem;">
{% if is_enabled %}
<i class="bi bi-toggle-on"></i>
{% else %}
<i class="bi bi-toggle-off"></i>
{% endif %}
</button>
</form>
</td>
<td><i class="bi bi-folder2 me-1 text-muted"></i> <strong>{{ g.name }}</strong></td>
<td class="text-muted small">{{ product_counts.get(g.evotor_id, 0) }}</td>
<td class="text-muted small">{{ g.evotor_id }}</td>
<td class="text-muted small">{{ g.fetched_at | datefmt }}</td>
<td>
<a href="/catalog/stores/{{ store.evotor_id }}/products?group={{ g.evotor_id }}" role="button" class="outline sm">
<i class="bi bi-box-seam"></i> Товары
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="text-center py-5 text-muted">
<i class="bi bi-folder" style="font-size:2rem;"></i>
<p class="mt-2">Группы для этого магазина ещё не загружены.</p>
</div>
{% endif %}
</article>
{% endblock %}

View File

@@ -1,83 +1,78 @@
{% extends "base.html" %}
{% block title %}Товары — {{ store.name }} — ЭВОСИНК{% endblock %}
{% block title %}Товары — {{ store.name }} — Мои Товары{% endblock %}
{% block page_title %}Каталог Эвотор{% endblock %}
{% block content %}
<nav aria-label="breadcrumb" class="mb-3">
<ol class="breadcrumb">
<li><a href="/catalog/stores">Магазины</a></li>
<li>{{ store.name }}</li>
<li>Товары</li>
</ol>
</nav>
<ol class="breadcrumb">
<li><a href="/catalog/stores">Магазины</a></li>
<li>{{ store.name }}</li>
<li>Товары</li>
</ol>
<div class="d-flex justify-between align-center mb-3">
<h1 style="font-size:1.3rem; margin:0;"><i class="bi bi-box-seam me-2"></i>Товары — {{ store.name }}</h1>
<span class="text-muted small">Всего: {{ products | length }}</span>
</div>
<div class="pg-title">Товары — {{ store.name }}</div>
<div class="pg-sub">Всего: {{ products | length }}</div>
{% if groups %}
<article class="card mb-3">
<div class="card-body">
<form method="get" class="d-flex gap-2 align-center flex-wrap">
<select name="group" style="width:auto; margin:0;" onchange="this.form.submit()">
<option value="">Все группы</option>
{% for g in groups %}
<option value="{{ g.evotor_id }}" {% if group_id == g.evotor_id %}selected{% endif %}>{{ g.name }}</option>
{% endfor %}
</select>
{% if group_id %}
<a href="/catalog/stores/{{ store.evotor_id }}/products" role="button" class="outline secondary sm">Сбросить</a>
{% endif %}
</form>
</div>
</article>
<div class="card" style="margin-bottom:16px;padding:14px 20px;">
<form method="get" style="display:flex;gap:8px;align-items:center;flex-wrap:wrap;">
<select class="inp" name="group" style="width:auto;" onchange="this.form.submit()">
<option value="">Все группы</option>
{% for g in groups %}
<option value="{{ g.evotor_id }}" {% if group_id == g.evotor_id %}selected{% endif %}>{{ g.name }}</option>
{% endfor %}
</select>
{% if group_id %}
<a href="/catalog/stores/{{ store.evotor_id }}/products" class="btn btn-outline btn-sm">Сбросить</a>
{% endif %}
</form>
</div>
{% endif %}
<article class="card">
{% if products %}
<div class="table-scroll">
<table class="align-middle">
<thead>
<tr>
<th>Название</th>
<th>Группа</th>
<th>Артикул</th>
<th>Цена</th>
<th>Остаток</th>
<th>Ед.</th>
<th>Продаётся</th>
<th>Обновлено</th>
</tr>
</thead>
<tbody>
{% for p in products %}
<tr>
<td>{{ p.name }}</td>
<td class="text-muted small">{{ group_map.get(p.group_evotor_id) or '—' }}</td>
<td class="text-muted small">{{ p.article_number or '—' }}</td>
<td>{% if p.price is not none %}{{ p.price | price }}{% else %}—{% endif %}</td>
<td>{% if p.quantity is not none %}{{ p.quantity }}{% else %}—{% endif %}</td>
<td class="text-muted small">{{ p.measure_name or '—' }}</td>
<td>
{% if p.allow_to_sell %}
<i class="bi bi-check-circle text-success"></i>
{% elif p.allow_to_sell == false %}
<i class="bi bi-x-circle text-danger"></i>
{% else %}
<span class="text-muted"></span>
{% endif %}
</td>
<td class="text-muted small">{{ p.fetched_at | datefmt }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="text-center py-5 text-muted">
<i class="bi bi-box-seam" style="font-size:2rem;"></i>
<p class="mt-2">Товары не найдены.</p>
</div>
{% endif %}
</article>
<div class="card" style="padding:0;">
{% if products %}
<div class="table-wrap">
<table class="tbl">
<thead>
<tr>
<th>Название</th>
<th>Группа</th>
<th>Артикул</th>
<th>Цена</th>
<th>Остаток</th>
<th>Ед.</th>
<th>Продаётся</th>
<th>Обновлено</th>
</tr>
</thead>
<tbody>
{% for p in products %}
<tr>
<td><div class="tbl-name">{{ p.name }}</div></td>
<td style="font-size:12px;color:#9EA8BE;">{{ group_map.get(p.group_evotor_id) or '—' }}</td>
<td><span class="mono" style="font-size:11px;color:#9EA8BE;">{{ p.article_number or '—' }}</span></td>
<td><span class="mono">{% if p.price is not none %}{{ p.price | price }}{% else %}—{% endif %}</span></td>
<td><span class="mono" style="color:{% if p.quantity is not none and p.quantity == 0 %}#E53935{% else %}#1C1F2E{% endif %};">{% if p.quantity is not none %}{{ p.quantity }}{% else %}—{% endif %}</span></td>
<td style="font-size:12px;color:#9EA8BE;">{{ p.measure_name or '—' }}</td>
<td>
{% if p.allow_to_sell %}
<span class="tag tag-gr" style="font-size:10.5px;"><i class="bi bi-check-circle"></i></span>
{% elif p.allow_to_sell == false %}
<span class="tag tag-rd" style="font-size:10.5px;"><i class="bi bi-x-circle"></i></span>
{% else %}
<span style="color:#9EA8BE;"></span>
{% endif %}
</td>
<td><span class="mono" style="font-size:11px;color:#9EA8BE;">{{ p.fetched_at | datefmt }}</span></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="empty-state">
<i class="bi bi-box-seam"></i>
<p>Товары не найдены.</p>
</div>
{% endif %}
</div>
{% endblock %}

View File

@@ -1,66 +1,62 @@
{% extends "base.html" %}
{% block title %}Магазины — ЭВОСИНК{% endblock %}
{% block title %}Магазины — Мои Товары{% endblock %}
{% block page_title %}Каталог Эвотор{% endblock %}
{% block content %}
<div class="d-flex justify-between align-center mb-3">
<h1 style="font-size:1.3rem; margin:0;"><i class="bi bi-shop me-2"></i>Магазины Эвотор</h1>
<span class="text-muted small">Всего: {{ stores | length }}</span>
</div>
<div class="pg-title">Магазины Эвотор</div>
<div class="pg-sub">Выберите магазины для синхронизации · Всего: {{ stores | length }}</div>
<article class="card">
{% if stores %}
<div class="table-scroll">
<table class="align-middle">
<thead>
<tr>
<th>Синхронизация</th>
<th>Название</th>
<th>Адрес</th>
<th>ID</th>
<th>Обновлено</th>
<th></th>
</tr>
</thead>
<tbody>
{% for s in stores %}
{% set is_enabled = (enabled_ids is none) or (s.evotor_id in enabled_ids) %}
<tr class="{% if not is_enabled %}text-muted{% endif %}">
<td>
<form method="post" action="/catalog/stores/{{ s.evotor_id }}/toggle" style="margin:0;">
<button type="submit"
class="outline sm {% if is_enabled %}success{% else %}secondary{% endif %}"
title="{% if is_enabled %}Отключить синхронизацию{% else %}Включить синхронизацию{% endif %}"
style="padding:0.2rem 0.6rem;">
{% if is_enabled %}
<i class="bi bi-toggle-on"></i>
{% else %}
<i class="bi bi-toggle-off"></i>
{% endif %}
</button>
</form>
</td>
<td><strong>{{ s.name }}</strong></td>
<td class="text-muted">{{ s.address or '—' }}</td>
<td class="text-muted small">{{ s.evotor_id }}</td>
<td class="text-muted small">{{ s.fetched_at | datefmt }}</td>
<td>
<a href="/catalog/stores/{{ s.evotor_id }}/products" role="button" class="outline sm" title="Товары">
<i class="bi bi-box-seam"></i> Товары
</a>
<a href="/catalog/stores/{{ s.evotor_id }}/groups" role="button" class="outline secondary sm" title="Группы">
<i class="bi bi-folder"></i> Группы
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="text-center py-5 text-muted">
<i class="bi bi-shop" style="font-size:2rem;"></i>
<p class="mt-2">Магазины ещё не загружены.<br>Синхронизация выполняется каждые {{ refresh_interval }} сек. автоматически.</p>
</div>
{% endif %}
</article>
<div class="card" style="padding:0;">
{% if stores %}
<div class="table-wrap">
<table class="tbl">
<thead>
<tr>
<th>Синхронизация</th>
<th>Название</th>
<th>Адрес</th>
<th>ID</th>
<th>Обновлено</th>
<th></th>
</tr>
</thead>
<tbody>
{% for s in stores %}
{% set is_enabled = (enabled_ids is none) or (s.evotor_id in enabled_ids) %}
<tr>
<td>
<form method="post" action="/catalog/stores/{{ s.evotor_id }}/toggle" style="margin:0;">
<button type="submit" class="tog {% if is_enabled %}on{% endif %}"
title="{% if is_enabled %}Отключить синхронизацию{% else %}Включить синхронизацию{% endif %}"
style="border:none;background:none;padding:0;cursor:pointer;"></button>
</form>
</td>
<td>
<div class="tbl-name">{{ s.name }}</div>
</td>
<td style="color:#9EA8BE;font-size:12px;">{{ s.address or '—' }}</td>
<td><span class="mono" style="font-size:11px;color:#9EA8BE;">{{ s.evotor_id }}</span></td>
<td><span class="mono" style="font-size:11px;color:#9EA8BE;">{{ s.fetched_at | datefmt }}</span></td>
<td>
<div style="display:flex;gap:6px;">
<a href="/catalog/stores/{{ s.evotor_id }}/products" class="btn btn-outline btn-xs">
<i class="bi bi-box-seam"></i> Товары
</a>
<a href="/catalog/stores/{{ s.evotor_id }}/groups" class="btn btn-outline btn-xs">
<i class="bi bi-folder"></i> Группы
</a>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="empty-state">
<i class="bi bi-shop"></i>
<p>Магазины ещё не загружены.<br>Синхронизация выполняется каждые {{ refresh_interval }} сек. автоматически.</p>
</div>
{% endif %}
</div>
{% endblock %}