Чтобы тестовое задание не отпугнуло сильных кандидатов, оно должно отвечать трем правилам: 1. **Быть реалистичным** (отражать ваши реальные задачи). 2. **Иметь границы** (не требовать написания бэкенда, занимать 4–6 часов). 3. **Оставлять место для архитектурных решений** (чтобы вы увидели, как кандидат думает). Ниже представлен готовый текст тестового задания, который вы можете отправлять кандидатам. Он охватывает 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) *Если у тебя останется время и желание выделиться:* 1. Добавь клиентскую или "серверную" (мокированную) фильтрацию по статусу заявки в URL (через Search Params TanStack Router'а). 2. Напиши 1-2 Unit-теста (Vitest) на утилитарную функцию или хук. 3. Напиши простейший E2E тест (Playwright) на прохождение флоу «Заполнение и отправка формы». --- ### 📦 Что мы будем оценивать (Критерии приемки) 1. **Type Safety:** Отсутствие `any`, грамотное использование Generics для ответов "API" и типизация роутов. 2. **Оптимизация:** Как ты работаешь с рендерами таблицы при поступлении WS-сообщений (не тормозит ли интерфейс). 3. **Архитектура:** Разделение логики (UI отдельно, работа с API отдельно, WS-клиент вынесен логично). 4. **Качество работы с TanStack Query:** Правильное использование `queryKey`, мутаций и инвалидации кэша. ### 📥 Формат сдачи * Код выложить на GitHub/GitLab (публичный или приватный репозиторий — во втором случае дай нам доступы). * В `README.md` укажи команду для запуска (`npm run dev`) и кратко опиши принятые архитектурные решения (почему сделал так, а не иначе). * Если задеплоишь на Vercel/Netlify — это будет супер! Удачи! Если возникнут вопросы по логике задания — смело пиши, мы на связи. --- ### 💡 Рекомендации для вас (нанимающего): **Как проверять это задание, когда кандидат его пришлет:** 1. **Смотрите на `package.json`:** Использовал ли он ровно то, что просили? 2. **Смотрите на папку `types` или `interfaces`:** Если там каша или `any`, кандидат не знает TypeScript. 3. **Проверьте интеграцию WS + React Query:** Слабый кандидат при получении события по сокету вызовет `queryClient.invalidateQueries()` (это вызовет лишний запрос на сервер). Сильный кандидат сделает `queryClient.setQueryData()` (точечно обновит кэш). Это маркер Senior-разработчика. 4. **Роутер:** Проверьте, использует ли он генерацию типов TanStack Router, или пишет роуты руками как в старом React Router.