Skip to content

Commit 38e2e7f

Browse files
committed
[PRAC/cont] Add modal window for row "Delete" btn
Organiz "separate" modal window for deleting client from tbl. Worth noting: - that this instead of "confirm".. now there is a modal window for each "main" button (like on the mockup). core: B-3 / JS-BL
1 parent b8ddf3a commit 38e2e7f

File tree

4 files changed

+208
-18
lines changed

4 files changed

+208
-18
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@
201201
.crm__output-table-body-row {
202202
border-bottom: 1px solid var(--text-gray);
203203
height: 65px;
204+
transition: border-bottom var(--short) ease;
204205
}
205206

206207
.crm__output-table-body-row:focus-visible {
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
.modal-delete__dialog {
2+
position: relative;
3+
top: 220px;
4+
left: 25px;
5+
}
6+
7+
.modal-delete__content-wrap {
8+
display: flex;
9+
flex-direction: column;
10+
align-items: center;
11+
border: none;
12+
border-radius: 0;
13+
padding: 25px 30px;
14+
max-width: 450px;
15+
outline: none;
16+
}
17+
18+
.modal-delete__header,
19+
.modal-delete__body,
20+
.modal-delete__footer {
21+
padding: 0;
22+
}
23+
24+
.modal-delete__header,
25+
.modal-delete__footer {
26+
border: none;
27+
}
28+
29+
.modal-delete__header {
30+
margin-bottom: 11px;
31+
}
32+
33+
.modal-delete__header-title {
34+
font-weight: var(--bold);
35+
font-size: 18px;
36+
color: var(--black);
37+
}
38+
39+
.modal-delete__header .modal-delete__header-x-btn {
40+
position: relative;
41+
top: -12px;
42+
right: -110px;
43+
padding: 5px;
44+
}
45+
46+
.modal-delete__header .modal-delete__header-x-btn:focus {
47+
box-shadow: 0 0 0 .25rem var(--bootstrap-red);
48+
opacity: .5;
49+
}
50+
51+
.modal-delete__body {
52+
margin-bottom: 25px;
53+
}
54+
55+
.modal-delete__body-text {
56+
max-width: 275px;
57+
color: var(--black);
58+
text-align: center;
59+
}
60+
61+
.modal-delete__footer-btns-wrap {
62+
display: flex;
63+
flex-direction: column;
64+
row-gap: 5px;
65+
margin: 0;
66+
}
67+
68+
.modal-delete-btn {
69+
margin: 0;
70+
border: none;
71+
padding: 0;
72+
background: transparent;
73+
outline: none;
74+
}
75+
76+
.modal-delete__footer-delete-btn {
77+
align-self: center;
78+
padding: 10px 35px;
79+
max-width: 130px;
80+
color: var(--white);
81+
background-color: var(--main-purple);
82+
transition-property: color, background-color;
83+
transition-duration: var(--short);
84+
transition-timing-function: ease;
85+
}
86+
87+
.modal-delete__footer-delete-btn:focus-visible:not(:hover) {
88+
background-color: var(--dark-purple);
89+
}
90+
91+
.modal-delete__footer-delete-btn:focus-visible:active {
92+
background-color: var(--gray);
93+
}
94+
95+
.modal-delete__footer-delete-btn:active {
96+
background-color: var(--gray);
97+
}
98+
99+
.modal-delete__footer-cancel-btn {
100+
align-self: center;
101+
padding: 2px;
102+
max-width: 130px;
103+
font-weight: var(--regular);
104+
color: var(--black);
105+
text-decoration-line: underline;
106+
transition: color var(--short) ease;
107+
}
108+
109+
.modal-delete__footer-cancel-btn:focus-visible {
110+
color: var(--dark-purple);
111+
}
112+
113+
.modal-delete__footer-cancel-btn:focus-visible:active {
114+
color: var(--gray);
115+
}
116+
117+
.modal-delete__footer-cancel-btn:active {
118+
color: var(--gray);
119+
}
120+
121+
/* media queries, any-hover */
122+
123+
@media (any-hover: hover) {
124+
.modal-delete__footer-delete-btn:hover:not(:active) {
125+
background-color: var(--light-purple);
126+
}
127+
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@
66
@import url("crm-output.css");
77
@import url("crm-add.css");
88
@import url("modal-type.css");
9+
@import url("modal-delete.css");
910
@import url("custom-tippy.css");

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

Lines changed: 79 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -688,12 +688,20 @@
688688

689689
const clientServerId = row.getAttribute('data-server-id'); // фиксация серверного id (из атрибута)
690690

691-
// вызов "общей" функции, для удаления клиента/строки (передача соответствующих аргументов)
692-
deleteBodyRowsClients(
693-
[clientServerId],
694-
`Вы уверены, что хотите удалить клиента?`,
695-
event.target
696-
);
691+
if (!clientServerId) {
692+
console.error('Ошибка: отсутствует ID клиента для удаления!');
693+
return; // нет ID или не корректен, возврат
694+
}
695+
696+
// вызов/создание "отдельного" модального окна, для последующего удаления клиента/строки
697+
const deleteModal = createDeleteModalWindow(clientServerId);
698+
document.body.append(deleteModal);
699+
// инициализация модального окна, через Bootstrap API
700+
const modalInstance = new bootstrap.Modal(deleteModal);
701+
modalInstance.show(); // отображение
702+
703+
// принудительное удаление атрибута aria-hidden="true" с модального окна (исключение ошибки с ARIA)
704+
deleteAriaHiddenTrue(deleteModal);
697705
}
698706

699707
// добавление обработчика события на таблицу (удаление строки)
@@ -702,18 +710,11 @@
702710
// ** удаление элементов/строк таблицы данных о клиентах (ОБЩАЯ ЛОГИКА)
703711
async function deleteBodyRowsClients(
704712
clientsServerIdsToDelete,
705-
confirmMessage = null,
706713
currentBtn = null
707714
) {
708-
if (confirmMessage) {
709-
const confirmed = confirm(confirmMessage);
710-
711-
if (!confirmed) {
712-
if (currentBtn) {
713-
currentBtn.blur(); // снятие фокуса с кнопки, при отмене действия
714-
}
715-
return;
716-
}
715+
// если кнопка передаётся, снятие фокуса (после прожатия)
716+
if (currentBtn) {
717+
currentBtn.blur();
717718
}
718719

719720
clientsServerIdsToDelete.forEach(async (serverId) => {
@@ -1781,7 +1782,7 @@
17811782
}
17821783

17831784
// отработка удаления клиента/строки
1784-
await deleteBodyRowsClients([clientServerId], null, event.target);
1785+
await deleteBodyRowsClients([clientServerId], event.target);
17851786

17861787
// закрытие модального окна после удаления
17871788
const modalInstance = bootstrap.Modal.getInstance(modalWrap);
@@ -1794,6 +1795,66 @@
17941795
return modalWrap; // возврат модального окна (т.е. здесь/без добавления в DOM.. позже, при клике)
17951796
}
17961797

1798+
// TODO: стилизация по аналогии (расположение окна..)
1799+
// ** создание "отдельного" модального окна, для удаления клиента из таблицы (при прожатии "Удалить" кнопки)
1800+
function createDeleteModalWindow(clientId) {
1801+
const deleteModalWrap = document.createElement('div');
1802+
deleteModalWrap.classList.add(
1803+
'modal-delete',
1804+
'crm__delete-modal-wrap',
1805+
'modal',
1806+
'fade'
1807+
);
1808+
deleteModalWrap.setAttribute('id', 'modal-delete-client');
1809+
deleteModalWrap.setAttribute('tabindex', '-1');
1810+
1811+
deleteModalWrap.innerHTML = `
1812+
<div class="modal-delete__dialog modal-dialog">
1813+
<div class="modal-delete__content-wrap modal-content">
1814+
<div class="modal-delete__header modal-header">
1815+
<h2 class="modal-delete__header-title modal-title">Удалить клиента</h2>
1816+
<button class="modal-delete__header-x-btn btn-close" data-bs-dismiss="modal" type="button" aria-label="Закрыть"></button>
1817+
</div>
1818+
<div class="modal-delete__body modal-body">
1819+
<p class="modal-delete__body-text">Вы действительно хотите удалить данного клиента?</p>
1820+
</div>
1821+
<div class="modal-delete__footer modal-footer">
1822+
<div class="modal-delete__footer-btns-wrap">
1823+
<button class="modal-delete__footer-delete-btn modal-delete-btn" id="modal-footer-delete-btn" type="button">Удалить</button>
1824+
<button class="modal-delete__footer-cancel-btn modal-delete-btn" id="modal-footer-cancel-btn" type="button" data-bs-dismiss="modal">Отмена</button>
1825+
</div>
1826+
</div>
1827+
</div>
1828+
</div>
1829+
`;
1830+
1831+
// фиксация внутренней "свеже" созданной "X" кнопки
1832+
const deleteModalXBtn = deleteModalWrap.querySelector(
1833+
'.modal-delete__header-x-btn'
1834+
);
1835+
// фиксация внутренней "свеже" созданной "Удалить" кнопки
1836+
const deleteModalBtn = deleteModalWrap.querySelector(
1837+
'.modal-delete__footer-delete-btn'
1838+
);
1839+
1840+
// вызов/инициализация tooltips для "X" модальной кнопки (для кнопки закрытия модального окна, с задержкой)
1841+
setTimeout(() => {
1842+
initTippy(deleteModalXBtn, 'закрыть', 'left');
1843+
}, 0);
1844+
1845+
// организация удаления клиента/строки
1846+
deleteModalBtn.addEventListener('click', async () => {
1847+
await deleteBodyRowsClients([clientId]);
1848+
// закрытие модального окна, через Bootstrap API
1849+
const modalInstance = bootstrap.Modal.getInstance(deleteModalWrap);
1850+
if (modalInstance) {
1851+
modalInstance.hide(); // скрытие
1852+
}
1853+
});
1854+
1855+
return deleteModalWrap; // передача/возврат модального окна
1856+
}
1857+
17971858
// ** организация принудительного удаления атрибута aria-hidden="true" с модальных окон (исключение ошибок с ARIA)
17981859
function deleteAriaHiddenTrue(modalWrap) {
17991860
// мониторинг/ожидание появления соответствующего атрибута
@@ -2534,7 +2595,7 @@
25342595
content,
25352596
theme: 'main',
25362597
delay: [50, 0],
2537-
offset: [0, 13],
2598+
offset: [0, 10],
25382599
placement: side,
25392600
animation: 'scale', // анимация появления/скрытия (через дополнительный файл/подключение)
25402601
trigger: 'mouseenter', // только по наведению мыши (исключение вывода по клику, в другом месте)

0 commit comments

Comments
 (0)