/* 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();
});
}