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);
|
||
} |