index.html 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. <script>
  11. // Redux продвинутый и модуль
  12. // Редьюсеры
  13. // задание 1 promiseReducer
  14. {
  15. const initialState = {};
  16. const promiseReducer = (state = initialState, action) => {
  17. const { type, key, payload, error } = action;
  18. switch (type) {
  19. case 'ACTION_PENDING':
  20. return {
  21. ...state,
  22. [key]: { status: 'PENDING', payload: null, error: null },
  23. };
  24. case 'ACTION_FULFILLED':
  25. return {
  26. ...state,
  27. [key]: { status: 'FULFILLED', payload, error: null },
  28. };
  29. case 'ACTION_REJECTED':
  30. return {
  31. ...state,
  32. [key]: { status: 'REJECTED', payload: null, error },
  33. };
  34. default:
  35. return state;
  36. }
  37. };
  38. const actionPromise = (key, promise) => {
  39. return (dispatch) => {
  40. dispatch({ type: 'ACTION_PENDING', key });
  41. promise
  42. .then((res) => {
  43. dispatch({ type: 'ACTION_FULFILLED', key, payload: res });
  44. })
  45. .catch((err) => {
  46. dispatch({ type: 'ACTION_REJECTED', key, error: err });
  47. });
  48. };
  49. };
  50. const store = createStore(promiseReducer);
  51. store.subscribe(() => console.log(store.getState()));
  52. store.dispatch(actionPromise('delay', delay(1000)));
  53. store.dispatch(
  54. actionPromise(
  55. 'luke',
  56. fetch('https://swapi.dev/api/people/1').then((res) => res.json()),
  57. ),
  58. );
  59. store.dispatch(
  60. actionPromise(
  61. 'tatooine',
  62. fetch('https://swapi.dev/api/planets/1').then((res) => res.json()),
  63. ),
  64. );
  65. }
  66. // задание 2 authReducer
  67. {
  68. // Этот редьюсер отвечает за хранение и обработку состояния залогиненности пользователя. Есть два вида состояния: залогинен и не залогинен. Если пользователь залогинен, то состояние будет иметь вид: {token: "jwt токен", payload: {.....раскодированная информация из токена}}. Если же пользователь не залогинен, то состояние будет пустым объектом {}. Редьюсер обрабатывает два типа экшенов: AUTH_LOGIN и AUTH_LOGOUT. Экшен AUTH_LOGIN используется для логина и принимает в качестве аргумента токен, а экшен AUTH_LOGOUT используется для разлогинивания. В случае, если токен не удалось раскодировать, редьюсер возвращает пустой объект, то есть разлогинивает пользователя.
  69. }
  70. // задание 3 cartReducer
  71. {
  72. }
  73. // GraphQL запросы
  74. // Запрос на список корневых категорий
  75. {
  76. results = CategoryFind((query = { parent: null }));
  77. }
  78. // Запрос для получения одной категории с товарами и картинками
  79. {
  80. query {
  81. category(_id: "5f9df9a5f5f5f5f5f5f5f5f5"){
  82. name
  83. products{
  84. name
  85. image
  86. }
  87. subcategories{
  88. name
  89. }
  90. }
  91. }
  92. }
  93. // Запрос на получение товара с описанием и картинками
  94. {
  95. query {
  96. good(_id: "5f9df9a5f5f5f5f5f5f5f5f5"){
  97. name
  98. description
  99. images
  100. }
  101. }
  102. }
  103. // Запрос на регистрацию
  104. {
  105. mutation {
  106. userUpsert(
  107. input: {
  108. username: "newuser"
  109. password: "password123"
  110. }
  111. ) {
  112. user {
  113. _id
  114. username
  115. }
  116. }
  117. }
  118. }
  119. {
  120. mutation {
  121. userUpsert(
  122. _id: "5f9df9a5f5f5f5f5f5f5f5f5",
  123. input: {
  124. username: "updateduser"
  125. password: "newpassword123"
  126. }
  127. ) {
  128. user {
  129. _id
  130. username
  131. }
  132. }
  133. }
  134. }
  135. // Запрос на логин
  136. {
  137. query login($username: String!, $password: String!) {
  138. login(username: $username, password: $password) {
  139. token
  140. }
  141. }
  142. }
  143. // Параметры :
  144. {
  145. {
  146. "username": "your_username",
  147. "password": "your_password"
  148. }
  149. }
  150. // Запрос истории заказов
  151. {
  152. query OrderFind {
  153. OrderFind {
  154. _id
  155. date
  156. status
  157. items {
  158. _id
  159. good {
  160. _id
  161. name
  162. price
  163. }
  164. quantity
  165. }
  166. total
  167. }
  168. }
  169. }
  170. // Запрос оформления заказа
  171. {
  172. mutation OrderUpsert($orderGoods: [OrderGoodInput]) {
  173. OrderUpsert(orderGoods: $orderGoods) {
  174. _id
  175. }
  176. }
  177. }
  178. {
  179. variables: {
  180. orderGoods: [
  181. {good: {_id: "5f16b2efa7d8d922f4df9f9c"}, count: 2},
  182. {good: {_id: "5f16b2efa7d8d922f4df9f9d"}, count: 3}
  183. ]
  184. }
  185. }
  186. // Вспомогательные функции
  187. // getGql
  188. {
  189. function getGQL(url) {
  190. return function gql(query, variables = {}) {
  191. return fetch(url, {
  192. method: 'POST',
  193. headers: {
  194. 'Content-Type': 'application/json',
  195. 'Authorization': `Bearer ${localStorage.getItem('authToken')}`
  196. },
  197. body: JSON.stringify({
  198. query,
  199. variables
  200. })
  201. })
  202. .then(res => res.json())
  203. .then(data => {
  204. if (data.errors) {
  205. throw data.errors;
  206. }
  207. return data.data[Object.keys(data.data)[0]];
  208. });
  209. }
  210. }
  211. }
  212. // localStoredReducer
  213. {
  214. function localStoredReducer(originalReducer, localStorageKey){
  215. let firstRun = true;
  216. function wrapper(state, action){
  217. if(firstRun){
  218. firstRun = false;
  219. try {
  220. const storedState = JSON.parse(localStorage.getItem(localStorageKey));
  221. if(storedState) return storedState;
  222. } catch (error) {
  223. console.log(error);
  224. }
  225. }
  226. const newState = originalReducer(state, action);
  227. localStorage.setItem(localStorageKey, JSON.stringify(newState));
  228. return newState;
  229. }
  230. return wrapper;
  231. }
  232. }
  233. {
  234. const store = createStore(localStoredReducer(cartReducer, 'cart'))
  235. store.subscribe(() => console.log(store.getState()))
  236. store.dispatch(actionCartAdd({_id: 'пиво', price: 50}))
  237. store.dispatch(actionCartAdd({_id: 'чипсы', price: 75}))
  238. }
  239. </script>
  240. </body>
  241. </html>