290 lines
10 KiB
JavaScript
290 lines
10 KiB
JavaScript
/* 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();
|
||
});
|
||
}
|