💻

Тестовые задания

Калькулятор валют с курсами

📌 Функционал
  1. Ввод данных
      • Сумма для конвертации (input)
      • Валюта «из» (select, например USD)
      • Валюта «в» (select, например EUR)
  1. Получение курса
      • При клике «Конвертировать» — запрашиваем курс
      • Выводим результат на экран, например: 100 USD → 92 EUR
  1. История / избранные пары
      • Отображаем список последних 10 конвертаций
      • Храним этот список в localStorage
      • Добавляем кнопку «Очистить историю»
      • Сортировка истории (по дате, сумме)
  1. Обработка состояний запроса
      • Loader во время загрузки данных по сети
      • Если API не отвечает/Нет интернета → показываем ошибку
API
  • https://api.exchangeratesapi.io
✅ Чеклист для ревью
Корректно работает ввод суммы, выбор валют, кнопка конвертации
Добавляет результаты в localStorage
Ограничивает историю 10 записями
Чистит историю кнопкой «Clear History»
Показывает ошибку при сбое API
Показывает loader при загрузке данных
 

Виджет авторизации

📌 Функционал
Необходимо написать виджет авторизации.
Реализовать api-сервер со следующими endpoint:
POST /v1/auth/sign-in Params: { login: string, passwrod: string } Response: { authToken: string } POST /v2/auth/sign-in Params: { login: string, passwrod: string } Response: authToken in cookies GET /users/me Params: authToken in cookies Response: { login: string }
Реализовать форму на клиенте с переключателем формата регистрации (v1, v2). После заполнения формы должен показываться блок с login-ом пользователя.
Выписывать настоящие токены не нужно. Придумайте рандомный токен и валидируйте его хардкодом на сервере, чтобы не усложнять себе задание.
✅ Чеклист для ревью
API реализует возвращение токена в cookies и устанавливает на клиент
API реализует возвращение токена в body
На фронте можно переключиться между версиями авторизации
 

Многошаговая форма

📌 Функционал
Нужно реализовать многошаговый конструктор формы, где структура формы полностью описывается конфигом, получаемым с бэкенда.
 

Технический стек

  • React
  • TypeScript (must have)
  • Любой менеджер состояния (React контекст, Zustand, Redux, jotai и т.п.).
  • Без UI-фреймворков типа MUI/Antd — стили можно простые, через CSS/SCSS/Styled Components/…
 

Функциональные требования

  1. Многошаг
      • Форма разбита на шаги (pages).
      • Есть навигация “Назад/Далее”.
      • Нельзя перейти дальше, пока текущий шаг невалиден.
      • Отображать прогресс (например, “Шаг 2 из 4” или прогресс-бар).
  1. Конфиг-драйв форма (SDUI/BDUI)
      • Структура формы не захардкожена в JSX, а описана в JSON-конфиге, который фронт получает с API.
      • На основе конфига рендерятся:
        • Заголовки шагов
        • Поля формы
        • Правила валидации
        • Условия видимости полей
  1. Типы полей (минимум такие)
      • text — обычный текстовый инпут
      • number
      • select — выпадающий список
      • checkbox
      • radio
      • textarea
  1. Валидация
      • Поддержать в конфиге:
        • required
        • minLength, maxLength (для текстовых)
        • min, max (для number)
        • pattern (RegExp строкой)
      • Ошибки показывать пользователю под полем или рядом.
  1. Условная видимость полей (conditional logic)
      • В конфиге поле может иметь условие вида “показывать только если другое поле имеет такое-то значение”.
      • Например:
        • если hasCar === true, показываем поля о машине;
        • если employmentStatus === "self_employed", показываем блок полей о бизнесе.
  1. Загрузка конфига и отправка результата
      • При старте приложение запрашивает конфиг по API GET /api/form.
      • После прохождения всех шагов и успешной валидации — отправить данные формы на POST /api/form.
      • Обработать:
        • состояние загрузки конфига
        • ошибку при загрузке
        • состояние отправки формы, успех/ошибка
  1. UX
      • Кнопка “Назад” недоступна на первом шаге.
      • Кнопка “Далее” дизейблится или показывает ошибки, если есть невалидные обязательные поля.
      • При ошибке отправки формы показать пользователю сообщение.

      Формат конфига

      Пример ответа GET /api/form:
      { "title": "Регистрация пользователя", "pages": [ { "id": "personal", "title": "Личные данные", "fields": [ { "id": "firstName", "type": "text", "label": "Имя", "placeholder": "Введите имя", "validation": { "required": true, "minLength": 2, "maxLength": 30 } }, { "id": "age", "type": "number", "label": "Возраст", "validation": { "required": true, "min": 18, "max": 120 } }, { "id": "employmentStatus", "type": "radio", "label": "Занятость", "options": [ { "value": "employed", "label": "Работаю по найму" }, { "value": "self_employed", "label": "Самозанятый/бизнес" }, { "value": "unemployed", "label": "Не работаю" } ], "validation": { "required": true } } ] }, { "id": "business", "title": "Данные о бизнесе", "fields": [ { "id": "companyName", "type": "text", "label": "Название компании", "visibilityCondition": { "fieldId": "employmentStatus", "operator": "eq", "value": "self_employed" }, "validation": { "required": true, "minLength": 2 } }, { "id": "employeesCount", "type": "number", "label": "Количество сотрудников", "visibilityCondition": { "fieldId": "employmentStatus", "operator": "eq", "value": "self_employed" } } ] }, { "id": "other", "title": "Прочее", "fields": [ { "id": "hasCar", "type": "checkbox", "label": "Есть ли у вас авто?" }, { "id": "carModel", "type": "text", "label": "Марка автомобиля", "visibilityCondition": { "fieldId": "hasCar", "operator": "eq", "value": true }, "validation": { "required": true } } ] } ] }

      Будет плюсом

      • Поддержка сохранения прогресса (например, в localStorage).
      • Integration тесты на ключевые части логики (валидация, условная видимость).