Чтобы тестовое задание не отпугнуло сильных кандидатов, оно должно отвечать трем правилам:
- Быть реалистичным (отражать ваши реальные задачи).
- Иметь границы (не требовать написания бэкенда, занимать 4–6 часов).
- Оставлять место для архитектурных решений (чтобы вы увидели, как кандидат думает).
Ниже представлен готовый текст тестового задания, который вы можете отправлять кандидатам. Он охватывает 100% вашего стека.
Тестовое задание: «Real-time Дашборд Заявок» (Frontend)
Привет! Спасибо за интерес к нашей команде. Чтобы мы могли оценить твои навыки работы с нашим техническим стеком (React, TS, TanStack экосистема, WebSockets), мы подготовили небольшое практическое задание.
Мы ценим твое время, поэтому не ждем от тебя написания бэкенда. Всю серверную часть (API и WebSockets) достаточно замокать на клиенте (через setTimeout / setInterval или библиотеку вроде msw).
Ожидаемое время выполнения: 4–6 часов. Главный критерий: Качество архитектуры, типизации и чистота кода важнее, чем 100% реализованного функционала «на костылях».
📝 Легенда
Тебе нужно разработать мини-SPA для оператора технической поддержки — Дашборд управления заявками (Tickets).
🛠 Технический стек (Обязательно)
- Сборка: Vite
- Фреймворк: React 18+
- Типизация: Strict TypeScript
- Роутинг: TanStack Router (File-based routing)
- Данные: TanStack Query (React Query)
- Стейт: Zustand
- UI/Формы: React Hook Form + Zod, CSS Modules / SCSS (или Mantine, если удобно)
- Таблицы:
mantine-react-table(или аналог, если с Mantine не работал)
🚀 Задачи
1. Роутинг (TanStack Router)
Настрой Type-safe роутинг для двух страниц:
/— Страница со списком заявок (Таблица)./tickets/new— Страница создания новой заявки (Форма).
2. Таблица заявок (TanStack Query + Mantine React Table)
На главной странице отобрази таблицу заявок.
- Поля:
id,title,status(Open, In Progress, Resolved),createdAt,priority(Low, Medium, High). - Функционал: Реализуй Infinite Scroll (бесконечную подгрузку) или серверную пагинацию, используя
useInfiniteQuery/useQuery. - Сделай имитацию задержки ответа сервера (500ms), чтобы показать состояния загрузки (скелетоны или спиннеры).
3. Real-time обновления (WebSockets / STOMP)
- Напиши мок (фальшивый) WebSocket-клиент, который раз в 10–15 секунд присылает событие: «Статус заявки [ID] изменен на [Новый статус]».
- Главная задача: При получении этого события обнови данные в кэше TanStack Query точечно (без полного рефетча всего списка), чтобы статус в таблице изменился в реальном времени.
4. Глобальный стейт (Zustand)
- Реализуй систему уведомлений (Toasts).
- Когда по WebSocket приходит изменение статуса, показывай всплывающее уведомление (через Zustand-стор) в углу экрана.
5. Форма создания (React Hook Form + Zod)
На странице /tickets/new создай форму добавления заявки:
- Поля: Название (строка, мин 5 символов), Описание (текст), Приоритет (селект).
- Настрой строгую валидацию через Zod.
- При успешном сабмите: используй
useMutation(имитация отправки на сервер), инвалидируй кэш списка заявок и сделай редирект на главную страницу (/).
🌟 Будет плюсом (Nice to have)
Если у тебя останется время и желание выделиться:
- Добавь клиентскую или "серверную" (мокированную) фильтрацию по статусу заявки в URL (через Search Params TanStack Router'а).
- Напиши 1-2 Unit-теста (Vitest) на утилитарную функцию или хук.
- Напиши простейший E2E тест (Playwright) на прохождение флоу «Заполнение и отправка формы».
📦 Что мы будем оценивать (Критерии приемки)
- Type Safety: Отсутствие
any, грамотное использование Generics для ответов "API" и типизация роутов. - Оптимизация: Как ты работаешь с рендерами таблицы при поступлении WS-сообщений (не тормозит ли интерфейс).
- Архитектура: Разделение логики (UI отдельно, работа с API отдельно, WS-клиент вынесен логично).
- Качество работы с TanStack Query: Правильное использование
queryKey, мутаций и инвалидации кэша.
📥 Формат сдачи
- Код выложить на GitHub/GitLab (публичный или приватный репозиторий — во втором случае дай нам доступы).
- В
README.mdукажи команду для запуска (npm run dev) и кратко опиши принятые архитектурные решения (почему сделал так, а не иначе). - Если задеплоишь на Vercel/Netlify — это будет супер!
Удачи! Если возникнут вопросы по логике задания — смело пиши, мы на связи.
💡 Рекомендации для вас (нанимающего):
Как проверять это задание, когда кандидат его пришлет:
- Смотрите на
package.json: Использовал ли он ровно то, что просили? - Смотрите на папку
typesилиinterfaces: Если там каша илиany, кандидат не знает TypeScript. - Проверьте интеграцию WS + React Query: Слабый кандидат при получении события по сокету вызовет
queryClient.invalidateQueries()(это вызовет лишний запрос на сервер). Сильный кандидат сделаетqueryClient.setQueryData()(точечно обновит кэш). Это маркер Senior-разработчика. - Роутер: Проверьте, использует ли он генерацию типов TanStack Router, или пишет роуты руками как в старом React Router.