magic.js 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849
  1. {//все готово до выполнения модуля
  2. // // delay
  3. // const delay = ms => new Promise(ok => setTimeout(() => ok(ms), ms))
  4. // // createStore
  5. // function createStore(reducer) {
  6. // let state = reducer(undefined, {}) //стартовая инициализация состояния, запуск редьюсера со state === undefined
  7. // let cbs = [] //массив подписчиков
  8. // const getState = () => state //функция, возвращающая переменную из замыкания
  9. // const subscribe = cb => (cbs.push(cb), //запоминаем подписчиков в массиве
  10. // () => cbs = cbs.filter(c => c !== cb)) //возвращаем функцию unsubscribe, которая удаляет подписчика из списка
  11. // const dispatch = action => {
  12. // if (typeof action === 'function') { //если action - не объект, а функция
  13. // return action(dispatch, getState) //запускаем эту функцию и даем ей dispatch и getState для работы
  14. // }
  15. // const newState = reducer(state, action) //пробуем запустить редьюсер
  16. // if (newState !== state) { //проверяем, смог ли редьюсер обработать action
  17. // state = newState //если смог, то обновляем state
  18. // for (let cb of cbs) {
  19. // cb()
  20. // } //и запускаем подписчиков
  21. // }
  22. // }
  23. // return {
  24. // getState, //добавление функции getState в результирующий объект
  25. // dispatch,
  26. // subscribe //добавление subscribe в объект
  27. // }
  28. // }
  29. // // ========================================================================================================
  30. // // promiseReducer
  31. // function promiseReducer(state = {}, { type, status, payload, error, nameOfPromise }) {
  32. // if (type === 'PROMISE') {
  33. // return {
  34. // ...state,
  35. // [nameOfPromise]: { status, payload, error }
  36. // }
  37. // }
  38. // return state
  39. // }
  40. // // Акшоны:
  41. // // Соответственно, имя промиса будет передаваться в редьюсер как ключ в объекте action, а так же:
  42. // const actionPending = nameOfPromise => ({ nameOfPromise, type: 'PROMISE', status: 'PENDING' }) // в actionPending - единственный параметр
  43. // const actionFulfilled = (nameOfPromise, payload) => ({ nameOfPromise, type: 'PROMISE', status: 'FULFILLED', payload }) // как первый параметр, payload станет вторым параметром
  44. // const actionRejected = (nameOfPromise, error) => ({ nameOfPromise, type: 'PROMISE', status: 'REJECTED', error }) // по аналогии с actionFulfilled
  45. // const actionPromise = (nameOfPromise, promise) => // первый параметр, второй параметр - сам промис, который мы будем обрабатывать;
  46. // async dispatch => {
  47. // dispatch(actionPending(nameOfPromise)) //сигнализируем redux, что промис начался
  48. // try {
  49. // const payload = await promise //ожидаем промиса
  50. // dispatch(actionFulfilled(nameOfPromise, payload)) //сигнализируем redux, что промис успешно выполнен
  51. // return payload //в месте запуска store.dispatch с этим thunk можно так же получить результат промиса
  52. // }
  53. // catch (error) {
  54. // dispatch(actionRejected(nameOfPromise, error)) //в случае ошибки - сигнализируем redux, что промис несложился
  55. // }
  56. // }
  57. // //=========================================================================================================
  58. // // authReducer
  59. // const jwtDecode = function (token) {
  60. // try {
  61. // let parseData = token.split('.')[1]
  62. // return JSON.parse(atob(parseData))
  63. // }
  64. // catch (e) {
  65. // return undefined
  66. // }
  67. // }
  68. // function authReducer(state = {}, { type, token }) {
  69. // if (type === 'AUTH_LOGIN') {
  70. // let payload = jwtDecode(token)
  71. // return state = {
  72. // token,
  73. // payload
  74. // }
  75. // }
  76. // if (type === 'AUTH_LOGOUT') {
  77. // return {}
  78. // }
  79. // return state
  80. // }
  81. // // проверка (и экшенкриейторы бонусом):
  82. // const actionAuthLogin = token => ({ type: 'AUTH_LOGIN', token })
  83. // const actionAuthLogout = () => ({ type: 'AUTH_LOGOUT' })
  84. // // const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOnsiaWQiOiI2Mzc3ZTEzM2I3NGUxZjVmMmVjMWMxMjUiLCJsb2dpbiI6InRlc3Q1IiwiYWNsIjpbIjYzNzdlMTMzYjc0ZTFmNWYyZWMxYzEyNSIsInVzZXIiXX0sImlhdCI6MTY2ODgxMjQ1OH0.t1eQlRwkcP7v9JxUPMo3dcGKprH-uy8ujukNI7xE3A0"
  85. // //=========================================================================================================
  86. // // cartReducer
  87. // function cartReducer(state = {}, { type, count, good }) {
  88. // if (type === 'CART_ADD') {
  89. // return {
  90. // ...state,
  91. // [good._id]: {
  92. // good,
  93. // count: (state[good._id] ? state[good._id].count + count : count)
  94. // }
  95. // }
  96. // }
  97. // if (type === 'CART_SUB') {
  98. // if (state[good._id]) {
  99. // let newCount = state[good._id].count - count
  100. // if (newCount > 0) {
  101. // return {
  102. // ...state,
  103. // [good._id]: {
  104. // good,
  105. // count: newCount
  106. // }
  107. // }
  108. // } else {
  109. // delete state[good._id]
  110. // return { ...state }
  111. // }
  112. // } else {
  113. // return undefined
  114. // }
  115. // }
  116. // if (type === 'CART_DEL') {
  117. // delete state[good._id]
  118. // return { ...state }
  119. // }
  120. // if (type === 'CART_SET') {
  121. // if (count > 0) {
  122. // return {
  123. // ...state,
  124. // [good._id]: {
  125. // good,
  126. // count
  127. // }
  128. // }
  129. // } else {
  130. // delete state[good._id]
  131. // return { ...state }
  132. // }
  133. // }
  134. // if (type === 'CART_CLEAR') {
  135. // return state = {}
  136. // }
  137. // return state
  138. // }
  139. // // экшоны:
  140. // // Добавление товара.Должен добавлять новый ключ в state, или обновлять, если ключа в state ранее не было, увеличивая количество
  141. // const actionCartAdd = (good, count = 1) => ({ type: 'CART_ADD', count, good })
  142. // // Уменьшение количества товара.Должен уменьшать количество товара в state, или удалять его если количество будет 0 или отрицательным
  143. // const actionCartSub = (good, count = 1) => ({ type: 'CART_SUB', count, good })
  144. // // Удаление товара.Должен удалять ключ из state
  145. // const actionCartDel = (good) => ({ type: 'CART_DEL', good })
  146. // // Задание количества товара.В отличие от добавления и уменьшения, не учитывает того количества, которое уже было в корзине, а тупо назначает количество поверху(или создает новый ключ, если в корзине товара не было).Если count 0 или отрицательное число - удаляем ключ из корзины;
  147. // const actionCartSet = (good, count = 1) => ({ type: 'CART_SET', count, good })
  148. // // Очистка корзины.state должен стать пустым объектом { }
  149. // const actionCartClear = () => ({ type: 'CART_CLEAR' })
  150. // //=========================================================================================================
  151. // // ========================================================================================================
  152. // // GraphQL запросы
  153. // // Запрос на список корневых категорий
  154. // const findCategory = `query baseCategory($searchVariablesCategory: String){
  155. // CategoryFind(query: $searchVariablesCategory){
  156. // _id name parent {
  157. // _id
  158. // name
  159. // }
  160. // }
  161. // }`
  162. // const findCategoryVar = {
  163. // searchVariablesCategory: JSON.stringify([{ parent: null }])
  164. // }
  165. // const actionCategoryFind = () => actionPromise('CategoryFind', gql(findCategory, findCategoryVar))
  166. // //=========================================================================================================
  167. // // Запрос для получения одной категории с товарами и картинками
  168. // const findOneCategory = `query categoryFindOne($searchVariablesCategoryOne: String,) {
  169. // CategoryFindOne(query: $searchVariablesCategoryOne){
  170. // _id name parent{
  171. // _id name
  172. // }
  173. // goods{
  174. // _id name description price
  175. // images{
  176. // url
  177. // }
  178. // }
  179. // subCategories{
  180. // _id name
  181. // }
  182. // }
  183. // }`
  184. // const findOneCategoryVar = {
  185. // searchVariablesCategoryOne: JSON.stringify([{ _id: "6262ca7dbf8b206433f5b3d1" }])
  186. // }
  187. // const actionCategoryFindOne = () => actionPromise('CategoryFindOne', gql(findOneCategory, findOneCategoryVar))
  188. // //=========================================================================================================
  189. // // Запрос на получение товара с описанием и картинками
  190. // const findGoodWithImage = `query oneGoodWithImages($searchVariablesGoodOne: String) {
  191. // GoodFindOne(query: $searchVariablesGoodOne){
  192. // _id name price description images {
  193. // url
  194. // }
  195. // }
  196. // }
  197. // `
  198. // const findGoodWithImageVar = {
  199. // searchVariablesGoodOne: JSON.stringify([{ _id: "62c9472cb74e1f5f2ec1a0d3" }])
  200. // }
  201. // const actionGoodFindOne = () => actionPromise('GoodFindOne', gql(findGoodWithImage, findGoodWithImageVar))
  202. // //=========================================================================================================
  203. // // Запрос на регистрацию - работает, если не залогинен пользователь
  204. // const registration = `mutation registration($loginReg:String,$passwordReg:String ){
  205. // UserUpsert(user:{
  206. // login:$loginReg, password:$passwordReg
  207. // }){
  208. // _id createdAt
  209. // }
  210. // }`
  211. // const registrationVar = {
  212. // loginReg: "abababa", // вот тут нужно в параметры запихнуть переменную, которую будем получать
  213. // passwordReg: "123123" // вот тут нужно в параметры запихнуть переменную, которую будем получать
  214. // }
  215. // const actionUserUpsert = () => actionPromise('UserUpsert', gql(registration, registrationVar))
  216. // //=========================================================================================================
  217. // // Запрос на логин
  218. // const checkLogin = `query login($login: String, $password: String){
  219. // login(login: $login, password: $password)
  220. // }
  221. // `
  222. // const checkLoginVar = {
  223. // login: "abababa", // вот тут нужно в параметры запихнуть переменную, которую будем получать
  224. // password: "123123" // вот тут нужно в параметры запихнуть переменную, которую будем получать
  225. // }
  226. // const actionLogin = () => actionPromise('login', gql(checkLogin, checkLoginVar))
  227. // //=========================================================================================================
  228. // // Запрос истории заказов - нужно учитывать, что работает только, если вместе с заголовком отправить JWT-token от пользователя
  229. // const orderFind = `query order ($order: String){
  230. // OrderFind(query: $order){
  231. // _id total orderGoods{
  232. // good {
  233. // _id
  234. // name
  235. // price
  236. // }
  237. // }
  238. // }
  239. // }
  240. // `
  241. // const orderFindVar = {
  242. // order: JSON.stringify([{}])
  243. // }
  244. // const actionOrderFind = () => actionPromise('login', gql(orderFind, orderFindVar))
  245. // //=========================================================================================================
  246. // // Запрос оформления заказа - нужно добить: После успешного оформления заказа на бэке задиспатчить экшон очистки корзины
  247. // const orderCreate = `mutation myOrder($createOrder: OrderInput){
  248. // OrderUpsert(order: $createOrder) {
  249. // orderGoods{
  250. // count good{
  251. // _id
  252. // }
  253. // }
  254. // }
  255. // }`
  256. // const orderCreateVar = {
  257. // createOrder: JSON.stringify({ orderGoods: { count: 2, good: { _id: "62c9472cb74e1f5f2ec1a0d2" } } }) // вот тут нужно в параметры запихнуть переменную, которую будем получать
  258. // }
  259. // const actionOrderUpsert = () => actionPromise('login', gql(orderCreate, orderCreateVar))
  260. // // ========================================================================================================
  261. // // ========================================================================================================
  262. // // Вспомогательные функции
  263. // // getGql - переделка из HW18 функции gql (делаем запрос на бэк)
  264. // function getGql(endpoint) {
  265. // let headers = {
  266. // 'Content-Type': 'application/json;charset=utf-8',
  267. // 'Accept': 'application/json',
  268. // }
  269. // if ('authToken' in localStorage) {
  270. // headers.Authorization = 'Bearer ' + localStorage.authToken
  271. // }
  272. // return async function gql(query, variables = {}) {
  273. // let result = await fetch(endpoint, {
  274. // method: 'POST',
  275. // headers,
  276. // body: JSON.stringify({
  277. // query,
  278. // variables
  279. // })
  280. // }).then(res => res.json())
  281. // if (('errors' in result) && !('data' in result)) {
  282. // throw new Error(JSON.stringify(result.errors))
  283. // }
  284. // result = Object.values(result.data)[0]
  285. // return result
  286. // }
  287. // }
  288. // //=========================================================================================================
  289. // // localStoredReducer
  290. // function localStoredReducer(originalReducer, localStorageKey) {
  291. // function wrapper(state, action) {
  292. // if (!state) {
  293. // try {
  294. // return JSON.parse(localStorage[localStorageKey])
  295. // }
  296. // catch (error) {
  297. // }
  298. // }
  299. // const newState = originalReducer(state, action)
  300. // localStorage[localStoredReducer] = JSON.stringify(newState)
  301. // return newState
  302. // }
  303. // return wrapper
  304. // }
  305. // //=========================================================================================================
  306. // // Модуль
  307. }
  308. // createStore
  309. function createStore(reducer) {
  310. let state = reducer(undefined, {}) //стартовая инициализация состояния, запуск редьюсера со state === undefined
  311. let cbs = [] //массив подписчиков
  312. const getState = () => state //функция, возвращающая переменную из замыкания
  313. const subscribe = cb => (cbs.push(cb), //запоминаем подписчиков в массиве
  314. () => cbs = cbs.filter(c => c !== cb)) //возвращаем функцию unsubscribe, которая удаляет подписчика из списка
  315. const dispatch = action => {
  316. if (typeof action === 'function') { //если action - не объект, а функция
  317. return action(dispatch, getState) //запускаем эту функцию и даем ей dispatch и getState для работы
  318. }
  319. const newState = reducer(state, action) //пробуем запустить редьюсер
  320. if (newState !== state) { //проверяем, смог ли редьюсер обработать action
  321. state = newState //если смог, то обновляем state
  322. for (let cb of cbs) {
  323. cb()
  324. } //и запускаем подписчиков
  325. }
  326. }
  327. return {
  328. getState, //добавление функции getState в результирующий объект
  329. dispatch,
  330. subscribe //добавление subscribe в объект
  331. }
  332. }
  333. // созание функции комбайнРедьюсер
  334. function combineReducers(reducers) {
  335. function totalReducer(state = {}, action) {
  336. const newTotalState = {}
  337. for (const [reducerName, reducer] of Object.entries(reducers)) {
  338. const newSubState = reducer(state[reducerName], action)
  339. if (newSubState !== state[reducerName]) {
  340. newTotalState[reducerName] = newSubState
  341. }
  342. }
  343. if (Object.keys(newTotalState).length) {
  344. return { ...state, ...newTotalState }
  345. }
  346. return state
  347. }
  348. return totalReducer
  349. }
  350. // создаем объект с редьюсерами
  351. const reducers = {
  352. promise: promiseReducer, //допилить много имен для многих промисо
  353. auth: authReducer, //часть предыдущего ДЗ
  354. cart: cartReducer, //часть предыдущего ДЗ
  355. }
  356. // скармливаем объект с редьюсерами в компайн-редьюсер
  357. const totalReducer = combineReducers(reducers)
  358. // ========================================================================================================
  359. // promiseReducer
  360. function promiseReducer(state = {}, { type, status, payload, error, nameOfPromise }) {
  361. if (type === 'PROMISE') {
  362. return {
  363. ...state,
  364. [nameOfPromise]: { status, payload, error }
  365. }
  366. }
  367. return state
  368. }
  369. // Акшоны:
  370. // Соответственно, имя промиса будет передаваться в редьюсер как ключ в объекте action, а так же:
  371. const actionPending = nameOfPromise => ({ nameOfPromise, type: 'PROMISE', status: 'PENDING' }) // в actionPending - единственный параметр
  372. const actionFulfilled = (nameOfPromise, payload) => ({ nameOfPromise, type: 'PROMISE', status: 'FULFILLED', payload }) // как первый параметр, payload станет вторым параметром
  373. const actionRejected = (nameOfPromise, error) => ({ nameOfPromise, type: 'PROMISE', status: 'REJECTED', error }) // по аналогии с actionFulfilled
  374. const actionPromise = (nameOfPromise, promise) => // первый параметр, второй параметр - сам промис, который мы будем обрабатывать;
  375. async dispatch => {
  376. dispatch(actionPending(nameOfPromise)) //сигнализируем redux, что промис начался
  377. try {
  378. const payload = await promise //ожидаем промиса
  379. dispatch(actionFulfilled(nameOfPromise, payload)) //сигнализируем redux, что промис успешно выполнен
  380. return payload //в месте запуска store.dispatch с этим thunk можно так же получить результат промиса
  381. }
  382. catch (error) {
  383. dispatch(actionRejected(nameOfPromise, error)) //в случае ошибки - сигнализируем redux, что промис несложился
  384. }
  385. }
  386. const store = createStore(totalReducer) // создаем магаз с редюсером
  387. store.subscribe(() => console.log(store.getState())) // для контроля выводим все изменения в магазине в консоль
  388. //=========================================================================================================
  389. // authReducer
  390. const jwtDecode = function (token) {
  391. try {
  392. let parseData = token.split('.')[1]
  393. return JSON.parse(atob(parseData))
  394. }
  395. catch (e) {
  396. return undefined
  397. }
  398. }
  399. function authReducer(state = {}, { type, token }) {
  400. if (type === 'AUTH_LOGIN') {
  401. let payload = jwtDecode(token)
  402. return state = {
  403. token,
  404. payload
  405. }
  406. }
  407. if (type === 'AUTH_LOGOUT') {
  408. return {}
  409. }
  410. return state
  411. }
  412. // проверка (и экшенкриейторы бонусом):
  413. const actionAuthLogin = token => ({ type: 'AUTH_LOGIN', token })
  414. const actionAuthLogout = () => ({ type: 'AUTH_LOGOUT' })
  415. // const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOnsiaWQiOiI2Mzc3ZTEzM2I3NGUxZjVmMmVjMWMxMjUiLCJsb2dpbiI6InRlc3Q1IiwiYWNsIjpbIjYzNzdlMTMzYjc0ZTFmNWYyZWMxYzEyNSIsInVzZXIiXX0sImlhdCI6MTY2ODgxMjQ1OH0.t1eQlRwkcP7v9JxUPMo3dcGKprH-uy8ujukNI7xE3A0"
  416. //=========================================================================================================
  417. // cartReducer
  418. function cartReducer(state = {}, { type, count, good }) {
  419. if (type === 'CART_ADD') {
  420. return {
  421. ...state,
  422. [good._id]: {
  423. good,
  424. count: (state[good._id] ? state[good._id].count + count : count)
  425. }
  426. }
  427. }
  428. if (type === 'CART_SUB') {
  429. if (state[good._id]) {
  430. let newCount = state[good._id].count - count
  431. if (newCount > 0) {
  432. return {
  433. ...state,
  434. [good._id]: {
  435. good,
  436. count: newCount
  437. }
  438. }
  439. } else {
  440. delete state[good._id]
  441. return { ...state }
  442. }
  443. } else {
  444. return undefined
  445. }
  446. }
  447. if (type === 'CART_DEL') {
  448. delete state[good._id]
  449. return { ...state }
  450. }
  451. if (type === 'CART_SET') {
  452. if (count > 0) {
  453. return {
  454. ...state,
  455. [good._id]: {
  456. good,
  457. count
  458. }
  459. }
  460. } else {
  461. delete state[good._id]
  462. return { ...state }
  463. }
  464. }
  465. if (type === 'CART_CLEAR') {
  466. return state = {}
  467. }
  468. return state
  469. }
  470. // экшоны:
  471. // Добавление товара.Должен добавлять новый ключ в state, или обновлять, если ключа в state ранее не было, увеличивая количество
  472. const actionCartAdd = (good, count = 1) => ({ type: 'CART_ADD', count, good })
  473. // Уменьшение количества товара.Должен уменьшать количество товара в state, или удалять его если количество будет 0 или отрицательным
  474. const actionCartSub = (good, count = 1) => ({ type: 'CART_SUB', count, good })
  475. // Удаление товара.Должен удалять ключ из state
  476. const actionCartDel = (good) => ({ type: 'CART_DEL', good })
  477. // Задание количества товара.В отличие от добавления и уменьшения, не учитывает того количества, которое уже было в корзине, а тупо назначает количество поверху(или создает новый ключ, если в корзине товара не было).Если count 0 или отрицательное число - удаляем ключ из корзины;
  478. const actionCartSet = (good, count = 1) => ({ type: 'CART_SET', count, good })
  479. // Очистка корзины.state должен стать пустым объектом { }
  480. const actionCartClear = () => ({ type: 'CART_CLEAR' })
  481. //=========================================================================================================
  482. // ========================================================================================================
  483. // GraphQL запросы
  484. // Запрос на список корневых категорий
  485. const findCategory = `query baseCategory($searchVariablesCategory: String){
  486. CategoryFind(query: $searchVariablesCategory){
  487. _id name parent {
  488. _id
  489. name
  490. }
  491. }
  492. }`
  493. const findCategoryVar = {
  494. searchVariablesCategory: JSON.stringify([{ parent: null }])
  495. }
  496. const actionCategoryFind = () => actionPromise('CategoryFind', gql(findCategory, findCategoryVar))
  497. //=========================================================================================================
  498. // Запрос для получения одной категории с товарами и картинками
  499. const findOneCategory = `query categoryFindOne($searchVariablesCategoryOne: String,) {
  500. CategoryFindOne(query: $searchVariablesCategoryOne){
  501. _id name parent{
  502. _id name
  503. }
  504. goods{
  505. _id name description price
  506. images{
  507. url
  508. }
  509. }
  510. subCategories{
  511. _id name
  512. }
  513. }
  514. }`
  515. const findOneCategoryVar = {
  516. searchVariablesCategoryOne: JSON.stringify([{ _id: "6262ca7dbf8b206433f5b3d1" }])
  517. }
  518. const actionCategoryFindOne = () => actionPromise('CategoryFindOne', gql(findOneCategory, findOneCategoryVar))
  519. //=========================================================================================================
  520. // Запрос на получение товара с описанием и картинками
  521. const findGoodWithImage = `query oneGoodWithImages($searchVariablesGoodOne: String) {
  522. GoodFindOne(query: $searchVariablesGoodOne){
  523. _id name price description images {
  524. url
  525. }
  526. }
  527. }
  528. `
  529. const findGoodWithImageVar = {
  530. searchVariablesGoodOne: JSON.stringify([{ _id: "62c9472cb74e1f5f2ec1a0d3" }])
  531. }
  532. const actionGoodFindOne = () => actionPromise('GoodFindOne', gql(findGoodWithImage, findGoodWithImageVar))
  533. //=========================================================================================================
  534. // Запрос на регистрацию - работает, если не залогинен пользователь
  535. const registration = `mutation registration($loginReg:String,$passwordReg:String ){
  536. UserUpsert(user:{
  537. login:$loginReg, password:$passwordReg
  538. }){
  539. _id createdAt
  540. }
  541. }`
  542. const registrationVar = {
  543. loginReg: "abababa", // вот тут нужно в параметры запихнуть переменную, которую будем получать
  544. passwordReg: "123123" // вот тут нужно в параметры запихнуть переменную, которую будем получать
  545. }
  546. const actionUserUpsert = () => actionPromise('UserUpsert', gql(registration, registrationVar))
  547. //=========================================================================================================
  548. // Запрос на логин
  549. const checkLogin = `query login($login: String, $password: String){
  550. login(login: $login, password: $password)
  551. }
  552. `
  553. const checkLoginVar = {
  554. login: "abababa", // вот тут нужно в параметры запихнуть переменную, которую будем получать
  555. password: "123123" // вот тут нужно в параметры запихнуть переменную, которую будем получать
  556. }
  557. const actionLogin = () => actionPromise('login', gql(checkLogin, checkLoginVar))
  558. //=========================================================================================================
  559. // Запрос истории заказов - нужно учитывать, что работает только, если вместе с заголовком отправить JWT-token от пользователя
  560. const orderFind = `query order ($order: String){
  561. OrderFind(query: $order){
  562. _id total orderGoods{
  563. good {
  564. _id
  565. name
  566. price
  567. }
  568. }
  569. }
  570. }
  571. `
  572. const orderFindVar = {
  573. order: JSON.stringify([{}])
  574. }
  575. const actionOrderFind = () => actionPromise('login', gql(orderFind, orderFindVar))
  576. //=========================================================================================================
  577. // Запрос оформления заказа - нужно добить: После успешного оформления заказа на бэке задиспатчить экшон очистки корзины
  578. const orderCreate = `mutation myOrder($createOrder: OrderInput){
  579. OrderUpsert(order: $createOrder) {
  580. orderGoods{
  581. count good{
  582. _id
  583. }
  584. }
  585. }
  586. }`
  587. const orderCreateVar = {
  588. createOrder: JSON.stringify({ orderGoods: { count: 2, good: { _id: "62c9472cb74e1f5f2ec1a0d2" } } }) // вот тут нужно в параметры запихнуть переменную, которую будем получать
  589. }
  590. const actionOrderUpsert = () => actionPromise('login', gql(orderCreate, orderCreateVar))
  591. // ========================================================================================================
  592. // ========================================================================================================
  593. // Вспомогательные функции
  594. // getGql - переделка из HW18 функции gql (делаем запрос на бэк)
  595. function getGql(endpoint) {
  596. let headers = {
  597. 'Content-Type': 'application/json;charset=utf-8',
  598. 'Accept': 'application/json',
  599. }
  600. if ('authToken' in localStorage) {
  601. headers.Authorization = 'Bearer ' + localStorage.authToken
  602. }
  603. return async function gql(query, variables = {}) {
  604. let result = await fetch(endpoint, {
  605. method: 'POST',
  606. headers,
  607. body: JSON.stringify({
  608. query,
  609. variables
  610. })
  611. }).then(res => res.json())
  612. if (('errors' in result) && !('data' in result)) {
  613. throw new Error(JSON.stringify(result.errors))
  614. }
  615. result = Object.values(result.data)[0]
  616. return result
  617. }
  618. }
  619. //=========================================================================================================
  620. // localStoredReducer
  621. function localStoredReducer(originalReducer, localStorageKey) {
  622. function wrapper(state, action) {
  623. if (!state) {
  624. try {
  625. return JSON.parse(localStorage[localStorageKey])
  626. }
  627. catch (error) {
  628. }
  629. }
  630. const newState = originalReducer(state, action)
  631. localStorage[localStoredReducer] = JSON.stringify(newState)
  632. return newState
  633. }
  634. return wrapper
  635. }
  636. //=========================================================================================================
  637. // Модуль