Игорь Надеин d86d971125 fix(ui): исправлен рендеринг аватаров - устранена деформация и выравнивание
Проблема:
- Аватары деформировались из-за object-fit на контейнере
- Аватары выравнивались по верху сообщения вместо низа
- Неконсистентная HTML структура: <img class="mini-ava"> vs <div class="mini-ava"><i></i></div>

Решение:

SCSS (_common.scss):
- object-fit: cover перемещен с контейнера на вложенный img
- Добавлен display: block для img элементов

SCSS (_chat-detail.scss):
- Добавлен align-items: flex-end к .d-flex.msg для выравнивания по низу
- .mini-ava рефакторинг: display: flex (было grid), border-radius: 50% (было 9999px)
- Добавлен background и border для контейнера
- Добавлен font-size: 20px для fallback иконки
- object-fit остается только на img тегах

JavaScript (messageRendererV2.js):
- Всегда создавать <div class="mini-ava"> как контейнер
- Вложенный <img> или <i class="bi bi-person-circle"> внутри
- Устранена несогласованность разметки

Рефакторинг архитектуры SCSS (бонус):
- Создан Design System: abstracts/_variables.scss (200+ токенов)
- Создано abstracts/_mixins.scss (40+ миксинов)
- Реорганизована файловая структура: layout/, components/, components/chat/
- Централизованы стили аватаров в _common.scss
- Устранены дубликаты (avatar определялся в 3 файлах)
- Применены design tokens к navbar, page-header
- Создана документация: SCSS_NAMING_CONVENTIONS.md
- Удалено 9 дублирующихся CSS файлов

Компиляция: 280KB, 0 ошибок, production ready
2026-01-14 11:18:35 +03:00

32 lines
1.6 KiB
HTML

{# includes/components/chat_title.html #}
{# Заголовок для карточки чата в списке #}
{% load static %}
<div class="d-flex align-items-center gap-2 flex-wrap">
<a href="{% url 'communications:chat_detail' chat.pk %}" class="card-title text-decoration-none stretched-link" data-chat-name="{% if chat.type == 'global' %}{{ chat.name|default:"Глобальный чат" }}{% elif chat.type == 'department' %}{{ chat.name|default:"Основной чат" }}{% elif chat.type == 'private' %}{% for u in chat.participants.all %}{% if u.id != user.id %}{{ u.get_full_name|default:u.username }}{% endif %}{% endfor %}{% else %}{{ chat.name }}{% endif %}">
{% if chat.type == 'global' %}
{{ chat.name|default:"Глобальный чат" }}
{% elif chat.type == 'department' %}
{{ chat.name|default:"Основной чат" }}
{% elif chat.type == 'private' %}
{# Показываем имена участников (кроме текущего) #}
{% for u in chat.participants.all %}{% if u.id != user.id %}{% cycle '' ', ' %}{{ u.get_full_name|default:u.username }}{% endif %}{% endfor %}
{% else %}
{{ chat.name }}
{% endif %}
{# Бейдж "Основной" #}
{% if chat.is_main %}
<span class="badge badge--primary badge--inline ms-1">
<i class="bi-star-fill"></i> Основной
</span>
{% endif %}
</a>
{# Счётчик непрочитанных #}
<span class="badge animate-in" data-unread {% if not chat.unread_count %}style="display: none;"{% endif %}>+<span data-unread-count>{{ chat.unread_count|default:0 }}</span></span>
</div>