21.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514
  1. const delay = (ms) => new Promise((res) => setTimeout(() => res(ms), ms));
  2. //localStorage.removeItem("authToken");
  3. const urlConst = "http://shop-roles.asmer.fs.a-level.com.ua";
  4. goLogin.onclick = () => (loginForm.style.display = "");
  5. goLogoff.onclick = () => {
  6. localStorage.removeItem("authToken");
  7. checkAuthToken();
  8. };
  9. const checkAuthToken = function () {
  10. registrationForm.style.display = "none";
  11. loginForm.style.display = "none";
  12. forImage.style.display = "none";
  13. forBasket.style.display = "none";
  14. basketLogo.style.display = "none";
  15. goLogin.style.display = "";
  16. goRegistration.style.display = "";
  17. goLogoff.style.display = "none";
  18. if (localStorage.authToken) {
  19. goLogin.style.display = "none";
  20. goRegistration.style.display = "none";
  21. goLogoff.style.display = "";
  22. basketLogo.style.display = "";
  23. setBasketBtnOn();
  24. return true;
  25. }
  26. setBasketBtnOff();
  27. return false;
  28. };
  29. window.onload = checkAuthToken;
  30. const setBasketBtnOff = function () {
  31. document.querySelectorAll(".putInBasketBtn").forEach((el) => el.setAttribute("disabled", "disabled"));
  32. };
  33. const setBasketBtnOn = function () {
  34. document.querySelectorAll(".putInBasketBtn").forEach((el) => el.removeAttribute("disabled"));
  35. };
  36. const getGQL = (url) => (query, variables = {}) => {
  37. return fetch(url, {
  38. method: "POST",
  39. headers: {
  40. Accept: "application/json",
  41. "Content-Type": "application/json",
  42. ...(localStorage.authToken ? { Authorization: `Bearer ${localStorage.authToken}` } : {}),
  43. },
  44. body: JSON.stringify({ query, variables }),
  45. })
  46. .then((res) => res.json())
  47. .catch((err) => console.log(err));
  48. };
  49. const gql = getGQL(urlConst + `/graphql`);
  50. async function categories(parentEl = leftSide, parentID = null) {
  51. let result = await gql(
  52. `query categories ($query:String){
  53. CategoryFind(query:$query){
  54. _id
  55. name
  56. }
  57. }`,
  58. { query: JSON.stringify([{ "parent._id": parentID }, { sort: [{ name: 1 }] }]) }
  59. );
  60. // console.log(result);
  61. if (result.errors) return;
  62. let ul = document.createElement("ul");
  63. parentEl.append(ul);
  64. for (let { name, _id } of result.data.CategoryFind) {
  65. let li = document.createElement("li");
  66. li.innerText = name;
  67. li.style.fontWeight = "";
  68. let loaded;
  69. li.onclick = (event) => {
  70. if (event) event.stopPropagation();
  71. li.parentElement.parentElement.style.fontWeight = "";
  72. [].forEach.call(li.parentElement.children, (el) => (el.style.fontWeight = ""));
  73. li.style.fontWeight = "700";
  74. if (!loaded) {
  75. categories(li, _id);
  76. loaded = true;
  77. } else {
  78. loaded = false;
  79. [].forEach.call(li.children, (el) => el.remove());
  80. }
  81. mainBlock.innerText = "";
  82. categoryTitle.innerText = "";
  83. subMenu.innerText = "";
  84. showAllInCategory(_id, name);
  85. };
  86. ul.append(li);
  87. let span = document.createElement("span");
  88. span.innerText = name;
  89. subMenu.append(span);
  90. span.onclick = () => {
  91. li.onclick();
  92. };
  93. }
  94. }
  95. categories();
  96. function showAllInCategory(_id, name) {
  97. let h = document.createElement("h1");
  98. h.append(name);
  99. categoryTitle.append(h);
  100. categoryTitle.append(`_${_id} - id категории`);
  101. showGoodsInCategory(mainBlock, _id);
  102. showAllGoodsInAllSubcategories(mainBlock, _id);
  103. }
  104. async function showGoodsInCategory(parentEl, _id) {
  105. let result = await gql(
  106. `query GoodsFromCatSort ($sort:String){
  107. GoodFind(query: $sort) {
  108. _id
  109. name
  110. description
  111. price
  112. images {
  113. _id
  114. createdAt
  115. text
  116. url
  117. originalFileName
  118. }
  119. }
  120. }`,
  121. { sort: JSON.stringify([{ "categories._id": _id }, { sort: [{ name: 1 }] }]) }
  122. );
  123. if (result.errors) return;
  124. for (let { name, _id, description, price, images } of result.data.GoodFind) {
  125. let shelfToker = document.createElement("div");
  126. shelfToker.classList.add("shelfToker");
  127. shelfToker.onclick = (e) => {
  128. e.stopPropagation();
  129. shelfToker.classList.add("shelfTokerBig");
  130. };
  131. parentEl.append(shelfToker);
  132. let h3 = document.createElement("h3");
  133. h3.append(name);
  134. shelfToker.append(h3);
  135. h3 = document.createElement("h3");
  136. h3.append("$ " + price);
  137. shelfToker.append(h3);
  138. let p = document.createElement("p");
  139. let h4 = document.createElement("h4");
  140. h4.append("Описание: ");
  141. p.append(h4);
  142. p.append(description);
  143. shelfToker.append(p);
  144. let divImg = document.createElement("div");
  145. divImg.classList.add("divImg");
  146. for (let img of images) {
  147. let divImgOne = document.createElement("div");
  148. divImgOne.classList.add("divImgOne");
  149. let imgNode = document.createElement("img");
  150. imgNode.src = urlConst + `/` + img.url;
  151. divImgOne.append(imgNode);
  152. divImg.append(divImgOne);
  153. let namberOfImg = 0;
  154. imgNode.onclick = (e) => {
  155. e.stopPropagation();
  156. forImage.style.display = "";
  157. forImgSrc.src = urlConst + `/` + images[namberOfImg].url;
  158. forImage.onclick = () => {
  159. forImgSrc.src = urlConst + `/` + images[namberOfImg++ % (images.lenght ? images.lenght : 1)].url;
  160. };
  161. let imgKeyEsc = (ev) => {
  162. if (ev.code === "Escape") {
  163. forImage.style.display = "none";
  164. window.removeEventListener("keydown", imgKeyEsc);
  165. }
  166. };
  167. window.addEventListener("keydown", imgKeyEsc);
  168. };
  169. }
  170. shelfToker.append(divImg);
  171. let count = document.createElement("input");
  172. count.setAttribute("type", "number");
  173. count.setAttribute("min", "1");
  174. count.setAttribute("placeholder", "1");
  175. count.value = "1";
  176. count.onclick = (e) => {
  177. e.stopPropagation();
  178. };
  179. shelfToker.append(count);
  180. let putInBasketBtn = document.createElement("button");
  181. putInBasketBtn.append("Добавить в корзину");
  182. putInBasketBtn.classList.add("putInBasketBtn");
  183. if (!localStorage.authToken) putInBasketBtn.setAttribute("disabled", "disabled");
  184. putInBasketBtn.onclick = (e) => {
  185. e.stopPropagation();
  186. addToBasket(_id, count.value);
  187. };
  188. shelfToker.append(putInBasketBtn);
  189. shelfToker.insertAdjacentHTML("beforeEnd", `<div>${_id} - id товара</div>`);
  190. let shelfTokerExitBtn = document.createElement("button");
  191. shelfTokerExitBtn.classList.add("shelfTokerExitBtn");
  192. shelfTokerExitBtn.append("Вернуться назад");
  193. shelfTokerExitBtn.onclick = (e) => {
  194. e.stopPropagation();
  195. shelfToker.classList.remove("shelfTokerBig");
  196. };
  197. shelfToker.append(shelfTokerExitBtn);
  198. }
  199. }
  200. async function addToBasket(_idValue, countValue) {
  201. let result = await gql(
  202. `mutation newOrder1($order1:OrderInput) {
  203. OrderUpsert(order: $order1) {
  204. _id
  205. total
  206. }
  207. }`,
  208. { order1: { orderGoods: [{ count: +countValue, good: { _id: _idValue } }] } }
  209. );
  210. if (result.errors) {
  211. alert("Ошибка сервера при заказе");
  212. console.log(result.errors);
  213. return;
  214. }
  215. // console.log(result);
  216. alert(`Поздравляем с успешным заказом на сумму $${result.data.OrderUpsert.total}`);
  217. }
  218. async function showAllGoodsInAllSubcategories(parentEl, catId) {
  219. let result = await gql(
  220. `query subCategories ($subcat:String){
  221. CategoryFind(query: $subcat) {
  222. name
  223. _id
  224. }
  225. }`,
  226. { subcat: JSON.stringify([{ "parent._id": catId }, { sort: [{ name: 1 }] }]) }
  227. );
  228. if (result.errors) return;
  229. for (let { _id } of result.data.CategoryFind) {
  230. showGoodsInCategory(parentEl, _id);
  231. showAllGoodsInAllSubcategories(parentEl, _id);
  232. }
  233. }
  234. function CreateInputField(parentNode, hidden = false, isCheckNeed = false) {
  235. let inpEl = document.createElement("input");
  236. inpEl.setAttribute("type", hidden ? "password" : "text");
  237. inpEl.setAttribute("placeholder", hidden ? "Password" : "Login");
  238. inpEl.oninput = (isUser = true) => {
  239. if (isUser && this.onChange && typeof this.onChange === "function") {
  240. this.onChange(inpEl.value);
  241. }
  242. };
  243. parentNode.append(inpEl);
  244. let div = document.createElement("div");
  245. let checkBox = document.createElement("input");
  246. checkBox.setAttribute("type", "checkbox");
  247. div.append(checkBox);
  248. let seePassword = document.createElement("span");
  249. seePassword.append("Показать пароль");
  250. div.append(seePassword);
  251. checkBox.oninput = () => {
  252. if (checkBox.checked) {
  253. inpEl.setAttribute("type", "text");
  254. } else inpEl.setAttribute("type", "password");
  255. };
  256. inpEl.addEventListener("keydown", (e) => {
  257. if (["Enter", "NumpadEnter"].includes(e.code)) {
  258. this.onEnter();
  259. }
  260. });
  261. if (isCheckNeed) {
  262. parentNode.append(div);
  263. }
  264. this.getValue = function () {
  265. return inpEl.value;
  266. };
  267. this.getCheckStatus = function () {
  268. return checkBox.checked;
  269. };
  270. this.setValue = function (value = "") {
  271. inpEl.value = value;
  272. };
  273. this.setCheckBox = function (value = false) {
  274. checkBox.checked = value;
  275. };
  276. this.onChange = () => {};
  277. this.onEnter = () => {};
  278. }
  279. function CreateLoginForm(parentNode) {
  280. let loginField = new CreateInputField(parentNode);
  281. let passwordField = new CreateInputField(parentNode, true, true);
  282. let loginButton = document.createElement("button");
  283. loginButton.append("Войти");
  284. loginButton.setAttribute("disabled", "disabled");
  285. parentNode.append(loginButton);
  286. let canselButton = document.createElement("button");
  287. canselButton.append("Отмена");
  288. parentNode.append(canselButton);
  289. loginField.onChange = passwordField.onChange = () => {
  290. if (loginField.getValue() && passwordField.getValue()) {
  291. loginButton.removeAttribute("disabled");
  292. } else loginButton.setAttribute("disabled", "disabled");
  293. };
  294. loginField.onEnter = passwordField.onEnter = () => loginButton.onclick();
  295. canselButton.onclick = () => {
  296. this.clearAndClose();
  297. };
  298. loginButton.onclick = () => {
  299. if (this.submit && typeof this.submit === "function") {
  300. let loginInfo = {
  301. login: loginField.getValue(),
  302. password: passwordField.getValue(),
  303. };
  304. this.submit(loginInfo);
  305. }
  306. };
  307. this.submit = () => {};
  308. this.clearAndClose = function () {
  309. loginField.setValue();
  310. passwordField.setValue();
  311. passwordField.setCheckBox();
  312. parentNode.style.display = "none";
  313. };
  314. }
  315. let loginObject = new CreateLoginForm(loginForm);
  316. loginObject.submit = (loginInfo) => {
  317. loginToDB(loginInfo);
  318. };
  319. async function loginToDB({ login, password } = {}) {
  320. let result = await gql(
  321. `query login($login: String, $password: String) {
  322. login(login: $login, password: $password)
  323. }`,
  324. { login, password }
  325. );
  326. if (result.errors) {
  327. alert("Ошибка авторизации");
  328. return;
  329. }
  330. if (result.data.login) {
  331. localStorage.authToken = result.data.login;
  332. loginObject.clearAndClose();
  333. loginForm.style.display = "none";
  334. checkAuthToken();
  335. } else alert("Ошибка!\nВведите правильные логин и пароль.");
  336. }
  337. basketLogo.onclick = () => {
  338. showBasket(forBasket);
  339. };
  340. async function showBasket(parentNode) {
  341. let result = await gql(
  342. `query FindOrders($lookOrders2:String){
  343. OrderFind(query:$lookOrders2){
  344. total
  345. orderGoods{
  346. good{
  347. name
  348. images{
  349. url
  350. }
  351. }
  352. price
  353. count
  354. total
  355. }
  356. }
  357. }`,
  358. { lookOrders2: JSON.stringify([{}]) }
  359. // { lookOrders2: JSON.stringify([{}, { sort: [{ total: 1 }] }]) }
  360. // ++++++++++++++ а вот эта сортировка ну никак не работает...??? ++++++++++++++++++++++++++
  361. );
  362. if (result.errors) {
  363. alert("Ошибка сервера...");
  364. console.log(result.errors);
  365. return;
  366. }
  367. parentNode.style.display = "";
  368. // console.log(result);
  369. let masterTotal = 0;
  370. forBasket.innerHTML = "";
  371. result.data.OrderFind.forEach((order) => {
  372. let div1order = document.createElement("div");
  373. forBasket.append(div1order);
  374. showOrder(div1order, order);
  375. let h = document.createElement("h4");
  376. div1order.append(h);
  377. h.append(`Всего за заказ: $${order.total}`);
  378. masterTotal += order.total;
  379. });
  380. h = document.createElement("h2");
  381. forBasket.append(h);
  382. h.append(`ИТОГО: $${masterTotal}`);
  383. let exitBasketBtn = document.createElement("button");
  384. exitBasketBtn.append("Вернуться назад");
  385. forBasket.append(exitBasketBtn);
  386. exitBasketBtn.onclick = () => {
  387. forBasket.style.display = "none";
  388. };
  389. forBasket.scrollTop = 0;
  390. // forBasket.scrollBy(0, 0);
  391. //
  392. }
  393. const showOrder = function (parent, { orderGoods: orderArray, total: total1Order }) {
  394. //
  395. for (let { good, price, count, total: total1pozition } of orderArray) {
  396. let div = document.createElement("div");
  397. parent.append(div);
  398. let img = document.createElement("img");
  399. div.append(img);
  400. img.src = urlConst + `/` + good.images[0].url;
  401. let p = document.createElement("p");
  402. div.append(p);
  403. p.append(good.name);
  404. p = document.createElement("p");
  405. div.append(p);
  406. p.append(`Цена: $${price}`);
  407. p = document.createElement("p");
  408. div.append(p);
  409. p.append(`Кол-во: ${count}`);
  410. p = document.createElement("p");
  411. div.append(p);
  412. p.append(`Всего: $${total1pozition}`);
  413. }
  414. };