@eohjsc/react-native-smart-city 0.3.95 → 0.3.97

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/package.json +1 -1
  2. package/src/commons/ActionGroup/__test__/OnOffTemplate.test.js +0 -6
  3. package/src/commons/ActionGroup/__test__/OneBigButtonTemplate.test.js +0 -8
  4. package/src/commons/BottomButtonView/index.js +3 -1
  5. package/src/commons/ButtonPopup/index.js +1 -0
  6. package/src/commons/Device/ProgressBar/__test__/ProgressBar.test.js +0 -10
  7. package/src/commons/SelectGateway/index.js +1 -0
  8. package/src/commons/SelectGateway/styles.js +3 -0
  9. package/src/commons/SubUnit/OneTap/__test__/SubUnitAutomate.test.js +4 -1
  10. package/src/commons/SubUnit/OneTap/index.js +5 -1
  11. package/src/configs/Constants.js +3 -0
  12. package/src/screens/AQIGuide/__test__/AQIGuide.test.js +0 -11
  13. package/src/screens/AddNewGateway/ScanModbusQR.js +4 -0
  14. package/src/screens/AddNewGateway/SelectDeviceType.js +10 -2
  15. package/src/screens/AddNewGateway/ShareWifiPassword.js +1 -1
  16. package/src/screens/AddNewGateway/__test__/SelectDeviceType.test.js +8 -2
  17. package/src/screens/Automate/MultiUnits.js +5 -1
  18. package/src/screens/Automate/ScriptDetail/__test__/index.test.js +4 -1
  19. package/src/screens/Automate/ScriptDetail/index.js +5 -1
  20. package/src/screens/Automate/__test__/MultiUnits.test.js +4 -1
  21. package/src/screens/Automate/__test__/index.test.js +4 -1
  22. package/src/screens/Automate/index.js +5 -1
  23. package/src/screens/Notification/__test__/NotificationItem.test.js +42 -2
  24. package/src/screens/Notification/components/NotificationItem.js +23 -1
  25. package/src/screens/ScanChipQR/components/InvalidQRCode/index.js +4 -0
  26. package/src/screens/Sharing/MemberList.js +1 -1
  27. package/src/screens/Sharing/__test__/MemberList.test.js +4 -1
  28. package/src/screens/SubUnit/AddSubUnit.js +0 -1
  29. package/src/screens/SubUnit/__test__/AddSubUnit.test.js +2 -1
  30. package/src/screens/SubUnit/__test__/Detail.test.js +0 -38
  31. package/src/screens/SubUnit/__test__/EditSubUnit.test.js +0 -10
  32. package/src/screens/Unit/AddMenu.js +5 -1
  33. package/src/screens/WaterQualityGuide/__test__/index.test.js +0 -8
  34. package/src/utils/Apis/axios.js +3 -0
  35. package/src/utils/I18n/translations/en.js +28 -12
  36. package/src/utils/I18n/translations/vi.js +30 -12
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.3.95",
4
+ "version": "0.3.97",
5
5
  "description": "TODO",
6
6
  "main": "index.js",
7
7
  "files": [
@@ -1,6 +1,5 @@
1
1
  import React from 'react';
2
2
  import { View } from 'react-native';
3
- import { useSelector } from 'react-redux';
4
3
  import { act, create } from 'react-test-renderer';
5
4
 
6
5
  import { DEVICE_TYPE, AccessibilityLabel } from '../../../configs/Constants';
@@ -92,11 +91,6 @@ describe('Test OnOffTemplate', () => {
92
91
  };
93
92
 
94
93
  sensor = { name: 'Sensor' };
95
-
96
- const localState = {
97
- isOnSwich: false,
98
- };
99
- useSelector.mockImplementation((getter) => getter(localState));
100
94
  });
101
95
 
102
96
  it('render with template OnOffSimpleActionTemplate', async () => {
@@ -1,8 +1,6 @@
1
- /* eslint-disable promise/prefer-await-to-callbacks */
2
1
  import React from 'react';
3
2
  import { create, act } from 'react-test-renderer';
4
3
  import { TouchableOpacity } from 'react-native';
5
- import { useSelector } from 'react-redux';
6
4
 
7
5
  import OneBigButtonTemplate from '../OneBigButtonTemplate';
8
6
  import { mockSCStore } from '../../../context/mockStore';
@@ -46,12 +44,6 @@ describe('Test OneBigButtonTemplate', () => {
46
44
  let sensor;
47
45
 
48
46
  beforeEach(() => {
49
- const localState = {
50
- isOnSwich: false,
51
- };
52
- useSelector.mockImplementation((cb) => {
53
- return cb(localState);
54
- });
55
47
  sensor = { name: 'Sensor' };
56
48
  });
57
49
 
@@ -23,6 +23,7 @@ const BottomButtonView = memo(
23
23
  accessibilityLabelPrefix = '',
24
24
  disableBackgroundMainButton = false,
25
25
  disableBackgroundSecondButton = false,
26
+ disableKeyBoardAnimated = false,
26
27
  }) => {
27
28
  const transY = useKeyboardAnimated();
28
29
  const [keyboardAnim] = useState(new Animated.Value(0));
@@ -42,7 +43,8 @@ const BottomButtonView = memo(
42
43
  typeMain === 'CardShadow'
43
44
  ? styleCustom.container1
44
45
  : styleCustom.container,
45
- { bottom: keyboardAnim },
46
+ // eslint-disable-next-line react-native/no-inline-styles
47
+ { bottom: disableKeyBoardAnimated ? 0.1 : keyboardAnim },
46
48
  rowButton && styleCustom.horizontalContainer,
47
49
  style,
48
50
  ]}
@@ -61,6 +61,7 @@ const ButtonPopup = ({
61
61
  typeSecondary={typeSecondary}
62
62
  accessibilityLabelPrefix={AccessibilityLabel.PREFIX.BUTTON_POPUP}
63
63
  semiboldSecond={semiboldSecond}
64
+ disableKeyBoardAnimated
64
65
  />
65
66
  {thirdTitle && (
66
67
  <BottomButtonView
@@ -1,6 +1,4 @@
1
- /* eslint-disable promise/prefer-await-to-callbacks */
2
1
  import React from 'react';
3
- import { useSelector } from 'react-redux';
4
2
  import renderer, { act } from 'react-test-renderer';
5
3
 
6
4
  import ProgressBar from '..';
@@ -21,14 +19,6 @@ const wrapComponent = (item, data) => (
21
19
 
22
20
  describe('Test ProgressBar', () => {
23
21
  let tree;
24
- beforeEach(() => {
25
- const localState = {
26
- language: 'en',
27
- };
28
- useSelector.mockImplementation((cb) => {
29
- return cb(localState);
30
- });
31
- });
32
22
 
33
23
  it('render ProgressBar', async () => {
34
24
  const item = {
@@ -140,6 +140,7 @@ const SelectGateway = ({
140
140
  rightTitle={t('ok')}
141
141
  onRightClick={handleButtonModalOk}
142
142
  styleButton={styles.bottomButton}
143
+ wrapStyle={styles.wrapViewButton}
143
144
  />
144
145
  </View>
145
146
  </ModalCustom>
@@ -73,4 +73,7 @@ export default StyleSheet.create({
73
73
  bottomButton: {
74
74
  paddingVertical: 11,
75
75
  },
76
+ wrapViewButton: {
77
+ position: 'relative',
78
+ },
76
79
  });
@@ -282,7 +282,10 @@ describe('test Item', () => {
282
282
  });
283
283
  expect(mockedNavigate).not.toBeCalled();
284
284
  expect(spyToastError).toBeCalledWith(
285
- getTranslate('en', 'reach_max_automations_per_unit')
285
+ getTranslate(
286
+ 'en',
287
+ "You've reached the [0] limit. Remove one automation or upgrade your plan for a better experience."
288
+ )
286
289
  );
287
290
  });
288
291
 
@@ -40,7 +40,11 @@ const SubUnitAutomate = ({ isOwner, listAutomate, unit, wrapItemStyle }) => {
40
40
  const handleOnAddNew = () => {
41
41
  if (unit?.id) {
42
42
  if (permissions.max_automations_per_unit <= totalAutomates) {
43
- ToastBottomHelper.error(t('reach_max_automations_per_unit'));
43
+ ToastBottomHelper.error(
44
+ t('reach_max_automations_per_unit', {
45
+ length: permissions.max_automations_per_unit,
46
+ })
47
+ );
44
48
  return;
45
49
  }
46
50
  }
@@ -220,6 +220,8 @@ export const NOTIFICATION_TYPES = {
220
220
  NOTIFY_UPGRADE_SYSTEM: 'NOTIFY_UPGRADE_SYSTEM',
221
221
  NOTIFY_CHANGE_UNIT_OLD_OWNER: 'NOTIFY_CHANGE_UNIT_OLD_OWNER',
222
222
  NOTIFY_CHANGE_UNIT_NEW_OWNER: 'NOTIFY_CHANGE_UNIT_NEW_OWNER',
223
+ TRIAL_WILL_END: 'TRIAL_WILL_END',
224
+ FREE_TRIAL_SUBSCRIPTION: 'FREE_TRIAL_SUBSCRIPTION',
223
225
  AIR_QUALITY: 'AIR_QUALITY',
224
226
  TURBIDITY: 'TURBIDITY',
225
227
  PH: 'PH',
@@ -230,6 +232,7 @@ export const NOTIFICATION_TYPES = {
230
232
  SOS: 'SOS',
231
233
  FILTER_WATER: 'FILTER_WATER',
232
234
  LOW_BATTERY: 'LOW_BATTERY',
235
+ BROADCAST_NOTIFICATION: 'BROADCAST_NOTIFICATION',
233
236
  };
234
237
 
235
238
  export const ACTIVITY_LOG_TYPES = {
@@ -1,6 +1,4 @@
1
- /* eslint-disable promise/prefer-await-to-callbacks */
2
1
  import React from 'react';
3
- import { useSelector } from 'react-redux';
4
2
  import { act, create } from 'react-test-renderer';
5
3
  import AQIGuide from '..';
6
4
  import Text from '../../../commons/Text';
@@ -25,15 +23,6 @@ jest.mock('react', () => ({
25
23
  }));
26
24
 
27
25
  describe('test AQIGuide', () => {
28
- beforeEach(() => {
29
- const localState = {
30
- language: 'en',
31
- };
32
- useSelector.mockImplementation((cb) => {
33
- return cb(localState);
34
- });
35
- });
36
-
37
26
  it('render', async () => {
38
27
  let tree;
39
28
  await act(async () => {
@@ -84,6 +84,7 @@ const ScanModbusQR = memo(({ route }) => {
84
84
  onLeftClick={handleCancel}
85
85
  rightTitle={t('ok')}
86
86
  onRightClick={setHidePopupGuide}
87
+ wrapStyle={styles.wrapViewButton}
87
88
  />
88
89
  </View>
89
90
  </ModalCustom>
@@ -119,6 +120,9 @@ const styles = StyleSheet.create({
119
120
  txtCenter: {
120
121
  textAlign: 'center',
121
122
  },
123
+ wrapViewButton: {
124
+ position: 'relative',
125
+ },
122
126
  });
123
127
 
124
128
  export default ScanModbusQR;
@@ -156,7 +156,11 @@ const SelectDeviceType = ({ route }) => {
156
156
 
157
157
  if (['gateway_qr', 'wifi_device_qr'].includes(itemSelect)) {
158
158
  if (permissions?.max_chips_per_unit <= unitCountSummary?.total_chips) {
159
- ToastBottomHelper.error(t('reach_max_chips_per_unit'));
159
+ ToastBottomHelper.error(
160
+ t('reach_max_chips_per_unit', {
161
+ length: permissions?.max_chips_per_unit,
162
+ })
163
+ );
160
164
  return false;
161
165
  }
162
166
  }
@@ -165,7 +169,11 @@ const SelectDeviceType = ({ route }) => {
165
169
  if (
166
170
  permissions?.max_configs_per_unit <= unitCountSummary?.total_configs
167
171
  ) {
168
- ToastBottomHelper.error(t('reach_max_configs_per_unit'));
172
+ ToastBottomHelper.error(
173
+ t('reach_max_configs_per_unit', {
174
+ length: permissions?.max_configs_per_unit,
175
+ })
176
+ );
169
177
  return false;
170
178
  }
171
179
  }
@@ -132,7 +132,7 @@ const ShareWifiPassword = ({ route }) => {
132
132
  gateway: [data.gateway],
133
133
  }));
134
134
  }
135
- if (data?.status && !data?.gateway) {
135
+ if (data?.status === 'error' && !data?.gateway) {
136
136
  isWrongPassword.current = false;
137
137
  setDataGateway((prev) => ({
138
138
  ...prev,
@@ -147,7 +147,10 @@ describe('Test select device type', () => {
147
147
  });
148
148
  expect(mockedNavigate).not.toBeCalled();
149
149
  expect(spyToastError).toBeCalledWith(
150
- getTranslate('en', 'reach_max_configs_per_unit')
150
+ getTranslate(
151
+ 'en',
152
+ "You've reached the [1] limit. Remove one config or upgrade your plan for a better experience."
153
+ )
151
154
  );
152
155
  });
153
156
 
@@ -186,7 +189,10 @@ describe('Test select device type', () => {
186
189
  });
187
190
  expect(mockedNavigate).not.toBeCalled();
188
191
  expect(spyToastError).toBeCalledWith(
189
- getTranslate('en', 'reach_max_chips_per_unit')
192
+ getTranslate(
193
+ 'en',
194
+ "You've reached the [1] limit. Remove one chip or upgrade your plan for a better experience."
195
+ )
190
196
  );
191
197
  });
192
198
 
@@ -78,7 +78,11 @@ const MultiUnits = () => {
78
78
  const handleOnAddNew = useCallback(() => {
79
79
  if (unit?.id) {
80
80
  if (permissions?.max_automations_per_unit <= data.length) {
81
- ToastBottomHelper.error(t('reach_max_automations_per_unit'));
81
+ ToastBottomHelper.error(
82
+ t('reach_max_automations_per_unit', {
83
+ length: permissions.max_automations_per_unit,
84
+ })
85
+ );
82
86
  return;
83
87
  }
84
88
  } else if (!permissions?.smart_script_for_multi_unit) {
@@ -271,7 +271,10 @@ describe('Test ScriptDetail', () => {
271
271
  });
272
272
  expect(mockNavigate).not.toBeCalled();
273
273
  expect(spyToastError).toBeCalledWith(
274
- getTranslate('en', 'reach_max_actions_per_automation')
274
+ getTranslate(
275
+ 'en',
276
+ "You've reached the [0] limit. Remove one action or upgrade your plan for a better experience."
277
+ )
275
278
  );
276
279
  });
277
280
 
@@ -302,7 +302,11 @@ const ItemAdd = ({ automate, index }) => {
302
302
 
303
303
  const onPressAddAction = useCallback(() => {
304
304
  if (permissions?.max_actions_per_automation <= index) {
305
- ToastBottomHelper.error(t('reach_max_actions_per_automation'));
305
+ ToastBottomHelper.error(
306
+ t('reach_max_actions_per_automation', {
307
+ length: permissions?.max_actions_per_automation,
308
+ })
309
+ );
306
310
  return;
307
311
  }
308
312
  const navParams = {
@@ -252,7 +252,10 @@ describe('Test MultiUnits', () => {
252
252
  });
253
253
  expect(mockedNavigate).not.toBeCalled();
254
254
  expect(spyToastError).toBeCalledWith(
255
- getTranslate('en', 'reach_max_automations_per_unit')
255
+ getTranslate(
256
+ 'en',
257
+ "You've reached the [0] limit. Remove one automation or upgrade your plan for a better experience."
258
+ )
256
259
  );
257
260
  });
258
261
 
@@ -148,7 +148,10 @@ describe('Test Automate', () => {
148
148
  });
149
149
  expect(mockedNavigate).not.toBeCalled();
150
150
  expect(spyToastError).toBeCalledWith(
151
- getTranslate('en', 'reach_max_automations_per_unit')
151
+ getTranslate(
152
+ 'en',
153
+ "You've reached the [0] limit. Remove one automation or upgrade your plan for a better experience."
154
+ )
152
155
  );
153
156
  });
154
157
 
@@ -85,7 +85,11 @@ const Automate = () => {
85
85
  if (id) {
86
86
  // only limit per unit
87
87
  if (permissions.max_automations_per_unit <= automates.length) {
88
- ToastBottomHelper.error(t('reach_max_automations_per_unit'));
88
+ ToastBottomHelper.error(
89
+ t('reach_max_automations_per_unit', {
90
+ length: permissions.max_automations_per_unit,
91
+ })
92
+ );
89
93
  return;
90
94
  }
91
95
  } else if (!permissions?.smart_script_for_multi_unit) {
@@ -12,8 +12,8 @@ import { API } from '../../../configs';
12
12
  import api from '../../../utils/Apis/axios';
13
13
  import { AccessibilityLabel } from '../../../configs/Constants';
14
14
 
15
- const wrapComponent = (item) => (
16
- <SCProvider initState={mockSCStore({})}>
15
+ const wrapComponent = (item, stateData = {}) => (
16
+ <SCProvider initState={mockSCStore(stateData)}>
17
17
  <NotificationItem item={item} />
18
18
  </SCProvider>
19
19
  );
@@ -321,4 +321,44 @@ describe('test NotificationItem', () => {
321
321
  '. You cannot access to this unit anymore.'
322
322
  );
323
323
  });
324
+
325
+ test('test case BROADCAST_NOTIFICATION', async () => {
326
+ item.content_code = NOTIFICATION_TYPES.BROADCAST_NOTIFICATION;
327
+ item.params = {
328
+ message: {
329
+ vi: 'vi message',
330
+ en: 'en message',
331
+ },
332
+ };
333
+ await act(async () => {
334
+ tree = await create(wrapComponent(item));
335
+ });
336
+ const instance = tree.root;
337
+ const customText = instance.findByProps({
338
+ accessibilityLabel: AccessibilityLabel.CUSTOM_TEXT,
339
+ });
340
+ expect(customText.props.children).toEqual('en message');
341
+ });
342
+
343
+ test('test case BROADCAST_NOTIFICATION language is vi', async () => {
344
+ item.content_code = NOTIFICATION_TYPES.BROADCAST_NOTIFICATION;
345
+ item.params = {
346
+ message: {
347
+ vi: 'vi message',
348
+ en: 'en message',
349
+ },
350
+ };
351
+
352
+ const localState = {
353
+ language: 'vi',
354
+ };
355
+ await act(async () => {
356
+ tree = await create(wrapComponent(item, localState));
357
+ });
358
+ const instance = tree.root;
359
+ const customText = instance.findByProps({
360
+ accessibilityLabel: AccessibilityLabel.CUSTOM_TEXT,
361
+ });
362
+ expect(customText.props.children).toEqual('vi message');
363
+ });
324
364
  });
@@ -12,10 +12,12 @@ import { useTranslations } from '../../../hooks/Common/useTranslations';
12
12
  import { axiosPost } from '../../../utils/Apis/axios';
13
13
  import Routes from '../../../utils/Route';
14
14
  import { AccessibilityLabel } from '../../../configs/Constants';
15
+ import { useSCContextSelector } from '../../../context';
15
16
 
16
17
  const NotificationItem = memo(({ item }) => {
17
18
  const t = useTranslations();
18
19
  const navigation = useNavigation();
20
+ const language = useSCContextSelector((state) => state.language);
19
21
  const { id, icon, created_at, is_read, params, content_code } = item;
20
22
  const [isRead, setIsRead] = useState(is_read);
21
23
  const timeFormat = moment(created_at).format('LT DD/MM/YYYY');
@@ -386,10 +388,30 @@ const NotificationItem = memo(({ item }) => {
386
388
  },
387
389
  iconContent: <Image source={Images.logo} style={styles.logo} />,
388
390
  };
391
+ case NOTIFICATION_TYPES.TRIAL_WILL_END: // to do Canh remove later
392
+ return {
393
+ content: customColorText(
394
+ t('text_notification_content_when_trial_will_end')
395
+ ),
396
+ redirect: () => null,
397
+ iconContent: <Image source={Images.logo} style={styles.logo} />,
398
+ };
399
+ case NOTIFICATION_TYPES.FREE_TRIAL_SUBSCRIPTION:
400
+ return {
401
+ content: customColorText(
402
+ t('text_notification_content_your_account_upgraded_3_month')
403
+ ),
404
+ };
405
+ case NOTIFICATION_TYPES.BROADCAST_NOTIFICATION:
406
+ return {
407
+ content: params?.message[language],
408
+ redirect: () => null,
409
+ iconContent: <Image source={Images.logo} style={styles.logo} />,
410
+ };
389
411
  default:
390
412
  return null;
391
413
  }
392
- }, [content_code, customColorText, icon, navigation, params, t]);
414
+ }, [content_code, customColorText, icon, navigation, params, t, language]);
393
415
 
394
416
  const { content, redirect, iconContent } = renderItem() || {};
395
417
 
@@ -19,6 +19,7 @@ const InvalidQRCode = ({ isInvalidQrCode, goBack, onRetry }) => {
19
19
  onLeftClick={goBack}
20
20
  rightTitle={t('retry')}
21
21
  onRightClick={onRetry}
22
+ wrapStyle={styles.wrapViewButton}
22
23
  />
23
24
  </BottomSheet>
24
25
  );
@@ -30,4 +31,7 @@ const styles = StyleSheet.create({
30
31
  warningContainer: {
31
32
  paddingHorizontal: 16,
32
33
  },
34
+ wrapViewButton: {
35
+ position: 'relative',
36
+ },
33
37
  });
@@ -40,7 +40,7 @@ const MemberList = ({ route }) => {
40
40
  if (permissions?.max_members_per_unit <= dataMembers.length) {
41
41
  ToastBottomHelper.error(
42
42
  t('reach_max_members_per_unit', {
43
- max: permissions?.max_members_per_unit,
43
+ length: permissions?.max_members_per_unit,
44
44
  })
45
45
  );
46
46
  return;
@@ -101,7 +101,10 @@ describe('test MemberList', () => {
101
101
  });
102
102
  expect(mockedNavigate).not.toBeCalled();
103
103
  expect(spyToastError).toBeCalledWith(
104
- getTranslate('en', 'reach_max_members_per_unit')
104
+ getTranslate(
105
+ 'en',
106
+ "You've reached the [0] limit. Remove one member or upgrade your plan for a better experience."
107
+ )
105
108
  );
106
109
  });
107
110
  });
@@ -124,7 +124,6 @@ const AddSubUnit = ({ route }) => {
124
124
  cleanData();
125
125
  } else {
126
126
  awaitCreate.current = false;
127
- ToastBottomHelper.error(t('text_create_sub_unit_fail'));
128
127
  }
129
128
  }
130
129
  }
@@ -182,7 +182,8 @@ describe('Test AddSubUnit', () => {
182
182
  expect(Toast.show).toHaveBeenCalledWith({
183
183
  type: 'error',
184
184
  position: 'bottom',
185
- text1: getTranslate('en', 'text_create_sub_unit_fail'),
185
+ text1: 'CLIENT_ERROR',
186
+ text2: undefined,
186
187
  visibilityTime: 1000,
187
188
  });
188
189
  });
@@ -1,5 +1,4 @@
1
1
  import React from 'react';
2
- import { useSelector } from 'react-redux';
3
2
  import { act, create } from 'react-test-renderer';
4
3
  import Toast from 'react-native-toast-message';
5
4
  import SubUnitDetail from '../Detail';
@@ -47,23 +46,6 @@ const wrapComponent = (route) => (
47
46
 
48
47
  describe('Test SubUnitDetail', () => {
49
48
  let route;
50
- let stationState = {
51
- id: 2,
52
- camera: {
53
- id: 1,
54
- uri: 'camera-uri',
55
- preview_uri: 'camera-preview-uri',
56
- },
57
- sensors: [
58
- {
59
- icon: '',
60
- id: 1,
61
- action: { icon: '', color: '' },
62
- name: '',
63
- value: '',
64
- },
65
- ],
66
- };
67
49
 
68
50
  beforeEach(() => {
69
51
  route = {
@@ -80,26 +62,6 @@ describe('Test SubUnitDetail', () => {
80
62
  },
81
63
  },
82
64
  };
83
-
84
- const localState = {
85
- language: 'en',
86
- auth: {
87
- account: {
88
- user: {
89
- id: 2,
90
- },
91
- },
92
- },
93
- unit: {
94
- unitDetail: {
95
- id: 1,
96
- stations: [stationState],
97
- },
98
- },
99
- };
100
- useSelector.mockImplementation((getter) => {
101
- return getter(localState);
102
- });
103
65
  });
104
66
 
105
67
  afterEach(() => {
@@ -3,7 +3,6 @@ import { TouchableOpacity, Image } from 'react-native';
3
3
  import MockAdapter from 'axios-mock-adapter';
4
4
  import { AlertAction, ImagePicker, ViewButtonBottom } from '../../../commons';
5
5
  import { API } from '../../../configs';
6
- import { useSelector } from 'react-redux';
7
6
  import { act, create } from 'react-test-renderer';
8
7
  import Toast from 'react-native-toast-message';
9
8
 
@@ -78,15 +77,6 @@ describe('Test EditSubUnit', () => {
78
77
  },
79
78
  },
80
79
  };
81
- const localState = {
82
- language: 'en',
83
- unit: {
84
- unitDetail: {
85
- id: 1,
86
- },
87
- },
88
- };
89
- useSelector.mockImplementation((getter) => getter(localState));
90
80
 
91
81
  mockedDispatch.mockClear();
92
82
  mock.reset();
@@ -33,7 +33,11 @@ const AddMenu = memo(({ unit, afterItemClick, showAdd, setHideAdd }) => {
33
33
  onClick: () => {
34
34
  // 2 is station favorite and smart
35
35
  if (unit.stations.length - 2 >= permissions.max_stations_per_unit) {
36
- ToastBottomHelper.error(t('reach_max_stations_per_unit'));
36
+ ToastBottomHelper.error(
37
+ t('reach_max_stations_per_unit', {
38
+ length: permissions.max_stations_per_unit,
39
+ })
40
+ );
37
41
  return;
38
42
  }
39
43
  navigation.navigate(Routes.AddSubUnitStack, {
@@ -1,6 +1,4 @@
1
- /* eslint-disable promise/prefer-await-to-callbacks */
2
1
  import React from 'react';
3
- import { useSelector } from 'react-redux';
4
2
  import WaterQualityGuide from '../index';
5
3
  import { create, act } from 'react-test-renderer';
6
4
  import { AccessibilityLabel } from '../../../configs/Constants';
@@ -28,12 +26,6 @@ describe('Test WaterQualityGuide', () => {
28
26
  let route;
29
27
 
30
28
  beforeEach(() => {
31
- const localState = {
32
- language: 'en',
33
- };
34
- useSelector.mockImplementation((cb) => {
35
- return cb(localState);
36
- });
37
29
  Date.now = jest.fn(() => new Date('2021-01-24T12:00:00.000Z'));
38
30
  route = {
39
31
  params: {
@@ -78,6 +78,9 @@ const parseErrorResponse = async (error) => {
78
78
  if (firstKey !== 'non_field_errors') {
79
79
  message = `${firstKey}: ${message}`;
80
80
  }
81
+ if (firstKey === 'detail') {
82
+ message = error.data[firstKey];
83
+ }
81
84
  } else {
82
85
  message = error.data || error.problem;
83
86
  }
@@ -882,6 +882,13 @@ export default {
882
882
  'Your ownership of **unit_name** has been assigned to **new_owner_name**.',
883
883
  text_notification_content_change_unit_for_new_owner:
884
884
  'You are now the owner of **unit_name**.',
885
+ text_notification_content_when_trial_will_end:
886
+ 'The service usage period is only **days** days left, ' +
887
+ 'Package **product_name** will automatically renew on **trial_end** with **amount** **currency**',
888
+ text_notification_content_your_account_upgraded_3_month:
889
+ 'Congratulations! Your account has just been upgraded to a 3-month free PREMIUM plan ' +
890
+ 'as a sincere thanking word to your loyalty of the BETA version of E-Ra IoT Platform. ' +
891
+ "Let's experience the new features now!",
885
892
  this_spot_does_not_exsit: 'This spot does not exist',
886
893
  please_scan_again_or_contact_the_parking_manager:
887
894
  'Please scan again or contact the parking manager',
@@ -1389,21 +1396,30 @@ export default {
1389
1396
  value_must_be_less_than_max: 'Value must be less than {max}',
1390
1397
  value_must_be_a_number: 'Value must be a number',
1391
1398
  reach_max_stations_per_unit:
1392
- 'You have reached the maximum number of sub-units',
1399
+ "You've reached the [{length}] limit. Remove one sub-unit or upgrade your plan for a better experience.",
1393
1400
  not_support_plug_and_play: 'Not support plug and play',
1394
1401
  reach_max_actions_per_automation:
1395
- 'You have reached the maximum number of actions',
1402
+ "You've reached the [{length}] limit. Remove one action or upgrade your plan for a better experience.",
1396
1403
  reach_max_automations_per_unit:
1397
- 'You have reached the maximum number of automations',
1398
- reach_max_members_per_unit: 'You have reached the maximum number of members',
1399
- reach_max_chips_per_unit: 'You have reached the maximum number of gateway',
1400
- reach_max_configs_per_unit: 'You have reached the maximum number of tags',
1401
- no_permission_plug_and_play_modbus: "You don't have permission to add modbus",
1402
- no_permission_plug_and_play_zigbee: "You don't have permission to add zigbee",
1403
- no_permission_plug_and_play_wifi: "You don't have permission to add wifi",
1404
+ "You've reached the [{length}] limit. Remove one automation or upgrade your plan for a better experience.",
1405
+ reach_max_members_per_unit:
1406
+ "You've reached the [{length}] limit. Remove one member or upgrade your plan for a better experience.",
1407
+ reach_max_chips_per_unit:
1408
+ "You've reached the [{length}] limit. Remove one chip or upgrade your plan for a better experience.",
1409
+ reach_max_configs_per_unit:
1410
+ "You've reached the [{length}] limit. Remove one config or upgrade your plan for a better experience.",
1411
+ no_permission_plug_and_play_modbus:
1412
+ 'Add modbus is currently not available on your Subscription. Please upgrade your plan for a better experience!',
1413
+ no_permission_plug_and_play_zigbee:
1414
+ 'Add zigbee is currently not available on your Subscription. Please upgrade your plan for a better experience!',
1415
+ no_permission_plug_and_play_wifi:
1416
+ 'Add wifi is currently not available on your Subscription. Please upgrade your plan for a better experience!',
1404
1417
  no_permission_plug_and_play_gateway:
1405
- "You don't have permission to add gateway",
1418
+ 'Add gateway is currently not available on your Subscription. Please upgrade your plan for a better experience!',
1419
+ no_permission_view_action_log:
1420
+ // eslint-disable-next-line max-len
1421
+ 'View action log is currently not available on your Subscription. Please upgrade your plan for a better experience!',
1406
1422
  no_permission_smart_script_for_multi_unit:
1407
- "You don't have permission to access feature Smart script for Multi Unit",
1408
- no_permission_view_action_log: "You don't have permission to view action log",
1423
+ // eslint-disable-next-line max-len
1424
+ 'Smart script for Multi Unit is currently not available on your Subscription. Please upgrade your plan for a better experience!',
1409
1425
  };
@@ -898,6 +898,13 @@ export default {
898
898
  'Quyền sở hữu **unit_name** của bạn đã được chỉ định cho **new_owner_name**.',
899
899
  text_notification_content_change_unit_for_new_owner:
900
900
  'Bạn hiện là chủ sở hữu của **unit_name**.',
901
+ text_notification_content_when_trial_will_end:
902
+ 'Thời hạn sử dụng dịch vụ chỉ còn **days** ngày, ' +
903
+ 'Gói **product_name** sẽ tự động gia hạn vào ngày **trial_end** với **amount** **currency**',
904
+ text_notification_content_your_account_upgraded_3_month:
905
+ 'Xin chúc mừng! Tài khoản của bạn vừa được nâng cấp lên gói PREMIUM miễn phí 3 tháng ' +
906
+ 'nhằm tri ân người dùng phiên bản BETA của E-Ra IoT Platform. ' +
907
+ 'Chúng tôi xin cảm ơn sự ủng hộ của bạn. Cùng trải nghiệm các tính năng mới ngay thôi!',
901
908
  this_spot_does_not_exsit: 'Vị trí đỗ này không tồn tại',
902
909
  please_scan_again_or_contact_the_parking_manager:
903
910
  'Vui lòng quét lại hoặc liên hệ với người quản lý bãi đậu xe',
@@ -1397,18 +1404,29 @@ export default {
1397
1404
  value_must_be_less_than_max: 'Giá trị phải nhỏ hơn {max}',
1398
1405
  value_must_be_a_number: 'Giá trị phải là một số',
1399
1406
  reach_max_stations_per_unit:
1400
- 'Đã đạt đến số lượng tối đa của các trạm trong một đơn vị',
1407
+ 'Bạn đã đạt giới hạn [{length}]. Vui lòng xoá bớt một sub-unit hoặc nâng cấp gói để có trải nghiệm tốt hơn.',
1401
1408
  not_support_plug_and_play: 'Không hỗ trợ kết nối tự động',
1402
- reach_max_actions_per_automation: 'Đã đạt đến số lượng tối đa hành động',
1403
- reach_max_automations_per_unit: 'Đã đạt đến số lượng tối đa tự động hóa',
1404
- reach_max_members_per_unit: 'Đã đạt đến số lượng tối đa thành viên',
1405
- reach_max_chips_per_unit: 'Đã đạt đến số lượng tối đa chip',
1406
- reach_max_configs_per_unit: 'Đã đạt đến số lượng tối đa thông số',
1407
- no_permission_plug_and_play_modbus: 'Không quyền kết nối tự động modbus',
1408
- no_permission_plug_and_play_zigbee: 'Không có quyền kết nối tự động zigbee',
1409
- no_permission_plug_and_play_wifi: 'Không quyền kết nối tự động wifi',
1410
- no_permission_plug_and_play_gateway: 'Không có quyền kết nối tự động gateway',
1409
+ reach_max_actions_per_automation:
1410
+ 'Bạn đã đạt giới hạn [{length}]. Vui lòng xoá bớt một action hoặc nâng cấp gói để có trải nghiệm tốt hơn.',
1411
+ reach_max_automations_per_unit:
1412
+ 'Bạn đã đạt giới hạn [{length}]. Vui lòng xoá bớt một automation hoặc nâng cấp gói để có trải nghiệm tốt hơn.',
1413
+ reach_max_members_per_unit:
1414
+ 'Bạn đã đạt giới hạn [{length}]. Vui lòng xoá bớt một member hoặc nâng cấp gói để có trải nghiệm tốt hơn.',
1415
+ reach_max_chips_per_unit:
1416
+ 'Bạn đã đạt giới hạn [{length}]. Vui lòng xoá bớt một chip hoặc nâng cấp gói để có trải nghiệm tốt hơn.',
1417
+ reach_max_configs_per_unit:
1418
+ 'Bạn đã đạt giới hạn [{length}]. Vui lòng xoá bớt một config hoặc nâng cấp gói để có trải nghiệm tốt hơn.',
1419
+ no_permission_plug_and_play_modbus:
1420
+ 'Kết nối tự động modbus hiện tại chưa hỗ trợ trên gói của bạn. Vui lòng nâng cấp gói để có trải nghiệm tốt hơn!',
1421
+ no_permission_plug_and_play_zigbee:
1422
+ 'Kết nối tự động zigbee hiện tại chưa hỗ trợ trên gói của bạn. Vui lòng nâng cấp gói để có trải nghiệm tốt hơn!',
1423
+ no_permission_plug_and_play_wifi:
1424
+ 'Kết nối tự động wifi hiện tại chưa hỗ trợ trên gói của bạn. Vui lòng nâng cấp gói để có trải nghiệm tốt hơn!',
1425
+ no_permission_plug_and_play_gateway:
1426
+ 'Kết nối tự động gateway hiện tại chưa hỗ trợ trên gói của bạn. Vui lòng nâng cấp gói để có trải nghiệm tốt hơn!',
1427
+ no_permission_view_action_log:
1428
+ 'Xem lịch sử hoạt động hiện tại chưa hỗ trợ trên gói của bạn. Vui lòng nâng cấp gói để có trải nghiệm tốt hơn!',
1411
1429
  no_permission_smart_script_for_multi_unit:
1412
- 'Không quyền truy cập tính năng Kịch bản thông minh liên quan đến nhiều địa điểm',
1413
- no_permission_view_action_log: 'Không quyền xem lịch sử hoạt dộng',
1430
+ // eslint-disable-next-line max-len
1431
+ 'Kịch bản thông minh cho nhiều địa điểm hiện tại chưa hỗ trợ trên gói của bạn. Vui lòng nâng cấp gói để có trải nghiệm tốt hơn!',
1414
1432
  };