contentoh-components-library 21.3.33 → 21.3.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/components/atoms/CustomSelectItem/index.js +1 -1
  2. package/dist/components/atoms/InputText/index.js +1 -1
  3. package/dist/components/atoms/ProductPercentCard/index.js +1 -1
  4. package/dist/components/atoms/Select/index.js +1 -1
  5. package/dist/components/molecules/ButtonDownloadFile/index.js +1 -1
  6. package/dist/components/molecules/CarouselImagesLogin/index.js +2 -2
  7. package/dist/components/molecules/ImageTooltip/index.js +7 -21
  8. package/dist/components/molecules/ProductNameHeader/index.js +0 -1
  9. package/dist/components/molecules/SelectV2/index.js +1 -1
  10. package/dist/components/organisms/Chat/Chat.stories.js +6 -5
  11. package/dist/components/organisms/Chat/ChatLists/index.js +2 -2
  12. package/dist/components/organisms/Chat/ContentChat/index.js +97 -58
  13. package/dist/components/organisms/Chat/Footer/index.js +21 -22
  14. package/dist/components/organisms/Chat/index.js +1 -1
  15. package/dist/components/organisms/FullProductNameHeader/index.js +7 -1
  16. package/dist/components/pages/ProviderProductEdition/ProviderProductEdition.stories.js +9 -6
  17. package/dist/global-files/handle_http.js +33 -31
  18. package/package.json +1 -1
  19. package/src/components/atoms/CustomSelectItem/index.js +2 -1
  20. package/src/components/atoms/InputText/index.js +1 -1
  21. package/src/components/atoms/ProductPercentCard/index.js +2 -2
  22. package/src/components/atoms/Select/index.js +1 -1
  23. package/src/components/molecules/ButtonDownloadFile/index.js +1 -1
  24. package/src/components/molecules/CarouselImagesLogin/index.js +2 -2
  25. package/src/components/molecules/ImageTooltip/index.js +7 -17
  26. package/src/components/molecules/ProductNameHeader/index.js +0 -1
  27. package/src/components/molecules/SelectV2/index.js +1 -1
  28. package/src/components/organisms/Chat/Chat.stories.js +5 -4
  29. package/src/components/organisms/Chat/ChatLists/index.js +2 -2
  30. package/src/components/organisms/Chat/ContentChat/index.js +45 -36
  31. package/src/components/organisms/Chat/ContentChat/styles.js +1 -1
  32. package/src/components/organisms/Chat/Footer/index.js +4 -8
  33. package/src/components/organisms/Chat/index.js +1 -1
  34. package/src/components/organisms/FullProductNameHeader/index.js +8 -3
  35. package/src/components/pages/ProviderProductEdition/ProviderProductEdition.stories.js +11 -5
  36. package/src/global-files/handle_http.js +11 -13
@@ -75,9 +75,17 @@ export const ContentChat = (props) => {
75
75
  if (processUpdateID !== undefined) clearTimeout(processUpdateID);
76
76
  };
77
77
  }, []);
78
+
79
+ const stopUpdate = () => {
80
+ if (processUpdateID !== undefined) {
81
+ clearTimeout(processUpdateID);
82
+ setProcessUpdateID(undefined);
83
+ }
84
+ };
85
+
78
86
  // al cargar el componente
79
87
  useEffect(() => {
80
- if (dataChat) {
88
+ if (dataChat && showPopUpChat) {
81
89
  stopUpdate();
82
90
  if (dataChat.code) {
83
91
  setErrorChat({
@@ -93,12 +101,15 @@ export const ContentChat = (props) => {
93
101
  else if (chatType === "order_product") getInitialOrderProduct();
94
102
  else getInitialTicket();
95
103
  }
104
+ if (!showPopUpChat) {
105
+ stopUpdate();
106
+ }
96
107
  }, [dataChat, showPopUpChat]);
97
108
 
98
109
  // comenzar temporizador del update de 20s
99
110
  useEffect(() => {
100
- //return; -- descomentarizar para hacer pruebas sin update
101
- if (startUpdate == 0) return;
111
+ // return; // -- descomentarizar para hacer pruebas sin update
112
+ if (startUpdate === 0) return;
102
113
  const processID = setTimeout(() => {
103
114
  setRunUpdate((prev) => prev + 1);
104
115
  }, 15000);
@@ -109,10 +120,10 @@ export const ContentChat = (props) => {
109
120
  // ejecutar update
110
121
  useEffect(() => {
111
122
  if (chatType === "merchant_product") {
112
- if (singleChat.items) getUpdateLatestMerchantProduct();
123
+ if (singleChat.items) getUpdateLatestMerchantProduct(true);
113
124
  else getInitialMerchantProduct();
114
125
  } else if (chatType === "order_product") {
115
- if (companies) getUpdateLatestOrderProduct();
126
+ if (companies) getUpdateLatestOrderProduct(true);
116
127
  else getInitialOrderProduct();
117
128
  } else {
118
129
  if (singleChat.items) getUpdateLatestTicket(true);
@@ -146,6 +157,7 @@ export const ContentChat = (props) => {
146
157
  return;
147
158
  }
148
159
  // success
160
+ setStartUpdate((prev) => prev + 1);
149
161
  setCurrentUser({
150
162
  id: response.body.data.currentUserId,
151
163
  companyId: response.body.data.currentCompanyId,
@@ -379,16 +391,18 @@ export const ContentChat = (props) => {
379
391
  /*=======================================================================
380
392
  PETICION GET UPDATE_LATEST SEGUN EL TIPO DE CHAT
381
393
  ======================================================================= */
382
- const getUpdateLatestMerchantProduct = async () => {
394
+ const getUpdateLatestMerchantProduct = async (fromUpdate = false) => {
383
395
  const paramsQuery = {
384
396
  getType: "updateLatest",
385
397
  id: JSON.stringify(dataChat.id),
386
398
  version: JSON.stringify(dataChat.version),
387
399
  date: encodeURIComponent(lastUpdateDate),
388
400
  };
401
+ const paramsHeaders = { Authorization: dataChat.userToken };
389
402
  const response = await fetchGET(
390
403
  process.env.REACT_APP_PRODUCTS_CHAT_ENDPOINT,
391
- paramsQuery
404
+ paramsQuery,
405
+ paramsHeaders
392
406
  );
393
407
  if (!response.body) {
394
408
  console.log("ERROR updateLatest:", {
@@ -398,6 +412,7 @@ export const ContentChat = (props) => {
398
412
  return;
399
413
  }
400
414
  // success
415
+ setStartUpdate((prev) => prev + 1);
401
416
  setLastUpdateDate(response.body.data.lastUpdateDate);
402
417
  // actualizar la lista de los users
403
418
  updateAllUsers(response.body.users);
@@ -405,12 +420,13 @@ export const ContentChat = (props) => {
405
420
  let newSingleChat = { ...singleChat };
406
421
  newSingleChat.items = addNewItemsChat(
407
422
  newSingleChat.items,
408
- response.body.items
423
+ response.body.items,
424
+ fromUpdate
409
425
  );
410
426
  setSingleChat(newSingleChat);
411
427
  };
412
428
 
413
- const getUpdateLatestOrderProduct = async () => {
429
+ const getUpdateLatestOrderProduct = async (fromUpdate = false) => {
414
430
  const paramsQuery = {
415
431
  getType: "updateLatest",
416
432
  id: JSON.stringify(dataChat.id),
@@ -436,7 +452,7 @@ export const ContentChat = (props) => {
436
452
  return;
437
453
  }
438
454
  // success
439
-
455
+ setStartUpdate((prev) => prev + 1);
440
456
  // cuando cambie la lista de chats por un cambio de version o estatus
441
457
  if (response.body.data.status) {
442
458
  setIsLoading(true);
@@ -481,7 +497,8 @@ export const ContentChat = (props) => {
481
497
  Object.keys(response.body.companies).forEach((companyId) => {
482
498
  companiesList[companyId].items = addNewItemsChat(
483
499
  companiesList[companyId].items,
484
- response.body.companies[companyId].items
500
+ response.body.companies[companyId].items,
501
+ fromUpdate
485
502
  );
486
503
  });
487
504
  setCompanies(companiesList);
@@ -609,15 +626,13 @@ export const ContentChat = (props) => {
609
626
  };
610
627
 
611
628
  const createItemsMerchantProduct = async (items = []) => {
612
- const paramsBody = {
613
- id: JSON.stringify(dataChat.id),
614
- version: JSON.stringify(dataChat.version),
615
- userId: JSON.stringify(currentUser.id),
616
- items: JSON.stringify(items),
617
- };
629
+ const { id, version } = dataChat;
630
+ const paramsBody = { id, version, items };
631
+ const paramsHeaders = { Authorization: dataChat.userToken };
618
632
  const response = await fetchPOST(
619
633
  process.env.REACT_APP_PRODUCTS_CHAT_ENDPOINT,
620
- paramsBody
634
+ paramsBody,
635
+ paramsHeaders
621
636
  );
622
637
  if (!response.body) {
623
638
  return {
@@ -629,17 +644,16 @@ export const ContentChat = (props) => {
629
644
 
630
645
  const createItemsOrderProduct = async (items = []) => {
631
646
  const paramsBody = {
632
- id: JSON.stringify(dataChat.id),
633
- version: JSON.stringify(currentArticle.version),
634
- userId: JSON.stringify(currentUser.id),
635
- items: JSON.stringify(items),
636
- orderId: JSON.stringify(dataChat.orderId),
637
- sentCompanyId: JSON.stringify(currentUser.companyId),
638
- receivedCompanyId: JSON.stringify(activeCompanyId),
647
+ id: dataChat.id,
648
+ version: currentArticle.version,
649
+ items,
650
+ orderId: dataChat.orderId,
639
651
  };
652
+ const paramsHeaders = { Authorization: dataChat.userToken };
640
653
  const response = await fetchPOST(
641
654
  process.env.REACT_APP_PRODUCTS_CHAT_ENDPOINT,
642
- paramsBody
655
+ paramsBody,
656
+ paramsHeaders
643
657
  );
644
658
  if (!response.body) {
645
659
  return {
@@ -655,9 +669,11 @@ export const ContentChat = (props) => {
655
669
  userId: JSON.stringify(dataChat.currentUser.id),
656
670
  items: JSON.stringify(items),
657
671
  };
672
+ const paramsHeaders = { Authorization: dataChat.userToken };
658
673
  const response = await fetchPOST(
659
674
  process.env.REACT_APP_TICKETS_CHAT_ENDPOINT,
660
- paramsBody
675
+ paramsBody,
676
+ paramsHeaders
661
677
  );
662
678
  if (!response.body) {
663
679
  return {
@@ -739,8 +755,8 @@ export const ContentChat = (props) => {
739
755
  }, 5000);
740
756
  }
741
757
  return Object.values(itemsId).sort((a, b) => {
742
- if (a.id < b.id) return 1;
743
- if (a.id > b.id) return -1;
758
+ if (a.id > b.id) return 1;
759
+ if (a.id < b.id) return -1;
744
760
  return 0;
745
761
  });
746
762
  };
@@ -755,13 +771,6 @@ export const ContentChat = (props) => {
755
771
  setAllUsers(currentUsers);
756
772
  };
757
773
 
758
- const stopUpdate = () => {
759
- if (processUpdateID !== undefined) {
760
- clearTimeout(processUpdateID);
761
- setProcessUpdateID(undefined);
762
- }
763
- };
764
-
765
774
  const renderBodyChat = () => {
766
775
  if (isLoading) return <Loading />;
767
776
  if (errorChat.existError) {
@@ -1,5 +1,5 @@
1
1
  import styled from "styled-components";
2
- import { GlobalColors, FontFamily } from "../../../../global-files/variables";
2
+ import { FontFamily } from "../../../../global-files/variables";
3
3
 
4
4
  export const Container = styled.div`
5
5
  width: 100%;
@@ -3,13 +3,11 @@ import {
3
3
  ContainerItemCarrousel,
4
4
  ContainerMain,
5
5
  ContainerSecondary,
6
- ContainerTooltipFileName,
7
6
  } from "./styles";
8
7
  import { useEffect, useState, useRef } from "react";
9
8
  import AWS from "aws-sdk";
10
9
  import { v4 as uuidv4 } from "uuid";
11
10
  import { Image as CustomImage } from "../../../atoms/Image";
12
- import { ImageTooltip } from "../../../molecules/ImageTooltip";
13
11
  import {
14
12
  faArrowUp as IconSend,
15
13
  faImage as IconImage,
@@ -21,7 +19,7 @@ import { ButtonV2 } from "../../../atoms/ButtonV2";
21
19
  import { IconFile } from "../../../atoms/IconFile";
22
20
  import { Modal } from "../../Modal";
23
21
  import { Tooltip } from "../../../atoms/Tooltip";
24
- import { Fade, Tooltip as TooltipMUI, Zoom } from "@mui/material";
22
+ import { Fade, Tooltip as TooltipMUI } from "@mui/material";
25
23
  import { ButtonFileChooser } from "../../../atoms/ButtonFileChooser";
26
24
  import { Slide } from "@mui/material";
27
25
  // carrousel
@@ -186,7 +184,7 @@ export const Footer = (props) => {
186
184
  }
187
185
  // enviar file a AWS
188
186
  customFiles.push({
189
- itemType: file.type.split("/")[0] == "image" ? "img" : "file",
187
+ itemType: file.type.split("/")[0] === "image" ? "img" : "file",
190
188
  key: fileKey,
191
189
  errorOwn: errorMessage,
192
190
  });
@@ -208,6 +206,7 @@ export const Footer = (props) => {
208
206
  }
209
207
  });
210
208
  } catch (err) {
209
+ console.log(err);
211
210
  disableSecondaryContainer(false);
212
211
  setModalAlert({
213
212
  show: true,
@@ -236,10 +235,7 @@ export const Footer = (props) => {
236
235
  valueItem.height = imgSize.height;
237
236
  }
238
237
  }
239
- items.push({
240
- type: file.itemType,
241
- value: JSON.stringify(valueItem),
242
- });
238
+ items.push({ type: file.itemType, value: JSON.stringify(valueItem) });
243
239
  }
244
240
  }
245
241
 
@@ -166,7 +166,7 @@ export const Chat = (props) => {
166
166
 
167
167
  // convertir user TECH a NORMAL si es el propietario del ticket
168
168
  let isUserTech = currentUser.isUserTech;
169
- if (isUserTech && currentUser.id == ticketOwnerUserId) {
169
+ if (isUserTech && currentUser.id === ticketOwnerUserId) {
170
170
  isUserTech = false;
171
171
  }
172
172
  setData({
@@ -19,6 +19,7 @@ export const FullProductNameHeader = ({
19
19
  showApproveRejectAll,
20
20
  }) => {
21
21
  const [retailers, setRetailers] = useState([]);
22
+
22
23
  useEffect(() => {
23
24
  const rtls = headerData?.retailers || headerData?.retailersAvailable;
24
25
  servicesData &&
@@ -33,6 +34,12 @@ export const FullProductNameHeader = ({
33
34
  });
34
35
  setRetailers(rtls);
35
36
  }, [servicesData]);
37
+
38
+ const getTime = (date) => {
39
+ if (!date) return "";
40
+ return new Date(date).toLocaleDateString();
41
+ };
42
+
36
43
  return (
37
44
  <Container>
38
45
  <ProductNameHeader
@@ -45,9 +52,7 @@ export const FullProductNameHeader = ({
45
52
  percentRequired={percent}
46
53
  percent={percent?.toFixed(0)}
47
54
  priority={headerData?.prio}
48
- date={new Date(
49
- headerData?.article?.timestamp || headerData?.timestamp
50
- ).toLocaleDateString()}
55
+ date={getTime(headerData?.article?.timestamp || headerData?.timestamp)}
51
56
  />
52
57
  <div className="features-bar-container">
53
58
  <FeaturesBar
@@ -12,11 +12,11 @@ export const ProviderProductEditionDefault = Template.bind({});
12
12
  ProviderProductEditionDefault.args = {
13
13
  tabsSections: {
14
14
  Descripción: true,
15
- "Ficha técnica": true,
16
- Imágenes: true,
15
+ "Ficha técnica": false,
16
+ Imágenes: false,
17
17
  },
18
18
  token:
19
- "eyJraWQiOiJkQWJkZCtlclwvTlwveVRQUWNvUlVyOCtrNUd2M1hMM2N1MWUzQ09zWExVRnc9IiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiI1ODg0YWUzNC01OWQ2LTQ0NTQtYjk4ZS04MjE1MThiY2MzYTciLCJjb2duaXRvOmdyb3VwcyI6WyJ1c3VhcmlvX2NvbnRlbnRvaCJdLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiaXNzIjoiaHR0cHM6XC9cL2NvZ25pdG8taWRwLnVzLWVhc3QtMS5hbWF6b25hd3MuY29tXC91cy1lYXN0LTFfWE1aUWRxa0dqIiwicGhvbmVfbnVtYmVyX3ZlcmlmaWVkIjpmYWxzZSwiY29nbml0bzp1c2VybmFtZSI6IjU4ODRhZTM0LTU5ZDYtNDQ1NC1iOThlLTgyMTUxOGJjYzNhNyIsImNvZ25pdG86cm9sZXMiOlsiYXJuOmF3czppYW06Ojg5ODY3MDIzMjgwNzpyb2xlXC9jb250ZW50b2gtZGV2LXVzLWVhc3QtMS1sYW1iZGFSb2xlIl0sImF1ZCI6IjVhYzh0cGdzNmdic3ExM2ZydnJwaWVlcDQwIiwiZXZlbnRfaWQiOiIwM2UyYWU3NS1hNzg0LTQwM2UtODE1YS0wOWUzYTZkYjg1M2UiLCJ0b2tlbl91c2UiOiJpZCIsImF1dGhfdGltZSI6MTY4MDAyNzUyNSwibmFtZSI6IkNhZGVuYSBJc21hZWwiLCJwaG9uZV9udW1iZXIiOiIrNTIzMTExMzY2MzM2IiwiZXhwIjoxNjgwMDMxMTI1LCJpYXQiOjE2ODAwMjc1MjUsImVtYWlsIjoiY2FkZW5hLmlzbWFlbEBhbGxmcmVlbWFpbC5uZXQifQ.cHoFb-dn2q9GkDfippwUGNLMMtn-1-36Jhuhi8zhHEKlvPf6QIqCzM7vs0WBAkCNlOLrE3pr00LwemQi9TMJENqnQ2d2mbZ9QrOwFDSxkk-8-J7wbcRdaLmQFebIJmx8Ta1mAJDqEXsx7LTWW8D1N28bA3DKUS7Jnw411kC-4C2nT-zr0jRD5D0998dOROkDg6_Rp27sPE-B3H3Su0Of4C6olqYLNdZSCRJBTiXs5zJqmvZxtDcr20EFTWfNzXjHP2BNsylUHe9AKZI_pNjA3zhApfddZiYHWt8IMsJCSoW8yp8orZkwNew0BaHCFCk2UjyQu3NlW8i6D4aVnullqQ",
19
+ "eyJraWQiOiJkQWJkZCtlclwvTlwveVRQUWNvUlVyOCtrNUd2M1hMM2N1MWUzQ09zWExVRnc9IiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiI1ODg0YWUzNC01OWQ2LTQ0NTQtYjk4ZS04MjE1MThiY2MzYTciLCJjb2duaXRvOmdyb3VwcyI6WyJ1c3VhcmlvX2NvbnRlbnRvaCJdLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiaXNzIjoiaHR0cHM6XC9cL2NvZ25pdG8taWRwLnVzLWVhc3QtMS5hbWF6b25hd3MuY29tXC91cy1lYXN0LTFfWE1aUWRxa0dqIiwicGhvbmVfbnVtYmVyX3ZlcmlmaWVkIjpmYWxzZSwiY29nbml0bzp1c2VybmFtZSI6IjU4ODRhZTM0LTU5ZDYtNDQ1NC1iOThlLTgyMTUxOGJjYzNhNyIsImNvZ25pdG86cm9sZXMiOlsiYXJuOmF3czppYW06Ojg5ODY3MDIzMjgwNzpyb2xlXC9jb250ZW50b2gtZGV2LXVzLWVhc3QtMS1sYW1iZGFSb2xlIl0sImF1ZCI6IjVhYzh0cGdzNmdic3ExM2ZydnJwaWVlcDQwIiwiZXZlbnRfaWQiOiJlZjViNDQzYi02ODc0LTQ2NGQtOWZiZS00Y2UwNWU4ZDQ3YTEiLCJ0b2tlbl91c2UiOiJpZCIsImF1dGhfdGltZSI6MTY4MDAzODYyNiwibmFtZSI6IkNhZGVuYSBJc21hZWwiLCJwaG9uZV9udW1iZXIiOiIrNTIzMTExMzY2MzM2IiwiZXhwIjoxNjgwMDQyMjI1LCJpYXQiOjE2ODAwMzg2MjYsImVtYWlsIjoiY2FkZW5hLmlzbWFlbEBhbGxmcmVlbWFpbC5uZXQifQ.rhufpJdUaJOpiKtXJgNoDq863ecFnLp63c9_6NeEbpYYNN19d_xac8aZADN-QMpkmz1oxtqfxf_-JN5jMJexi9gJCRb9O7-xL75v_G9UjdmE8sRA6qRNb_tFUCt1oee_ulgqm_2wTjb7qGMGvY1eb1J1IX2pBYKnBy64KM6J5xFfZ57ac_bGruYhCzUexPBWyZKc5ckoY2zJqK5m5Ok7ds0m1hC0t-eQSGX_8KMsGQKiHevQ07cZUQ9mxOGVweRuAqITNx8fVmpD9QTpoZJJ5STVVcKO2CS0ltyE_DNlyejO7mZqbKvGEeLYc4ga0nozK9aP8H2cN_topT0d4JZ5rA",
20
20
  articleId: 238,
21
21
  category: 846,
22
22
  version: 2,
@@ -59,7 +59,13 @@ ProviderProductEditionDefault.args = {
59
59
  ],
60
60
  },
61
61
  location: {
62
- state: { origin: "Contentoh", withChat: true },
62
+ pathname: "/EditProducts",
63
+ search: "",
64
+ hash: "",
65
+ state: {
66
+ withChat: true,
67
+ },
68
+ key: "24vwut",
63
69
  },
64
70
  user: {
65
71
  id_user: 59,
@@ -93,7 +99,7 @@ ProviderProductEditionDefault.args = {
93
99
  products_limit: "500",
94
100
  type: "PyMES",
95
101
  },
96
- src: "https://content-management-profile.s3.amazonaws.com/id-59/59.png?1680027527535",
102
+ src: "https://content-management-profile.s3.amazonaws.com/id-59/59.png?1680038627077",
97
103
  },
98
104
  company: {
99
105
  id_company: 817,
@@ -1,6 +1,14 @@
1
1
  import axios from "axios";
2
2
 
3
- //============================================================
3
+ const objToQueryString = (obj) => {
4
+ if (!Object.values(obj).length) return null;
5
+ return Object.entries(obj)
6
+ .map(
7
+ ([key, value]) => `${key}=${encodeURIComponent(JSON.stringify(value))}`
8
+ )
9
+ .join("&");
10
+ };
11
+
4
12
  /**
5
13
  * funcion que realiza un axios GET
6
14
  *
@@ -10,10 +18,7 @@ import axios from "axios";
10
18
  * body: {} | undefined ,
11
19
  * message: string,
12
20
  * errorDetail: string
13
- * }> }
14
- *
15
- */
16
- //============================================================
21
+ * }> } */
17
22
  export const fetchGET = (
18
23
  endpoint = "",
19
24
  paramsQuery = {},
@@ -21,16 +26,9 @@ export const fetchGET = (
21
26
  ) => {
22
27
  return new Promise(async (response) => {
23
28
  try {
24
- let URL = endpoint;
29
+ let URL = `${endpoint}?${objToQueryString(paramsQuery)}`;
25
30
  const keysParamsQuery = Object.keys(paramsQuery);
26
31
  // agregar cada param query a la URL
27
- keysParamsQuery.forEach((key, index) => {
28
- if (index == 0) {
29
- URL += `?${key}=${paramsQuery[key]}`;
30
- } else {
31
- URL += `&${key}=${paramsQuery[key]}`;
32
- }
33
- });
34
32
  const respHTTPjson = await axios.get(URL, { headers: paramsHeaders });
35
33
  // verificar si existe un error en la peticion realizada
36
34
  if (respHTTPjson.status !== 200) {