└── README.md /README.md: -------------------------------------------------------------------------------- 1 | # Привет! 2 | 3 | Это тестовое задание на стажировку в KODE. 4 | 5 | ## Что нужно сделать 6 | 7 | В качестве тестового задания мы предлагаем тебе реализовать небольшое приложение, в котором есть всего по чуть-чуть: вёрстки, работы с API, преобразования данных и т.д. 8 | 9 | ## Какие требования к процессу и результату 10 | 11 | Первое, что нужно сделать — это прочитать и разобраться во всех требованиях, дизайне и API, указанных в этом документе. 12 | Затем разбить проект на отдельные задачи, то есть декомпозировать. 13 | После планирования можно переходить к программированию. 14 | Двигаясь по собственному плану, реализуй тестовое задание. 15 | 16 | 17 | ## Что нужно использовать 18 | 1. Создайте чистый vite проект на основе шаблона `react-ts` 19 | 20 | `$ npm create vite kode-intership-2025-react --template react-ts` 21 | 22 | 2. React Router 23 | 3. Axios 24 | 25 | ### Рекомендуется дополнительно использовать 26 | - Effector \ redux 27 | - styled-components 28 | 29 | > - Рекомендованный стэк не ограничивает тебя по применению других технологий и библиотек. 30 | 31 | ### Не рекомендуется 32 | - Использовать готовый UI-kit (нам важно понимать что ты умеешь не только использовать готовые компоненты, но и верстать самостоятельно) 33 | 34 | 35 | ## Дизайн 36 | 37 | Хороший дизайн для клиентского разработчика — отличный способ быстро понять, что предстоит сделать. Не забываем, что вёрстка должна быть адаптивной. 38 | 39 | [https://www.figma.com/file/GRRKONipVClULsfdCAuVs1/KODE-Trainee-Dev-Осень'21?node-id=11%3A14414](https://www.figma.com/file/GRRKONipVClULsfdCAuVs1/KODE-Trainee-Dev-%D0%9E%D1%81%D0%B5%D0%BD%D1%8C'21?node-id=11%3A14414) 40 | 41 | ## API 42 | 43 | Спецификация метода API - [https://kode-frontend-team.stoplight.io/docs/koder-stoplight/e981f97438300-get-users-list](https://kode-frontend-team.stoplight.io/docs/koder-stoplight/e981f97438300-get-users-list) 44 | 45 | ### Получить всех пользователей 46 | 47 | ```javascript 48 | const options = { 49 | method: "GET", 50 | headers: { "Content-Type": "application/json" }, 51 | }; 52 | fetch( 53 | "https://stoplight.io/mocks/kode-frontend-team/koder-stoplight/86566464/users?__example=all", 54 | options 55 | ) 56 | .then((response) => response.json()) 57 | .then((response) => console.log(response)) 58 | .catch((err) => console.error(err)); 59 | ``` 60 | 61 | ### Получить пользователей определённого департамента 62 | 63 | ```javascript 64 | const options = { 65 | method: "GET", 66 | headers: { "Content-Type": "application/json" }, 67 | }; 68 | fetch( 69 | "https://stoplight.io/mocks/kode-frontend-team/koder-stoplight/86566464/users?__example=frontend", 70 | options 71 | ) 72 | .then((response) => response.json()) 73 | .then((response) => console.log(response)) 74 | .catch((err) => console.error(err)); 75 | ``` 76 | 77 | > Параметр `__example` может принимать одно из значений: 78 | > `android` `ios` `design` `management` `qa` `back_office` `frontend` `hr` `pr` `backend` `support` `analytics` 79 | 80 | ### Пример запроса для тестирования на разных данных (генерируется автоматически при каждом запросе) 81 | 82 | ```javascript 83 | const options = { 84 | method: "GET", 85 | headers: { "Content-Type": "application/json" }, 86 | }; 87 | 88 | fetch( 89 | "https://stoplight.io/mocks/kode-frontend-team/koder-stoplight/86566464/users?__dynamic=true", 90 | options 91 | ) 92 | .then((response) => response.json()) 93 | .then((response) => console.log(response)) 94 | .catch((err) => console.error(err)); 95 | ``` 96 | 97 | ### Запрос, который вернёт ошибку с http кодом 500 98 | 99 | ```javascript 100 | const options = { 101 | method: "GET", 102 | headers: { "Content-Type": "application/json" }, 103 | }; 104 | fetch( 105 | "https://stoplight.io/mocks/kode-frontend-team/koder-stoplight/86566464/users?__code=500&__dynamic=true", 106 | options 107 | ) 108 | .then((response) => response.json()) 109 | .then((response) => console.log(response)) 110 | .catch((err) => console.error(err)); 111 | ``` 112 | 113 | ## Функциональные требования 114 | 115 | ### Запуск 116 | 117 | Когда пользователь открывает сайт, необходимо загрузить актуальный список всех работников компании. 118 | 119 | При входе в приложение необходимо отобразить экран 2.0.0. Изначально он должен быть в состоянии загрузки, экран 1.0.0. Если при загрузке произошла ошибка, отсутствует интернет-соединение или API вернул ошибку, необходимо отобразить экран «Критическая ошибка». В случае успеха необходимо отобразить Top App Bar и список людей. 120 | 121 | ### Top App Bar 122 | 123 | Компонент находится вверху экрана и представляет собой поле для поиска с иконкой «Поиск», кнопкой «Сортировка» и панелью вкладок. При переключении между вкладками на главном экране список работников фильтруется и отображаются только люди, работающие в выбранном департаменте, либо все, если выбрана вкладка «Все». 124 | 125 | #### Возможны 2 вида реализации 126 | 127 | 1. **Простая.** Использовать фильтрацию пользователей на клиенте. 128 | 2. **Чуть сложнее.** Использовать серверную фильтрацию по параметру `__example` 129 | 130 | ##### Задания со звёздочкой 131 | 132 | 1. Рассказать о преимуществах и недостатках разных способов реализации пагинации 133 | 134 | #### Соответствия названия вкладок с полем "department" из запроса API: 135 | 136 | ``` 137 | android -> Android 138 | ios -> iOS 139 | design -> Дизайн 140 | management -> Менеджмент 141 | qa -> QA 142 | back_office -> Бэк-офис 143 | frontend -> Frontend 144 | hr -> HR 145 | pr -> PR 146 | backend -> Backend 147 | support -> Техподдержка 148 | analytics -> Аналитика 149 | ``` 150 | 151 | При нажатии на кнопку «Фильтр» открывается модальное окно с вариантами сортировки списка работников. Есть два варианта сортировки: «По алфавиту» (по умолчанию), «По дню рождения». При переключении варианта сортировки модальное окно должно закрываться, а список на главной странице должен обновиться. 152 | 153 | Когда пользователь вводит текст в поисковое поле, необходимо фильтровать список на главном экране и отображать только работников, соответствующих параметрам поиска. Поиск может осуществляться по имени, фамилии или никнейму, состоящему из двух символов. 154 | 155 | В случае отсутствия результатов поиска необходимо отобразить информацию о том, что ничего не было найдено. Экран "2.0.2Г Люди (Ошибка поиска)" 156 | 157 | ### Страница «Главная» 158 | 159 | На странице должна быть расположена верхняя панель приложения, на которой должны находиться: 160 | 161 | - поле для поиска; 162 | - панель вкладок для группировки загруженного списка пользователей; 163 | - список работников. 164 | 165 | Список должен обновляться каждый раз, когда меняются параметры поиска, обновляется вариант сортировки или пользователь переключает вкладки департаментов. 166 | 167 | Пользователь имеет возможность скроллить список работников. 168 | 169 | В режиме сортировки «По алфавиту» для каждого работника отображается его фотография, имя, никнейм и департамент. 170 | 171 | В режиме сортировки «По дню рождения» список отображается от ближайшей даты дня рождения вниз. Если день рождения следующего работника будет только в следующем году, то необходимо отобразить блок с годом, экран 2.0.1. 172 | 173 | Когда пользователь кликнет на человека, необходимо открыть экран информации о человеке (экран «детали»). 174 | 175 | ##### Задание со звёздочкой 176 | 177 | Поиск, обновление списка должно происходить только после того, как пользователь закончил печатать. 178 | 179 | ### Страница «детали» 180 | 181 | Должна быть реализована как отдельный роут в приложении. 182 | 183 | Должна быть возможность попасть на страницу по ссылке. 184 | 185 | Вверху экрана деталей должна отображаться кнопка назад для навигации на главный экран. Также можно вернуться на главный экран, если нажать кнопку назад в браузере. 186 | 187 | В шапке экрана должна отображаться аватарка пользователя, имя, никнейм и название департамента. 188 | Ниже находится дата рождения и номер телефона. При нажатии на номер телефона необходимо открыть приложение для звонка по номеру. 189 | 190 | ## Дополнительные задания 191 | 192 | Дополнительные задания не обязательны для выполнения, но очень желательны. Если ты не успеваешь — лучше сделать хорошо основную часть. 193 | 194 | ### Реализовать real-time отслеживание состояния сети устройства 195 | 196 | При отключении устройства от сети, верхняя панель приложения должна измениться на сообщение об ошибке сети, экран 2.0.0.А — Люди (Ошибка). 197 | При этом должна остаться возможность пользоваться приложением в offline, теми данными, которые успели загрузится до отключения сети. 198 | 199 | При восстановлении доступа к сети: 200 | 201 | 1. Верхняя панель приложения должна измениться на сообщение о загрузке, экран 2.0.0.А — Люди (Загрузка). 202 | 2. Список на активной вкладке должен обновиться. 203 | 204 | ### Сохранение состояния фильтрации и поиска 205 | 206 | Ожидаемый результат: 207 | 208 | - На главном экране выбрана сортировка «по дню рождения» 209 | - Введена строка поиска 210 | - Отображается результат поиска 211 | - Пользователь переходит на экран «детали» 212 | - Возвращается назад 213 | - Состояние поиска и сортировки сохранено. 214 | 215 | ### Кэширование результатов запроса по различным параметрам 216 | 217 | Для запроса пользователей с параметром фильтра результат должен кэшироваться на клиенте на 5 минут. 218 | 219 | Ожидаемый результат: 220 | 221 | 1. Переход на вкладку «Все» 222 | - Выполняется запрос без фильтрации. 223 | 2. Переход на вкладку «Дизайн» 224 | - Выполняется запрос с фильтрацией по полю department. 225 | 3. Переход на вкладку «Все» 226 | - До истечения 5 минут запрос не выполняется, данные отображаются из кэша. 227 | - После истечения 5 минут запрос выполняется, отображаются свежие данные. 228 | 4. Повторный переход на вкладку «Дизайн» 229 | - До истечения 5 минут запрос не выполняется, данные отображаются из кэша. 230 | - После истечения 5 минут запрос выполняется, отображаются свежие данные. 231 | 232 | ### Реализовать темную тему для приложения 233 | - Цвета подобрать на свой вкус 234 | - Добавить контрол переключения темы 235 | - Устанавливать тему в зависимости от системных настроек пользователя 236 | 237 | ### Добавить локализацию 238 | - Добавить возможность переключать язык интрефейса 239 | - Устанавливать язык в зависимости от системных настроек пользователя 240 | 241 | ### Опубликовать проект на github pages 242 | - Опубликуй свой проект, добавь ссылку в `README.md` 243 | 244 | ## Критерии приемки задания 245 | 1. Создай чистый публичный репозиторий на github.com 246 | 2. Первым коммитом добавь свою декомпозицию данного задания в `README.md`. По пунктам, что будешь делать и в какой последовательности. 247 | 3. Укажи свои ФИ в начале `README.md` 248 | 4. Выполни задание и пушни результат в `main` ветку 249 | 5. Отправь ссылку на свой репозиторий в TBD 250 | 251 | > Старайся добавлять атомарные коммиты с понятным описанием, показывая ход выполнения задания 252 | 253 | > Обрати внимание на детали дизайна, старайся прорабатывать все состояния интрефейса. 254 | > Верстка должна быть аккуратной. 255 | 256 | ### На этом всё, желаем удачи! 257 | --------------------------------------------------------------------------------