From cd1f3a1e877e227cda22eaa4e750bb5ac0b11ec6 Mon Sep 17 00:00:00 2001 From: ParkSuMin Date: Sat, 3 Jan 2026 18:22:36 +0300 Subject: [PATCH] Beautify --- public/app.js | 941 ++++++++++++++++++++++++++------------------------ 1 file changed, 485 insertions(+), 456 deletions(-) diff --git a/public/app.js b/public/app.js index 74b98f5..c0ca81b 100644 --- a/public/app.js +++ b/public/app.js @@ -8,92 +8,92 @@ const inventoryList = document.getElementById('inventory'); const advanceButton = document.getElementById('advance-date'); const API_BASE = - window.location.protocol === 'file:' ? 'http://localhost:3000' : window.location.origin; + window.location.protocol === 'file:' ? 'http://localhost:3000' : window.location.origin; let products = []; let orders = []; let currentDate = ''; function getLocalISODate() { - const now = new Date(); - const offsetMs = now.getTimezoneOffset() * 60 * 1000; - return new Date(now.getTime() - offsetMs).toISOString().slice(0, 10); + const now = new Date(); + const offsetMs = now.getTimezoneOffset() * 60 * 1000; + return new Date(now.getTime() - offsetMs).toISOString().slice(0, 10); } class OrderCard { - constructor(order, allOrders, allProducts) { - this.order = order; - this.orders = allOrders; - this.products = allProducts; - } + constructor(order, allOrders, allProducts) { + this.order = order; + this.orders = allOrders; + this.products = allProducts; + } - build() { - const card = document.createElement('div'); - card.className = 'card shadow-sm order-card'; + build() { + const card = document.createElement('div'); + card.className = 'card shadow-sm order-card'; - const body = document.createElement('div'); - body.className = 'card-body'; + const body = document.createElement('div'); + body.className = 'card-body'; - body.appendChild(this.buildHeader()); - body.appendChild(this.buildItemsSection()); + body.appendChild(this.buildHeader()); + body.appendChild(this.buildItemsSection()); - card.appendChild(body); - return card; - } + card.appendChild(body); + return card; + } - buildHeader() { - const header = document.createElement('div'); - header.className = 'd-flex justify-content-between flex-wrap gap-2'; + buildHeader() { + const header = document.createElement('div'); + header.className = 'd-flex justify-content-between flex-wrap gap-2'; - const info = document.createElement('div'); - const name = document.createElement('h3'); - name.className = 'h5 mb-1'; - name.textContent = this.order.customer_name; + const info = document.createElement('div'); + const name = document.createElement('h3'); + name.className = 'h5 mb-1'; + name.textContent = this.order.customer_name; - const idMeta = document.createElement('div'); - idMeta.className = 'text-muted order-meta'; - idMeta.textContent = `ID: ${this.order.id}`; + const idMeta = document.createElement('div'); + idMeta.className = 'text-muted order-meta'; + idMeta.textContent = `ID: ${this.order.id}`; - const dateMeta = document.createElement('div'); - dateMeta.className = 'text-muted order-meta'; - dateMeta.textContent = `Дата: ${this.order.order_date}`; + const dateMeta = document.createElement('div'); + dateMeta.className = 'text-muted order-meta'; + dateMeta.textContent = `Дата: ${this.order.order_date}`; - info.appendChild(name); - info.appendChild(idMeta); - info.appendChild(dateMeta); + info.appendChild(name); + info.appendChild(idMeta); + info.appendChild(dateMeta); - const actions = document.createElement('div'); - actions.className = 'd-flex gap-2 align-items-start'; - actions.appendChild(this.buildButton('Изменить', 'btn-outline-secondary', { - action: 'edit-order', - id: this.order.id - })); - actions.appendChild(this.buildButton('Удалить', 'btn-outline-danger', { - action: 'delete-order', - id: this.order.id - })); + const actions = document.createElement('div'); + actions.className = 'd-flex gap-2 align-items-start'; + actions.appendChild(this.buildButton('Изменить', 'btn-outline-secondary', { + action: 'edit-order', + id: this.order.id + })); + actions.appendChild(this.buildButton('Удалить', 'btn-outline-danger', { + action: 'delete-order', + id: this.order.id + })); - header.appendChild(info); - header.appendChild(actions); + header.appendChild(info); + header.appendChild(actions); - return header; - } + return header; + } - buildItemsSection() { - const wrapper = document.createElement('div'); - wrapper.className = 'mt-3'; + buildItemsSection() { + const wrapper = document.createElement('div'); + wrapper.className = 'mt-3'; - wrapper.appendChild(this.buildItemsTable()); - wrapper.appendChild(this.buildAddItemForm()); + wrapper.appendChild(this.buildItemsTable()); + wrapper.appendChild(this.buildAddItemForm()); - return wrapper; - } + return wrapper; + } - buildItemsTable() { - const table = document.createElement('table'); - table.className = 'table table-sm align-middle'; + buildItemsTable() { + const table = document.createElement('table'); + table.className = 'table table-sm align-middle'; - table.innerHTML = ` + table.innerHTML = ` ID @@ -104,473 +104,502 @@ class OrderCard { `; - const body = document.createElement('tbody'); - this.order.items.forEach((item) => { - body.appendChild(this.buildItemRow(item)); - }); + const body = document.createElement('tbody'); + this.order.items.forEach((item) => { + body.appendChild(this.buildItemRow(item)); + }); - table.appendChild(body); - return table; - } + table.appendChild(body); + return table; + } - buildItemRow(item) { - const row = document.createElement('tr'); + buildItemRow(item) { + const row = document.createElement('tr'); - const idCell = document.createElement('td'); - idCell.className = 'text-muted small'; - idCell.textContent = item.product_id ?? item.id; + const idCell = document.createElement('td'); + idCell.className = 'text-muted small'; + idCell.textContent = item.product_id ?? item.id; - const productCell = document.createElement('td'); - const productSelect = this.buildProductSelect(item); - productSelect.classList.add('form-select-sm'); - productSelect.dataset.action = 'item-product'; - productSelect.dataset.itemId = item.id; - productSelect.setAttribute('aria-label', 'Товар'); - productCell.appendChild(productSelect); + const productCell = document.createElement('td'); + const productSelect = this.buildProductSelect(item); + productSelect.classList.add('form-select-sm'); + productSelect.dataset.action = 'item-product'; + productSelect.dataset.itemId = item.id; + productSelect.setAttribute('aria-label', 'Товар'); + productCell.appendChild(productSelect); - const quantityCell = document.createElement('td'); - const quantityInput = document.createElement('input'); - quantityInput.type = 'number'; - quantityInput.min = '1'; - quantityInput.className = 'form-control form-control-sm'; - quantityInput.value = item.quantity; - quantityInput.dataset.action = 'item-quantity'; - quantityInput.dataset.itemId = item.id; - quantityInput.setAttribute('aria-label', 'Количество'); - quantityCell.appendChild(quantityInput); + const quantityCell = document.createElement('td'); + const quantityInput = document.createElement('input'); + quantityInput.type = 'number'; + quantityInput.min = '1'; + quantityInput.className = 'form-control form-control-sm'; + quantityInput.value = item.quantity; + quantityInput.dataset.action = 'item-quantity'; + quantityInput.dataset.itemId = item.id; + quantityInput.setAttribute('aria-label', 'Количество'); + quantityCell.appendChild(quantityInput); - const actionsCell = document.createElement('td'); - actionsCell.className = 'text-end item-actions'; - actionsCell.appendChild(this.buildItemActionButtons(item)); - actionsCell.appendChild(this.buildMoveControls(item)); + const actionsCell = document.createElement('td'); + actionsCell.className = 'text-end item-actions'; + actionsCell.appendChild(this.buildItemActionButtons(item)); + actionsCell.appendChild(this.buildMoveControls(item)); - row.appendChild(idCell); - row.appendChild(productCell); - row.appendChild(quantityCell); - row.appendChild(actionsCell); + row.appendChild(idCell); + row.appendChild(productCell); + row.appendChild(quantityCell); + row.appendChild(actionsCell); - return row; - } + return row; + } - buildItemActionButtons(item) { - const wrapper = document.createElement('div'); - wrapper.className = 'd-flex gap-2 justify-content-end'; + buildItemActionButtons(item) { + const wrapper = document.createElement('div'); + wrapper.className = 'd-flex gap-2 justify-content-end'; - wrapper.appendChild( - this.buildButton('Сохранить', 'btn-outline-primary', { - action: 'save-item', - orderId: this.order.id, - itemId: item.id - }) - ); - wrapper.appendChild( - this.buildButton('Удалить', 'btn-outline-danger', { - action: 'delete-item', - orderId: this.order.id, - itemId: item.id - }) - ); + wrapper.appendChild( + this.buildButton('Сохранить', 'btn-outline-primary', { + action: 'save-item', + orderId: this.order.id, + itemId: item.id + }) + ); + wrapper.appendChild( + this.buildButton('Удалить', 'btn-outline-danger', { + action: 'delete-item', + orderId: this.order.id, + itemId: item.id + }) + ); - return wrapper; - } + return wrapper; + } - buildMoveControls(item) { - const wrapper = document.createElement('div'); - wrapper.className = 'd-flex gap-2 justify-content-end mt-2'; + buildMoveControls(item) { + const wrapper = document.createElement('div'); + wrapper.className = 'd-flex gap-2 justify-content-end mt-2'; - const select = document.createElement('select'); - select.className = 'form-select form-select-sm'; - select.dataset.action = 'move-target'; - select.dataset.itemId = item.id; - select.setAttribute('aria-label', 'Выбор заказа для перемещения'); + const select = document.createElement('select'); + select.className = 'form-select form-select-sm'; + select.dataset.action = 'move-target'; + select.dataset.itemId = item.id; + select.setAttribute('aria-label', 'Выбор заказа для перемещения'); - const placeholder = document.createElement('option'); - placeholder.value = ''; - placeholder.textContent = 'Переместить в...'; - select.appendChild(placeholder); + const placeholder = document.createElement('option'); + placeholder.value = ''; + placeholder.textContent = 'Переместить в...'; + select.appendChild(placeholder); - this.orders - .filter((otherOrder) => otherOrder.id !== this.order.id) - .forEach((otherOrder) => { - const option = document.createElement('option'); - option.value = otherOrder.id; - option.textContent = otherOrder.customer_name; - select.appendChild(option); - }); + this.orders + .filter((otherOrder) => otherOrder.id !== this.order.id) + .forEach((otherOrder) => { + const option = document.createElement('option'); + option.value = otherOrder.id; + option.textContent = otherOrder.customer_name; + select.appendChild(option); + }); - wrapper.appendChild(select); - wrapper.appendChild( - this.buildButton('Перенести', 'btn-outline-secondary', { - action: 'move-item', - itemId: item.id - }) - ); + wrapper.appendChild(select); + wrapper.appendChild( + this.buildButton('Перенести', 'btn-outline-secondary', { + action: 'move-item', + itemId: item.id + }) + ); - return wrapper; - } + return wrapper; + } - buildAddItemForm() { - const form = document.createElement('form'); - form.className = 'row g-2 align-items-end'; - form.dataset.action = 'add-item'; - form.dataset.orderId = this.order.id; + buildAddItemForm() { + const form = document.createElement('form'); + form.className = 'row g-2 align-items-end'; + form.dataset.action = 'add-item'; + form.dataset.orderId = this.order.id; - const productCol = document.createElement('div'); - productCol.className = 'col-md-6'; - const productLabel = document.createElement('label'); - productLabel.className = 'form-label'; - productLabel.textContent = 'Товар'; - const productSelect = this.buildProductSelect(); - const productSelectId = `add-item-product-${this.order.id}`; - productSelect.name = 'productId'; - productSelect.id = productSelectId; - productLabel.htmlFor = productSelectId; - productCol.appendChild(productLabel); - productCol.appendChild(productSelect); + const productCol = document.createElement('div'); + productCol.className = 'col-md-6'; + const productLabel = document.createElement('label'); + productLabel.className = 'form-label'; + productLabel.textContent = 'Товар'; + const productSelect = this.buildProductSelect(); + const productSelectId = `add-item-product-${this.order.id}`; + productSelect.name = 'productId'; + productSelect.id = productSelectId; + productLabel.htmlFor = productSelectId; + productCol.appendChild(productLabel); + productCol.appendChild(productSelect); - const quantityCol = document.createElement('div'); - quantityCol.className = 'col-md-3'; - const quantityLabel = document.createElement('label'); - quantityLabel.className = 'form-label'; - quantityLabel.textContent = 'Кол-во'; - const quantityInput = document.createElement('input'); - const quantityInputId = `add-item-quantity-${this.order.id}`; - quantityInput.type = 'number'; - quantityInput.min = '1'; - quantityInput.className = 'form-control'; - quantityInput.name = 'quantity'; - quantityInput.id = quantityInputId; - quantityLabel.htmlFor = quantityInputId; - quantityInput.required = true; - quantityCol.appendChild(quantityLabel); - quantityCol.appendChild(quantityInput); + const quantityCol = document.createElement('div'); + quantityCol.className = 'col-md-3'; + const quantityLabel = document.createElement('label'); + quantityLabel.className = 'form-label'; + quantityLabel.textContent = 'Кол-во'; + const quantityInput = document.createElement('input'); + const quantityInputId = `add-item-quantity-${this.order.id}`; + quantityInput.type = 'number'; + quantityInput.min = '1'; + quantityInput.className = 'form-control'; + quantityInput.name = 'quantity'; + quantityInput.id = quantityInputId; + quantityLabel.htmlFor = quantityInputId; + quantityInput.required = true; + quantityCol.appendChild(quantityLabel); + quantityCol.appendChild(quantityInput); - const actionCol = document.createElement('div'); - actionCol.className = 'col-md-3'; - const addButton = document.createElement('button'); - addButton.type = 'submit'; - addButton.className = 'btn btn-success w-100'; - addButton.textContent = 'Добавить позицию'; - actionCol.appendChild(addButton); + const actionCol = document.createElement('div'); + actionCol.className = 'col-md-3'; + const addButton = document.createElement('button'); + addButton.type = 'submit'; + addButton.className = 'btn btn-success w-100'; + addButton.textContent = 'Добавить позицию'; + actionCol.appendChild(addButton); - form.appendChild(productCol); - form.appendChild(quantityCol); - form.appendChild(actionCol); + form.appendChild(productCol); + form.appendChild(quantityCol); + form.appendChild(actionCol); - return form; - } + return form; + } - buildProductSelect(selectedId) { - const select = document.createElement('select'); - select.className = 'form-select'; - this.products.forEach((product) => { - const option = document.createElement('option'); - option.value = product.id; - option.textContent = product.name; - if (selectedId && product.id === selectedId) { - option.selected = true; - } - select.appendChild(option); - }); - return select; - } + buildProductSelect(selectedId) { + const select = document.createElement('select'); + select.className = 'form-select'; + this.products.forEach((product) => { + const option = document.createElement('option'); + option.value = product.id; + option.textContent = product.name; + if (selectedId && product.id === selectedId) { + option.selected = true; + } + select.appendChild(option); + }); + return select; + } - buildButton(label, style, data = {}) { - const button = document.createElement('button'); - button.type = 'button'; - button.className = `btn ${style} btn-sm`; - button.textContent = label; - Object.entries(data).forEach(([key, value]) => { - button.dataset[key] = value; - }); - return button; - } + buildButton(label, style, data = {}) { + const button = document.createElement('button'); + button.type = 'button'; + button.className = `btn ${style} btn-sm`; + button.textContent = label; + Object.entries(data).forEach(([key, value]) => { + button.dataset[key] = value; + }); + return button; + } } function showNotification(message, type = 'warning') { - notification.textContent = message; - notification.className = `alert alert-${type}`; - notification.classList.remove('d-none'); + notification.textContent = message; + notification.className = `alert alert-${type}`; + notification.classList.remove('d-none'); - setTimeout(() => { - notification.classList.add('d-none'); - }, 4000); + setTimeout(() => { + notification.classList.add('d-none'); + }, 4000); } function resolveApiUrl(url) { - if (url.startsWith('http://') || url.startsWith('https://')) { - return url; - } - if (url.startsWith('/')) { - return `${API_BASE}${url}`; - } - return `${API_BASE}/${url}`; + if (url.startsWith('http://') || url.startsWith('https://')) { + return url; + } + if (url.startsWith('/')) { + return `${API_BASE}${url}`; + } + return `${API_BASE}/${url}`; } async function fetchJson(url, options) { - const response = await fetch(resolveApiUrl(url), options); - if (!response.ok) { - const payload = await response.json().catch(() => ({ message: 'Ошибка запроса.' })); - throw new Error(payload.message || 'Ошибка запроса.'); - } - if (response.status === 204) { - return null; - } - return response.json(); + const response = await fetch(resolveApiUrl(url), options); + if (!response.ok) { + const payload = await response.json().catch(() => ({ + message: 'Ошибка запроса.' + })); + throw new Error(payload.message || 'Ошибка запроса.'); + } + if (response.status === 204) { + return null; + } + return response.json(); } function renderInventory() { - inventoryList.innerHTML = ''; - products.forEach((product) => { - const item = document.createElement('li'); - item.className = 'list-group-item d-flex justify-content-between align-items-center'; - item.innerHTML = ` + inventoryList.innerHTML = ''; + products.forEach((product) => { + const item = document.createElement('li'); + item.className = 'list-group-item d-flex justify-content-between align-items-center'; + item.innerHTML = ` ${product.name} ${product.quantity} `; - inventoryList.appendChild(item); - }); + inventoryList.appendChild(item); + }); } function renderOrders() { - ordersContainer.innerHTML = ''; - if (orders.length === 0) { - ordersContainer.innerHTML = '

Заказы отсутствуют.

'; - return; - } + ordersContainer.innerHTML = ''; + if (orders.length === 0) { + ordersContainer.innerHTML = '

Заказы отсутствуют.

'; + return; + } - orders.forEach((order) => { - const card = new OrderCard(order, orders, products).build(); - ordersContainer.appendChild(card); - }); + orders.forEach((order) => { + const card = new OrderCard(order, orders, products).build(); + ordersContainer.appendChild(card); + }); } function normalizeProducts(data) { - if (!Array.isArray(data)) { - return []; - } - return data.map((product) => ({ - id: product.id ?? product.ID, - name: product.name ?? product.pr_name, - quantity: product.quantity ?? product.count - })); + if (!Array.isArray(data)) { + return []; + } + return data.map((product) => ({ + id: product.id ?? product.ID, + name: product.name ?? product.pr_name, + quantity: product.quantity ?? product.count + })); } function normalizeOrderItems(items) { - if (!Array.isArray(items)) { - return []; - } - return items.map((item, index) => ({ - id: item.id ?? item.item_id ?? `${item.product_id ?? item.productId ?? 'item'}-${index}`, - product_id: item.product_id ?? item.productId ?? item.product, - product_name: item.product_name ?? item.name, - quantity: item.quantity, - price: item.price - })); + if (!Array.isArray(items)) { + return []; + } + return items.map((item, index) => ({ + id: item.id ?? item.item_id ?? `${item.product_id ?? item.productId ?? 'item'}-${index}`, + product_id: item.product_id ?? item.productId ?? item.product, + product_name: item.product_name ?? item.name, + quantity: item.quantity, + price: item.price + })); } function normalizeOrders(data) { - if (!Array.isArray(data)) { - return []; - } - return data.map((order) => ({ - id: order.id ?? order.ID, - customer_name: order.customer_name ?? order.customer, - order_date: order.order_date ?? order.date, - status: order.status, - total_amount: order.total_amount ?? order.total, - items: normalizeOrderItems(order.items) - })); + if (!Array.isArray(data)) { + return []; + } + return data.map((order) => ({ + id: order.id ?? order.ID, + customer_name: order.customer_name ?? order.customer, + order_date: order.order_date ?? order.date, + status: order.status, + total_amount: order.total_amount ?? order.total, + items: normalizeOrderItems(order.items) + })); } async function refreshData() { - const [currentDateData, productsData, ordersData] = await Promise.all([ - fetchJson('/api/current-date'), - fetchJson('/api/products'), - fetchJson('/api/orders') - ]); - currentDate = currentDateData.currentDate; - products = normalizeProducts(productsData); - orders = normalizeOrders(ordersData); + const [currentDateData, productsData, ordersData] = await Promise.all([ + fetchJson('/api/current-date'), + fetchJson('/api/products'), + fetchJson('/api/orders') + ]); + currentDate = currentDateData.currentDate; + products = normalizeProducts(productsData); + orders = normalizeOrders(ordersData); - currentDateEl.textContent = currentDate; - orderDateInput.min = currentDate; - if (!orderDateInput.value) { - orderDateInput.value = currentDate; - } + currentDateEl.textContent = currentDate; + orderDateInput.min = currentDate; + if (!orderDateInput.value) { + orderDateInput.value = currentDate; + } - renderInventory(); - renderOrders(); + renderInventory(); + renderOrders(); } function initializeApp() { - const requiredElements = [ - notification, - currentDateEl, - orderDateInput, - customerNameInput, - orderForm, - ordersContainer, - inventoryList, - advanceButton - ]; + const requiredElements = [ + notification, + currentDateEl, + orderDateInput, + customerNameInput, + orderForm, + ordersContainer, + inventoryList, + advanceButton + ]; - if (requiredElements.some((element) => !element)) { - console.error('Missing required elements. Проверьте разметку страницы.'); - return; - } - - const initialDate = getLocalISODate(); - currentDate = initialDate; - currentDateEl.textContent = initialDate; - orderDateInput.min = initialDate; - if (!orderDateInput.value) { - orderDateInput.value = initialDate; - } - - orderForm.addEventListener('submit', async (event) => { - event.preventDefault(); - try { - await fetchJson('/api/orders', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - customerName: customerNameInput.value.trim(), - orderDate: orderDateInput.value - }) - }); - customerNameInput.value = ''; - orderDateInput.value = currentDate; - await refreshData(); - } catch (error) { - showNotification(error.message, 'warning'); + if (requiredElements.some((element) => !element)) { + console.error('Missing required elements. Проверьте разметку страницы.'); + return; } - }); - advanceButton.addEventListener('click', async () => { - try { - await fetchJson('/api/current-date/advance', { method: 'POST' }); - await refreshData(); - showNotification('Дата переведена. Заказы за сегодня отправлены.', 'success'); - } catch (error) { - showNotification(error.message, 'warning'); + const initialDate = getLocalISODate(); + currentDate = initialDate; + currentDateEl.textContent = initialDate; + orderDateInput.min = initialDate; + if (!orderDateInput.value) { + orderDateInput.value = initialDate; } - }); - ordersContainer.addEventListener('submit', async (event) => { - if (event.target.matches('form[data-action="add-item"]')) { - event.preventDefault(); - const orderId = event.target.dataset.orderId; - const productId = event.target.productId.value; - const quantity = Number.parseInt(event.target.quantity.value, 10); + orderForm.addEventListener('submit', async (event) => { + event.preventDefault(); + try { + await fetchJson('/api/orders', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + customerName: customerNameInput.value.trim(), + orderDate: orderDateInput.value + }) + }); + customerNameInput.value = ''; + orderDateInput.value = currentDate; + await refreshData(); + } catch (error) { + showNotification(error.message, 'warning'); + } + }); - try { - const response = await fetchJson(`/api/orders/${orderId}/items`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ productId, quantity }) - }); - const order = orders.find((entry) => entry.id === orderId); - const product = products.find((entry) => entry.id === productId); - if (order) { - const newItem = normalizeOrderItems([ - { - id: response?.itemId, - product_id: productId, - product_name: product?.name, - quantity + advanceButton.addEventListener('click', async () => { + try { + await fetchJson('/api/current-date/advance', { + method: 'POST' + }); + await refreshData(); + showNotification('Дата переведена. Заказы за сегодня отправлены.', 'success'); + } catch (error) { + showNotification(error.message, 'warning'); + } + }); + + ordersContainer.addEventListener('submit', async (event) => { + if (event.target.matches('form[data-action="add-item"]')) { + event.preventDefault(); + const orderId = event.target.dataset.orderId; + const productId = event.target.productId.value; + const quantity = Number.parseInt(event.target.quantity.value, 10); + + try { + const response = await fetchJson(`/api/orders/${orderId}/items`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + productId, + quantity + }) + }); + const order = orders.find((entry) => entry.id === orderId); + const product = products.find((entry) => entry.id === productId); + if (order) { + const newItem = normalizeOrderItems([{ + id: response?.itemId, + product_id: productId, + product_name: product?.name, + quantity + }])[0]; + order.items = [...order.items, newItem]; + renderOrders(); + } + event.target.reset(); + await refreshData(); + } catch (error) { + showNotification(error.message, 'warning'); } - ])[0]; - order.items = [...order.items, newItem]; - renderOrders(); } - event.target.reset(); - await refreshData(); - } catch (error) { + }); + + ordersContainer.addEventListener('click', async (event) => { + const { + action, + id, + itemId, + orderId + } = event.target.dataset; + + try { + if (action === 'delete-order') { + await fetchJson(`/api/orders/${id}`, { + method: 'DELETE' + }); + await refreshData(); + return; + } + + if (action === 'edit-order') { + const newName = prompt('Введите новое ФИО заказчика', ''); + if (newName === null) { + return; + } + const newDate = prompt('Введите дату заказа (YYYY-MM-DD)', currentDate); + if (!newDate) { + return; + } + Date + await fetchJson(`/api/orders/${id}`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + customerName: newName, + orderDate: newDate + }) + }); + await refreshData(); + return; + } + + if (action === 'save-item') { + const quantityInput = ordersContainer.querySelector( + `[data-action="item-quantity"][data-item-id="${itemId}"]` + ); + const productSelect = ordersContainer.querySelector( + `[data-action="item-product"][data-item-id="${itemId}"]` + ); + + await fetchJson(`/api/orders/${orderId}/items/${itemId}`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + productId: productSelect.value, + quantity: Number.parseInt(quantityInput.value, 10) + }) + }); + await refreshData(); + return; + } + + if (action === 'delete-item') { + await fetchJson(`/api/orders/${orderId}/items/${itemId}`, { + method: 'DELETE' + }); + await refreshData(); + return; + } + + if (action === 'move-item') { + const targetSelect = ordersContainer.querySelector( + `[data-action="move-target"][data-item-id="${itemId}"]` + ); + if (!targetSelect.value) { + showNotification('Выберите заказ для перемещения.', 'warning'); + return; + } + await fetchJson(`/api/order-items/${itemId}/move`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + targetOrderId: targetSelect.value + }) + }); + await refreshData(); + return; + } + } catch (error) { + showNotification(error.message, 'warning'); + } + }); + + refreshData().catch((error) => { showNotification(error.message, 'warning'); - } - } - }); - - ordersContainer.addEventListener('click', async (event) => { - const { action, id, itemId, orderId } = event.target.dataset; - - try { - if (action === 'delete-order') { - await fetchJson(`/api/orders/${id}`, { method: 'DELETE' }); - await refreshData(); - return; - } - - if (action === 'edit-order') { - const newName = prompt('Введите новое ФИО заказчика', ''); - if (newName === null) { - return; - } - const newDate = prompt('Введите дату заказа (YYYY-MM-DD)', currentDate); - if (!newDate) { - return; - } - Date - await fetchJson(`/api/orders/${id}`, { - method: 'PUT', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ customerName: newName, orderDate: newDate }) - }); - await refreshData(); - return; - } - - if (action === 'save-item') { - const quantityInput = ordersContainer.querySelector( - `[data-action="item-quantity"][data-item-id="${itemId}"]` - ); - const productSelect = ordersContainer.querySelector( - `[data-action="item-product"][data-item-id="${itemId}"]` - ); - - await fetchJson(`/api/orders/${orderId}/items/${itemId}`, { - method: 'PUT', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - productId: productSelect.value, - quantity: Number.parseInt(quantityInput.value, 10) - }) - }); - await refreshData(); - return; - } - - if (action === 'delete-item') { - await fetchJson(`/api/orders/${orderId}/items/${itemId}`, { method: 'DELETE' }); - await refreshData(); - return; - } - - if (action === 'move-item') { - const targetSelect = ordersContainer.querySelector( - `[data-action="move-target"][data-item-id="${itemId}"]` - ); - if (!targetSelect.value) { - showNotification('Выберите заказ для перемещения.', 'warning'); - return; - } - await fetchJson(`/api/order-items/${itemId}/move`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ targetOrderId: targetSelect.value }) - }); - await refreshData(); - return; - } - } catch (error) { - showNotification(error.message, 'warning'); - } - }); - - refreshData().catch((error) => { - showNotification(error.message, 'warning'); - }); + }); } initializeApp(); \ No newline at end of file