From 4c6dec9df8b53114aac5e56bfbf6d0911ba84d21 Mon Sep 17 00:00:00 2001 From: necitboss Date: Mon, 11 Nov 2024 19:11:32 +0300 Subject: [PATCH 1/3] kharitonov_for_docker_first_change --- main/_front/src/html/add-edit.html | 24 ++- main/_front/src/html/components.html | 4 + main/_front/src/html/login.html | 6 +- main/_front/src/js/add-edit.js | 249 +++++++++++++++++++++++++ main/_front/src/js/components.js | 30 ++- main/_front/src/js/elems/add-edit.js | 118 ------------ main/_front/src/js/login.js | 66 ++++++- main/_front/src/scss/_base.scss | 4 + main/_front/src/scss/blocks/_form.scss | 6 + main/_front/src/scss/elems/_btn.scss | 17 +- main/controllers/AdminController.js | 1 - main/index.js | 12 +- main/utils/checkAuth.js | 2 +- 13 files changed, 385 insertions(+), 154 deletions(-) create mode 100644 main/_front/src/js/add-edit.js delete mode 100644 main/_front/src/js/elems/add-edit.js diff --git a/main/_front/src/html/add-edit.html b/main/_front/src/html/add-edit.html index 5f0c8b8..a69fe69 100644 --- a/main/_front/src/html/add-edit.html +++ b/main/_front/src/html/add-edit.html @@ -8,7 +8,7 @@ Document - + @@ -67,7 +67,7 @@

Добавление/Редактирование

Выберите
тип продукта

-
+
- +
-
Выберите обязательные поля
-
-
+
Выберите обязательные поля
+
+
Сокет (разъем на плате)
@@ -258,16 +258,14 @@

Количество:

-
+
Количество слотов ОЗУ
- - -
+
Тип памяти
diff --git a/main/_front/src/html/components.html b/main/_front/src/html/components.html index a71d0f8..9a53f1e 100644 --- a/main/_front/src/html/components.html +++ b/main/_front/src/html/components.html @@ -238,6 +238,10 @@

Cокет

+
diff --git a/main/_front/src/html/login.html b/main/_front/src/html/login.html index 01979d2..c76011a 100644 --- a/main/_front/src/html/login.html +++ b/main/_front/src/html/login.html @@ -63,9 +63,9 @@

Пора Cобрать ПК

Вход в панель администратора

-
+
-

Вход

+

Вход

Почта @@ -74,7 +74,9 @@

Вход

Пароль
+
Неверный логин или пароль
+
diff --git a/main/_front/src/js/add-edit.js b/main/_front/src/js/add-edit.js new file mode 100644 index 0000000..fa8495d --- /dev/null +++ b/main/_front/src/js/add-edit.js @@ -0,0 +1,249 @@ +const main_properties_tilte = document.querySelector("#main_properties_title"); +const name = document.querySelector('#name input'); +const price = document.querySelector('#price input'); +const count = document.querySelector('#count .stepper__value'); +const type = document.querySelector('#type'); +const main_properties = document.querySelector('#main_properties'); +const other_properties = document.querySelector('#properties_list'); +const btn_submit = document.querySelector('#submit'); +const socket = document.querySelector('#socket'); +const ram_count= document.querySelector('#ram_count'); +const ram_type = document.querySelector('#ram_type'); + +const choiceLists = document.querySelectorAll(".choice"); + +choiceLists.forEach((choiceList) => { + const isType = choiceList.id === "type"; + const choiceItems = choiceList.querySelectorAll(".choice__elem"); + choiceItems.forEach((choice) => { + if (choice.classList.contains("active")) { + choiceList.dataset.value = choice.dataset.value; + // console.log(choice.dataset.value); + } + choice.addEventListener("click", (e) => { + choiceItems.forEach((choice) => { + if (choice === e.target) { + choiceList.dataset.value = choice.dataset.value; + choice.classList.add("active"); + // console.log(choice.dataset.value); + }else { + choice.classList.remove("active"); + } + }); + if (isType){ + if (choiceList.dataset.value === "cpu") { + main_properties_tilte.classList.remove('hide'); + socket.classList.remove('hide'); + ram_count.classList.add('hide'); + ram_type.classList.add('hide'); + }else if (choiceList.dataset.value === "motherboard"){ + main_properties_tilte.classList.remove('hide'); + socket.classList.remove('hide'); + ram_count.classList.remove('hide'); + ram_type.classList.remove('hide'); + }else if (choiceList.dataset.value === "ram"){ + main_properties_tilte.classList.remove('hide'); + socket.classList.add('hide'); + ram_count.classList.add('hide'); + ram_type.classList.remove('hide'); + }else { + main_properties_tilte.classList.add('hide'); + socket.classList.add('hide'); + ram_count.classList.add('hide'); + ram_type.classList.add('hide'); + } + } + }); + }); + if (isType){ + if (choiceList.dataset.value === "cpu") { + main_properties_tilte.classList.remove('hide'); + socket.classList.remove('hide'); + ram_count.classList.add('hide'); + ram_type.classList.add('hide'); + }else if (choiceList.dataset.value === "motherboard"){ + main_properties_tilte.classList.remove('hide'); + socket.classList.remove('hide'); + ram_count.classList.remove('hide'); + ram_type.classList.remove('hide'); + }else if (choiceList.dataset.value === "ram"){ + main_properties_tilte.classList.remove('hide'); + socket.classList.add('hide'); + ram_count.classList.add('hide'); + ram_type.classList.remove('hide'); + }else { + main_properties_tilte.classList.add('hide'); + socket.classList.add('hide'); + ram_count.classList.add('hide'); + ram_type.classList.add('hide'); + } + } +}) + +const steppers = document.querySelectorAll('.stepper'); +const checkMinDisabled = (element) => { + return Number(element.textContent) <= 1; +} +const checkMaxDisabled = (element, maxValue) => { + return Number(element.textContent) >= Number(maxValue); +} +const writeDataValue = (element, value) => { + element.dataset.value = value; +} + +steppers.forEach(stepper => { + + + const minus_btn = stepper.querySelector('.stepper__minus'); + const plus_btn = stepper.querySelector('.stepper__plus'); + const value = stepper.querySelector('.stepper__value'); + if (value.textContent) writeDataValue(stepper, value.textContent); + + const max = stepper.dataset.max; + + if (checkMinDisabled(value)){ + minus_btn.disabled = true; + value.textContent = "1"; + } + if (checkMaxDisabled(value, max)){ + plus_btn.disabled = true; + value.textContent = max; + } + + minus_btn.addEventListener('click', (e) => { + let count = Number(value.textContent); + if (count > 1) { + count--; + value.textContent = count; + plus_btn.disabled = false; + writeDataValue(stepper, value.textContent); + if (checkMinDisabled(value)){ + minus_btn.disabled = true; + value.textContent = "1"; + } + } + }) + + plus_btn.addEventListener('click', (e) => { + let count = Number(value.textContent); + if (count < max) { + count++; + value.textContent = count; + minus_btn.disabled = false; + writeDataValue(stepper, value.textContent); + if (checkMaxDisabled(value, max)){ + plus_btn.disabled = true; + value.textContent = max; + } + } + }) +}) + +// Начало файла, считай (все выше - скопировано из других для удобства разработки) + +const input_property_name = document.querySelector("#property_name>input"); +const input_property_value = document.querySelector("#property_value>input"); + +const properties_list = document.querySelector("#properties_list") + +const handleDelete = (e) => { + e.currentTarget.parentElement.remove(); +} + +const property_btn = document.querySelector("#property_btn"); +property_btn.addEventListener('click', (e) => { + const input_name = input_property_name.value; + const input_value = input_property_value.value; + if (input_name !== "" && input_value !== "") { + properties_list.insertAdjacentHTML('beforeend', ` +
+
+
${input_name}
+
${input_value}
+
+ +
+ `) + properties_list.querySelectorAll(".property .property__btn").forEach(button => { + button.removeEventListener("click", handleDelete); + button.addEventListener("click", handleDelete); + }) + input_property_name.value = ""; + input_property_value.value = ""; + } +}) + +document.addEventListener("DOMContentLoaded", function() { + fetch('http://localhost:4444/auth/authorized', { + method: 'GET', + headers: { + 'Authorization': 'Bearer ' + localStorage.getItem('authToken'), + 'Content-Type': 'application/json' + } + }) + .then(res => res.json()) + .then(data => { + if (data.message === true) { + + }else { + window.location.href = 'login' + } + }) +}) + + + +btn_submit.addEventListener('click', (e) => { + // console.log(name.value); + // console.log(price.value); + // console.log(Number(count.textContent)); + // console.log(type.dataset.value); + // console.log(main_properties); + // console.log(); + let otherPropertiesArray = [] + other_properties.querySelectorAll(".property").forEach(property => { + // console.log(property); + otherPropertiesArray.push({ + name: property.querySelector(".property__name").textContent, + value: property.querySelector(".property__value").textContent, + }) + }) + let mainPropertiesArray = [] + main_properties.querySelectorAll(".add-right__choice").forEach(property => { + if (property.classList.contains('hide')){ + return; + } + mainPropertiesArray.push({ + name: property.querySelector(".add-right__choice-title").textContent, + value: property.querySelector(".choice").dataset.value + }) + }) + // console.log(mainPropertiesArray); + // console.log(otherPropertiesArray); + const object = { + name: name.value, + type: type.dataset.value, + price: price.value, + count: Number(count.textContent), + main_properties: mainPropertiesArray, + other_properties: otherPropertiesArray + } + if (name.value !== "" && type.dataset.value !== "" && String(price.value)!== "" && count.textContent!== ""){ + fetch('http://localhost:4444/components', { + method: 'POST', + headers: { + 'Authorization': 'Bearer ' + localStorage.getItem('authToken'), + 'Content-Type': 'application/json' + }, + body: JSON.stringify(object) + }) + .then(res => res.json()) + .then(data => { + if (!data.message){ + window.location.href = '/' + } + }) + } +}) \ No newline at end of file diff --git a/main/_front/src/js/components.js b/main/_front/src/js/components.js index 55a5f23..6457d39 100644 --- a/main/_front/src/js/components.js +++ b/main/_front/src/js/components.js @@ -22,7 +22,9 @@ choiceLists.forEach((choiceList) => { }) const cards_place = document.querySelector("#cards_place"); - + +let isAdmin = false; + const addCards = () => { fetch("http://localhost:4444/components") .then(res => res.json()) @@ -34,13 +36,31 @@ const addCards = () => {
${item.name}
${item.price} ₽
- + + ${isAdmin ? ``: ''}
`) }) }) } - -addCards(); - \ No newline at end of file +const btn_add = document.querySelector("#add"); + +document.addEventListener("DOMContentLoaded", function() { + fetch('http://localhost:4444/auth/authorized', { + method: 'GET', + headers: { + 'Authorization': 'Bearer ' + localStorage.getItem('authToken'), + 'Content-Type': 'application/json' + } + }) + .then(res => res.json()) + .then(data => { + if (data.message === true) { + isAdmin = true; + btn_add.parentElement.classList.remove('hide'); + } + addCards(); + }) +}) + diff --git a/main/_front/src/js/elems/add-edit.js b/main/_front/src/js/elems/add-edit.js deleted file mode 100644 index abe6c29..0000000 --- a/main/_front/src/js/elems/add-edit.js +++ /dev/null @@ -1,118 +0,0 @@ -const choiceLists = document.querySelectorAll(".choice"); - -choiceLists.forEach((choiceList) => { - const choiceItems = choiceList.querySelectorAll(".choice__elem"); - choiceItems.forEach((choice) => { - if (choice.classList.contains("active")) { - choiceList.dataset.value = choice.dataset.value; - // console.log(choice.dataset.value); - } - choice.addEventListener("click", (e) => { - choiceItems.forEach((choice) => { - if (choice === e.target) { - choiceList.dataset.value = choice.dataset.value; - choice.classList.add("active"); - console.log(choice.dataset.value); - }else { - choice.classList.remove("active"); - } - }); - }); - }); -}) - -const steppers = document.querySelectorAll('.stepper'); -const checkMinDisabled = (element) => { - return Number(element.textContent) <= 1; -} -const checkMaxDisabled = (element, maxValue) => { - return Number(element.textContent) >= Number(maxValue); -} -const writeDataValue = (element, value) => { - element.dataset.value = value; -} - -steppers.forEach(stepper => { - - - const minus_btn = stepper.querySelector('.stepper__minus'); - const plus_btn = stepper.querySelector('.stepper__plus'); - const value = stepper.querySelector('.stepper__value'); - if (value.textContent) writeDataValue(stepper, value.textContent); - - const max = stepper.dataset.max; - - if (checkMinDisabled(value)){ - minus_btn.disabled = true; - value.textContent = "1"; - } - if (checkMaxDisabled(value, max)){ - plus_btn.disabled = true; - value.textContent = max; - } - - minus_btn.addEventListener('click', (e) => { - let count = Number(value.textContent); - if (count > 1) { - count--; - value.textContent = count; - plus_btn.disabled = false; - writeDataValue(stepper, value.textContent); - if (checkMinDisabled(value)){ - minus_btn.disabled = true; - value.textContent = "1"; - } - } - }) - - plus_btn.addEventListener('click', (e) => { - let count = Number(value.textContent); - if (count < max) { - count++; - value.textContent = count; - minus_btn.disabled = false; - writeDataValue(stepper, value.textContent); - if (checkMaxDisabled(value, max)){ - plus_btn.disabled = true; - value.textContent = max; - } - } - }) -}) - -// Начало файла, считай (все выше - скопировано из других для удобства разработки) - -const input_property_name = document.querySelector("#property_name>input"); -const input_property_value = document.querySelector("#property_value>input"); - -const properties_list = document.querySelector("#properties_list") - -const handleDelete = (e) => { - e.currentTarget.parentElement.remove(); -} - -const property_btn = document.querySelector("#property_btn"); -property_btn.addEventListener('click', (e) => { - const name = input_property_name.value; - const value = input_property_value.value; - if (name !== "" && value !== "") { - properties_list.insertAdjacentHTML('beforeend', ` -
-
-
${name}
-
${value}
-
- -
- `) - properties_list.querySelectorAll(".property .property__btn").forEach(button => { - button.removeEventListener("click", handleDelete); - button.addEventListener("click", handleDelete); - }) - input_property_name.value = ""; - input_property_value.value = ""; - } -}) - diff --git a/main/_front/src/js/login.js b/main/_front/src/js/login.js index b5e7abd..cb4d0bf 100644 --- a/main/_front/src/js/login.js +++ b/main/_front/src/js/login.js @@ -1,9 +1,57 @@ -// const login = document.querySelector('#login input'); -// const password = document.querySelector('#password input'); -// -// const btn_submit = document.querySelector('#submit'); -// btn_submit.addEventListener('click', (e) => { -// fetch( 'http://localhost:5000/auth/login', { -// -// }) -// }) \ No newline at end of file +const login = document.querySelector('#login input'); +const password = document.querySelector('#password input'); + +const title = document.querySelector('#title'); +const btn_submit = document.querySelector('#submit'); +const btn_logout = document.querySelector('#logout'); +const form_not_true = document.querySelector('#form-not-true'); + +btn_submit.addEventListener('click', (e) => { + if (login.value !== "" && password.value !== "") { + fetch('http://localhost:4444/auth/login', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + "login": String(login.value), + "password": String(password.value) + }) + }) + .then(res => res.json()) + .then(data => { + console.log(data); + if (data.token){ + localStorage.setItem('authToken', data.token); + window.location.href = '/' + }else { + form_not_true.classList.remove('hide'); + } + }) + } +}) + +document.addEventListener("DOMContentLoaded", function() { + fetch('http://localhost:4444/auth/authorized', { + method: 'GET', + headers: { + 'Authorization': 'Bearer ' + localStorage.getItem('authToken'), + 'Content-Type': 'application/json' + } + }) + .then(res => res.json()) + .then(data => { + if (data.message === true) { + title.textContent = "Вы уже вошли в панель администратора" + login.parentElement.classList.add('hide'); + password.parentElement.classList.add('hide'); + btn_submit.classList.add('hide'); + btn_logout.classList.remove('hide'); + btn_logout.addEventListener('click', (e) => { + localStorage.removeItem('authToken'); + window.location.reload() + }) + } + document.querySelector('.form').classList.remove('hide'); + }) +}) \ No newline at end of file diff --git a/main/_front/src/scss/_base.scss b/main/_front/src/scss/_base.scss index 424c7e7..5c0141b 100644 --- a/main/_front/src/scss/_base.scss +++ b/main/_front/src/scss/_base.scss @@ -15,3 +15,7 @@ body { background-color: #F8F8F8; border-radius: 10px; } + +.hide { + display: none !important; +} \ No newline at end of file diff --git a/main/_front/src/scss/blocks/_form.scss b/main/_front/src/scss/blocks/_form.scss index a95311f..5c64782 100644 --- a/main/_front/src/scss/blocks/_form.scss +++ b/main/_front/src/scss/blocks/_form.scss @@ -23,4 +23,10 @@ .form__input { width: 100%; +} + +.form__not_true { + color: #DC3545; + font-size: 18px; + font-weight: 500; } \ No newline at end of file diff --git a/main/_front/src/scss/elems/_btn.scss b/main/_front/src/scss/elems/_btn.scss index 07186a8..5c60a15 100644 --- a/main/_front/src/scss/elems/_btn.scss +++ b/main/_front/src/scss/elems/_btn.scss @@ -5,13 +5,14 @@ background: $primary; font-size: 18px; line-height: 21px; - color: white; + color: #fff; font-weight: bold; text-decoration: none; border-radius: 8px; min-width: 190px; border: 1px solid $primary; padding: 12px; + text-align: center; transition: background-color 0.2s ease, color 0.2s ease, opacity 0.2s ease; &-big { min-width: 275px; @@ -25,8 +26,20 @@ &:disabled { background: $primary; - color: white; + color: #fff; opacity: 0.4; cursor: not-allowed; } + &-red { + background-color: #DC3545; + border: 1px solid #DC3545; + &:hover { + background-color: #fff; + color: #DC3545; + } + &:disabled { + background-color: #DC3545; + color: #fff; + } + } } \ No newline at end of file diff --git a/main/controllers/AdminController.js b/main/controllers/AdminController.js index 97aa1ac..c825858 100644 --- a/main/controllers/AdminController.js +++ b/main/controllers/AdminController.js @@ -73,4 +73,3 @@ export const login = async (req, res) => { }) } } - diff --git a/main/index.js b/main/index.js index 88350e8..44f5170 100644 --- a/main/index.js +++ b/main/index.js @@ -36,16 +36,22 @@ app.get('/login', (req, res) => { res.sendFile(path.join(__dirname + `/_front/${folder}/login.html`)); }); +app.get('/add-edit', (req, res) => { + res.sendFile(path.join(__dirname + `/_front/${folder}/add-edit.html`)) +}) + app.post('/auth/register', register); app.post('/auth/login', login); - - app.post('/components', checkAuth, addComponent) app.get('/components', getAll) app.get('/components/:id', getOne); - +app.get('/auth/authorized', checkAuth, (req, res) => { + res.json({ + message: true + }) +}); app.listen(PORT, (err) => { if (err) { diff --git a/main/utils/checkAuth.js b/main/utils/checkAuth.js index 7f00c0c..04c50ec 100644 --- a/main/utils/checkAuth.js +++ b/main/utils/checkAuth.js @@ -7,7 +7,7 @@ export default (req, res, next) => { if (token){ try { const decoded = jwt.verify(token, 'secret2314'); - // req.adminId = decoded.id; + req.adminId = decoded.id; next(); } catch (err) { return res.status(403).json({ From 3b9a5f1973b9e2ae9be5a0a7003c53a8df66b2f1 Mon Sep 17 00:00:00 2001 From: necitboss Date: Mon, 11 Nov 2024 19:24:15 +0300 Subject: [PATCH 2/3] fix bugs --- main/_front/src/js/login.js | 2 +- main/controllers/AdminController.js | 14 +++++++++++--- main/index.js | 2 +- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/main/_front/src/js/login.js b/main/_front/src/js/login.js index cb4d0bf..5f3f944 100644 --- a/main/_front/src/js/login.js +++ b/main/_front/src/js/login.js @@ -41,7 +41,7 @@ document.addEventListener("DOMContentLoaded", function() { }) .then(res => res.json()) .then(data => { - if (data.message === true) { + if (data.message === "Вы авторизованы") { title.textContent = "Вы уже вошли в панель администратора" login.parentElement.classList.add('hide'); password.parentElement.classList.add('hide'); diff --git a/main/controllers/AdminController.js b/main/controllers/AdminController.js index c825858..2d315d3 100644 --- a/main/controllers/AdminController.js +++ b/main/controllers/AdminController.js @@ -14,7 +14,6 @@ export const register = async (req, res) => { passwordHash: hash }) const admin = await doc.save(); - console.log("here1") const token = jwt.sign({ _id: admin._id, }, @@ -23,10 +22,8 @@ export const register = async (req, res) => { expiresIn: '30d', } ); - console.log("here2") const {passwordHash, ...AdminData} = admin._doc; - console.log("here3") res.json({ ...AdminData, token @@ -41,6 +38,17 @@ export const register = async (req, res) => { export const login = async (req, res) => { try { const msg = "Неверный логин или пароль"; + if (!AdminModel.find()[0]) { + const password = "12345"; + const salt = await bcrypt.genSalt(10); + const hash = await bcrypt.hash(password, salt); + + const doc = new AdminModel({ + login: "admin", + passwordHash: hash + }) + await doc.save(); + } const admin = await AdminModel.findOne({login: req.body.login}); if (!admin) { return res.status(404).json({ diff --git a/main/index.js b/main/index.js index 44f5170..4a3a9e2 100644 --- a/main/index.js +++ b/main/index.js @@ -49,7 +49,7 @@ app.get('/components', getAll) app.get('/components/:id', getOne); app.get('/auth/authorized', checkAuth, (req, res) => { res.json({ - message: true + message: "Вы авторизованы" }) }); From 7510471968a3a1ed0ebfd3b99f6cdfb138553ab6 Mon Sep 17 00:00:00 2001 From: necitboss Date: Mon, 11 Nov 2024 19:32:16 +0300 Subject: [PATCH 3/3] switch to production mode --- main/_front/dist/add-edit.html | 26 ++- main/_front/dist/components-admin.html | 4 +- main/_front/dist/components.html | 10 +- main/_front/dist/css/style.css | 27 ++- main/_front/dist/index.html | 15 -- main/_front/dist/js/add-edit.js | 249 +++++++++++++++++++++++++ main/_front/dist/js/components.js | 30 ++- main/_front/dist/js/elems/add-edit.js | 118 ------------ main/_front/dist/js/login.js | 57 ++++++ main/_front/dist/login.html | 18 +- main/_front/gulpfile.js | 4 +- main/_front/src/js/login.js | 2 +- main/index.js | 5 +- 13 files changed, 393 insertions(+), 172 deletions(-) delete mode 100644 main/_front/dist/index.html create mode 100644 main/_front/dist/js/add-edit.js delete mode 100644 main/_front/dist/js/elems/add-edit.js create mode 100644 main/_front/dist/js/login.js diff --git a/main/_front/dist/add-edit.html b/main/_front/dist/add-edit.html index b0dad57..496c7ab 100644 --- a/main/_front/dist/add-edit.html +++ b/main/_front/dist/add-edit.html @@ -20,7 +20,7 @@

Пора Cобрать ПК

- Комплектующие + Комплектующие Конфигуратор Готовые сборки @@ -41,7 +41,7 @@

Пора Cобрать ПК

- + Добавление/Редактирование

Выберите
тип продукта

-
+
- +
-
Выберите обязательные поля
-
-
+
Выберите обязательные поля
+
+
Сокет (разъем на плате)
@@ -258,16 +258,14 @@

Количество:

-
+
Количество слотов ОЗУ
- - -
+
Тип памяти
diff --git a/main/_front/dist/components-admin.html b/main/_front/dist/components-admin.html index dbf1033..5fb1bb3 100644 --- a/main/_front/dist/components-admin.html +++ b/main/_front/dist/components-admin.html @@ -21,7 +21,7 @@

Пора Cобрать ПК

diff --git a/main/_front/dist/css/style.css b/main/_front/dist/css/style.css index 8c4ba2f..ffb8dce 100644 --- a/main/_front/dist/css/style.css +++ b/main/_front/dist/css/style.css @@ -103,18 +103,23 @@ body { border-radius: 10px; } +.hide { + display: none !important; +} + .btn { display: inline-block; background: #712CF9; font-size: 18px; line-height: 21px; - color: white; + color: #fff; font-weight: bold; text-decoration: none; border-radius: 8px; min-width: 190px; border: 1px solid #712CF9; padding: 12px; + text-align: center; transition: background-color 0.2s ease, color 0.2s ease, opacity 0.2s ease; } .btn-big { @@ -128,10 +133,22 @@ body { } .btn:disabled { background: #712CF9; - color: white; + color: #fff; opacity: 0.4; cursor: not-allowed; } +.btn-red { + background-color: #DC3545; + border: 1px solid #DC3545; +} +.btn-red:hover { + background-color: #fff; + color: #DC3545; +} +.btn-red:disabled { + background-color: #DC3545; + color: #fff; +} .checkbox-group { display: flex; @@ -643,6 +660,12 @@ body { width: 100%; } +.form__not_true { + color: #DC3545; + font-size: 18px; + font-weight: 500; +} + .section { margin-top: 30px; } diff --git a/main/_front/dist/index.html b/main/_front/dist/index.html deleted file mode 100644 index a36cc85..0000000 --- a/main/_front/dist/index.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - Document - - - - -

Hello, world!

- - \ No newline at end of file diff --git a/main/_front/dist/js/add-edit.js b/main/_front/dist/js/add-edit.js new file mode 100644 index 0000000..fa8495d --- /dev/null +++ b/main/_front/dist/js/add-edit.js @@ -0,0 +1,249 @@ +const main_properties_tilte = document.querySelector("#main_properties_title"); +const name = document.querySelector('#name input'); +const price = document.querySelector('#price input'); +const count = document.querySelector('#count .stepper__value'); +const type = document.querySelector('#type'); +const main_properties = document.querySelector('#main_properties'); +const other_properties = document.querySelector('#properties_list'); +const btn_submit = document.querySelector('#submit'); +const socket = document.querySelector('#socket'); +const ram_count= document.querySelector('#ram_count'); +const ram_type = document.querySelector('#ram_type'); + +const choiceLists = document.querySelectorAll(".choice"); + +choiceLists.forEach((choiceList) => { + const isType = choiceList.id === "type"; + const choiceItems = choiceList.querySelectorAll(".choice__elem"); + choiceItems.forEach((choice) => { + if (choice.classList.contains("active")) { + choiceList.dataset.value = choice.dataset.value; + // console.log(choice.dataset.value); + } + choice.addEventListener("click", (e) => { + choiceItems.forEach((choice) => { + if (choice === e.target) { + choiceList.dataset.value = choice.dataset.value; + choice.classList.add("active"); + // console.log(choice.dataset.value); + }else { + choice.classList.remove("active"); + } + }); + if (isType){ + if (choiceList.dataset.value === "cpu") { + main_properties_tilte.classList.remove('hide'); + socket.classList.remove('hide'); + ram_count.classList.add('hide'); + ram_type.classList.add('hide'); + }else if (choiceList.dataset.value === "motherboard"){ + main_properties_tilte.classList.remove('hide'); + socket.classList.remove('hide'); + ram_count.classList.remove('hide'); + ram_type.classList.remove('hide'); + }else if (choiceList.dataset.value === "ram"){ + main_properties_tilte.classList.remove('hide'); + socket.classList.add('hide'); + ram_count.classList.add('hide'); + ram_type.classList.remove('hide'); + }else { + main_properties_tilte.classList.add('hide'); + socket.classList.add('hide'); + ram_count.classList.add('hide'); + ram_type.classList.add('hide'); + } + } + }); + }); + if (isType){ + if (choiceList.dataset.value === "cpu") { + main_properties_tilte.classList.remove('hide'); + socket.classList.remove('hide'); + ram_count.classList.add('hide'); + ram_type.classList.add('hide'); + }else if (choiceList.dataset.value === "motherboard"){ + main_properties_tilte.classList.remove('hide'); + socket.classList.remove('hide'); + ram_count.classList.remove('hide'); + ram_type.classList.remove('hide'); + }else if (choiceList.dataset.value === "ram"){ + main_properties_tilte.classList.remove('hide'); + socket.classList.add('hide'); + ram_count.classList.add('hide'); + ram_type.classList.remove('hide'); + }else { + main_properties_tilte.classList.add('hide'); + socket.classList.add('hide'); + ram_count.classList.add('hide'); + ram_type.classList.add('hide'); + } + } +}) + +const steppers = document.querySelectorAll('.stepper'); +const checkMinDisabled = (element) => { + return Number(element.textContent) <= 1; +} +const checkMaxDisabled = (element, maxValue) => { + return Number(element.textContent) >= Number(maxValue); +} +const writeDataValue = (element, value) => { + element.dataset.value = value; +} + +steppers.forEach(stepper => { + + + const minus_btn = stepper.querySelector('.stepper__minus'); + const plus_btn = stepper.querySelector('.stepper__plus'); + const value = stepper.querySelector('.stepper__value'); + if (value.textContent) writeDataValue(stepper, value.textContent); + + const max = stepper.dataset.max; + + if (checkMinDisabled(value)){ + minus_btn.disabled = true; + value.textContent = "1"; + } + if (checkMaxDisabled(value, max)){ + plus_btn.disabled = true; + value.textContent = max; + } + + minus_btn.addEventListener('click', (e) => { + let count = Number(value.textContent); + if (count > 1) { + count--; + value.textContent = count; + plus_btn.disabled = false; + writeDataValue(stepper, value.textContent); + if (checkMinDisabled(value)){ + minus_btn.disabled = true; + value.textContent = "1"; + } + } + }) + + plus_btn.addEventListener('click', (e) => { + let count = Number(value.textContent); + if (count < max) { + count++; + value.textContent = count; + minus_btn.disabled = false; + writeDataValue(stepper, value.textContent); + if (checkMaxDisabled(value, max)){ + plus_btn.disabled = true; + value.textContent = max; + } + } + }) +}) + +// Начало файла, считай (все выше - скопировано из других для удобства разработки) + +const input_property_name = document.querySelector("#property_name>input"); +const input_property_value = document.querySelector("#property_value>input"); + +const properties_list = document.querySelector("#properties_list") + +const handleDelete = (e) => { + e.currentTarget.parentElement.remove(); +} + +const property_btn = document.querySelector("#property_btn"); +property_btn.addEventListener('click', (e) => { + const input_name = input_property_name.value; + const input_value = input_property_value.value; + if (input_name !== "" && input_value !== "") { + properties_list.insertAdjacentHTML('beforeend', ` +
+
+
${input_name}
+
${input_value}
+
+ +
+ `) + properties_list.querySelectorAll(".property .property__btn").forEach(button => { + button.removeEventListener("click", handleDelete); + button.addEventListener("click", handleDelete); + }) + input_property_name.value = ""; + input_property_value.value = ""; + } +}) + +document.addEventListener("DOMContentLoaded", function() { + fetch('http://localhost:4444/auth/authorized', { + method: 'GET', + headers: { + 'Authorization': 'Bearer ' + localStorage.getItem('authToken'), + 'Content-Type': 'application/json' + } + }) + .then(res => res.json()) + .then(data => { + if (data.message === true) { + + }else { + window.location.href = 'login' + } + }) +}) + + + +btn_submit.addEventListener('click', (e) => { + // console.log(name.value); + // console.log(price.value); + // console.log(Number(count.textContent)); + // console.log(type.dataset.value); + // console.log(main_properties); + // console.log(); + let otherPropertiesArray = [] + other_properties.querySelectorAll(".property").forEach(property => { + // console.log(property); + otherPropertiesArray.push({ + name: property.querySelector(".property__name").textContent, + value: property.querySelector(".property__value").textContent, + }) + }) + let mainPropertiesArray = [] + main_properties.querySelectorAll(".add-right__choice").forEach(property => { + if (property.classList.contains('hide')){ + return; + } + mainPropertiesArray.push({ + name: property.querySelector(".add-right__choice-title").textContent, + value: property.querySelector(".choice").dataset.value + }) + }) + // console.log(mainPropertiesArray); + // console.log(otherPropertiesArray); + const object = { + name: name.value, + type: type.dataset.value, + price: price.value, + count: Number(count.textContent), + main_properties: mainPropertiesArray, + other_properties: otherPropertiesArray + } + if (name.value !== "" && type.dataset.value !== "" && String(price.value)!== "" && count.textContent!== ""){ + fetch('http://localhost:4444/components', { + method: 'POST', + headers: { + 'Authorization': 'Bearer ' + localStorage.getItem('authToken'), + 'Content-Type': 'application/json' + }, + body: JSON.stringify(object) + }) + .then(res => res.json()) + .then(data => { + if (!data.message){ + window.location.href = '/' + } + }) + } +}) \ No newline at end of file diff --git a/main/_front/dist/js/components.js b/main/_front/dist/js/components.js index 55a5f23..6457d39 100644 --- a/main/_front/dist/js/components.js +++ b/main/_front/dist/js/components.js @@ -22,7 +22,9 @@ choiceLists.forEach((choiceList) => { }) const cards_place = document.querySelector("#cards_place"); - + +let isAdmin = false; + const addCards = () => { fetch("http://localhost:4444/components") .then(res => res.json()) @@ -34,13 +36,31 @@ const addCards = () => {
${item.name}
${item.price} ₽
- + + ${isAdmin ? ``: ''}
`) }) }) } - -addCards(); - \ No newline at end of file +const btn_add = document.querySelector("#add"); + +document.addEventListener("DOMContentLoaded", function() { + fetch('http://localhost:4444/auth/authorized', { + method: 'GET', + headers: { + 'Authorization': 'Bearer ' + localStorage.getItem('authToken'), + 'Content-Type': 'application/json' + } + }) + .then(res => res.json()) + .then(data => { + if (data.message === true) { + isAdmin = true; + btn_add.parentElement.classList.remove('hide'); + } + addCards(); + }) +}) + diff --git a/main/_front/dist/js/elems/add-edit.js b/main/_front/dist/js/elems/add-edit.js deleted file mode 100644 index abe6c29..0000000 --- a/main/_front/dist/js/elems/add-edit.js +++ /dev/null @@ -1,118 +0,0 @@ -const choiceLists = document.querySelectorAll(".choice"); - -choiceLists.forEach((choiceList) => { - const choiceItems = choiceList.querySelectorAll(".choice__elem"); - choiceItems.forEach((choice) => { - if (choice.classList.contains("active")) { - choiceList.dataset.value = choice.dataset.value; - // console.log(choice.dataset.value); - } - choice.addEventListener("click", (e) => { - choiceItems.forEach((choice) => { - if (choice === e.target) { - choiceList.dataset.value = choice.dataset.value; - choice.classList.add("active"); - console.log(choice.dataset.value); - }else { - choice.classList.remove("active"); - } - }); - }); - }); -}) - -const steppers = document.querySelectorAll('.stepper'); -const checkMinDisabled = (element) => { - return Number(element.textContent) <= 1; -} -const checkMaxDisabled = (element, maxValue) => { - return Number(element.textContent) >= Number(maxValue); -} -const writeDataValue = (element, value) => { - element.dataset.value = value; -} - -steppers.forEach(stepper => { - - - const minus_btn = stepper.querySelector('.stepper__minus'); - const plus_btn = stepper.querySelector('.stepper__plus'); - const value = stepper.querySelector('.stepper__value'); - if (value.textContent) writeDataValue(stepper, value.textContent); - - const max = stepper.dataset.max; - - if (checkMinDisabled(value)){ - minus_btn.disabled = true; - value.textContent = "1"; - } - if (checkMaxDisabled(value, max)){ - plus_btn.disabled = true; - value.textContent = max; - } - - minus_btn.addEventListener('click', (e) => { - let count = Number(value.textContent); - if (count > 1) { - count--; - value.textContent = count; - plus_btn.disabled = false; - writeDataValue(stepper, value.textContent); - if (checkMinDisabled(value)){ - minus_btn.disabled = true; - value.textContent = "1"; - } - } - }) - - plus_btn.addEventListener('click', (e) => { - let count = Number(value.textContent); - if (count < max) { - count++; - value.textContent = count; - minus_btn.disabled = false; - writeDataValue(stepper, value.textContent); - if (checkMaxDisabled(value, max)){ - plus_btn.disabled = true; - value.textContent = max; - } - } - }) -}) - -// Начало файла, считай (все выше - скопировано из других для удобства разработки) - -const input_property_name = document.querySelector("#property_name>input"); -const input_property_value = document.querySelector("#property_value>input"); - -const properties_list = document.querySelector("#properties_list") - -const handleDelete = (e) => { - e.currentTarget.parentElement.remove(); -} - -const property_btn = document.querySelector("#property_btn"); -property_btn.addEventListener('click', (e) => { - const name = input_property_name.value; - const value = input_property_value.value; - if (name !== "" && value !== "") { - properties_list.insertAdjacentHTML('beforeend', ` -
-
-
${name}
-
${value}
-
- -
- `) - properties_list.querySelectorAll(".property .property__btn").forEach(button => { - button.removeEventListener("click", handleDelete); - button.addEventListener("click", handleDelete); - }) - input_property_name.value = ""; - input_property_value.value = ""; - } -}) - diff --git a/main/_front/dist/js/login.js b/main/_front/dist/js/login.js new file mode 100644 index 0000000..cb4d0bf --- /dev/null +++ b/main/_front/dist/js/login.js @@ -0,0 +1,57 @@ +const login = document.querySelector('#login input'); +const password = document.querySelector('#password input'); + +const title = document.querySelector('#title'); +const btn_submit = document.querySelector('#submit'); +const btn_logout = document.querySelector('#logout'); +const form_not_true = document.querySelector('#form-not-true'); + +btn_submit.addEventListener('click', (e) => { + if (login.value !== "" && password.value !== "") { + fetch('http://localhost:4444/auth/login', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + "login": String(login.value), + "password": String(password.value) + }) + }) + .then(res => res.json()) + .then(data => { + console.log(data); + if (data.token){ + localStorage.setItem('authToken', data.token); + window.location.href = '/' + }else { + form_not_true.classList.remove('hide'); + } + }) + } +}) + +document.addEventListener("DOMContentLoaded", function() { + fetch('http://localhost:4444/auth/authorized', { + method: 'GET', + headers: { + 'Authorization': 'Bearer ' + localStorage.getItem('authToken'), + 'Content-Type': 'application/json' + } + }) + .then(res => res.json()) + .then(data => { + if (data.message === true) { + title.textContent = "Вы уже вошли в панель администратора" + login.parentElement.classList.add('hide'); + password.parentElement.classList.add('hide'); + btn_submit.classList.add('hide'); + btn_logout.classList.remove('hide'); + btn_logout.addEventListener('click', (e) => { + localStorage.removeItem('authToken'); + window.location.reload() + }) + } + document.querySelector('.form').classList.remove('hide'); + }) +}) \ No newline at end of file diff --git a/main/_front/dist/login.html b/main/_front/dist/login.html index af08e29..6a50c19 100644 --- a/main/_front/dist/login.html +++ b/main/_front/dist/login.html @@ -8,6 +8,8 @@ Document + + @@ -19,7 +21,7 @@

Пора Cобрать ПК

-
+
-

Вход

-
+

Вход

+
Почта
-
+
Пароль
- +
Неверный логин или пароль
+ +
diff --git a/main/_front/gulpfile.js b/main/_front/gulpfile.js index 0a0514b..5a80285 100644 --- a/main/_front/gulpfile.js +++ b/main/_front/gulpfile.js @@ -11,7 +11,7 @@ import sassGlob from 'gulp-sass-glob'; import newer from "gulp-newer"; import {deleteAsync} from "del"; -const isProduction = false; +const isProduction = true; const publicPath = isProduction? "dist/" : "_public/"; @@ -62,7 +62,7 @@ export const js = () => { } export const clear = () => { - return deleteAsync("./_public"); + return deleteAsync(isProduction ? "dist" : "./_public"); } export const img = () => { diff --git a/main/_front/src/js/login.js b/main/_front/src/js/login.js index 5f3f944..cb4d0bf 100644 --- a/main/_front/src/js/login.js +++ b/main/_front/src/js/login.js @@ -41,7 +41,7 @@ document.addEventListener("DOMContentLoaded", function() { }) .then(res => res.json()) .then(data => { - if (data.message === "Вы авторизованы") { + if (data.message === true) { title.textContent = "Вы уже вошли в панель администратора" login.parentElement.classList.add('hide'); password.parentElement.classList.add('hide'); diff --git a/main/index.js b/main/index.js index 4a3a9e2..235d1eb 100644 --- a/main/index.js +++ b/main/index.js @@ -7,7 +7,7 @@ import {addComponent, getAll, getOne} from "./controllers/ComponentsController.j import path from 'path'; const app = express(); -const isProduction = false; +const isProduction = true; const folder = isProduction? "dist": "_public"; const PORT = 4444; @@ -28,7 +28,6 @@ app.use(express.static(__dirname + `/_front/${folder}`)); app.get('/', (req, res) => { - console.log(path.join(__dirname + `/_front/${folder}/components.html`)); res.sendFile(path.join(__dirname + `/_front/${folder}/components.html`)); }); @@ -49,7 +48,7 @@ app.get('/components', getAll) app.get('/components/:id', getOne); app.get('/auth/authorized', checkAuth, (req, res) => { res.json({ - message: "Вы авторизованы" + message: true }) });