Skip to content

Commit 6f3288c

Browse files
committed
[PRAC/cont] Add logic to correct init/server arr
Correct init/server clients arr (edit ID, add fullName/timing prop's). Worth noting: - preparation for rendering data in the table (2). core: B-3 / JS-BL
1 parent 3e5c255 commit 6f3288c

File tree

1 file changed

+132
-71
lines changed
  • core-courses/3-js-basic-level/practicum-js-basic-level/sb-crm-client/js

1 file changed

+132
-71
lines changed

core-courses/3-js-basic-level/practicum-js-basic-level/sb-crm-client/js/index.js

Lines changed: 132 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -227,47 +227,6 @@
227227
outputTable.append(outTableHead, outTableBody);
228228
crmOutputContainer.append(outputTitleWrap, outputTable);
229229

230-
// ** организация кнопки для добавления "нового" клиента (последующее открытие модального окна, ряд сопутствующих действий)
231-
const addBtnWrap = document.createElement('div');
232-
const addBtn = document.createElement('button');
233-
const addBtnIcon = document.createElement('i');
234-
235-
addBtnWrap.classList.add('crm__add-btn-wrap');
236-
addBtn.classList.add('crm__add-btn');
237-
addBtnIcon.classList.add('crm__add-btn-icon', 'bi', 'bi-person-plus-fill');
238-
239-
addBtn.setAttribute('id', 'add-btn');
240-
addBtn.setAttribute('type', 'button');
241-
242-
addBtn.textContent = 'Добавить клиента';
243-
244-
addBtn.append(addBtnIcon);
245-
addBtnWrap.append(addBtn);
246-
crmAddContainer.append(addBtnWrap);
247-
248-
// обработка клика по кнопке, создание/отображение модального окна
249-
addBtn.addEventListener('click', () => {
250-
const modalWrap = createModalWindowByType('add'); // создание по типу "add"
251-
252-
crmAddContainer.append(modalWrap); // добавление в DOM
253-
254-
// инициализация через Bootstrap API
255-
const bootstrapModal = new bootstrap.Modal(modalWrap);
256-
bootstrapModal.show(); // отображение
257-
258-
// добавление валидации для вводимых данных/в модальном окне (для "основных" инпутов, ФИО)
259-
const allModalBodyFormInputs =
260-
modalWrap.querySelectorAll('.modal__body-input');
261-
mainInputsValidation(allModalBodyFormInputs, {
262-
allowOnlyRussian: true,
263-
singleHyphen: true,
264-
noExtraSpaces: true,
265-
});
266-
267-
// принудительное удаление атрибута aria-hidden="true" с модального окна (исключение ошибки с ARIA)
268-
deleteAriaHiddenTrue(modalWrap);
269-
});
270-
271230
// ** появление/скрытие поля для ввода данных/фильтрационного инпута (по нажатию на logo, на 320px)
272231
searchLogoImg.addEventListener('click', () => {
273232
document
@@ -292,7 +251,7 @@
292251

293252
// ! ТЕСТИРОВАНИЕ
294253
// addClientsToTable(clientsDataArrWithIds); // отрисовка данных, наполнение таблицы клиентов
295-
console.log(clientsDataArrWithIds); // ? ВЫВОД МАССИВА ОБЪЕКТОВ
254+
// console.log(clientsDataArrWithIds); // ? ВЫВОД МАССИВА ОБЪЕКТОВ
296255
} catch (error) {
297256
console.error('Не удалось загрузить список клиентов..', error);
298257
alert('Ошибка при загрузке данных с сервера!?');
@@ -309,10 +268,106 @@
309268

310269
getClientsServerListData(); // получение данных о клиентах (с сервера)
311270

312-
// TODO:
313-
// ** наполнение таблицы данных о клиентах (согласно откорректированного исходного, далее формирующегося массива)
271+
// ** наполнение таблицы данных о клиентах (согласно откорректированного/формирующегося массива)
314272
let updateClientsDataArr = [];
315273

274+
function addClientsToTable(clientsServerData = []) {
275+
// ??
276+
// const selectedBodyRows = getSelectedBodyRows(); // сохранение выделенных body-строк (если такие есть)
277+
278+
outTableBody.innerHTML = ''; // предварительная очистка таблицы
279+
updateClientsDataArr = correctInitArr(clientsServerData);
280+
// ! ТЕСТИРОВАНИЕ
281+
// console.log(updateClientsDataArr); // ? ВЫВОД МАССИВА ОБЪЕКТОВ
282+
283+
if (updateClientsDataArr.length === 0) {
284+
// TODO:
285+
const emptyTableRow = createEmptyTableMessageRow(); // если массив клиентов/таблица данных пуста, вывод сообщения
286+
outTableBody.append(emptyTableRow);
287+
} else {
288+
for (const [index, client] of updateClientsDataArr.entries()) {
289+
// TODO:
290+
const clientTableTrRow = createClientTableTrRow(index, client);
291+
outTableBody.append(clientTableTrRow);
292+
}
293+
}
294+
295+
// ??
296+
// addClickListenersToBodyRows(); // добавление прослушки для всех строк (кроме заглавной), при компоновке, после пере-компоновки (новой отрисовки), для возможности выделения по клику
297+
// restoreSelectedBodyRows(selectedBodyRows); // восстановление выделенных body-строк (если такие были)
298+
}
299+
300+
// ** корректировка исходного/серверного массива клиентов (обработка ID, добавление свойства fullName и временных свойств)
301+
function correctInitArr(clientsServerData = []) {
302+
const newClientsDataArr = structuredClone(clientsServerData); // клонирование входящего массива (серверного)
303+
304+
for (const client of newClientsDataArr) {
305+
client.shortId = client.id.slice(-6); // сокращение серверного ID (до 6 цифр)
306+
client.fullName = `${client.surname} ${client.name} ${client.patronymic}`; // получение "общего" fullName
307+
308+
// преобразование серверных "createdAt" и "updatedAt" в отдельные поля, как даты и времени
309+
if (client.createdAt) {
310+
const createdAtDate = conversionStringDate(client.createdAt);
311+
client.createdAtDate = createdAtDate.toLocaleDateString('ru-RU'); // дата создания
312+
client.createdAtTime = createdAtDate.toLocaleTimeString('ru-RU', {
313+
hour: '2-digit',
314+
minute: '2-digit',
315+
}); // время создания
316+
}
317+
318+
if (client.updatedAt) {
319+
const updatedAtDate = conversionStringDate(client.updatedAt);
320+
client.updatedAtDate = updatedAtDate.toLocaleDateString('ru-RU'); // дата изменений
321+
client.updatedAtTime = updatedAtDate.toLocaleTimeString('ru-RU', {
322+
hour: '2-digit',
323+
minute: '2-digit',
324+
}); // время изменений
325+
}
326+
}
327+
328+
return newClientsDataArr; // передача откорректированного/дополненного массива
329+
}
330+
331+
// ** преобразование строковой даты в объект Date
332+
function conversionStringDate(dateString) {
333+
return new Date(dateString); // возврат "полноценного" объекта Date
334+
}
335+
336+
// ** изменение направления стрелки/svg-icon, согласно прожатия по заглавной ячейке (при сортировке данных)
337+
const allHeaderRowCells = document.querySelectorAll(
338+
'.crm__output-table-head-cell'
339+
);
340+
341+
function changeIconDirection(event) {
342+
const headerRowCell = event.currentTarget; // фиксация всей/целиком "th" заглавной ячейки
343+
const cellIcon = headerRowCell.querySelector('.head-cell__icon'); // определение иконки внутри ячейки
344+
const cellSort = headerRowCell.querySelector('.head-cell__sort'); // определение доп. текста, типа "А-Я"
345+
346+
// проверка/подтверждение наличия иконки (переключение)
347+
if (cellIcon) {
348+
cellIcon.classList.toggle('head-cell__icon-up');
349+
cellIcon.classList.toggle('head-cell__icon-down');
350+
}
351+
352+
// проверка/подтверждение наличия доп. текста (замена)
353+
if (cellSort) {
354+
cellSort.textContent = cellSort.textContent === 'А-Я' ? 'Я-А' : 'А-Я';
355+
}
356+
}
357+
358+
// организация прослушек "для каждой" заглавной ячейки
359+
allHeaderRowCells.forEach((cell) => {
360+
cell.addEventListener('click', (event) => changeIconDirection(event)); // передача события
361+
362+
// отработка сортировки/сброса сортировки через TAB/Enter (изменение направления стелок)
363+
cell.addEventListener('keydown', (event) => {
364+
if (event.key === 'Enter') {
365+
event.preventDefault();
366+
changeIconDirection(event); // передача события
367+
}
368+
});
369+
});
370+
316371
// ** организация "общей/универсальной" логики для валидации полей ввода/инпутов (согласно передаваемых параметров)
317372
function mainInputsValidation(inputs, options) {
318373
inputs.forEach((input) =>
@@ -932,39 +987,45 @@
932987
noExtraSpaces: true,
933988
});
934989

935-
// ** изменение направления стрелки/svg-icon, согласно прожатия по заглавной ячейке (при сортировке данных)
936-
const allHeaderRowCells = document.querySelectorAll(
937-
'.crm__output-table-head-cell'
938-
);
990+
// ** организация кнопки для добавления "нового" клиента (последующее открытие модального окна, ряд сопутствующих действий)
991+
const addBtnWrap = document.createElement('div');
992+
const addBtn = document.createElement('button');
993+
const addBtnIcon = document.createElement('i');
939994

940-
function changeIconDirection(event) {
941-
const headerRowCell = event.currentTarget; // фиксация всей/целиком "th" заглавной ячейки
942-
const cellIcon = headerRowCell.querySelector('.head-cell__icon'); // определение иконки внутри ячейки
943-
const cellSort = headerRowCell.querySelector('.head-cell__sort'); // определение доп. текста, типа "А-Я"
995+
addBtnWrap.classList.add('crm__add-btn-wrap');
996+
addBtn.classList.add('crm__add-btn');
997+
addBtnIcon.classList.add('crm__add-btn-icon', 'bi', 'bi-person-plus-fill');
944998

945-
// проверка/подтверждение наличия иконки (переключение)
946-
if (cellIcon) {
947-
cellIcon.classList.toggle('head-cell__icon-up');
948-
cellIcon.classList.toggle('head-cell__icon-down');
949-
}
999+
addBtn.setAttribute('id', 'add-btn');
1000+
addBtn.setAttribute('type', 'button');
9501001

951-
// проверка/подтверждение наличия доп. текста (замена)
952-
if (cellSort) {
953-
cellSort.textContent = cellSort.textContent === 'А-Я' ? 'Я-А' : 'А-Я';
954-
}
955-
}
1002+
addBtn.textContent = 'Добавить клиента';
9561003

957-
// организация прослушек "для каждой" заглавной ячейки
958-
allHeaderRowCells.forEach((cell) => {
959-
cell.addEventListener('click', (event) => changeIconDirection(event)); // передача события
1004+
addBtn.append(addBtnIcon);
1005+
addBtnWrap.append(addBtn);
1006+
crmAddContainer.append(addBtnWrap);
9601007

961-
// отработка сортировки/сброса сортировки через TAB/Enter (изменение направления стелок)
962-
cell.addEventListener('keydown', (event) => {
963-
if (event.key === 'Enter') {
964-
event.preventDefault();
965-
changeIconDirection(event); // передача события
966-
}
1008+
// обработка клика по кнопке, создание/отображение модального окна
1009+
addBtn.addEventListener('click', () => {
1010+
const modalWrap = createModalWindowByType('add'); // создание по типу "add"
1011+
1012+
crmAddContainer.append(modalWrap); // добавление в DOM
1013+
1014+
// инициализация через Bootstrap API
1015+
const bootstrapModal = new bootstrap.Modal(modalWrap);
1016+
bootstrapModal.show(); // отображение
1017+
1018+
// добавление валидации для вводимых данных/в модальном окне (для "основных" инпутов, ФИО)
1019+
const allModalBodyFormInputs =
1020+
modalWrap.querySelectorAll('.modal__body-input');
1021+
mainInputsValidation(allModalBodyFormInputs, {
1022+
allowOnlyRussian: true,
1023+
singleHyphen: true,
1024+
noExtraSpaces: true,
9671025
});
1026+
1027+
// принудительное удаление атрибута aria-hidden="true" с модального окна (исключение ошибки с ARIA)
1028+
deleteAriaHiddenTrue(modalWrap);
9681029
});
9691030

9701031
// ** создание "универсального" модального окна, для добавления или изменения данных клиента (согласно передаваемого типа)

0 commit comments

Comments
 (0)