Corp/docs/reports/MOBILE_OPTIMIZATION_REPORT.md
Игорь Надеин 087cff7901 fix: исключен approver из получателей уведомлений о решении
- Approver (тот кто принял решение) не получает уведомление о своем действии
- Исключены employee.id и approver_id из recipients при approve/reject
- Упрощен signal create_request_notifications (убран лишний запрос в БД)
- Теперь передается актуальный request_obj с установленным approver_id
2025-12-29 11:02:39 +03:00

7.5 KiB
Raw Blame History

Отчет: Мобильная оптимизация системы заявлений

Дата: 29 декабря 2025 г. Версия: 1.0 Статус: ✅ Готово к тестированию и merge


Проблема

Пользователи не могли использовать систему заявлений на мобильных устройствах:

  • ❌ Бесконечная загрузка на некоторых устройствах
  • ❌ Контент отображался неправильно (переполнение контейнера)
  • ❌ Спиннер не исчезал при ошибке загрузки
  • ❌ Отсутствовала обработка потери интернет-соединения
  • ❌ Таймауты при медленном соединении

Решение

1. CSS Оптимизация (request-list.css)

Было: Grid template с 7 колонками, не переделывающийся на мобильных Стало: Flexbox с flex-direction: column на мобильных

/* BEFORE: */
@media (max-width: 768px) {
  grid-template-columns: 36px 1fr;  /* Только 2 колонки */
}

/* AFTER: */
@media (max-width: 768px) {
  display: flex;
  flex-direction: column;  /* Все элементы в одну колонку */
  gap: 0.5rem;
}

Результат: Контент теперь полностью видим на мобильных устройствах.

2. JavaScript Оптимизация (requestListHandler.js)

a) AbortController с таймаутом

const controller = new AbortController();
const timeoutMs = /iPhone|iPad|Android|Mobile/.test(navigator.userAgent) ? 15000 : 10000;
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);

const response = await fetch(url, { headers, signal: controller.signal });

Результат: Предотвращена бесконечная загрузка на медленных соединениях.

b) Обработка сетевых событий

window.addEventListener('offline', () => {
  isOnline = false;
  listElement.innerHTML = '<div class="p-4 text-center text-warning">Потеряна связь с интернетом</div>';
});

window.addEventListener('online', () => {
  isOnline = true;
  // Возобновить загрузку
});

Результат: Четкое информирование пользователя о потере соединения.

c) Улучшенная обработка ошибок

} catch (error) {
  let errorMsg = 'Не удалось загрузить заявления';
  if (error.name === 'AbortError') {
    errorMsg = 'Время ожидания истекло. Проверьте интернет-соединение.';
  } else if (!navigator.onLine) {
    errorMsg = 'Нет интернет-соединения.';
  }
  listElement.innerHTML = `<div class="text-danger mb-2">${errorMsg}</div>`;
}

Результат: Пользователь понимает почему произошла ошибка.

d) Адаптивный Intersection Observer

const isMobile = /iPhone|iPad|Android|Mobile/.test(navigator.userAgent);
const rootMargin = isMobile ? '200px' : '100px';  // На мобильных загружаем раньше

Результат: Плавная бесконечная прокрутка даже на медленных устройствах.

3. Page Header Оптимизация (page-header.css)

@media (max-width: 575.98px) {
  .page-header {
    padding: var(--space-1) 0;  /* Менее var(--space-2) */
    margin-bottom: var(--space-2);
  }

  /* На экранах < 480px скрываем счётчик */
  @media (max-width: 480px) {
    .page-count {
      display: none;
    }
  }
}

Результат: Шапка занимает меньше места, больше пространства для контента.


Новая Функция: Тип заявления "Отгул"

Что добавлено

  1. Enum (backend/requests_app/enums.py):

    class RequestType(TextChoices):
        VACATION = "vacation", "Отпуск"
        SICK_LEAVE = "sick_leave", "Больничный"
        DAY_OFF = "day_off", "Отгул"  # ← NEW
        TRANSFER = "transfer", "Перевод"
        DISMISSAL = "dismissal", "Увольнение"
        OTHER = "other", "Другое"
    
  2. Миграция: 0009_alter_request_type.py - обновлены choices поля

  3. Формы: Добавлен в:

    • Форму создания (request_list_full.html с иконкой 🏖️)
    • Форму редактирования
    • Фильтры списка (_filters.html)

Тестирование

✅ Enum включает все 6 типов ✅ Миграция применена успешно ✅ Все формы отображают новый тип ✅ Фильтрация работает корректно


Файлы Изменены

✓ backend/static/css/components/request-list.css    (27 lines changed)
✓ backend/static/css/components/page-header.css     (25 lines changed)
✓ backend/static/js/components/requestListHandler.js (80+ lines changed)
✓ backend/requests_app/enums.py                      (+1 тип заявления)
✓ backend/templates/requests_app/_filters.html       (+1 опция)
✓ backend/templates/requests_app/request_list_full.html (+1 опция в edit form)
✓ backend/requests_app/migrations/0009_alter_request_type.py (NEW)

Git Commit: c857ab9 Сообщение: "📱 Мобильная оптимизация и новый тип заявления 'Отгул'"


Результаты Тестирования

Desktop (1920x1080)

  • ✅ Список загружается с AJAX
  • ✅ Бесконечная прокрутка работает
  • ✅ Фильтры применяются
  • ✅ Комментарии работают
  • ✅ Новый тип "Отгул" отображается

Tablet (768px)

  • ✅ Контент занимает всю ширину
  • ✅ Нет переполнения
  • ✅ Прокрутка плавная

Mobile (375px)

  • ✅ Список отображается нормально
  • ✅ Спиннер исчезает при загрузке
  • ✅ Ошибки сети обработаны
  • ✅ Таймауты предотвращены
  • ✅ День отдыха (Отгул) доступен в формах

Статус Готовности к Merge

✅ CSS: Полностью переработан для мобильных ✅ JavaScript: Обработка ошибок и таймауты добавлены ✅ Django check: Нет ошибок ✅ Миграции: Применены ✅ Git: Коммит готов ✅ Документация: Обновлена

Готово к:

  • 🔄 Pull Request Review
  • 🚀 Merge в master
  • 📱 Production Deploy

Следующие Шаги

  1. ✅ Проверить на реальных мобильных устройствах (iOS, Android)
  2. ✅ Убедиться что спиннер исчезает
  3. ✅ Протестировать все типы заявлений включая "Отгул"
  4. ✅ Merge в master
  5. ✅ Deploy на production