Все работы

[ Коммерческий продукт ]

STEAM.KZ Platform

Две React/TypeScript SPA и серверные модули поверх образовательной платформы на WordPress и LearnDash — аналитика по ролям, отчёты школам в WhatsApp и челлендж для учителей.

steam.kz
Роль
Frontend Developer
Команда
STEAM.KZ
Период
Март — сентябрь 2026
Статус
Production
Интерфейс
  • React 19
  • TypeScript
  • TanStack Query
  • TanStack Router
  • TanStack Table
Сервер
  • PHP
  • WordPress REST API
Интеграции
  • WhatsApp Cloud API
  • Instagram Graph API
Документы
  • mPDF / FPDI
Пользовательская главная STEAM.KZ с курсами и предметами

Пользовательская главная STEAM.KZ.

Контекст

STEAM.KZ уже использовала WordPress и LearnDash для образовательного контента — сейчас на платформе 94 школы. Продукту потребовались отдельные кабинеты для учителей, администраторов школ, кураторов и управления платформой.

Существующую систему никто не переписывал с нуля. Задача — надстроить над WordPress связный прикладной слой: маршрутизацию, состояние, доступ по ролям, аналитику и отчётность. Позже к нему добавились два модуля, которые выходят за пределы сайта: отчёт, который сам приходит директору школы в WhatsApp, и челлендж, где учителя присылают ролики из Instagram.

Моя роль / где проходит граница

Моя зона — frontend и пользовательские сценарии. Я разрабатывал обе SPA — административную и клиентскую, — формы, таблицы, фильтры, навигацию по ролям, вход через WordPress, аналитику и весь путь до готового отчёта. Для модулей рассылки и челленджа я вёл и серверную часть плагина на PHP: схему таблиц, REST-контроллеры, планировщик и воркер рассылки, вебхуки и клиентов внешних API. CI и первые модульные тесты настроил коллега.

Я не создавал ни WordPress, ни LearnDash, ни исходную контентную платформу. Кейс — про надстроенный над ними продуктовый слой и про поставку изменений.

Обзор аналитики администратора платформы с фильтрами и KPI
Административная SPA: фильтры по периоду, региону и школе над общей аналитикой.

Решение 1 / одна аналитическая модель, разные роли

Администратор платформы фильтрует данные по периоду, региону и школе. Куратор переходит от общего обзора к выбранной школе. Администратор школы видит только свою школу — выбирать ему нечего.

За тремя дашбордами стоит одна продуктовая модель с тремя уровнями доступа.

Аналитика выбранной школы в интерфейсе куратора
Та же аналитика в интерфейсе администратора школы
Одна модель, разный охват: куратор выбирает школу, администратор школы уже в своей.

Решение 2 / отчёт, который доходит сам

Администратор школы и куратор собирают PDF по своей школе. Сборка отчёта берёт KPI и активность учителей, держит русские и казахские глифы, повторяет шапку таблицы на каждой странице и кладёт всё на фирменный бланк A4 через FPDI.

Тот же генератор раз в месяц отправляет отчёт директору в WhatsApp через Meta Cloud API. Планировщик ставит школы в очередь, воркер отправляет с повторами и эскалацией в Telegram, у всей рассылки есть рубильник. Под отчётом — кнопка оценки платформы от 0 до 5: ответ возвращается вебхуком и оживляет колонку удовлетворённости в дашбордах. На слово «стоп» школа отписывается.

Главное, что показал пилот на проде: статус sent в журнале означал «Meta приняла», а не «доставлено». Первая отправка была отмечена в журнале как успешная, но до телефона не дошла — Meta отбросила её из-за неактивного биллинга, а код этого не видел: причина приходит отдельным вебхуком статусов, который до этого отбрасывался. Теперь провал доставки пишется в журнал с причиной, строка возвращается в очередь на повтор, а повторная доставка того же вебхука не поднимает второй алерт.

Первая страница PDF-отчёта по школе на фирменном бланке
Страница сгенерированного отчёта. Синтетические данные, настоящий бланк и вёрстка. Отчёт целиком
Сообщение в WhatsApp с PDF-отчётом по школе за август и кнопкой «Оценить»
Список оценок платформы от 0 до 5 в WhatsApp
Оценка 3, затем «стоп» и подтверждение отписки на казахском и русском
Пилот на проде: отчёт приходит в WhatsApp, оценка возвращается списком, «стоп» отписывает школу. Имя получателя скрыто.

Решение 3 / проверка, которой не существовало

Челлендж мотивирует учителей снимать Reels о работе на платформе. Школе включают задание на период, учитель видит прогресс и приз и присылает ссылки на ролики, а принятые ролики собираются в сводную таблицу.

Техническое задание обещало, что соавторство с аккаунтом @steam_kz система проверит через Instagram API. Проверка живыми запросами показала, что такого пути нет: лента аккаунта отдаёт только собственные публикации, а чужой ролик до принятия приглашения недоступен вовсе. Рабочими оказались эндпоинты совместной работы, которые Meta выпустила в апреле 2026: приглашения к соавторству принимаются автоматически, после этого ролик виден с кодом и лайками и сверяется с присланной ссылкой.

Цена — лимит платформы, 50 принятий в сутки на аккаунт. Зато автоматика ловит то, о чём в задании не было ни слова: ролик, удалённый после зачёта, и соавторство, снятое задним числом. Соответствие ролика теме по-прежнему проверяет человек — для этого в админке есть отклонение с причиной.

Кабинет учителя: прогресс 1 из 2, ролик отклонён с причиной «не является рилсом»
Кабинет учителя: прогресс 2 из 2, оба ролика приняты, приз открыт
Кабинет учителя: ролик отклонён с причиной, затем возвращён в принятые — прогресс засчитан, приз открыт.

Результат / проверка

  • две React-SPA и четыре ролевых кабинета;
  • аналитика по месяцу, году и произвольному периоду;
  • отчёты в PDF — вручную из трёх дашбордов и ежемесячно в WhatsApp;
  • пилоты рассылки и челленджа пройдены на проде;
  • первая боевая рассылка 5 октября: отчёт дошёл до 80 школ из 94;
  • релизы v2.7 административной и v2.1 клиентской части.
Переход от месячной аналитики к карточке учителя и к годовой.

Ограничения

Цифр по выручке у меня нет. 94 школы — охват платформы, своим результатом я его не считаю.

Из 14 недошедших отчётов девять не ушли вовсе: в школе не назначен администратор, и получателя нет. Ещё пять отправлены на номера, где нет WhatsApp.