269 lines
11 KiB
JavaScript
269 lines
11 KiB
JavaScript
|
import { createObject } from "./api/createObject.js";
|
|||
|
import { delObject } from "./api/delObject.js";
|
|||
|
import { fetchAllCategories } from "./api/fetchAllCategoeies.js";
|
|||
|
import { fetchAllProducts } from "./api/fetchAllProducts.js";
|
|||
|
import { fetchAllRestaurantTypes } from "./api/fetchAllRestaurantTypes.js";
|
|||
|
import { updateObject } from "./api/updateObject.js";
|
|||
|
import { configurateObject } from "./helpers/configurateObject.js";
|
|||
|
import { validateModalForm } from "./helpers/formValidate.js";
|
|||
|
import { getBase64Image } from "./helpers/getBase64Image.js";
|
|||
|
import { getHTMLCategorySelectOption } from "./helpers/getHTMLCategorySelectOption.js";
|
|||
|
import { getHTMLRow } from "./helpers/getHTMLRow.js";
|
|||
|
import { resetForm } from "./helpers/resetForm.js";
|
|||
|
import { form, modal, parent } from "./variables.js";
|
|||
|
|
|||
|
//? ПЕРЕМЕННЫЕ
|
|||
|
|
|||
|
let products;
|
|||
|
let restaurantTypes;
|
|||
|
let categories;
|
|||
|
|
|||
|
//? СТАРТ ВСЕГО-ВСЕГО
|
|||
|
|
|||
|
async function start() {
|
|||
|
getAllRestarauntType();
|
|||
|
getAllCategories();
|
|||
|
drawAllProducts();
|
|||
|
}
|
|||
|
|
|||
|
if (parent) {
|
|||
|
start();
|
|||
|
}
|
|||
|
|
|||
|
//? ПОЛУЧЕНИЕ ВСЕХ ОБЪЕКТОВ
|
|||
|
|
|||
|
async function getAllRestarauntType() {
|
|||
|
try {
|
|||
|
// Получаю все категории массивом
|
|||
|
const data = await fetchAllRestaurantTypes();
|
|||
|
|
|||
|
for (const object of data) {
|
|||
|
// Создают <option></option> для каждой отдельной категории
|
|||
|
form.fieldRestaurantTypeSelect.innerHTML += getHTMLCategorySelectOption(object.name, object.id);
|
|||
|
}
|
|||
|
|
|||
|
restaurantTypes = data;
|
|||
|
} catch (err) {
|
|||
|
console.log(err);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
async function getAllCategories() {
|
|||
|
try {
|
|||
|
// Получаю все категории массивом
|
|||
|
const data = await fetchAllCategories();
|
|||
|
|
|||
|
for (const object of data) {
|
|||
|
// Создают <option></option> для каждой отдельной категории
|
|||
|
form.fieldCategorySelect.innerHTML += getHTMLCategorySelectOption(object.name, object.id);
|
|||
|
}
|
|||
|
|
|||
|
// Назначаю в переменную полученные категории
|
|||
|
categories = data;
|
|||
|
} catch (err) {
|
|||
|
console.log(err);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
async function drawAllProducts() {
|
|||
|
try {
|
|||
|
// Получаю все продукты
|
|||
|
const data = await fetchAllProducts();
|
|||
|
|
|||
|
for (const product of data) {
|
|||
|
// Ищу категорию объекта
|
|||
|
const category = categories.find(category => category.id === product.categoryId);
|
|||
|
// Ищу тип ресторана
|
|||
|
const restaurantType = restaurantTypes.find(type => type.id === product.restaurantTypeId);
|
|||
|
// Создаем строку в таблице
|
|||
|
parent.innerHTML += getHTMLRow(product, category.name, restaurantType.name);
|
|||
|
}
|
|||
|
|
|||
|
// Продукты грузим в переменную
|
|||
|
products = data;
|
|||
|
} catch (err) {
|
|||
|
console.log(err);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//? УДАЛЕНИЕ ОБЪЕКТА
|
|||
|
|
|||
|
async function deleteObject(currentDeleteButton) {
|
|||
|
// e - это кнопка, по которой нажали
|
|||
|
|
|||
|
try {
|
|||
|
// Если админ НЕ хочет удалять товар - то мы досрочно заканчиваем функцию
|
|||
|
if (!confirm("Вы правда хотите удалить этот объект?")) return;
|
|||
|
|
|||
|
// Получаю элемент строки в таблице
|
|||
|
const row = currentDeleteButton.parentElement.parentElement;
|
|||
|
// Достаю id продукта для удаления
|
|||
|
const id = row.dataset.id;
|
|||
|
// Удаляю объект из БД
|
|||
|
await delObject(id);
|
|||
|
// Удаление строки из таблицы
|
|||
|
row.remove();
|
|||
|
} catch (error) {
|
|||
|
console.log(error);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Чтобы работала кнопка Delete
|
|||
|
window.deleteObject = deleteObject;
|
|||
|
|
|||
|
// Флаг для понимания, модалка для обновления или для создания
|
|||
|
let isEditModal = true;
|
|||
|
|
|||
|
// Нужно чтобы насильно модалку закрыть
|
|||
|
const modalObject = new bootstrap.Modal(modal.root);
|
|||
|
|
|||
|
if (modal.root && modal.submitButton) {
|
|||
|
// Обработка превьюшки фотографии
|
|||
|
form.fieldPhoto.addEventListener('change', (event) => {
|
|||
|
const file = event.target.files[0];
|
|||
|
if (!file) return;
|
|||
|
|
|||
|
const reader = new FileReader();
|
|||
|
reader.readAsDataURL(file);
|
|||
|
reader.onload = () => {
|
|||
|
// reader.result - моя фотографии в base64
|
|||
|
// Мы ставим её в превью
|
|||
|
form.fieldPhotoPreview.src = reader.result;
|
|||
|
};
|
|||
|
});
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
//? РЕДАКТИРОВАНИЕ И СОЗДАНИЕ
|
|||
|
|
|||
|
//? Открытие модалки
|
|||
|
if (modal.root && modal.submitButton) {
|
|||
|
modal.root.addEventListener('show.bs.modal', event => {
|
|||
|
// event.relatedTarget.dataset.type - атрибут кнопки, на которую мы нажали (добавить или редактировать)
|
|||
|
// Проверяю, что кнопка, на которую я нажала, это кнопка создания объекта
|
|||
|
if (event.relatedTarget.dataset.type === "add") {
|
|||
|
isEditModal = false;
|
|||
|
modal.title.innerHTML = "Создать объект";
|
|||
|
modal.submitButton.innerHTML = "Создать";
|
|||
|
return;
|
|||
|
} else {
|
|||
|
modal.title.innerHTML = "Обновить объект";
|
|||
|
modal.submitButton.innerHTML = "Обновить";
|
|||
|
isEditModal = true;
|
|||
|
}
|
|||
|
|
|||
|
// Если модалка для редактирования, то мы должны подтащить продукт
|
|||
|
|
|||
|
// Получаем кнопку Edit, на которую нажали
|
|||
|
const button = event.relatedTarget;
|
|||
|
// Получаем id продукта, к которому привязана кнопка
|
|||
|
const id = +button.getAttribute('data-bs-whatever');
|
|||
|
// Достаю продукт из массив всех продуктов по моему id
|
|||
|
const product = products.find(product => product.id === id);
|
|||
|
|
|||
|
// Заполняем инпуты и т.д.
|
|||
|
form.fieldName.value = product.name;
|
|||
|
form.fieldPrice.value = product.price;
|
|||
|
form.fieldPhotoPreview.src = product.photo;
|
|||
|
form.fieldPhotoPreview.alt = product.name;
|
|||
|
form.fieldCategorySelect.value = product.categoryId;
|
|||
|
form.fieldRestaurantTypeSelect.value = product.restaurantTypeId;
|
|||
|
form.fieldInfo.value = product.info;
|
|||
|
|
|||
|
// В кнопку "Обновить" вшиваю id товара, который обновляем
|
|||
|
modal.submitButton.dataset.id = id;
|
|||
|
});
|
|||
|
|
|||
|
// Закрыли модалку - очистили форму
|
|||
|
modal.root.addEventListener('hide.bs.modal', () => {
|
|||
|
resetForm();
|
|||
|
});
|
|||
|
|
|||
|
// Создание товара - обязаны вставить фото
|
|||
|
// Обновление товара:
|
|||
|
// 1. Фото оставить старое
|
|||
|
// 2. Обновить фото
|
|||
|
|
|||
|
//? Обновление и создание объекта
|
|||
|
|
|||
|
// Обработчик события для кнопки submit (создаем или обновляем)
|
|||
|
modal.submitButton.addEventListener('click', async function (e) {
|
|||
|
try {
|
|||
|
if (!validateModalForm(isEditModal)) {
|
|||
|
alert("Ошибка в форме: не все поля заполнены");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
// Если мы редактируем товар, то мы получаем его id из кнопки submit,
|
|||
|
// т.к. для put запроса нам нужен id
|
|||
|
|
|||
|
// if (isEditModal) return +modal.submitButton.dataset.id
|
|||
|
// else return null
|
|||
|
const id = isEditModal ? +modal.submitButton.dataset.id : null; // null - ничто
|
|||
|
// Получаем фотографию товара
|
|||
|
const objectPhotoInputFiles = form.fieldPhoto.files;
|
|||
|
|
|||
|
// Создаёт объект продукта (+ для конвертации строки в число)
|
|||
|
const object = configurateObject(id, form.fieldName.value, +form.fieldCategorySelect.value,
|
|||
|
+form.fieldPrice.value, form.fieldInfo.value, +form.fieldRestaurantTypeSelect.value);
|
|||
|
|
|||
|
// Если кол-во фотографии > 0, т.е. мы её загрузили
|
|||
|
// (при создании или если при редактировании мы изменили фото)
|
|||
|
if (objectPhotoInputFiles.length > 0) {
|
|||
|
const file = objectPhotoInputFiles[0];
|
|||
|
// Получаем фото в base64
|
|||
|
const base64Image = await getBase64Image(file);
|
|||
|
// Загружаем фото в объект
|
|||
|
object.photo = base64Image;
|
|||
|
} else {
|
|||
|
// Если мы обновляем товар, то мы достаем его предыдущее фото (если мы его не обновили, см. выше)
|
|||
|
// И загрузили его в объект
|
|||
|
object.photo = products.find(product => product.id === id).photo;
|
|||
|
}
|
|||
|
|
|||
|
// Конвертирую объект в JSON-формат
|
|||
|
const objectJSON = JSON.stringify(object);
|
|||
|
|
|||
|
// Если мы обновляем товар, то вызываем соответствующую функцию
|
|||
|
if (isEditModal) await updateObjectFunc(id, objectJSON);
|
|||
|
else await addObject(objectJSON);
|
|||
|
|
|||
|
// Если всё ок - закрываем модалку и стираем данные из формы
|
|||
|
modalObject.hide();
|
|||
|
resetForm();
|
|||
|
|
|||
|
} catch (error) {
|
|||
|
console.log(error);
|
|||
|
}
|
|||
|
});
|
|||
|
};
|
|||
|
|
|||
|
async function updateObjectFunc(id, objectJSON) {
|
|||
|
// По id достаём строку, которую обновляем
|
|||
|
const row = document.querySelector(`tr[data-id="${id}"]`);
|
|||
|
// Делаем запрос на сервер и обновляем там объект
|
|||
|
const object = await updateObject(id, objectJSON);
|
|||
|
|
|||
|
// Теперь нужно обновить строку в таблице
|
|||
|
// Получаем объект категории
|
|||
|
const objectCategory = categories.find(category => category.id === object.categoryId);
|
|||
|
// Ищу тип ресторана
|
|||
|
const restaurantType = restaurantTypes.find(type => type.id === object.restaurantTypeId);
|
|||
|
// Создаем новую строку из новых данных и заменяем ей старую
|
|||
|
row.innerHTML = getHTMLRow(object, objectCategory.name, restaurantType.name);
|
|||
|
// Обновляем в глобальном массиве объект продукта
|
|||
|
products = products.map(product => (product.id === id ? object : product));
|
|||
|
}
|
|||
|
|
|||
|
async function addObject(objectJSON) {
|
|||
|
// Делаем запрос на создание объекта
|
|||
|
const object = await createObject(objectJSON);
|
|||
|
// Получаем категорию
|
|||
|
const objectCategory = categories.find(category => category.id === object.categoryId);
|
|||
|
// Ищу тип ресторана
|
|||
|
const restaurantType = restaurantTypes.find(type => type.id === object.restaurantTypeId);
|
|||
|
// Добавляем строку в таблицу
|
|||
|
parent.innerHTML += getHTMLRow(object, objectCategory.name, restaurantType.name);
|
|||
|
// Добавляем новый продукт в общий массив
|
|||
|
products.push(object);
|
|||
|
}
|