Онлайн песочница CodeSandbox: https://codesandbox.io/p/github/gukihuman/klerk-rubricator/main
Vercel (только фронтенд): https://klerk-rubricator.vercel.app
Скачать проект (автоматически создаст папку "klerk-rubricator").
git clone https://github.com/gukihuman/klerk-rubricator.git
Перейти в папку проекта, поставить зависимости и запустить dev сервер:
cd klerk-rubricator
npm install
npm run dev
Открыть http://localhost:3000/ в браузере.
Планировалось 10 часов, получилось ~14. Логика не сложная, но возникла проблема с API на продакшене (+2 часа). Плюс больше времени потратил на аккуратность (+2 часа), при чем оцениваю такую трату не эффективной - код и так получается хороший, я скорее немного зациклился.
- Оставил в консоли вывод полученных данных для удобства проверки задания. В работе такой вывод данных был бы убран, конечно.
- Комментарии в коде на английском, потому что так привык. В работе, разумеется, буду соблюдать принятую в проекте стилистику.
- Возник вопрос по поводу вывода суммы count'ов для родительской категории "Рубрики". Напрямую об этом не сказано, но я ришил добавить. Отвлекать на такую мелочь в рамках тех. задания не стал. В работе бы спросил в процессе выполнения.
- Общая сумма пустых рубрик отличается, т. к. некоторые из них все-таки имеют не нулевой count.
- Добавил API server-side обработчик, который принимает данные с основного API через обычную fetch функцию. Причина - неизвесная ошибка Nuxt'овского $fetch в продакшене: пробовал CodeSandbox, StackBlitz и Vercel (на dev сервере все в порядке). Другие API работают без проблем. Есть подозрение, что в нашей API нехватает каких-то заголовков и / или это связано с CORS. На углубление в понимание проблемы потребуется время. С другой стороны, server-side обработчик на фронтенде работает нормально и можно спокойно его использовать, если нет необходимости иметь статичный build. Можно даже, например, перенести часть логики обработки данных на сервер.
- Можно добавить анимацию для суммы выбранных рубрик, когда они меняются: сам счетчик растет или уменьшается. Конечно, анимация не должна быть долгой (не больше 100 мс).
- Хотелось бы проработать логику переключения отображения пустых рубрик. В данный момент переключение этой опции сбрасывает выбранные (с поставленной галочкой) рубрики и их счетчик, а так же закрывает категории кроме керневой. Это связано с тем, что по сути мы работаем с двумя разными массивами данных. Мне видится, что если у нас один список и есть опция отображения, то параметр allowEmpty можно было бы реализовать не за счет отдельного API запроса, как указано в тех. задании, а за счет фильтрации основного массива по принципу отсутствия count уже на фронтенде. Конечно, требуется обсудить это с руководилетем, может быть есть причины, почему такой вариант не подходит.
- Когда в категории есть выбранные элементы, но она закрыта, можно отображать кружок после названия или что-то подобное, чтобы показать, что в категории есть выбранные элементы.
Интересный выбор, с которым я столкнулся - использовать ли рекурсивный компонент для представления индивидуального слоя рубрик или просто использовать вложенный v-for несколько раз. Использование вложенного v-for потребовало бы установления некоторых ограничений для бэкенда: фронтенд может обрабатывать только до, например, 3-ех вложенных уровней, а хотелось бы, чтобы фронтенд представлял собой надежную архитектуру, способную стабильно обрабатывать данные с API, даже если в будущем появятся дополнительные вложенные уровни рубрик. Решил использовать рекурсивный компонент RubricLayer, который представляет индивидуальный слой рубрик и вызывает сам себя для дочерних рубрик. Можно было бы объединить с основным компонентом Rubricator, но это привело бы к нагромождению кода: пришлось бы добавлять динамический параметр isRoot и на него привязывать различия в template. Конечно появляется дополнительный компонент, который не инкапсулирован, но документация должна решить эту проблему. Конечно, в идеале бы не создавать лишних компонентов, и я бы предложил руководителю сделать один компонент с чуть более сложным внутренним кодом, если так удобнее.