|
275 | 275 | .classList.toggle('show-search-input'); |
276 | 276 | }); |
277 | 277 |
|
| 278 | + // ** [СЕРВЕР] организация запроса, получение данных/списка клиентов с сервера (корректировка входящих данных) |
| 279 | + let clientsDataArrWithIds; |
| 280 | + |
| 281 | + async function getClientsServerListData() { |
| 282 | + try { |
| 283 | + const response = await fetch('http://localhost:3000/api/clients'); // запрос на сервер |
| 284 | + |
| 285 | + // проверка успешности/выполнения запроса |
| 286 | + if (!response.ok) { |
| 287 | + throw new Error(`Ошибка: ${response.status}!`); |
| 288 | + } |
| 289 | + |
| 290 | + const data = await response.json(); // преобразование данных в JSON-формат |
| 291 | + clientsDataArrWithIds = addLocalIdsToClients(data); // добавление поля localId |
| 292 | + |
| 293 | + // ! ТЕСТИРОВАНИЕ |
| 294 | + // addClientsToTable(clientsDataArrWithIds); // отрисовка данных, наполнение таблицы клиентов |
| 295 | + console.log(clientsDataArrWithIds); // ? ВЫВОД МАССИВА ОБЪЕКТОВ |
| 296 | + } catch (error) { |
| 297 | + console.error('Не удалось загрузить список клиентов..', error); |
| 298 | + alert('Ошибка при загрузке данных с сервера!?'); |
| 299 | + } |
| 300 | + } |
| 301 | + |
| 302 | + // добавление поля localId (необходимого/возможно, для дальнейших отработок) |
| 303 | + function addLocalIdsToClients(clientsFromServer) { |
| 304 | + return clientsFromServer.map((client, index) => ({ |
| 305 | + ...client, // сохранение приходящих/серверных полей |
| 306 | + localId: index + 1, // добавление localId |
| 307 | + })); |
| 308 | + } |
| 309 | + |
| 310 | + getClientsServerListData(); // получение данных о клиентах (с сервера) |
| 311 | + |
278 | 312 | // TODO: |
279 | 313 | // ** наполнение таблицы данных о клиентах (согласно откорректированного исходного, далее формирующегося массива) |
280 | 314 | let updateClientsDataArr = []; |
|
898 | 932 | noExtraSpaces: true, |
899 | 933 | }); |
900 | 934 |
|
901 | | - // ** организация "дополнительной" логики для валидации полей ввода/инпутов в модальных окнах (при/в "submit" состояниях) |
902 | | - function additionalFormInputsValidation(allModalInputs, modalBodyForm) { |
903 | | - const validErrors = []; |
904 | | - // определение минимального количества букв/символов (для каждого инпут/типа поля) |
905 | | - const minLengths = { |
906 | | - 'modal-surname-input': 3, |
907 | | - 'modal-name-input': 2, |
908 | | - 'modal-patronymic-input': 5, |
909 | | - 'modal-contact-input': { |
910 | | - phone: 18, |
911 | | - 'extra-phone': 18, |
912 | | - vk: 7, |
913 | | - email: 6, |
914 | | - facebook: 5, |
915 | | - twitter: 3, |
916 | | - 'extra-contact': 3, |
917 | | - }, |
918 | | - }; |
919 | | - // использование названий как в drop-down меню |
920 | | - const contactTypeLabels = { |
921 | | - phone: 'Телефон', |
922 | | - 'extra-phone': 'Доп. телефон', |
923 | | - vk: 'Vk', |
924 | | - email: 'Email', |
925 | | - facebook: 'Facebook', |
926 | | - twitter: 'Twitter', |
927 | | - 'extra-contact': 'Доп. контакт', |
928 | | - }; |
929 | | - |
930 | | - allModalInputs.forEach((input) => { |
931 | | - const parent = input.parentNode; |
932 | | - const feedback = parent.querySelector('.invalid-feedback'); |
933 | | - |
934 | | - if (input.value.trim() === '' || !input.checkValidity()) { |
935 | | - // определение/вывод сообщения в зависимости от "класса" инпута |
936 | | - if (!input.classList.contains('is-invalid')) { |
937 | | - if (input.classList.contains('modal__body-add-contact-input')) { |
938 | | - validErrors.push('Заполните поле контакта или удалите!'); |
939 | | - if (feedback) |
940 | | - feedback.textContent = 'Заполните поле контакта или удалите!'; |
941 | | - } else if (!input.classList.contains('modal-patronymic-input')) { |
942 | | - validErrors.push(`Заполните поле "${input.placeholder}"!`); |
943 | | - if (feedback) |
944 | | - feedback.textContent = `Заполните поле "${input.placeholder}"!`; |
945 | | - } else if (input.classList.contains('modal-patronymic-input')) { |
946 | | - // индивидуальное сообщение для поля "Отчество", НО без добавления в массив ошибок |
947 | | - if (feedback) |
948 | | - feedback.textContent = |
949 | | - 'Заполните поле "Отчество" или оставьте его пустым!'; |
950 | | - } |
951 | | - |
952 | | - input.classList.add('is-invalid'); // выделение инпута "красным" |
953 | | - } |
954 | | - } else { |
955 | | - // проверка минимальной длины вводимых данных |
956 | | - const inputClass = Object.keys(minLengths).find((className) => |
957 | | - input.classList.contains(className) |
958 | | - ); |
959 | | - |
960 | | - // для полей ФИО |
961 | | - if (inputClass && typeof minLengths[inputClass] === 'number') { |
962 | | - if (input.value.length < minLengths[inputClass]) { |
963 | | - const fieldName = { |
964 | | - 'modal-surname-input': 'Фамилия', |
965 | | - 'modal-name-input': 'Имя', |
966 | | - 'modal-patronymic-input': 'Отчество', |
967 | | - }[inputClass]; |
968 | | - |
969 | | - validErrors.push( |
970 | | - `Поле "${fieldName}" должно быть не менее ${minLengths[inputClass]} символов!` |
971 | | - ); |
972 | | - input.classList.add('is-invalid'); |
973 | | - if (feedback) |
974 | | - feedback.textContent = validErrors[validErrors.length - 1]; |
975 | | - } |
976 | | - } |
977 | | - |
978 | | - // для строк контактов |
979 | | - if (input.classList.contains('modal-contact-input')) { |
980 | | - const hiddenInput = parent.querySelector('.modal-hidden-input'); |
981 | | - const contactType = hiddenInput ? hiddenInput.value : ''; |
982 | | - const minLength = minLengths['modal-contact-input'][contactType] || 0; |
983 | | - const contactLabel = contactTypeLabels[contactType] || 'Контакт'; |
984 | | - |
985 | | - if (input.value.length < minLength) { |
986 | | - validErrors.push( |
987 | | - `Поле "${contactLabel}" должно быть не менее ${minLength} символов!` |
988 | | - ); |
989 | | - input.classList.add('is-invalid'); |
990 | | - if (feedback) |
991 | | - feedback.textContent = validErrors[validErrors.length - 1]; |
992 | | - } |
993 | | - } |
994 | | - |
995 | | - // Если данные валидны, убираем ошибки |
996 | | - if (!input.classList.contains('is-invalid')) { |
997 | | - input.classList.remove('is-invalid'); |
998 | | - if (feedback) feedback.textContent = ''; |
999 | | - } |
1000 | | - } |
1001 | | - }); |
1002 | | - |
1003 | | - // добавление кастомного "класса-состояния" для формы (на основе этого последующая отработка) |
1004 | | - if (validErrors.length > 0) { |
1005 | | - modalBodyForm.classList.add('was-submitted'); |
1006 | | - } |
1007 | | - |
1008 | | - return validErrors; // возврат массива ошибок/сообщений |
1009 | | - } |
1010 | | - |
1011 | 935 | // ** изменение направления стрелки/svg-icon, согласно прожатия по заглавной ячейке (при сортировке данных) |
1012 | 936 | const allHeaderRowCells = document.querySelectorAll( |
1013 | 937 | '.crm__output-table-head-cell' |
|
2084 | 2008 | } |
2085 | 2009 | } |
2086 | 2010 |
|
2087 | | - // TODO: |
2088 | | - // await getClientsServerListData(); // обновление списка студентов (в контексте.. перерисовка таблицы) |
| 2011 | + await getClientsServerListData(); // обновление списка клиентов (в контексте.. перерисовка таблицы) |
2089 | 2012 | } catch (error) { |
2090 | 2013 | console.error('Ошибка при добавлении клиента..', error); |
2091 | 2014 | alert('Ошибка при добавлении клиента на сервер!'); |
|
2265 | 2188 | ); |
2266 | 2189 | } |
2267 | 2190 |
|
| 2191 | + // ** организация "дополнительной" логики для валидации полей ввода/инпутов в модальных окнах (при/в "submit" состояниях) |
| 2192 | + function additionalFormInputsValidation(allModalInputs, modalBodyForm) { |
| 2193 | + const validErrors = []; |
| 2194 | + // определение минимального количества букв/символов (для каждого инпут/типа поля) |
| 2195 | + const minLengths = { |
| 2196 | + 'modal-surname-input': 3, |
| 2197 | + 'modal-name-input': 2, |
| 2198 | + 'modal-patronymic-input': 5, |
| 2199 | + 'modal-contact-input': { |
| 2200 | + phone: 18, |
| 2201 | + 'extra-phone': 18, |
| 2202 | + vk: 7, |
| 2203 | + email: 6, |
| 2204 | + facebook: 5, |
| 2205 | + twitter: 3, |
| 2206 | + 'extra-contact': 3, |
| 2207 | + }, |
| 2208 | + }; |
| 2209 | + // использование названий как в drop-down меню |
| 2210 | + const contactTypeLabels = { |
| 2211 | + phone: 'Телефон', |
| 2212 | + 'extra-phone': 'Доп. телефон', |
| 2213 | + vk: 'Vk', |
| 2214 | + email: 'Email', |
| 2215 | + facebook: 'Facebook', |
| 2216 | + twitter: 'Twitter', |
| 2217 | + 'extra-contact': 'Доп. контакт', |
| 2218 | + }; |
| 2219 | + |
| 2220 | + allModalInputs.forEach((input) => { |
| 2221 | + const parent = input.parentNode; |
| 2222 | + const feedback = parent.querySelector('.invalid-feedback'); |
| 2223 | + |
| 2224 | + if (input.value.trim() === '' || !input.checkValidity()) { |
| 2225 | + // определение/вывод сообщения в зависимости от "класса" инпута |
| 2226 | + if (!input.classList.contains('is-invalid')) { |
| 2227 | + if (input.classList.contains('modal__body-add-contact-input')) { |
| 2228 | + validErrors.push('Заполните поле контакта или удалите!'); |
| 2229 | + if (feedback) |
| 2230 | + feedback.textContent = 'Заполните поле контакта или удалите!'; |
| 2231 | + } else if (!input.classList.contains('modal-patronymic-input')) { |
| 2232 | + validErrors.push(`Заполните поле "${input.placeholder}"!`); |
| 2233 | + if (feedback) |
| 2234 | + feedback.textContent = `Заполните поле "${input.placeholder}"!`; |
| 2235 | + } else if (input.classList.contains('modal-patronymic-input')) { |
| 2236 | + // индивидуальное сообщение для поля "Отчество", НО без добавления в массив ошибок |
| 2237 | + if (feedback) |
| 2238 | + feedback.textContent = |
| 2239 | + 'Заполните поле "Отчество" или оставьте его пустым!'; |
| 2240 | + } |
| 2241 | + |
| 2242 | + input.classList.add('is-invalid'); // выделение инпута "красным" |
| 2243 | + } |
| 2244 | + } else { |
| 2245 | + // проверка минимальной длины вводимых данных |
| 2246 | + const inputClass = Object.keys(minLengths).find((className) => |
| 2247 | + input.classList.contains(className) |
| 2248 | + ); |
| 2249 | + |
| 2250 | + // для полей ФИО |
| 2251 | + if (inputClass && typeof minLengths[inputClass] === 'number') { |
| 2252 | + if (input.value.length < minLengths[inputClass]) { |
| 2253 | + const fieldName = { |
| 2254 | + 'modal-surname-input': 'Фамилия', |
| 2255 | + 'modal-name-input': 'Имя', |
| 2256 | + 'modal-patronymic-input': 'Отчество', |
| 2257 | + }[inputClass]; |
| 2258 | + |
| 2259 | + validErrors.push( |
| 2260 | + `Поле "${fieldName}" должно содержать не менее ${minLengths[inputClass]} символов!` |
| 2261 | + ); |
| 2262 | + input.classList.add('is-invalid'); |
| 2263 | + if (feedback) |
| 2264 | + feedback.textContent = validErrors[validErrors.length - 1]; |
| 2265 | + } |
| 2266 | + } |
| 2267 | + |
| 2268 | + // для строк контактов |
| 2269 | + if (input.classList.contains('modal-contact-input')) { |
| 2270 | + const hiddenInput = parent.querySelector('.modal-hidden-input'); |
| 2271 | + const contactType = hiddenInput ? hiddenInput.value : ''; |
| 2272 | + const minLength = minLengths['modal-contact-input'][contactType] || 0; |
| 2273 | + const contactLabel = contactTypeLabels[contactType] || 'Контакт'; |
| 2274 | + |
| 2275 | + if (input.value.length < minLength) { |
| 2276 | + validErrors.push( |
| 2277 | + `Поле "${contactLabel}" должно содержать не менее ${minLength} символов!` |
| 2278 | + ); |
| 2279 | + input.classList.add('is-invalid'); |
| 2280 | + if (feedback) |
| 2281 | + feedback.textContent = validErrors[validErrors.length - 1]; |
| 2282 | + } |
| 2283 | + } |
| 2284 | + |
| 2285 | + // Если данные валидны, убираем ошибки |
| 2286 | + if (!input.classList.contains('is-invalid')) { |
| 2287 | + input.classList.remove('is-invalid'); |
| 2288 | + if (feedback) feedback.textContent = ''; |
| 2289 | + } |
| 2290 | + } |
| 2291 | + }); |
| 2292 | + |
| 2293 | + // добавление кастомного "класса-состояния" для формы (на основе этого последующая отработка) |
| 2294 | + if (validErrors.length > 0) { |
| 2295 | + modalBodyForm.classList.add('was-submitted'); |
| 2296 | + } |
| 2297 | + |
| 2298 | + return validErrors; // возврат массива ошибок/сообщений |
| 2299 | + } |
| 2300 | + |
2268 | 2301 | // ** организация блокировки доступности для модальной кнопки "Сохранить" (при "submit") |
2269 | 2302 | function updateSaveButtonState(modalBodyForm, saveButton) { |
2270 | 2303 | const allModalInputs = Array.from( |
|
0 commit comments