22.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772
  1. //
  2. // Корзина хранится в localstorage для всех пользователей.
  3. // Ключом для доступа к данным корзины конкретного пользователя служит его _id,
  4. // полученный из localStorage.authToken после авторизации.
  5. // Данные корзины для каждого пользователя сбрасываются только в момент покупки.
  6. // Наполнять корзину можно и анонимно. Но оформить этот заказ не получится.
  7. // В случае развития этого проекта можно организовать дополнительную логику для
  8. // анонимной корзины. Например: если после авторизации Ваша корзина из истории
  9. // оказалась пустой, то товары из анонимной корзины попадут в Вашу, но только в случае
  10. // если сессия не прерывалась.
  11. // Но мне кажется, что корзина должна быть организована на серверной стороне.
  12. //
  13. const delay = (ms) => new Promise((res) => setTimeout(() => res(ms), ms));
  14. // localStorage.removeItem("authToken");
  15. // "eyJzdWIiOnsibG9naW4iOiJfX2Fub255bW91c19fIn19"-- - {"sub":{"login": "__anonymous__"}}
  16. const urlConst = "http://shop-roles.asmer.fs.a-level.com.ua";
  17. const defaultLoginName = "__anonymous__";
  18. const defaultLoginId = "0";
  19. let loginName = defaultLoginName;
  20. let loginId = defaultLoginId;
  21. let basketObj = {};
  22. basketObj[defaultLoginId] = {};
  23. goLogin.onclick = () => {
  24. init();
  25. loginForm.style.display = "";
  26. };
  27. goLogoff.onclick = () => {
  28. localStorage.removeItem("authToken");
  29. loginName = defaultLoginName;
  30. init();
  31. };
  32. goRegistration.onclick = () => {
  33. init();
  34. registrationForm.style.display = "";
  35. };
  36. async function setLoginFromToken() {
  37. loginName = defaultLoginName;
  38. loginId = defaultLoginId;
  39. try {
  40. loginName = await JSON.parse(atob(localStorage.authToken.split(".")[1])).sub.login;
  41. loginId = await JSON.parse(atob(localStorage.authToken.split(".")[1])).sub.id;
  42. updateBasketObj();
  43. } catch (error) {
  44. console.log("Ошибка декодирования login из токена / либо пользователь разлогинился: ", error);
  45. }
  46. }
  47. const init = function () {
  48. if (!localStorage.basket) {
  49. localStorage.basket = JSON.stringify(basketObj);
  50. } else {
  51. basketObj = JSON.parse(localStorage.basket);
  52. }
  53. registrationForm.style.display = "none";
  54. loginForm.style.display = "none";
  55. forImage.style.display = "none";
  56. forBasket.style.display = "none";
  57. checkAuthToken();
  58. };
  59. async function checkAuthToken() {
  60. if (localStorage.authToken) {
  61. goLogin.style.display = "none";
  62. goRegistration.style.display = "none";
  63. goLogoff.style.display = "";
  64. historyDiv.style.display = "";
  65. nickNameDiv.style.display = "";
  66. await setLoginFromToken();
  67. nickNameSpan.innerHTML = loginName;
  68. return true;
  69. }
  70. goLogin.style.display = "";
  71. goRegistration.style.display = "";
  72. goLogoff.style.display = "none";
  73. historyDiv.style.display = "none";
  74. nickNameSpan.innerHTML = defaultLoginName;
  75. nickNameDiv.style.display = "none";
  76. setLoginFromToken();
  77. return false;
  78. }
  79. async function updateBasketObj() {
  80. if (!basketObj[loginId]) {
  81. basketObj[loginId] = {};
  82. }
  83. try {
  84. let temp = await JSON.stringify(basketObj);
  85. localStorage.basket = temp;
  86. } catch (error) {
  87. console.log("Ошибка localStorage.basket = JSON.stringify(basketObj) - ", error);
  88. }
  89. }
  90. const getGQL = (url) => (query, variables = {}) => {
  91. return fetch(url, {
  92. method: "POST",
  93. headers: {
  94. Accept: "application/json",
  95. "Content-Type": "application/json",
  96. ...(localStorage.authToken ? { Authorization: `Bearer ${localStorage.authToken}` } : {}),
  97. },
  98. body: JSON.stringify({ query, variables }),
  99. })
  100. .then((res) => res.json())
  101. .catch((err) => console.log(err));
  102. };
  103. const gql = getGQL(urlConst + `/graphql`);
  104. async function categories(parentEl = leftSide, parentID = null) {
  105. let result = await gql(
  106. `query categories ($query:String){
  107. CategoryFind(query:$query){
  108. _id
  109. name
  110. }
  111. }`,
  112. {
  113. query: JSON.stringify([{ "parent._id": parentID }, { sort: [{ name: 1 }] }]),
  114. }
  115. );
  116. if (result.errors) return;
  117. let ul = document.createElement("ul");
  118. parentEl.append(ul);
  119. for (let { name, _id } of result.data.CategoryFind) {
  120. let li = document.createElement("li");
  121. li.innerText = name;
  122. li.style.fontWeight = "";
  123. let loaded;
  124. li.onclick = (event) => {
  125. if (event) event.stopPropagation();
  126. li.parentElement.parentElement.style.fontWeight = "";
  127. [].forEach.call(li.parentElement.children, (el) => (el.style.fontWeight = ""));
  128. li.style.fontWeight = "700";
  129. if (!loaded) {
  130. categories(li, _id);
  131. loaded = true;
  132. } else {
  133. loaded = false;
  134. [].forEach.call(li.children, (el) => el.remove());
  135. }
  136. mainBlock.innerText = "";
  137. categoryTitle.innerText = "";
  138. subMenu.innerText = "";
  139. showAllInCategory(_id, name);
  140. };
  141. ul.append(li);
  142. let span = document.createElement("span");
  143. span.innerText = name;
  144. subMenu.append(span);
  145. span.onclick = () => {
  146. li.onclick();
  147. };
  148. }
  149. }
  150. categories();
  151. function showAllInCategory(_id, name) {
  152. let h = document.createElement("h1");
  153. h.append(name);
  154. categoryTitle.append(h);
  155. categoryTitle.append(`_${_id} - id категории`);
  156. showGoodsInCategory(mainBlock, _id);
  157. showAllGoodsInAllSubcategories(mainBlock, _id);
  158. }
  159. async function showGoodsInCategory(parentEl, _id) {
  160. let result = await gql(
  161. `query GoodsFromCatSort ($sort:String){
  162. GoodFind(query: $sort) {
  163. _id
  164. name
  165. description
  166. price
  167. images {
  168. _id
  169. createdAt
  170. text
  171. url
  172. originalFileName
  173. }
  174. }
  175. }`,
  176. {
  177. sort: JSON.stringify([{ "categories._id": _id }, { sort: [{ name: 1 }] }]),
  178. }
  179. );
  180. if (result.errors) return;
  181. for (let { name, _id, description, price, images } of result.data.GoodFind) {
  182. let shelfToker = document.createElement("div");
  183. shelfToker.classList.add("shelfToker");
  184. shelfToker.onclick = (e) => {
  185. e.stopPropagation();
  186. shelfToker.classList.add("shelfTokerBig");
  187. };
  188. parentEl.append(shelfToker);
  189. let h3 = document.createElement("h3");
  190. h3.append(name);
  191. shelfToker.append(h3);
  192. h3 = document.createElement("h3");
  193. h3.append("$ " + price);
  194. shelfToker.append(h3);
  195. let p = document.createElement("p");
  196. let h4 = document.createElement("h4");
  197. h4.append("Описание: ");
  198. p.append(h4);
  199. p.append(description);
  200. shelfToker.append(p);
  201. let divImg = document.createElement("div");
  202. divImg.classList.add("divImg");
  203. for (let img of images) {
  204. let divImgOne = document.createElement("div");
  205. divImgOne.classList.add("divImgOne");
  206. let imgNode = document.createElement("img");
  207. imgNode.src = urlConst + `/` + img.url;
  208. divImgOne.append(imgNode);
  209. divImg.append(divImgOne);
  210. let namberOfImg = 0;
  211. imgNode.onclick = (e) => {
  212. e.stopPropagation();
  213. forImage.style.display = "";
  214. forImgSrc.src = urlConst + `/` + images[namberOfImg].url;
  215. forImage.onclick = () => {
  216. forImgSrc.src = urlConst + `/` + images[namberOfImg++ % (images.lenght ? images.lenght : 1)].url;
  217. };
  218. let imgKeyEsc = (ev) => {
  219. if (ev.code === "Escape") {
  220. forImage.style.display = "none";
  221. window.removeEventListener("keydown", imgKeyEsc);
  222. }
  223. };
  224. window.addEventListener("keydown", imgKeyEsc);
  225. };
  226. }
  227. shelfToker.append(divImg);
  228. let count = document.createElement("input");
  229. count.setAttribute("type", "number");
  230. count.setAttribute("min", "1");
  231. count.value = "1";
  232. count.onclick = (e) => {
  233. e.stopPropagation();
  234. };
  235. shelfToker.append(count);
  236. let putInBasketBtn = document.createElement("button");
  237. putInBasketBtn.append("Добавить в корзину");
  238. putInBasketBtn.classList.add("putInBasketBtn");
  239. putInBasketBtn.onclick = (e) => {
  240. e.stopPropagation();
  241. addToBasket(_id, count.value);
  242. };
  243. shelfToker.append(putInBasketBtn);
  244. shelfToker.insertAdjacentHTML("beforeEnd", `<div>${_id} - id товара</div>`);
  245. let shelfTokerExitBtn = appendActionBtn(shelfToker, { onTop: false }, "Вернуться назад");
  246. shelfTokerExitBtn.classList.add("shelfTokerExitBtn");
  247. }
  248. }
  249. function addToBasket(_idValue, countValue) {
  250. basketObj[loginId][_idValue] = +countValue;
  251. updateBasketObj();
  252. alert(`Товар добавлен в корзину.`);
  253. }
  254. async function showAllGoodsInAllSubcategories(parentEl, catId) {
  255. let result = await gql(
  256. `query subCategories ($subcat:String){
  257. CategoryFind(query: $subcat) {
  258. name
  259. _id
  260. }
  261. }`,
  262. {
  263. subcat: JSON.stringify([{ "parent._id": catId }, { sort: [{ name: 1 }] }]),
  264. }
  265. );
  266. if (result.errors) return;
  267. for (let { _id } of result.data.CategoryFind) {
  268. showGoodsInCategory(parentEl, _id);
  269. showAllGoodsInAllSubcategories(parentEl, _id);
  270. }
  271. }
  272. function CreateInputField(parentNode, hidden = false, isCheckNeed = false) {
  273. let inpEl = document.createElement("input");
  274. inpEl.setAttribute("type", hidden ? "password" : "text");
  275. inpEl.setAttribute("placeholder", hidden ? "Password" : "Login");
  276. inpEl.oninput = (isUser = true) => {
  277. if (isUser && this.onChange && typeof this.onChange === "function") {
  278. this.onChange(inpEl.value);
  279. }
  280. };
  281. parentNode.append(inpEl);
  282. let div = document.createElement("div");
  283. let checkBox = document.createElement("input");
  284. checkBox.setAttribute("type", "checkbox");
  285. div.append(checkBox);
  286. let seePassword = document.createElement("span");
  287. seePassword.append("Показать пароль");
  288. div.append(seePassword);
  289. checkBox.oninput = () => {
  290. if (checkBox.checked) {
  291. inpEl.setAttribute("type", "text");
  292. } else inpEl.setAttribute("type", "password");
  293. };
  294. inpEl.addEventListener("keydown", (e) => {
  295. if (["Enter", "NumpadEnter"].includes(e.code)) {
  296. this.onEnter();
  297. }
  298. });
  299. if (isCheckNeed) {
  300. parentNode.append(div);
  301. }
  302. this.getValue = function () {
  303. return inpEl.value;
  304. };
  305. this.getCheckStatus = function () {
  306. return checkBox.checked;
  307. };
  308. this.setValue = function (value = "") {
  309. inpEl.value = value;
  310. };
  311. this.setCheckBox = function (value = false) {
  312. checkBox.checked = value;
  313. };
  314. this.onChange = () => {};
  315. this.onEnter = () => {};
  316. }
  317. function CreateLoginForm(parentNode, isModeLogin = true) {
  318. //isModeLogin = true - по умолчанию создается форма для логина
  319. // false - будет сождаваться форма для регистрации
  320. let loginField = new CreateInputField(parentNode);
  321. let passwordField = new CreateInputField(parentNode, true, true);
  322. // function CreateInputField(parentNode, hidden = false, isCheckNeed = false)
  323. let loginButton = document.createElement("button");
  324. loginButton.append(isModeLogin ? "Войти" : "Зарегистрироваться");
  325. loginButton.setAttribute("disabled", "disabled");
  326. parentNode.append(loginButton);
  327. let canselButton = document.createElement("button");
  328. canselButton.append("Отмена");
  329. parentNode.append(canselButton);
  330. loginField.onChange = passwordField.onChange = () => {
  331. if (loginField.getValue() && passwordField.getValue()) {
  332. loginButton.removeAttribute("disabled");
  333. } else loginButton.setAttribute("disabled", "disabled");
  334. };
  335. loginField.onEnter = passwordField.onEnter = () => loginButton.onclick();
  336. canselButton.onclick = () => {
  337. this.clearAndClose();
  338. };
  339. loginButton.onclick = () => {
  340. if (this.submit && typeof this.submit === "function") {
  341. let loginInfo = {
  342. login: loginField.getValue(),
  343. password: passwordField.getValue(),
  344. };
  345. this.submit(loginInfo);
  346. }
  347. };
  348. this.submit = () => {};
  349. this.clearAndClose = function () {
  350. loginField.setValue();
  351. passwordField.setValue();
  352. passwordField.setCheckBox();
  353. parentNode.style.display = "none";
  354. };
  355. }
  356. let loginFormObject = new CreateLoginForm(loginForm);
  357. let registrationFormObject = new CreateLoginForm(registrationForm, false);
  358. loginFormObject.submit = (loginInfo) => {
  359. loginToDB(loginInfo);
  360. };
  361. registrationFormObject.submit = (reginInfo) => {
  362. registrToDB(reginInfo);
  363. };
  364. async function loginToDB({ login, password } = {}) {
  365. let result = await gql(
  366. `query login($login: String, $password: String) {
  367. login(login: $login, password: $password)
  368. }`,
  369. { login, password }
  370. );
  371. if (result.errors) {
  372. alert("Ошибка сети");
  373. return;
  374. }
  375. if (result.data.login) {
  376. localStorage.authToken = result.data.login;
  377. loginFormObject.clearAndClose();
  378. loginForm.style.display = "none";
  379. registrationFormObject.clearAndClose();
  380. registrationForm.style.display = "none";
  381. checkAuthToken();
  382. } else alert("Ошибка!\nВведите правильные логин и пароль.");
  383. }
  384. async function registrToDB({ login, password } = {}) {
  385. let result = await gql(
  386. `mutation newUser($login: String, $password: String) {
  387. UserUpsert(user: {login: $login, password: $password}) {
  388. _id
  389. createdAt
  390. }
  391. }`,
  392. { login, password }
  393. );
  394. if (result.errors) {
  395. alert(`Ошибка регистрации:\n${result.errors[0].message}`);
  396. return;
  397. }
  398. alert("Вы успешно зарегистрированы.");
  399. loginToDB({ login, password });
  400. }
  401. historyDiv.onclick = () => {
  402. showOrderHistory(forBasket);
  403. };
  404. async function showOrderHistory(parentNode) {
  405. let result = await gql(
  406. `query FindOrders($lookOrders2:String){
  407. OrderFind(query:$lookOrders2){
  408. total
  409. orderGoods{
  410. good{
  411. name
  412. images{
  413. url
  414. }
  415. }
  416. price
  417. count
  418. total
  419. }
  420. }
  421. }`,
  422. { lookOrders2: JSON.stringify([{}]) }
  423. // { lookOrders2: JSON.stringify([{}, { sort: [{ total: 1 }] }]) }
  424. // ++++++++++++++ а вот эта сортировка ну никак не работает...??? +++++++++
  425. // потому что total - вычисляемое поле
  426. );
  427. if (result.errors) {
  428. alert("Ошибка сервера...");
  429. console.log(result.errors);
  430. return;
  431. }
  432. parentNode.style.display = "";
  433. let masterTotal = 0;
  434. forBasket.innerHTML = "";
  435. appendActionBtn(forBasket, { onTop: true }, "Вернуться назад");
  436. result.data.OrderFind.forEach((order) => {
  437. let div1order = document.createElement("div");
  438. forBasket.prepend(div1order);
  439. showOrder(div1order, order);
  440. let h = document.createElement("h4");
  441. div1order.append(h);
  442. h.append(`Всего за заказ: $${order.total}`);
  443. masterTotal += order.total;
  444. });
  445. h = document.createElement("h2");
  446. forBasket.prepend(h);
  447. h.append(`Общая сумма всех заказов: $${masterTotal}`);
  448. appendActionBtn(forBasket, { onTop: true }, "Вернуться назад");
  449. forBasket.scrollTop = 0;
  450. }
  451. const appendActionBtn = function (parent, { onTop = false }, innerText = "Вернуться назад") {
  452. let exitBtn = document.createElement("button");
  453. exitBtn.append(innerText);
  454. if (onTop) {
  455. parent.prepend(exitBtn);
  456. } else {
  457. parent.append(exitBtn);
  458. }
  459. exitBtn.onclick = () => {
  460. parent.style.display = "none";
  461. parent.innerHTML = "";
  462. };
  463. return exitBtn;
  464. };
  465. const showOrder = function (parent, { orderGoods: orderArray, total: total1Order }) {
  466. for (let { good, price, count, total: total1pozition } of orderArray) {
  467. if (!good) {
  468. good = {
  469. images: [
  470. {
  471. url: "",
  472. },
  473. ],
  474. name: "",
  475. };
  476. }
  477. // да, это костыль, но увы не смог составить запрос, чтобы вложенное поле
  478. // в обекте - в массиве не равнялось null
  479. // И вообще! Это ли не сервер должен следить, чтобы в базу чушь не заносили?
  480. div = document.createElement("div");
  481. parent.append(div);
  482. let img = document.createElement("img");
  483. div.append(img);
  484. img.src = urlConst + `/` + good.images[0].url;
  485. let p = document.createElement("p");
  486. div.append(p);
  487. p.append(good.name);
  488. p = document.createElement("p");
  489. div.append(p);
  490. p.append(`Цена: $${price}`);
  491. p = document.createElement("p");
  492. div.append(p);
  493. p.append(`Кол-во: ${count}`);
  494. p = document.createElement("p");
  495. div.append(p);
  496. p.append(`Всего: $${total1pozition}`);
  497. }
  498. };
  499. basketLogo.onclick = () => {
  500. showBasket(forBasket);
  501. };
  502. async function showBasket(parent) {
  503. parent.style.display = "";
  504. parent.innerHTML = "";
  505. appendActionBtn(parent, { onTop: true }, "Вернуться назад");
  506. if (!Object.keys(basketObj[loginId]).length) {
  507. let h = document.createElement("h3");
  508. h.append("Ваша корзина пустая");
  509. parent.append(h);
  510. } else {
  511. for (let [_id, count] of Object.entries(basketObj[loginId])) {
  512. await show1goodFromBasket(parent, _id, +count);
  513. }
  514. let hTotal = document.createElement("h3");
  515. hTotal.setAttribute("id", "hTotal");
  516. parent.append(hTotal);
  517. CountTotal(parent);
  518. }
  519. appendActionBtn(parent, { onTop: false }, "Вернуться назад");
  520. let btn = appendActionBtn(parent, { onTop: false }, "Оформить заказ (купить)");
  521. btn.setAttribute("id", "buyBtn");
  522. if (!Object.keys(basketObj[loginId]).length || loginId === "0") {
  523. btn.setAttribute("disabled", "disabled");
  524. }
  525. btn.onclick = async function () {
  526. parent.style.display = "none";
  527. parent.innerHTML = "";
  528. await buy();
  529. };
  530. if (loginId === "0") {
  531. let h = document.createElement("h3");
  532. h.append("Для оформления заказа необходимо авторизоваться");
  533. parent.append(h);
  534. }
  535. }
  536. const CountTotal = function (parent) {
  537. let totalCost = 0;
  538. let costFieldsAll = parent.querySelectorAll(".costField");
  539. [].forEach.call(costFieldsAll, (el) => {
  540. totalCost += +el.innerText.slice(1);
  541. });
  542. hTotal.innerText = `Общая сумма: $${totalCost}`;
  543. };
  544. async function get1goodFromDB(_id) {
  545. let result = await gql(
  546. `query oneGood ($_id:String){
  547. GoodFind(query:$_id ) {
  548. _id
  549. name
  550. price
  551. images {
  552. url
  553. }
  554. }
  555. }`,
  556. { _id: JSON.stringify([{ _id: _id }]) }
  557. );
  558. if (result.errors) {
  559. console.log("не смог купить:", result.errors);
  560. return;
  561. }
  562. return result.data.GoodFind[0];
  563. }
  564. async function show1goodFromBasket(parent, _id, count) {
  565. let item = await get1goodFromDB(_id);
  566. let div1 = document.createElement("div");
  567. parent.append(div1);
  568. let div = document.createElement("div");
  569. div1.append(div);
  570. let img = document.createElement("img");
  571. div.append(img);
  572. img.src = urlConst + `/` + item.images[0].url;
  573. let p = document.createElement("p");
  574. div.append(p);
  575. p.append(item.name);
  576. p = document.createElement("p");
  577. div.append(p);
  578. p.append(`Цена: $${item.price}`);
  579. let inpCount = document.createElement("input");
  580. inpCount.setAttribute("type", "number");
  581. inpCount.setAttribute("min", "1");
  582. inpCount.value = count;
  583. div.append(inpCount);
  584. let cost = document.createElement("p");
  585. cost.setAttribute("class", "costField");
  586. div.append(cost);
  587. cost.append(`$${Math.round(count * item.price)}`);
  588. let btn = appendActionBtn(div, { onTop: false }, "Удалить");
  589. inpCount.oninput = async function () {
  590. basketObj[loginId][_id] = +inpCount.value;
  591. await updateBasketObj();
  592. cost.innerHTML = `$${Math.round(inpCount.value * item.price)}`;
  593. CountTotal(parent);
  594. };
  595. btn.onclick = async function () {
  596. delete basketObj[loginId][_id];
  597. if (!Object.keys(basketObj[loginId]).length) {
  598. buyBtn.setAttribute("disabled", "disabled");
  599. }
  600. await updateBasketObj();
  601. // div.remove();
  602. CountTotal(parent);
  603. };
  604. // addEventListener();
  605. btn.onclick = async function () {
  606. delete basketObj[loginId][_id];
  607. if (!Object.keys(basketObj[loginId]).length) {
  608. buyBtn.setAttribute("disabled", "disabled");
  609. }
  610. await updateBasketObj();
  611. div.remove();
  612. CountTotal(parent);
  613. };
  614. }
  615. async function buy() {
  616. let order1 = { orderGoods: [] };
  617. for (let [_id, count] of Object.entries(basketObj[loginId])) {
  618. order1.orderGoods.push({
  619. count: count,
  620. good: { _id: _id },
  621. });
  622. }
  623. let result = await gql(
  624. `mutation newOrder1($order1:OrderInput) {
  625. OrderUpsert(order: $order1) {
  626. _id
  627. total
  628. }
  629. }`,
  630. { order1 }
  631. );
  632. if (result.errors) {
  633. console.log("не смог получить товар из DB для отображения в корзине:", result.errors);
  634. return;
  635. }
  636. console.log(result.data.OrderUpsert.total);
  637. alert(`Ваш заказ успешно оформлен. \nОбщая сумма заказа $${result.data.OrderUpsert.total}`);
  638. for (let key in basketObj[loginId]) {
  639. delete basketObj[loginId][key];
  640. }
  641. }
  642. window.onload = init;