diff --git a/config/routes/api.js b/config/routes/api.js index 2e38c42..2715885 100644 --- a/config/routes/api.js +++ b/config/routes/api.js @@ -1,5 +1,10 @@ const fs = require('fs'); +function checkAuthenticated(req, res, next) { + if (req.isAuthenticated()) return next(); + res.redirect('/admin'); +} + module.exports = function(server, db) { server.get('/api/items', async (req, res) => { if (req.query.q) { @@ -43,10 +48,14 @@ module.exports = function(server, db) { } }); - server.get('/api/items/search/:query', (req, res) => { - const query = req.query.q; - console.log(query); - }) + server.get('/api/items/data', checkAuthenticated, async (req, res) => { + try { + const data = await db.collection('info').find({}).toArray(); + res.json(data); + } catch (error) { + res.render('main/404'); + } + }); server.get('/api/items/:category', async (req, res) => { const items = await db.collection('items').find({category: req.params.category}).toArray(), diff --git a/config/routes/control-panel.js b/config/routes/control-panel.js index 340e03c..1be27d5 100644 --- a/config/routes/control-panel.js +++ b/config/routes/control-panel.js @@ -196,7 +196,9 @@ module.exports = function(server, db) { }); server.post('/control-panel/items/delete', checkAuthenticated, (req, res) => { try { - db.collection('items').deleteOne({"_id": ObjectID(req.body.id)}); + const id = ObjectID(req.body.id); + db.collection('items').deleteOne({"_id": id}); + db.collection('info').deleteOne({"_id": id}); res.redirect('/control-panel/items'); } catch (error) { res.render('main/404'); @@ -209,9 +211,11 @@ module.exports = function(server, db) { title: req.body.title, price: parseFloat(req.body.price), description: req.body.description, - category: JSON.parse(req.body.category) + category: JSON.parse(req.body.category), + info: req.body.data.split(',') } - db.collection('items').updateOne({"_id": ObjectID(data.id)}, {$set: {title: data.title, price: data.price, description: data.description, category: data.category.title}}); + db.collection('items').updateOne({"_id": ObjectID(data.id)}, {$set: {title: data.title, count: data.info.length, price: data.price, description: data.description, category: data.category.title}}); + db.collection('info').updateOne({"_id": ObjectID(data.id)}, {$set: {title: data.title, data: data.info}}); res.redirect('/control-panel/items'); } catch (error) { res.render('main/404'); diff --git a/dist/public/css/style.css b/dist/public/css/style.css index fd820be..b61bc5c 100644 --- a/dist/public/css/style.css +++ b/dist/public/css/style.css @@ -149,7 +149,7 @@ hr { background-color: #fff; margin-top: 7rem; padding: 25px; - width: 460px; + width: 560px; min-height: 230px; } .c_modal-content.editCategory { diff --git a/dist/views/admin/assets/templates/modals/edit_category.pug b/dist/views/admin/assets/templates/modals/edit_category.pug index aa71a34..47ea767 100644 --- a/dist/views/admin/assets/templates/modals/edit_category.pug +++ b/dist/views/admin/assets/templates/modals/edit_category.pug @@ -11,25 +11,25 @@ i.material-icons close .modal-content__form form(action="/control-panel/categories/update" method="POST") - .input-field.id - input(style="color: gray;" type="text" name="id" required readonly) + .input-field + input.id(style="color: gray;" type="text" name="id" required readonly) label ID категории - .input-field.originalTitle - input(style="color: gray;" type="text" name="originalTitle" required readonly) + .input-field + input.originalTitle(style="color: gray;" type="text" name="originalTitle" required readonly) label Старое название категории - .input-field.title - input(type="text" name="title" required) + .input-field + input.title(type="text" name="title" required) label Новое название категории - .input-field.type - textarea(class="materialize-textarea" type="text" name="type" required) + .input-field + textarea.type(class="materialize-textarea" type="text" name="type" required) label Тип аккаунтов - .input-field.img - select(name="img" required) + .input-field + select.img(name="img" required) option(value="" disabled selected) | Выберите иконку label(for="img") Иконка - .input-field.format - input(type="text" name="format" required) + .input-field + input.format(type="text" name="format" required) label Формат аккаунтов .edit_success button(type="submit" class="btn orange waves-effect" style="width: 100%;height:50px") Редактировать diff --git a/dist/views/admin/assets/templates/modals/edit_item.pug b/dist/views/admin/assets/templates/modals/edit_item.pug index 39b28df..ccb337c 100644 --- a/dist/views/admin/assets/templates/modals/edit_item.pug +++ b/dist/views/admin/assets/templates/modals/edit_item.pug @@ -21,11 +21,14 @@ input.price(id="price" type="text" name="price" required) label(for="price") Цена товара ₽ .input-field - textarea.description(id="description" class="materialize-textarea" type="text" name="description") + textarea.description(id="description" class="materialize-textarea" type="text" name="description" required) label(for="description") Описание товара .input-field select.category(name="category") label Категория + .input-field + textarea.data(id="data" class="materialize-textarea" type="text" name="data" placeholder="Перечислите аккаунты через запятую." required) + label(for="data") Данные товара .edit_success button(type="submit" class="btn orange waves-effect" style="width: 100%;height:50px") Редактировать // Edit Category END diff --git a/dist/views/admin/items.pug b/dist/views/admin/items.pug index b2846d1..f8ead17 100644 --- a/dist/views/admin/items.pug +++ b/dist/views/admin/items.pug @@ -40,21 +40,21 @@ body.has-fixed-sidenav .row form(action="/control-panel/items/create" method="POST") .input-field.col.l6.s12 - input(id="title" type="text" name="title") + input(id="title" type="text" name="title" required) label(for="title") Название товара .input-field.col.l6.s12 - input(id="price" type="text" name="price") - label(for="price") Цена товара ₽ + input(id="price" type="text" name="price" pattern="([0-9\.]+)" required) + label(for="price") Цена товара в рублях ₽ .input-field.col.l6.s12 - textarea(id="description" class="materialize-textarea" type="text" name="description") + textarea(id="description" class="materialize-textarea" type="text" name="description" required) label(for="description") Описание товара .input-field.col.l6.s12 - select#selectCategories(name="category") + select#selectCategories(name="category" required) option(value="" disabled selected) | Выберите категорию label Категория товара .input-field.col.s12 - textarea(class="materialize-textarea" type="text" placeholder="Пречеслите аккаунты в вашем формате через запятую." name="data") + textarea(class="materialize-textarea" type="text" placeholder="Пречеслите аккаунты в вашем формате через запятую." name="data" required) label Данные товара .col.s12 button(type="submit" class="btn") Добавить товар diff --git a/src/admin/components/items.component.js b/src/admin/components/items.component.js index 767b8c4..b77cb0e 100644 --- a/src/admin/components/items.component.js +++ b/src/admin/components/items.component.js @@ -27,13 +27,15 @@ export class ItemsComponent extends Component { async getItemsByText(text) { const items = await apiService.getItemsQuery(text), - categories = await apiService.getCategories(); - return renderItems(items, categories); + categories = await apiService.getCategories(), + data = await apiService.getItemsData(); + return renderItems(items, categories, data); } async getItemsByPage(page) { const items = await apiService.getItemsOffset(page), - categories = await apiService.getCategories(); - return renderItems(items, categories); + categories = await apiService.getCategories(), + data = await apiService.getItemsData(); + return renderItems(items, categories, data); } } \ No newline at end of file diff --git a/src/admin/components/pagination.component.js b/src/admin/components/pagination.component.js index 1ba9aa7..bad0e15 100644 --- a/src/admin/components/pagination.component.js +++ b/src/admin/components/pagination.component.js @@ -51,16 +51,16 @@ export class PaginationComponent extends Component { // выполняем запрос на сервер и выводим на данные async moveTo(page, insertTo, request) { - try { + const response = await request(page); + + if (response != '') { this.$el.setAttribute('data-page', page); insertTo.innerHTML = ''; this.loader.show(); - insertTo.insertAdjacentHTML('afterbegin', await request(page)); - this.loader.hide(); - } catch (error) { - this.loader.hide(); - this.$el.classList.add('hide'); - insertTo.parentNode.innerHTML = '

Товаров или категорий в магазине нету.

'; + insertTo.insertAdjacentHTML('afterbegin', response); + this.loader.hide(); + } else { + insertTo.innerHTML = 'Данных нету.'; } } diff --git a/src/admin/modals/deleteItem.modal.js b/src/admin/modals/deleteItem.modal.js index 996bf34..0c10f0e 100644 --- a/src/admin/modals/deleteItem.modal.js +++ b/src/admin/modals/deleteItem.modal.js @@ -21,7 +21,7 @@ export class deleteItemModal extends Modal { openHandler(e) { const data = JSON.parse(e.target.parentNode.parentNode.dataset.info); - this.$content.innerHTML = `Вы действительно хотите удалить товар:
"${data.title}"?`; + this.$content.innerHTML = `Вы действительно хотите удалить товар "${data.title}"? Находящиеся в нем аккаунты будут удалены.`; this.$button.onclick = this.deleteHandler.bind(this, data.id); } diff --git a/src/admin/modals/editCategory.modal.js b/src/admin/modals/editCategory.modal.js index b299e60..09618f2 100644 --- a/src/admin/modals/editCategory.modal.js +++ b/src/admin/modals/editCategory.modal.js @@ -10,24 +10,35 @@ export class editCategoryModal extends Modal { // перепишем метод для перевода ивента open в событие onchange init() { if (this.open) { + this.setElems(); this.open.addEventListener('change', this.show.bind(this)); this.close.addEventListener('click', this.hide.bind(this)); this.$el.querySelector('form').addEventListener('submit', this.updateCategory.bind(this)); } } + + setElems() { + this.$id = this.$el.querySelector('.id'); + this.$originalTitle = this.$el.querySelector('.originalTitle'); + this.$title = this.$el.querySelector('.title'); + this.$type = this.$el.querySelector('.type'); + this.$format = this.$el.querySelector('.format'); + this.$img = this.$el.querySelector('.img'); + } async openHandler(e) { - const data = JSON.parse(e.target.value); - this.$el.querySelector('form .id input').value = data.id; - this.$el.querySelector('form .originalTitle input').value = data.title[0].toUpperCase() + data.title.slice(1); - this.$el.querySelector('form .title input').value = data.title[0].toUpperCase() + data.title.slice(1); - this.$el.querySelector('form .type textarea').value = data.type; - this.$el.querySelector('form .format input').value = data.format; + const data = JSON.parse(e.target.value), + icons = await apiService.getIcons(); - const icons = await apiService.getIcons(); - const icons_html = renderIcons(icons); - this.$el.querySelector('form .img select').insertAdjacentHTML('beforeend', icons_html); - M.FormSelect.init(this.$el.querySelector('form .img select')); + this.$img.innerHTML = ''; + this.$id.value = data.id; + this.$originalTitle.value = data.title[0].toUpperCase() + data.title.slice(1); + this.$title.value = data.title[0].toUpperCase() + data.title.slice(1); + this.$type.value = data.type; + this.$format.value = data.format; + this.$img.insertAdjacentHTML('beforeend', renderIcons(icons)); + M.FormSelect.init(this.$img); + M.textareaAutoResize(this.$type); M.updateTextFields(); } diff --git a/src/admin/modals/editItem.modal.js b/src/admin/modals/editItem.modal.js index 9db6a27..b311390 100644 --- a/src/admin/modals/editItem.modal.js +++ b/src/admin/modals/editItem.modal.js @@ -21,6 +21,7 @@ export class editItemModal extends Modal { this.$price = this.$el.querySelector('.price'); this.$description = this.$el.querySelector('.description'); this.$category = this.$el.querySelector('.category'); + this.$data = this.$el.querySelector('.data'); } async openHandler(e) { @@ -33,7 +34,10 @@ export class editItemModal extends Modal { this.$price.value = data.price; this.$description.value = data.description; this.$category.insertAdjacentHTML('beforeend', renderCategories(categories)); + this.$data.value = data.data; M.FormSelect.init(this.$category); + M.textareaAutoResize(this.$description); + M.textareaAutoResize(this.$data); M.updateTextFields(); } } \ No newline at end of file diff --git a/src/admin/services/api.service.js b/src/admin/services/api.service.js index 5b4f31a..317eaf9 100644 --- a/src/admin/services/api.service.js +++ b/src/admin/services/api.service.js @@ -70,6 +70,15 @@ class ApiService { } } + async getItemsData() { + try { + const request = `${this.url}/api/items/data`; + return useRequest(request); + } catch (err) { + console.log(err); + } + } + async getIcons() { try { const request = `${this.url}/api/icons`; diff --git a/src/admin/templates/items.template.js b/src/admin/templates/items.template.js index 50e36f1..9902822 100644 --- a/src/admin/templates/items.template.js +++ b/src/admin/templates/items.template.js @@ -1,10 +1,13 @@ -export function renderItems(items, categories) { +export function renderItems(items, categories, info) { let html = ''; - categories.forEach(category => { - items.forEach(item => { - if (item.category.toLowerCase() === category.title.toLowerCase()) html += `alt${item.title}${item.category[0].toUpperCase() + item.category.slice(1)}${new Date(item.date).toLocaleDateString()}${item.count}${item.price} ₽` - }); - }); + if (!items.error) { + categories.forEach(category => { + items.forEach((item, i) => { + if (item.category.toLowerCase() === category.title.toLowerCase()) html += `alt${item.title}${item.category[0].toUpperCase() + item.category.slice(1)}${new Date(item.date).toLocaleDateString()}${item.count}${item.price} ₽` + }); + }); + } else html += 'Данных нету.'; + return html; } \ No newline at end of file