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