@eohjsc/react-native-smart-city 0.2.93 → 0.2.96

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 (65) hide show
  1. package/assets/images/Device/air-dry.svg +3 -0
  2. package/assets/images/Device/auto.svg +3 -0
  3. package/assets/images/Device/circulator.svg +4 -0
  4. package/assets/images/Device/clean.svg +5 -0
  5. package/package.json +2 -2
  6. package/src/Images/Common/member.svg +4 -0
  7. package/src/Images/Common/owner.svg +3 -0
  8. package/src/commons/ActionGroup/NumberUpDownActionTemplate.js +5 -1
  9. package/src/commons/ActionGroup/OptionsDropdownActionTemplate.js +5 -1
  10. package/src/commons/ActionGroup/StatesGridActionTemplate.js +42 -36
  11. package/src/commons/ActionGroup/StatesGridActionTemplateStyle.js +5 -10
  12. package/src/commons/ActionGroup/__test__/OptionsDropdownTemplate.test.js +2 -2
  13. package/src/commons/Connecting /__test__/Connecting.test.js +23 -0
  14. package/src/commons/Connecting /index.js +67 -0
  15. package/src/commons/Connecting /styles.js +28 -0
  16. package/src/commons/ConnectingProcess/index.js +3 -54
  17. package/src/commons/Explore/SearchBox/__test__/SearchBox.test.js +19 -0
  18. package/src/commons/Explore/SearchBox/index.js +2 -0
  19. package/src/commons/MenuActionMore/index.js +10 -3
  20. package/src/commons/Modal/ModalCustom.js +9 -1
  21. package/src/commons/Sharing/MemberList.js +5 -10
  22. package/src/commons/Sharing/RowMember.js +128 -38
  23. package/src/commons/Sharing/__test__/MemberList.test.js +3 -3
  24. package/src/commons/Sharing/__test__/RowMember.test.js +4 -4
  25. package/src/configs/API.js +12 -2
  26. package/src/configs/Colors.js +1 -0
  27. package/src/configs/Constants.js +13 -0
  28. package/src/hooks/Common/useSensorsStatus.js +33 -23
  29. package/src/navigations/UnitStack.js +16 -0
  30. package/src/screens/AddCommon/SelectSubUnit.js +1 -0
  31. package/src/screens/AddCommon/__test__/SelectSubUnit.test.js +2 -0
  32. package/src/screens/AddNewGateway/PlugAndPlay/ConnectWifiWarning.js +12 -3
  33. package/src/screens/AddNewGateway/PlugAndPlay/FirstWarning.js +5 -1
  34. package/src/screens/AddNewGateway/PlugAndPlay/GatewayWifiList.js +9 -1
  35. package/src/screens/EditActionsList/Styles/indexStyles.js +1 -0
  36. package/src/screens/EmergencyContacts/EmergencyContactsList.js +1 -1
  37. package/src/screens/EmergencyContacts/EmergencyContactsSelectContacts.js +29 -11
  38. package/src/screens/EmergencyContacts/__test__/EmergencyContactList.test.js +1 -0
  39. package/src/screens/EmergencyContacts/__test__/EmergencyContactsSelectContacts.test.js +56 -0
  40. package/src/screens/EnterPassword/__test__/EnterPassword.test.js +124 -0
  41. package/src/screens/EnterPassword/index.js +84 -0
  42. package/src/screens/EnterPassword/styles.js +36 -0
  43. package/src/screens/MoveToAnotherSubUnit/index.js +3 -1
  44. package/src/screens/Sharing/Components/ItemChangeRole.js +43 -0
  45. package/src/screens/Sharing/Components/SensorItem.js +7 -1
  46. package/src/screens/Sharing/Components/Styles/ItemChangeRoleStyles.js +35 -0
  47. package/src/screens/Sharing/Components/__test__/ItemChangeRole.test.js +37 -0
  48. package/src/screens/Sharing/Components/__test__/SensorItem.test.js +53 -0
  49. package/src/screens/Sharing/InfoMemberUnit.js +274 -0
  50. package/src/screens/Sharing/MemberList.js +50 -53
  51. package/src/screens/Sharing/SelectPermission.js +93 -12
  52. package/src/screens/Sharing/Styles/inforMemberUnitStyles.js +92 -0
  53. package/src/screens/Sharing/__test__/InfoMemberUnit.test.js +121 -0
  54. package/src/screens/Sharing/__test__/MemberList.test.js +9 -24
  55. package/src/screens/Sharing/__test__/SelectPermission.test.js +53 -0
  56. package/src/screens/Sharing/hooks/index.js +76 -32
  57. package/src/screens/Unit/Detail.js +12 -10
  58. package/src/screens/Unit/ManageUnit.js +5 -5
  59. package/src/screens/Unit/ManageUnitStyles.js +1 -0
  60. package/src/screens/UnitSummary/components/3PPowerConsumption/index.js +1 -1
  61. package/src/screens/UnitSummary/components/PowerConsumption/index.js +1 -1
  62. package/src/utils/I18n/translations/en.json +14 -2
  63. package/src/utils/I18n/translations/vi.json +11 -1
  64. package/src/utils/Route/index.js +2 -0
  65. package/src/utils/Utils.js +21 -0
@@ -0,0 +1,3 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M12.1302 0.511174C11.3959 1.343 4.08508 10.1691 4.08508 15.4443C4.08508 19.8876 7.68713 23.4894 12.1302 23.4894C16.5733 23.4894 20.1753 19.8876 20.1753 15.4443C20.1753 9.80224 12.1024 0.427685 12.1302 0.511174ZM11.6441 21.4844L11.6203 21.4839C9.92602 21.3784 7.67768 20.7243 6.57036 18.2043C6.47513 17.9873 6.57445 17.7332 6.79121 17.6375C7.00644 17.5443 7.26559 17.6479 7.35802 17.8581C8.29096 19.9816 10.2178 20.5348 11.6706 20.625C11.907 20.6395 12.0878 20.844 12.0733 21.0807C12.0587 21.3072 11.8703 21.4844 11.6441 21.4844Z" fill="#262626"/>
3
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M10 18C14.42 18 18 14.42 18 10C18 5.58 14.42 2 10 2C5.58 2 2 5.58 2 10C2 14.42 5.58 18 10 18ZM10 0C15.52 0 20 4.48 20 10C20 15.43 15.67 19.85 10.28 20H10C4.48 20 0 15.52 0 10C0 4.48 4.48 0 10 0ZM10.83 5H9.18L6 14H8.24L8.67 12.66H11.35L11.75 14H14L10.83 5ZM10.06 8.41L10.8 10.81H9.28L10.06 8.41Z" fill="#262626"/>
3
+ </svg>
@@ -0,0 +1,4 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M2.11682 11.024C2.40536 9.18824 3.22604 7.47741 4.47723 6.1034C5.72841 4.72939 7.35515 3.75257 9.15598 3.29389C10.9568 2.83521 12.8526 2.91484 14.6087 3.5229C16.3647 4.13096 17.9038 5.24075 19.0353 6.71483L19.6441 7.50745V4.69527H21.0013V10.1242H15.5724V8.76696H17.9944L17.6211 8.23323C16.7705 7.01113 15.5737 6.0715 14.1846 5.53525C12.7956 4.999 11.2778 4.89065 9.82666 5.22414C8.37551 5.55764 7.05734 6.31772 6.04175 7.40659C5.02617 8.49547 4.35963 9.86332 4.12789 11.3342L2.11682 11.024Z" fill="black"/>
3
+ <path d="M11.5006 22C10.0429 22.0056 8.60381 21.673 7.29637 21.0285C5.98894 20.3839 4.84881 19.4449 3.96561 18.2852L3.35723 17.4913V20.3034H2V14.8745H7.42891V16.2317H5.00694L5.38018 16.7655C6.23084 17.9875 7.4277 18.9271 8.81677 19.4633C10.2058 19.9996 11.7236 20.1079 13.1747 19.7744C14.6259 19.4409 15.9441 18.6809 16.9597 17.592C17.9753 16.5032 18.6419 15.1354 18.8737 13.6646L20.8852 13.9747C20.5347 16.2116 19.3964 18.2497 17.6756 19.7212C15.9548 21.1928 13.7648 22.001 11.5006 22Z" fill="black"/>
4
+ </svg>
@@ -0,0 +1,5 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M23.2968 16.5784C21.8701 16.5784 20.5301 16.028 19.5234 15.0284C18.517 14.0294 17.963 12.6988 17.963 11.2817C17.963 10.8934 17.648 10.5786 17.2598 10.5786C16.8715 10.5786 16.5567 10.8934 16.5567 11.2817C16.5567 12.6988 16.0024 14.0294 14.9961 15.0284C13.9894 16.028 12.6494 16.5784 11.2227 16.5784C10.8343 16.5784 10.5195 16.8932 10.5195 17.2816C10.5195 17.6699 10.8343 17.9847 11.2227 17.9847C14.1637 17.9847 16.5567 20.3678 16.5567 23.2969C16.5567 23.6853 16.8715 24.0001 17.2598 24.0001C17.648 24.0001 17.963 23.6853 17.963 23.2969C17.963 20.3678 20.3558 17.9847 23.2968 17.9847C23.6852 17.9847 23.9999 17.6699 23.9999 17.2816C23.9999 16.8932 23.6852 16.5784 23.2968 16.5784Z" fill="black"/>
3
+ <path d="M9.62036 11.0806C7.54962 11.0806 5.86487 9.40826 5.86487 7.35254C5.86487 6.96436 5.55011 6.64941 5.16174 6.64941C4.77338 6.64941 4.45862 6.96436 4.45862 7.35254C4.45862 9.40826 2.77386 11.0806 0.703125 11.0806C0.314758 11.0806 0 11.3955 0 11.7837C0 12.1721 0.314758 12.4868 0.703125 12.4868C2.77386 12.4868 4.45862 14.1644 4.45862 16.2264C4.45862 16.6146 4.77338 16.9295 5.16174 16.9295C5.55011 16.9295 5.86487 16.6146 5.86487 16.2264C5.86487 14.1644 7.54962 12.4868 9.62036 12.4868C10.0087 12.4868 10.3235 12.1721 10.3235 11.7837C10.3235 11.3955 10.0087 11.0806 9.62036 11.0806Z" fill="black"/>
4
+ <path d="M10.7642 4.85889C12.287 4.85889 13.5261 6.08844 13.5261 7.59961C13.5261 7.98779 13.8409 8.30273 14.2292 8.30273C14.6176 8.30273 14.9324 7.98779 14.9324 7.59961C14.9324 6.0835 16.1714 4.8501 17.6943 4.8501C18.0827 4.8501 18.3975 4.53516 18.3975 4.14697C18.3975 3.75861 18.0827 3.44385 17.6943 3.44385C16.1714 3.44385 14.9324 2.21429 14.9324 0.703125C14.9324 0.314758 14.6176 0 14.2292 0C13.8409 0 13.5261 0.314758 13.5261 0.703125C13.5261 2.21924 12.287 3.45264 10.7642 3.45264C10.3758 3.45264 10.061 3.7674 10.061 4.15576C10.061 4.54413 10.3758 4.85889 10.7642 4.85889Z" fill="black"/>
5
+ </svg>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@eohjsc/react-native-smart-city",
3
3
  "title": "React Native Smart Home",
4
- "version": "0.2.93",
4
+ "version": "0.2.96",
5
5
  "description": "TODO",
6
6
  "main": "index.js",
7
7
  "files": [
@@ -97,7 +97,7 @@
97
97
  "dependencies": {
98
98
  "@ant-design/icons-react-native": "^2.2.1",
99
99
  "@ant-design/react-native": "^4.0.5",
100
- "@eohjsc/highcharts": "^1.0.6",
100
+ "@eohjsc/highcharts": "^1.0.8",
101
101
  "@eohjsc/react-native-keyboard-aware-scroll-view": "^0.9.5",
102
102
  "@formatjs/intl-getcanonicallocales": "^1.4.5",
103
103
  "@formatjs/intl-numberformat": "^5.6.2",
@@ -0,0 +1,4 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M12 6C13.1046 6 14 5.10457 14 4C14 2.89543 13.1046 2 12 2C10.8954 2 10 2.89543 10 4C10 5.10457 10.8954 6 12 6Z" fill="#262626"/>
3
+ <path d="M15.89 8.11C15.5 7.72 14.83 7 13.53 7C13.32 7 12.11 7 10.99 7C8.24 6.99 6 4.75 6 2H4C4 5.16 6.11 7.84 9 8.71V22H11V16H13V22H15V10.05L18.95 14L20.36 12.59L15.89 8.11Z" fill="#262626"/>
4
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M21.753 9.0184C21.753 9.66253 21.2308 10.1847 20.5867 10.1847C20.4682 10.1847 20.3559 10.1617 20.2483 10.1291L18.5961 15.808H5.15687L3.50472 10.1291C3.39711 10.1617 3.28483 10.1847 3.16633 10.1847C2.52221 10.1847 2 9.66253 2 9.0184C2 8.37428 2.52221 7.85207 3.16633 7.85207C3.81046 7.85207 4.33266 8.37428 4.33266 9.0184C4.33266 9.24732 4.26424 9.45912 4.15041 9.6392L7.88142 12.1939L8.36195 7.3196C7.78003 7.25367 7.32625 6.76567 7.32625 6.16633C7.32625 5.52221 7.84846 5 8.49258 5C9.13671 5 9.65892 5.52221 9.65892 6.16633C9.65892 6.59305 9.42752 6.96224 9.08539 7.16565L11.8765 11.7398L14.6863 7.13517C14.3743 6.92585 14.1687 6.57035 14.1687 6.16633C14.1687 5.52221 14.6909 5 15.3351 5C15.9792 5 16.5014 5.52221 16.5014 6.16633C16.5014 6.79118 16.0091 7.2969 15.392 7.32707L15.8716 12.1939L19.6026 9.6392C19.4888 9.45912 19.4203 9.24732 19.4203 9.0184C19.4203 8.37428 19.9425 7.85207 20.5867 7.85207C21.2308 7.85207 21.753 8.37428 21.753 9.0184ZM5.15782 16.6384H18.5962V18.712H5.15782V16.6384Z" fill="#262626"/>
3
+ </svg>
@@ -39,7 +39,11 @@ const NumberUpDownActionTemplate = ({ actionGroup, doAction, sensor }) => {
39
39
 
40
40
  const doActionAndWatchConfig = useCallback(
41
41
  (actionData, actionValue, actionName) => {
42
- doAction(actionData, actionValue, actionName);
42
+ doAction(
43
+ actionData,
44
+ JSON.stringify({ temperature: actionValue }),
45
+ actionName
46
+ );
43
47
  if (!sensor?.is_managed_by_backend) {
44
48
  return;
45
49
  }
@@ -61,7 +61,11 @@ const OptionsDropdownActionTemplate = ({ actionGroup, doAction, sensor }) => {
61
61
  const value = getOptionValue(newOption);
62
62
  let actionName = `${sensor?.name} ${title?.toLowerCase()} ${value}`;
63
63
  actionName = actionName.replace(/\s+/g, ' ').trim();
64
- doAction(action_data, value, actionName);
64
+ doAction(
65
+ action_data,
66
+ JSON.stringify({ level: value, key_code: newOption?.value_int }),
67
+ actionName
68
+ );
65
69
  if (sensor?.is_managed_by_backend) {
66
70
  configuration.config && watchMultiConfigs([configuration.config]);
67
71
  }
@@ -8,6 +8,10 @@ import { watchMultiConfigs } from '../../iot/Monitor';
8
8
  import IconComponent from '../IconComponent';
9
9
  import styles from './StatesGridActionTemplateStyle';
10
10
  import { TESTID } from '../../configs/Constants';
11
+ import SvgClean from '../../../assets/images/Device/clean.svg';
12
+ import SvgCirculator from '../../../assets/images/Device/circulator.svg';
13
+ import SvgAuo from '../../../assets/images/Device/auto.svg';
14
+ import SvgAirDry from '../../../assets/images/Device/air-dry.svg';
11
15
 
12
16
  const buttonStyle = {
13
17
  OFF: {
@@ -21,21 +25,6 @@ const buttonStyle = {
21
25
  };
22
26
 
23
27
  const GridItem = ({ item, index, length, doAction, sensor, title }) => {
24
- const isFirst = index === 0;
25
- const isLast = index === length - 1;
26
- const isNextLine = index % 4 === 0;
27
-
28
- let extraStyle = {};
29
- if (isFirst || isNextLine) {
30
- extraStyle.marginLeft = 24;
31
- }
32
- if (isLast) {
33
- extraStyle.marginRight = 24;
34
- }
35
- if (index > 3) {
36
- extraStyle.marginTop = 24;
37
- }
38
-
39
28
  const {
40
29
  active,
41
30
  text,
@@ -46,6 +35,7 @@ const GridItem = ({ item, index, length, doAction, sensor, title }) => {
46
35
  config,
47
36
  } = item;
48
37
  const buttonOnOffStyle = active ? buttonStyle.ON : buttonStyle.OFF;
38
+ const checkIcon = /\d/.test(icon); // to do check icon svg and icon antDesign
49
39
 
50
40
  const doActionAndWatchConfig = useCallback(
51
41
  (actionData) => {
@@ -63,22 +53,40 @@ const GridItem = ({ item, index, length, doAction, sensor, title }) => {
63
53
 
64
54
  const iconKit = !!icon_kit_data && icon_kit_data.icon;
65
55
 
56
+ const iconSvg = useMemo(() => {
57
+ switch (icon) {
58
+ case 'clean-1':
59
+ return <SvgClean width={24} height={24} />;
60
+ case 'circulator-1':
61
+ return <SvgCirculator width={24} height={24} />;
62
+ case 'auto-1':
63
+ return <SvgAuo width={24} height={24} />;
64
+ case 'air-dry-1':
65
+ return <SvgAirDry width={24} height={24} />;
66
+ default:
67
+ return () => <></>;
68
+ }
69
+ }, [icon]);
70
+
66
71
  return (
67
72
  <View
68
- style={[styles.gridItem, extraStyle]}
73
+ style={[styles.gridItem]}
69
74
  testID={TESTID.STATES_GRID_ACTION_GRID_ITEM}
70
75
  >
71
76
  <TouchableOpacity
72
77
  style={[styles.button, buttonOnOffStyle]}
73
78
  onPress={() => doActionAndWatchConfig(action_data)}
74
79
  >
75
- <IconComponent
76
- icon={icon}
77
- iconKit={iconKit}
78
- icon_outlined={icon_outlined}
79
- isSendingCommand={false}
80
- size={24}
81
- />
80
+ {!checkIcon && (
81
+ <IconComponent
82
+ icon={icon}
83
+ iconKit={iconKit}
84
+ icon_outlined={icon_outlined}
85
+ isSendingCommand={false}
86
+ size={24}
87
+ />
88
+ )}
89
+ {checkIcon && <View>{iconSvg}</View>}
82
90
  </TouchableOpacity>
83
91
  <Text center color={Colors.Gray8} style={styles.textMargin}>
84
92
  {text}
@@ -116,19 +124,17 @@ const StatesGridActionTemplate = ({ actionGroup, doAction, sensor }) => {
116
124
  <Text type="H4" style={styles.textModeMargin}>
117
125
  {title}
118
126
  </Text>
119
- <View style={styles.center}>
120
- <View style={styles.wrapOption}>
121
- {options.map((item, index) => (
122
- <GridItem
123
- item={item}
124
- index={index}
125
- length={options.length}
126
- doAction={doAction}
127
- sensor={sensor}
128
- title={title}
129
- />
130
- ))}
131
- </View>
127
+ <View style={styles.wrapOption}>
128
+ {options.map((item, index) => (
129
+ <GridItem
130
+ item={item}
131
+ index={index}
132
+ length={options.length}
133
+ doAction={doAction}
134
+ sensor={sensor}
135
+ title={title}
136
+ />
137
+ ))}
132
138
  </View>
133
139
  </View>
134
140
  );
@@ -8,23 +8,18 @@ export default StyleSheet.create({
8
8
  marginHorizontal: 20,
9
9
  borderWidth: 1,
10
10
  borderColor: Colors.Gray4,
11
- borderTopWidth: 0,
11
+ borderTopRightRadius: 10,
12
+ borderTopLeftRadius: 10,
12
13
  borderBottomRightRadius: 10,
13
14
  borderBottomLeftRadius: 10,
14
- },
15
- center: {
16
- flex: 1,
17
- alignItems: 'center',
15
+ marginTop: 20,
18
16
  },
19
17
  wrapOption: {
20
18
  flex: 1,
21
19
  flexDirection: 'row',
20
+ justifyContent: 'space-between',
22
21
  flexWrap: 'wrap',
23
- width: 312,
24
- },
25
- gridItem: {
26
- width: 48,
27
- marginHorizontal: 12,
22
+ paddingHorizontal: 16,
28
23
  },
29
24
  textMargin: {
30
25
  marginTop: 8,
@@ -152,7 +152,7 @@ describe('Test OptionsDropdownActionTemplate', () => {
152
152
 
153
153
  expect(mockDoAction).toHaveBeenCalledWith(
154
154
  action_data,
155
- 1,
155
+ JSON.stringify({ level: 1, key_code: 1 }),
156
156
  'Sensor name fan speed 1'
157
157
  );
158
158
  is_managed_by_backend
@@ -221,7 +221,7 @@ describe('Test OptionsDropdownActionTemplate', () => {
221
221
 
222
222
  expect(mockDoAction).toHaveBeenCalledWith(
223
223
  action_data,
224
- 'level-1',
224
+ JSON.stringify({ level: 'level-1', key_code: 1 }),
225
225
  'Sensor name fan speed level-1'
226
226
  ); // doAction with text instead of int
227
227
 
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+ import renderer, { act } from 'react-test-renderer';
3
+ import Connecting from '../index';
4
+ import Text from '../../Text';
5
+ import { SCProvider } from '../../../context';
6
+ import { mockSCStore } from '../../../context/mockStore';
7
+
8
+ const wrapComponent = (route) => (
9
+ <SCProvider initState={mockSCStore({})}>
10
+ <Connecting route={route} />
11
+ </SCProvider>
12
+ );
13
+ describe('Test Connecting', () => {
14
+ let tree;
15
+ test('create Connecting', () => {
16
+ act(() => {
17
+ tree = renderer.create(wrapComponent());
18
+ });
19
+ const instance = tree.root;
20
+ const text = instance.findAllByType(Text);
21
+ expect(text).toHaveLength(4);
22
+ });
23
+ });
@@ -0,0 +1,67 @@
1
+ import React, { useEffect, useCallback, useState } from 'react';
2
+ import { View } from 'react-native';
3
+ import * as Progress from 'react-native-progress';
4
+ import Text from '../Text';
5
+ import { Colors, Constants } from '../../configs';
6
+ import styles from './styles';
7
+ import { useTranslations } from '../../hooks/Common/useTranslations';
8
+ import { HeaderCustom } from '../Header';
9
+
10
+ const Connecting = ({ isLoading, isConnect, isPercentConnect }) => {
11
+ const t = useTranslations();
12
+ const [percent, setPercent] = useState(0);
13
+
14
+ useEffect(() => {
15
+ processLoading();
16
+ }, [processLoading]);
17
+
18
+ const processLoading = useCallback(() => {
19
+ let interval;
20
+ if (isLoading) {
21
+ interval = setInterval(() => {
22
+ setPercent((prev) => {
23
+ if (prev === 1) {
24
+ clearInterval(interval);
25
+ return 1;
26
+ } else if (prev === 0.8 && isConnect) {
27
+ clearInterval(interval);
28
+ return 0.8;
29
+ } else {
30
+ return prev + 0.2;
31
+ }
32
+ });
33
+ }, 180);
34
+ } else {
35
+ clearInterval(interval);
36
+ }
37
+ }, [isConnect, isLoading]);
38
+ return (
39
+ <View style={styles.screen}>
40
+ <HeaderCustom title={t('connect_device')} isShowSeparator />
41
+ <View style={styles.body}>
42
+ <View style={styles.connecting}>
43
+ <Text type="H4" bold>
44
+ {t('connecting')}
45
+ </Text>
46
+ </View>
47
+ <View style={styles.percentLoad}>
48
+ <Progress.Bar
49
+ progress={isPercentConnect || percent}
50
+ animated={true}
51
+ color={Colors.Primary}
52
+ indeterminateAnimationDuration={1000}
53
+ height={7}
54
+ width={Constants.width - 80}
55
+ useNativeDriver={true}
56
+ />
57
+ <Text style={styles.textPercentLoad}>{`${parseInt(
58
+ (isPercentConnect || percent) * 100,
59
+ 10
60
+ )}%`}</Text>
61
+ </View>
62
+ </View>
63
+ </View>
64
+ );
65
+ };
66
+
67
+ export default Connecting;
@@ -0,0 +1,28 @@
1
+ import { StyleSheet } from 'react-native';
2
+ import { Constants } from '../../configs';
3
+
4
+ export default StyleSheet.create({
5
+ screen: {
6
+ flex: 1,
7
+ width: '100%',
8
+ },
9
+ body: {
10
+ width: '100%',
11
+ height: Constants.height - 50,
12
+ justifyContent: 'center',
13
+ alignItems: 'center',
14
+ },
15
+ connecting: {
16
+ flexDirection: 'row',
17
+ justifyContent: 'center',
18
+ marginBottom: 10,
19
+ },
20
+ percentLoad: {
21
+ flexDirection: 'row',
22
+ justifyContent: 'center',
23
+ alignItems: 'center',
24
+ },
25
+ textPercentLoad: {
26
+ marginLeft: 10,
27
+ },
28
+ });
@@ -3,14 +3,14 @@ import { SafeAreaView, View, TouchableOpacity } from 'react-native';
3
3
  import { useTranslations } from '../../hooks/Common/useTranslations';
4
4
  import Routes from '../../utils/Route';
5
5
  import { useNavigation } from '@react-navigation/native';
6
- import * as Progress from 'react-native-progress';
7
6
  import ImageSuccessfully from '../../Images/Common/SuccessfullyConnected.svg';
8
7
 
9
8
  import Text from '../Text';
10
9
  import { axiosPost } from '../../utils/Apis/axios';
11
- import { API, Colors, Constants } from '../../configs';
10
+ import { API, Colors } from '../../configs';
12
11
  import styles from './styles';
13
12
  import DeviceItem from './DeviceItem/DeviceItem';
13
+ import Connecting from '../Connecting ';
14
14
  import { useSCContextSelector } from '../../context';
15
15
 
16
16
  const ConnectingProcess = ({ route }) => {
@@ -29,31 +29,9 @@ const ConnectingProcess = ({ route }) => {
29
29
  wifi_pass,
30
30
  chip_id,
31
31
  } = route.params;
32
- const [percent, setPercent] = useState(0);
33
32
  const [isLoading, setIsLoading] = useState(true);
34
33
  const [sensor, setSensor] = useState(null);
35
34
  const user = useSCContextSelector((state) => state?.auth?.account?.user);
36
- useEffect(() => {
37
- processLoading();
38
- }, [processLoading]);
39
-
40
- const processLoading = useCallback(() => {
41
- let interval;
42
- if (isLoading) {
43
- interval = setInterval(() => {
44
- setPercent((prev) => {
45
- if (prev === 1) {
46
- clearInterval(interval);
47
- return 1;
48
- } else {
49
- return prev + 0.2;
50
- }
51
- });
52
- }, 180);
53
- } else {
54
- clearInterval(interval);
55
- }
56
- }, [isLoading]);
57
35
 
58
36
  const ConnectingDevice = useCallback(async () => {
59
37
  setIsLoading(true);
@@ -120,35 +98,6 @@ const ConnectingProcess = ({ route }) => {
120
98
  chip_id,
121
99
  ]);
122
100
 
123
- const Connecting = useCallback(() => {
124
- return (
125
- <>
126
- <View style={styles.progressBar}>
127
- <View style={styles.connecting}>
128
- <Text type="H4" bold>
129
- {t('connecting')}
130
- </Text>
131
- </View>
132
- </View>
133
- <View style={styles.percentLoad}>
134
- <Progress.Bar
135
- progress={percent}
136
- animated={true}
137
- color={Colors.Primary}
138
- indeterminateAnimationDuration={1000}
139
- height={7}
140
- width={Constants.width - 80}
141
- useNativeDriver={true}
142
- />
143
- <Text style={styles.textPercentLoad}>{`${parseInt(
144
- percent * 100,
145
- 10
146
- )}%`}</Text>
147
- </View>
148
- </>
149
- );
150
- }, [percent, t]);
151
-
152
101
  const ConnectingSuccess = useCallback(() => {
153
102
  return (
154
103
  <View style={styles.ConnectingSuccess}>
@@ -188,7 +137,7 @@ const ConnectingProcess = ({ route }) => {
188
137
  <Text bold style={styles.connectingText}>
189
138
  {t('connect_device')}
190
139
  </Text>
191
- {!!isLoading && <Connecting />}
140
+ {!!isLoading && <Connecting isLoading={isLoading} />}
192
141
  {!isLoading && <ConnectingSuccess />}
193
142
  </View>
194
143
  {!isLoading && (
@@ -4,6 +4,8 @@ import { TouchableOpacity } from 'react-native';
4
4
  import renderer, { act } from 'react-test-renderer';
5
5
  import { SCProvider } from '../../../../context';
6
6
  import { mockSCStore } from '../../../../context/mockStore';
7
+ import { TextInput } from 'react-native';
8
+ import { TESTID } from '../../../../configs/Constants';
7
9
 
8
10
  const mockedNavigate = jest.fn();
9
11
 
@@ -36,4 +38,21 @@ describe('Test SearchBox', () => {
36
38
  });
37
39
  expect(mockedNavigate.mock.calls.length).toBe(1);
38
40
  });
41
+
42
+ test('Onfocus searchBox', () => {
43
+ act(() => {
44
+ wrapper = renderer.create(wrapComponent());
45
+ });
46
+ const instance = wrapper.root;
47
+ const textInput = instance.find(
48
+ (item) =>
49
+ item.props.testID === TESTID.ON_FOCUS_SEARCH_B0X &&
50
+ item.type === TextInput
51
+ );
52
+
53
+ act(() => {
54
+ textInput.props.onFocus();
55
+ });
56
+ expect(textInput).toBeDefined();
57
+ });
39
58
  });
@@ -7,6 +7,7 @@ import { Colors } from '../../../configs';
7
7
  import Theme from '../../../configs/Theme';
8
8
  import Search from '../../../../assets/images/Explore/Search.svg';
9
9
  import ArrowBack from '../../../../assets/images/Explore/ArrowBack.svg';
10
+ import { TESTID } from '../../../configs/Constants';
10
11
 
11
12
  const SearchBox = memo(({ isBack, style, onFocus }) => {
12
13
  const t = useTranslations();
@@ -33,6 +34,7 @@ const SearchBox = memo(({ isBack, style, onFocus }) => {
33
34
  placeholderTextColor={Colors.Gray7}
34
35
  style={Theme.textSearchInput}
35
36
  onFocus={onFocusInput}
37
+ testID={TESTID.ON_FOCUS_SEARCH_B0X}
36
38
  />
37
39
  </View>
38
40
  );
@@ -1,4 +1,4 @@
1
- import React, { memo, useCallback, useEffect } from 'react';
1
+ import React, { memo, useCallback, useEffect, useState } from 'react';
2
2
  import { TouchableOpacity, ScrollView } from 'react-native';
3
3
  import Popover from 'react-native-popover-view';
4
4
 
@@ -19,10 +19,16 @@ const MenuActionMore = memo(
19
19
  wrapStyle,
20
20
  isTextCenter = true,
21
21
  }) => {
22
+ const [isDisable, setIsDisable] = useState(false);
22
23
  const onPress = useCallback(
23
- (item, index) => {
24
+ (item, index) => () => {
25
+ setIsDisable(true);
24
26
  hideMore && hideMore();
25
27
  onItemClick && onItemClick(item, index);
28
+ const timeout = setTimeout(() => {
29
+ setIsDisable(false);
30
+ clearTimeout(timeout);
31
+ }, 500);
26
32
  },
27
33
  [hideMore, onItemClick]
28
34
  );
@@ -52,9 +58,10 @@ const MenuActionMore = memo(
52
58
  styles.menuWrapper,
53
59
  isTextCenter ? styles.modalHeaderCenter : styles.modalHeader,
54
60
  ]}
55
- onPress={() => onPress(item, index)}
61
+ onPress={onPress(item, index)}
56
62
  key={index}
57
63
  testID={TESTID.TOUCHABLE_ACTION_ADD_MORE}
64
+ disabled={isDisable}
58
65
  >
59
66
  <Text style={styles.modalHeaderText}>{item.text}</Text>
60
67
  </TouchableOpacity>
@@ -1,10 +1,18 @@
1
- import React from 'react';
1
+ import React, { useEffect } from 'react';
2
2
  import Modal from 'react-native-modal';
3
3
  import { Colors } from '../../configs';
4
+ import { useStatusBarPreview } from '../../hooks/Common/useStatusBar';
4
5
 
5
6
  const ModalCustom = (props) => {
7
+ useEffect(() => {
8
+ // eslint-disable-next-line react-hooks/rules-of-hooks
9
+ useStatusBarPreview(
10
+ props.isVisible ? Colors.BlackTransparent3_5 : Colors.TextTransparent
11
+ );
12
+ }, [props.isVisible]);
6
13
  return (
7
14
  <Modal
15
+ isVisible
8
16
  hasBackdrop
9
17
  useNativeDriver
10
18
  animationIn={'slideInUp'}
@@ -1,29 +1,27 @@
1
- import React from 'react';
1
+ import React, { memo } from 'react';
2
2
  import { View, StyleSheet } from 'react-native';
3
3
  import { useTranslations } from '../../hooks/Common/useTranslations';
4
4
  import { Colors } from '../../configs';
5
5
  import Text from '../../commons/Text';
6
-
7
6
  import RowMember from './RowMember';
8
7
 
9
8
  const MemberList = ({
10
9
  dataMember,
11
10
  ownerId,
11
+ unit,
12
12
  currentUserId, //user is using app
13
- onPressRemove,
14
13
  }) => {
15
14
  const t = useTranslations();
16
-
17
15
  return (
18
16
  <View style={styles.box}>
19
17
  {!!dataMember.length &&
20
18
  dataMember.map((item, index) => (
21
19
  <RowMember
22
20
  member={item}
21
+ unit={unit}
23
22
  index={index}
24
23
  ownerId={ownerId}
25
24
  currentUserId={currentUserId}
26
- onPressRemove={onPressRemove}
27
25
  key={index.toString()}
28
26
  />
29
27
  ))}
@@ -33,13 +31,10 @@ const MemberList = ({
33
31
  </View>
34
32
  );
35
33
  };
36
- export default MemberList;
34
+ export default memo(MemberList);
35
+
37
36
  const styles = StyleSheet.create({
38
37
  box: {
39
- paddingBottom: 16,
40
- borderRadius: 20,
41
38
  backgroundColor: Colors.White,
42
- borderWidth: 1,
43
- borderColor: Colors.Gray4,
44
39
  },
45
40
  });