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) {
// Создают для каждой отдельной категории
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) {
// Создают для каждой отдельной категории
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);
}