Web-programming_Anisin_R.S..../js/discounts-table-logic.js
2024-01-10 20:47:54 +04:00

290 lines
10 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* 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
// удаляется все, что находится между тегами <table></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();
});
}