/* eslint-disable linebreak-style */ /* eslint-disable max-len */ /* eslint-disable linebreak-style */ // Модуль для работы с модальным окном // импорт компонента Modal из bootstrap import { Modal } from "bootstrap"; import { cntrls } from "./lines-ui"; import { getAllDiscountTypes, getAllLines, updateLine } from "./lines-rest-api"; import { drawLinesTable, drawDiscountSelect } from "./lines"; // поиск модального окна на странице const modal = document.getElementById("discounts-update"); // если он найден, то создается экземпляр компонента Modal // для программного управления модальным окном const myModal = modal ? new Modal(modal, {}) : null; // поиск тега с заголовком модального кона для его смены const modalTitle = document.getElementById("discounts-update-title"); // обнуление значений модального окна, т. к. // используется одно окно для всех операций function resetDiscountValues() { cntrls.discountLineId.value = ""; cntrls.discountName.value = ""; cntrls.percent.value = ""; } // функция для показа модального окна // перед показом происходит заполнение формы для редактирования // если объект item не пуст function showDiscountModal(item) { modalTitle.innerHTML = item === null ? "Добавить" : "Изменить"; console.info(item); if (item) { cntrls.discountLineId.value = item.id; cntrls.discountName.value = item.name; cntrls.percent.value = item.percent; } else { resetDiscountValues(); } myModal.show(); } // функция для скрытия модального окна function hideDiscountModal() { resetDiscountValues(); // удаление класса was-validated для скрытия результатов валидации cntrls.formDiscounts.classList.remove("was-validated"); myModal.hide(); } const serverUrl = "http://localhost:8081"; function createTableColumn(value) { const td = document.createElement("td"); td.textContent = value; return td; } function createTableAnchor(icon, callback) { const i = document.createElement("i"); i.classList.add("bi", icon); const a = document.createElement("a"); a.href = "#"; a.appendChild(i); a.onclick = (event) => { // чтобы в URL не добавлялась решетка event.preventDefault(); event.stopPropagation(); callback(); }; const td = document.createElement("td"); td.appendChild(a); return td; } function createTableRow(item, index, editCallback, deleteCallback) { const rowNumber = document.createElement("th"); rowNumber.scope = "row"; rowNumber.textContent = index + 1; const row = document.createElement("tr"); row.id = `discount-${item.id}`; row.appendChild(rowNumber); row.appendChild(createTableColumn(item.name)); row.appendChild(createTableColumn(`${item.percent}%`)); if (index !== 0) { row.appendChild(createTableAnchor("bi-pencil-square", editCallback)); row.appendChild(createTableAnchor("bi-trash", deleteCallback)); } else { row.appendChild(createTableColumn("")); row.appendChild(createTableColumn("")); } return row; } async function drawDiscountsTable() { console.info("Try to load data"); if (!cntrls.tableDiscounts) { return; } // вызов метода REST API для получения всех записей const data = await getAllDiscountTypes(); console.log(data); // очистка содержимого table // удаляется все, что находится между тегами
// но не атрибуты cntrls.tableDiscounts.innerHTML = ""; // цикл по результату ответа от сервера // используется лямбда-выражение // (item, index) => {} аналогично function(item, index) {} data.forEach((item, index) => { console.log(item); cntrls.tableDiscounts.appendChild( createTableRow( item, index, // функции передаются в качестве параметра // это очень удобно, так как аргументы функций доступны только // в данном месте кода и не передаются в сервисные модули () => showDiscountModal(item), () => removeLine(item.id), ), ); }); } function createDiscountObject(name, percent) { return { name, percent, }; } async function createLine(name, percent) { const discountObject = createDiscountObject(name, percent); const options = { method: "POST", body: JSON.stringify(discountObject), headers: { "Accept": "application/json", "Content-Type": "application/json", }, }; const response = await fetch(`${serverUrl}/discounts`, options); if (!response.ok) { throw response.statusText; } return response.json(); } // обращение к серверу для обновления записи по id (put) // объект отправляется в теле запроса (body) // id передается в качестве части пути URL get-запроса async function updateDiscountLine(id, name, percent) { const discountObject = createDiscountObject(name, percent); const options = { method: "PUT", body: JSON.stringify(discountObject), headers: { "Accept": "application/json", "Content-Type": "application/json", }, }; const response = await fetch(`${serverUrl}/discounts/${id}`, options); if (!response.ok) { throw response.statusText; } return response.json(); } async function addDiscountLine(name, percent) { console.info("Try to add item"); // вызов метода REST API для добавления записи const data = await createLine(name, percent); console.info("Added"); console.info(data); drawDiscountsTable(); drawDiscountSelect(); } async function editLine(id, name, percent) { console.info("Try to update item"); // вызов метода REST API для обновления записи const data = await updateDiscountLine(id, name, percent); console.info("Updated"); console.info(data); // загрузка и заполнение table drawDiscountsTable(); const allLines = await getAllLines(); allLines.forEach(async (item, index) => { // eslint-disable-next-line max-len await updateLine(index + 1, item.itemsId, item.price, item.name, item.image, item.discountsId); drawLinesTable(); }); } async function deleteLine(id) { const options = { method: "DELETE", }; const response = await fetch(`${serverUrl}/discounts/${id}`, options); if (!response.ok) { throw response.statusText; } return response.json(); } async function removeLine(id) { if (!confirm("Do you really want to remove this item?")) { console.info("Canceled"); return; } console.info("Try to remove item"); const allLines = await getAllLines(); const updatePromises = allLines.map(async (item, index) => { if (Number(id) === Number(item.discountsId)) { await updateLine(index + 1, item.itemsId, item.price, item.name, item.image, 1); drawLinesTable(); } }); await Promise.all(updatePromises); const data = await deleteLine(id); console.info(data); // загрузка и заполнение table drawDiscountsTable(); drawDiscountSelect(); } // eslint-disable-next-line import/prefer-default-export export function discountsForm() { console.info("discountsForm"); // загрузка и заполнение table drawDiscountsTable(); // обработчик события нажатия на кнопку для показа модального окна cntrls.buttonAddDiscount.addEventListener("click", () => showDiscountModal(null)); // обработчик события отправки формы // возникает при нажатии на кнопку (button) с типом submit // кнопка должна находится внутри тега form cntrls.formDiscounts.addEventListener("submit", async (event) => { console.info("Form onSubmit"); // отключение стандартного поведения формы при отправке // при отправке страница обновляется и JS перестает работать event.preventDefault(); event.stopPropagation(); // если форма не прошла валидацию, то ничего делать не нужно if (!cntrls.formDiscounts.checkValidity()) { return; } // получение id строки для редактирования // это значение содержится в скрытом input const currentId = cntrls.discountLineId.value; // если значение id не задано, // то необходимо выполнить добавление записи // иначе обновление записи if (!currentId) { await addDiscountLine( cntrls.discountName.value, cntrls.percent.value, ); } else { await editLine( currentId, cntrls.discountName.value, cntrls.percent.value, ); } // после выполнения добавления/обновления модальное окно скрывается hideDiscountModal(); }); }