@eohjsc/react-native-smart-city 0.4.84 → 0.4.86

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 (54) hide show
  1. package/assets/images/Notify.svg +9 -0
  2. package/package.json +1 -1
  3. package/src/commons/Automate/ItemAutomate.js +6 -1
  4. package/src/commons/Device/PMSensor/PMSensorIndicator.js +15 -8
  5. package/src/commons/Device/WaterQualitySensor/ListQualityIndicator.js +23 -15
  6. package/src/commons/Device/WaterQualitySensor/QualityIndicatorsItem.js +10 -9
  7. package/src/commons/MenuActionAddnew/index.js +6 -0
  8. package/src/commons/Sharing/WrapHeaderScrollable.js +1 -1
  9. package/src/commons/SubUnit/DeviceTemplate/ConfigValue/ConfigValue.js +2 -8
  10. package/src/commons/SubUnit/DeviceTemplate/EvaluationOverConfig/EvaluationOverConfig.js +2 -10
  11. package/src/commons/SubUnit/OneTap/ItemOneTap.js +4 -3
  12. package/src/commons/SubUnit/OneTap/__test__/SubUnitAutomate.test.js +14 -1
  13. package/src/commons/SubUnit/ShortDetail.js +14 -4
  14. package/src/configs/API.js +10 -0
  15. package/src/configs/AccessibilityLabel.js +3 -0
  16. package/src/navigations/UnitStack.js +10 -2
  17. package/src/screens/Automate/AddNewAction/SetupScriptNotify.js +92 -0
  18. package/src/screens/Automate/AddNewAction/Styles/SetupScriptNotifyStyles.js +57 -0
  19. package/src/screens/Automate/AddNewAction/__test__/SetupConfigCondition.test.js +13 -0
  20. package/src/screens/Automate/AddNewAction/__test__/SetupScriptNotify.test.js +84 -0
  21. package/src/screens/Automate/EditActionsList/__tests__/index.test.js +15 -4
  22. package/src/screens/Automate/EditActionsList/index.js +130 -72
  23. package/src/screens/Automate/ScriptDetail/Components/AddActionScript.js +168 -0
  24. package/src/screens/Automate/ScriptDetail/__test__/index.test.js +75 -6
  25. package/src/screens/Automate/ScriptDetail/index.js +147 -84
  26. package/src/screens/Device/__test__/mqttDetail.test.js +20 -20
  27. package/src/screens/Device/detail.js +1 -3
  28. package/src/screens/Sharing/{MemberList.js → UnitMemberList.js} +4 -4
  29. package/src/screens/Sharing/__test__/{MemberList.test.js → UnitMemberList.test.js} +2 -2
  30. package/src/screens/UnitSummary/__test__/index.test.js +2 -1
  31. package/src/screens/UnitSummary/components/3PPowerConsumption/__test__/3PPowerConsumption.test.js +37 -30
  32. package/src/screens/UnitSummary/components/3PPowerConsumption/index.js +105 -166
  33. package/src/screens/UnitSummary/components/AirQuality/SegmentedRoundChart.js +32 -0
  34. package/src/{commons/UnitSummary → screens/UnitSummary/components}/AirQuality/__test__/index.test.js +25 -15
  35. package/src/{commons/UnitSummary → screens/UnitSummary/components}/AirQuality/index.js +55 -71
  36. package/src/{commons/UnitSummary → screens/UnitSummary/components}/AirQuality/styles.js +1 -2
  37. package/src/screens/UnitSummary/components/PowerConsumption/__test__/PowerConsumption.test.js +26 -20
  38. package/src/screens/UnitSummary/components/PowerConsumption/index.js +59 -87
  39. package/src/screens/UnitSummary/components/RunningDevices/index.js +27 -23
  40. package/src/screens/UnitSummary/components/Temperature/ItemTemperature/index.js +33 -20
  41. package/src/screens/UnitSummary/components/Temperature/index.js +52 -79
  42. package/src/screens/UnitSummary/components/UvIndex/SegmentedRoundChart.js +36 -0
  43. package/src/screens/UnitSummary/components/UvIndex/__test__/index.test.js +8 -0
  44. package/src/screens/UnitSummary/components/UvIndex/index.js +16 -72
  45. package/src/screens/UnitSummary/components/UvIndex/styles.js +48 -0
  46. package/src/screens/UnitSummary/components/WaterQuality/Item/index.js +6 -4
  47. package/src/screens/UnitSummary/components/WaterQuality/__test__/index.test.js +26 -12
  48. package/src/screens/UnitSummary/components/WaterQuality/index.js +93 -3
  49. package/src/screens/UnitSummary/index.js +1 -9
  50. package/src/utils/I18n/translations/en.js +16 -1
  51. package/src/utils/I18n/translations/vi.js +15 -1
  52. package/src/utils/Route/index.js +1 -0
  53. package/src/screens/UnitSummary/components/PowerConsumption/ItemPower/index.js +0 -53
  54. package/src/screens/UnitSummary/components/PowerConsumption/__test__/ItemPower.test.js +0 -20
@@ -0,0 +1,9 @@
1
+ <svg width="28" height="33" viewBox="0 0 28 33" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M14.0003 32.6666C15.8337 32.6666 17.3337 31.1666 17.3337 29.3333H10.667C10.667 31.1666 12.1503 32.6666 14.0003 32.6666ZM24.0003 22.6666V14.3333C24.0003 9.21663 21.267 4.93329 16.5003 3.79996V2.66663C16.5003 1.28329 15.3837 0.166626 14.0003 0.166626C12.617 0.166626 11.5003 1.28329 11.5003 2.66663V3.79996C6.71699 4.93329 4.00033 9.19996 4.00033 14.3333V22.6666L0.666992 26V27.6666H27.3337V26L24.0003 22.6666Z" fill="url(#paint0_linear_2168_1847)"/>
3
+ <defs>
4
+ <linearGradient id="paint0_linear_2168_1847" x1="0.666992" y1="0.166626" x2="32.5129" y2="26.3255" gradientUnits="userSpaceOnUse">
5
+ <stop stop-color="#2B6B9F"/>
6
+ <stop offset="1" stop-color="#D5FFCB"/>
7
+ </linearGradient>
8
+ </defs>
9
+ </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.4.84",
4
+ "version": "0.4.86",
5
5
  "description": "TODO",
6
6
  "main": "index.js",
7
7
  "files": [
@@ -15,6 +15,7 @@ const ItemAutomate = ({
15
15
  index,
16
16
  setSelectedIndex,
17
17
  onPress,
18
+ enableScript = true,
18
19
  }) => {
19
20
  const t = useTranslations();
20
21
  const item = AUTOMATES[automate?.type];
@@ -57,7 +58,11 @@ const ItemAutomate = ({
57
58
  <View style={styles.row}>
58
59
  <View style={styles.wrapIcon}>{!!Icon && <Icon />}</View>
59
60
  <View style={styles.wrapTitle}>
60
- <Text type="H4" bold>
61
+ <Text
62
+ type="H4"
63
+ bold
64
+ color={enableScript ? Colors.Black : Colors.Gray7}
65
+ >
61
66
  {t(item?.title)}
62
67
  </Text>
63
68
  <Text type="Label" color={Colors.Gray8} numberOfLines={1}>
@@ -4,25 +4,32 @@ import { FlatList } from 'react-native';
4
4
  import QualityIndicatorItem from '../WaterQualitySensor/QualityIndicatorsItem';
5
5
  import styles from './PMSensorIndicatorStyles';
6
6
  import { keyExtractor, roundNumber } from '../../../utils/Utils';
7
+ import { useConfigGlobalState } from '../../../iot/states';
7
8
 
8
9
  const PMSensorIndicator = memo(({ data = [], style, isWidgetOrder }) => {
10
+ const [configValues] = useConfigGlobalState('configValues');
11
+
9
12
  const renderItem = useCallback(
10
13
  ({ item }) => {
11
- const getValue = ['', null, undefined, NaN].includes(item?.value)
12
- ? '--'
13
- : roundNumber(item?.value);
14
+ const { id, color, title, standard, evaluate, unit } = item || {};
15
+ const getValue =
16
+ configValues?.[id]?.value === undefined
17
+ ? '--'
18
+ : `${roundNumber(configValues[id].value)}`;
19
+
14
20
  return (
15
21
  <QualityIndicatorItem
16
- color={item.color}
17
- standard={item.standard}
22
+ key={id?.toString()}
23
+ color={color}
24
+ standard={title || standard}
18
25
  value={getValue}
19
- evaluate={item.evaluate}
20
- measure={item.unit}
26
+ evaluate={evaluate}
27
+ measure={unit}
21
28
  style={style}
22
29
  />
23
30
  );
24
31
  },
25
- [style]
32
+ [configValues, style]
26
33
  );
27
34
 
28
35
  const isScrollMode = data.length > 3;
@@ -2,25 +2,33 @@ import React, { useCallback } from 'react';
2
2
  import { View, StyleSheet, FlatList } from 'react-native';
3
3
 
4
4
  import QualityIndicatorItem from './QualityIndicatorsItem';
5
+ import { useConfigGlobalState } from '../../../iot/states';
5
6
 
6
7
  //using for Water quality sensor , power meter SENSOR, INdoor air sensor
7
8
  const ListQualityIndicator = ({ data, style }) => {
8
- const renderItem = useCallback(({ item }) => {
9
- const getValue = ['', null, undefined, NaN].includes(item?.value)
10
- ? '--'
11
- : item?.value;
9
+ const [configValues] = useConfigGlobalState('configValues');
10
+ const renderItem = useCallback(
11
+ ({ item }) => {
12
+ const { id, measure, color, title, standard, evaluate, unit } =
13
+ item || {};
14
+ const getValue =
15
+ configValues?.[id]?.value === undefined
16
+ ? '--'
17
+ : `${configValues[id].value} ${measure}`;
12
18
 
13
- return (
14
- <QualityIndicatorItem
15
- key={item.id.toString()}
16
- color={item.color}
17
- standard={item.standard}
18
- value={getValue}
19
- evaluate={item.evaluate}
20
- measure={item.unit}
21
- />
22
- );
23
- }, []);
19
+ return (
20
+ <QualityIndicatorItem
21
+ key={id?.toString()}
22
+ color={color}
23
+ standard={title || standard}
24
+ value={getValue}
25
+ evaluate={evaluate}
26
+ measure={unit}
27
+ />
28
+ );
29
+ },
30
+ [configValues]
31
+ );
24
32
  return (
25
33
  <View style={styles.standard}>
26
34
  <FlatList
@@ -22,14 +22,14 @@ const QualityIndicatorItem = memo(
22
22
  backgroundColor: color,
23
23
  };
24
24
  const navigation = useNavigation();
25
+ const measureText =
26
+ measure && measure.length ? `${value} ${measure}` : `${value}`;
25
27
 
26
28
  return (
27
29
  <View style={[styles.container, style, color && styles.containerPadding]}>
28
30
  <View style={[styles.line, styleColor]} />
29
31
  <View style={styles.rowFlex}>
30
- <Text size={14} color={Colors.Gray8} style={styles.txtMeasure}>
31
- {standard}
32
- </Text>
32
+ <Text style={styles.txtMeasure}>{standard}</Text>
33
33
  {type === 'machine_status' && (
34
34
  <TouchableOpacity
35
35
  onPress={() => navigation.navigate(descriptionScreen)}
@@ -43,13 +43,9 @@ const QualityIndicatorItem = memo(
43
43
  </TouchableOpacity>
44
44
  )}
45
45
  </View>
46
- <Text size={24} color={Colors.Gray9} style={styles.txtValue}>
47
- {measure && measure.length ? `${value} ${measure}` : `${value}`}
48
- </Text>
46
+ <Text style={styles.txtValue}>{measureText}</Text>
49
47
  {!!evaluate?.color && (
50
- <Text size={12} color={evaluate.color} style={styles.txtEvaluate}>
51
- {evaluate.text}
52
- </Text>
48
+ <Text style={styles.txtEvaluate}>{evaluate.text}</Text>
53
49
  )}
54
50
  </View>
55
51
  );
@@ -82,14 +78,19 @@ const styles = StyleSheet.create({
82
78
  txtMeasure: {
83
79
  lineHeight: 22,
84
80
  marginTop: 8,
81
+ fontSize: 14,
82
+ color: Colors.Gray8,
85
83
  },
86
84
  txtValue: {
87
85
  lineHeight: 32,
88
86
  marginTop: 16,
87
+ fontSize: 24,
88
+ color: Colors.Gray9,
89
89
  },
90
90
  txtEvaluate: {
91
91
  lineHeight: 20,
92
92
  marginTop: 8,
93
+ fontSize: 12,
93
94
  },
94
95
  iconInfo: {
95
96
  width: 40,
@@ -6,6 +6,7 @@ import { Colors } from '../../configs';
6
6
  import Text from '../Text';
7
7
  import ImageButton from '../ImageButton';
8
8
  import { ModalCustom } from '../Modal';
9
+ import packageJson from '../../../package.json';
9
10
 
10
11
  const keyExtractor = (item) => item.id.toString();
11
12
  const MenuActionAddnew = memo(
@@ -61,6 +62,11 @@ const MenuActionAddnew = memo(
61
62
  renderItem={renderItem}
62
63
  scrollIndicatorInsets={{ right: 1 }}
63
64
  />
65
+ <View style={styles.modalHeader}>
66
+ <Text
67
+ style={styles.modalHeaderText}
68
+ >{`v ${packageJson.version}`}</Text>
69
+ </View>
64
70
  </View>
65
71
  </View>
66
72
  </ModalCustom>
@@ -116,7 +116,7 @@ const styles = StyleSheet.create({
116
116
  scrollView: {
117
117
  flex: 1,
118
118
  paddingTop: Platform.select({
119
- ios: 0,
119
+ ios: 15,
120
120
  android: heightHeader + 16,
121
121
  }),
122
122
  },
@@ -1,22 +1,16 @@
1
- import React, { memo, useMemo } from 'react';
1
+ import React, { memo } from 'react';
2
2
  import styles from '../styles/ConfigValueStyles';
3
3
  import { Platform, View } from 'react-native';
4
4
  import Text from '../../../Text';
5
5
  import { useConfigGlobalState } from '../../../../iot/states';
6
- import { useWatchConfigs } from '../../../../hooks/IoT';
7
6
  import LastUpdatedText from '../../../Device/LastUpdatedText';
8
7
  import IconComponent from '../../../IconComponent';
9
8
  import { IconOutline } from '@ant-design/icons-react-native';
10
9
 
11
10
  const ConfigValue = ({ device, stationItem }) => {
12
- // eslint-disable-next-line no-unused-vars
13
- const [configValues, _] = useConfigGlobalState('configValues');
11
+ const [configValues] = useConfigGlobalState('configValues');
14
12
  const configValue = configValues[stationItem.configuration?.config];
15
- const configIds = useMemo(() => {
16
- return [stationItem.configuration?.config];
17
- }, [stationItem.configuration?.config]);
18
13
  const { icon_kit, icon } = device || {};
19
- useWatchConfigs(configIds);
20
14
 
21
15
  return (
22
16
  <>
@@ -1,4 +1,4 @@
1
- import React, { memo, useMemo } from 'react';
1
+ import React, { memo } from 'react';
2
2
  import styles from '../styles/ConfigValueStyles';
3
3
  import { Platform, View } from 'react-native';
4
4
  import Text from '../../../Text';
@@ -7,22 +7,14 @@ import {
7
7
  useEvaluateValue,
8
8
  useValueEvaluation,
9
9
  } from '../../../../screens/Device/hooks/useEvaluateValue';
10
- import { useWatchConfigs } from '../../../../hooks/IoT';
11
10
  import LastUpdatedText from '../../../Device/LastUpdatedText';
12
11
  import IconComponent from '../../../IconComponent';
13
12
  import { IconOutline } from '@ant-design/icons-react-native';
14
13
 
15
14
  export const EvaluationConfigWrapper = memo(
16
15
  ({ device, stationItem, Child }) => {
17
- // eslint-disable-next-line no-unused-vars
18
- const [configValues, _] = useConfigGlobalState('configValues');
16
+ const [configValues] = useConfigGlobalState('configValues');
19
17
  const configValue = configValues[stationItem.configuration?.config];
20
- const configIds = useMemo(() => {
21
- return [stationItem.configuration?.config];
22
- }, [stationItem.configuration?.config]);
23
-
24
- useWatchConfigs(configIds);
25
-
26
18
  const valueEvaluationObject = useValueEvaluation(
27
19
  stationItem.configuration?.config,
28
20
  device.unit_id,
@@ -22,6 +22,7 @@ import { AccessibilityLabel, AUTOMATE_TYPE } from '../../../configs/Constants';
22
22
  const ItemOneTap = memo(({ automate = {}, wrapSyles, onPressItem }) => {
23
23
  const { navigate } = useNavigation();
24
24
  const { id, type, script, activate_at, author = '' } = automate;
25
+ const { enable } = script;
25
26
  const t = useTranslations();
26
27
 
27
28
  const goToDetail = useCallback(() => {
@@ -69,7 +70,7 @@ const ItemOneTap = memo(({ automate = {}, wrapSyles, onPressItem }) => {
69
70
  <View style={[styles.container, wrapSyles]}>
70
71
  <View style={styles.boxIcon}>
71
72
  {displayIcon()}
72
- {type === AUTOMATE_TYPE.ONE_TAP && (
73
+ {type === AUTOMATE_TYPE.ONE_TAP && enable && (
73
74
  <TouchableOpacity
74
75
  accessibilityLabel={AccessibilityLabel.AUTOMATE_SCRIPT_ACTION}
75
76
  onPress={handleScriptAction}
@@ -86,7 +87,7 @@ const ItemOneTap = memo(({ automate = {}, wrapSyles, onPressItem }) => {
86
87
  numberOfLines={1}
87
88
  semibold
88
89
  size={14}
89
- color={Colors.Gray9}
90
+ color={enable ? Colors.Gray9 : Colors.Gray}
90
91
  type="Body"
91
92
  style={styles.name}
92
93
  accessibilityLabel={AccessibilityLabel.TEXT_AUTOMATE_NAME}
@@ -101,7 +102,7 @@ const ItemOneTap = memo(({ automate = {}, wrapSyles, onPressItem }) => {
101
102
  numberOfLines={1}
102
103
  semibold
103
104
  size={12}
104
- color={Colors.Gray8}
105
+ color={enable ? Colors.Gray8 : Colors.Gray}
105
106
  type="Label"
106
107
  >
107
108
  {activateAt && t('activated_time', { time: activateAt })}
@@ -49,6 +49,19 @@ describe('test Item', () => {
49
49
  name: 'Joshua Ray',
50
50
  icon: '',
51
51
  icon_kit: '',
52
+ enable: true,
53
+ },
54
+ },
55
+ {
56
+ id: 2,
57
+ user: 6,
58
+ type: 'one_tap',
59
+ activate_at: '2021-09-17T05:30:00Z',
60
+ script: {
61
+ name: 'Test',
62
+ icon: '',
63
+ icon_kit: '',
64
+ enable: false,
52
65
  },
53
66
  },
54
67
  ],
@@ -89,7 +102,7 @@ describe('test Item', () => {
89
102
  el.props.accessibilityLabel === AccessibilityLabel.GO_DETAIL &&
90
103
  el.type === TouchableOpacity
91
104
  );
92
- expect(goDetail).toHaveLength(1);
105
+ expect(goDetail).toHaveLength(2);
93
106
  await act(async () => {
94
107
  await goDetail[0].props.onPress();
95
108
  });
@@ -29,12 +29,22 @@ const ShortDetailSubUnit = ({ unit, station, isOwner }) => {
29
29
  useDevicesStatus(unit, station?.devices);
30
30
 
31
31
  const configsNeedWatching = useMemo(() => {
32
- const configIds = [];
33
- (station?.devices || []).forEach((device) => {
34
- if (device?.quick_action?.config_id && device?.is_managed_by_backend) {
35
- configIds.push(device.quick_action.config_id);
32
+ const configIds = (station?.devices || []).flatMap((device) => {
33
+ const ids = [];
34
+
35
+ if (device?.quick_action?.config_id && device.is_managed_by_backend) {
36
+ ids.push(device.quick_action.config_id);
37
+ }
38
+
39
+ if (device?.station_items?.length) {
40
+ ids.push(
41
+ ...device.station_items.map((item) => item.configuration.config)
42
+ );
36
43
  }
44
+
45
+ return ids;
37
46
  });
47
+
38
48
  return configIds;
39
49
  }, [station]);
40
50
 
@@ -87,16 +87,26 @@ const API = {
87
87
  AUTOMATE: {
88
88
  ACTION_ONE_TAP: (id) => `/property_manager/automate/${id}/action_one_tap/`,
89
89
  SCRIPT: (id) => `/property_manager/automate/${id}/script/`,
90
+ SCRIPT_ITEMS: (id) => `/property_manager/automate/${id}/script_items/`,
90
91
  ORDER_SCRIPT_ACTION: (id) =>
91
92
  `/property_manager/automate/${id}/order_script_action/`,
93
+ ORDER_SCRIPT_ITEMS: (id) =>
94
+ `/property_manager/automate/${id}/order_script_items/`,
92
95
  DELETE_SCRIPT_ACTION: (automateId, actionId) =>
93
96
  `/property_manager/automate/${automateId}/script_action/${actionId}/`,
97
+ DELETE_SCRIPT_ITEM: (automateId, itemId) =>
98
+ `/property_manager/automate/${automateId}/script_item/${itemId}/`,
94
99
  ADD_SCRIPT_ACTION: (id) =>
95
100
  `/property_manager/automate/${id}/add_script_action/`,
101
+ ADD_SCRIPT_NOTIFY: (id) =>
102
+ `/property_manager/automate/${id}/add_script_notify/`,
103
+
96
104
  FETCH_AUTOMATE: (automateId) => `/property_manager/automate/${automateId}/`,
97
105
  CREATE_AUTOMATE: () => '/property_manager/automate/',
98
106
  UPDATE_AUTOMATE: (automateId) =>
99
107
  `/property_manager/automate/${automateId}/`,
108
+ ENABLE_SCRIPT: (automateId) =>
109
+ `/property_manager/automate/${automateId}/enable_script/`,
100
110
  STAR_SCRIPT: (id) => `/property_manager/automate/${id}/star_script/`,
101
111
  UNSTAR_SCRIPT: (id) => `/property_manager/automate/${id}/unstar_script/`,
102
112
  GET_SMART: () => '/property_manager/automate/smart/',
@@ -241,6 +241,9 @@ export default {
241
241
  ICON_MORE: 'ICON_MORE',
242
242
  ICON_ARROW_RIGHT: 'ICON_ARROW_RIGHT',
243
243
  TEXT_AUTOMATE_NAME: 'TEXT_AUTOMATE_NAME',
244
+ AUTOMATE_LIST_SCRIPT_ACTION: 'AUTOMATE_LIST_SCRIPT_ACTION',
245
+ AUTOMATE_TITLE_NOTIFY: 'AUTOMATE_TITLE_NOTIFY',
246
+ AUTOMATE_MESSAGE_NOTIFY: 'AUTOMATE_MESSAGE_NOTIFY',
244
247
 
245
248
  // Parking input maunaly spot
246
249
  PARKING_SPOT_INFO_BUTTON: 'PARKING_SPOT_INFO_BUTTON',
@@ -19,7 +19,7 @@ import { Action } from '../context/actionType';
19
19
  import AQIGuide from '../screens/AQIGuide';
20
20
  import DeviceDetail from '../screens/Device/detail';
21
21
  import ChangePosition from '../screens/ChangePosition';
22
- import SharingMemberList from '../screens/Sharing/MemberList';
22
+ import UnitMemberList from '../screens/Sharing/UnitMemberList';
23
23
  import ManageSubUnit from '../screens/SubUnit/ManageSubUnit';
24
24
  import SelectAddress from '../screens/Unit/SelectAddress';
25
25
  import ChooseLocation from '../screens/Unit/ChooseLocation';
@@ -66,6 +66,7 @@ import ChooseAction from '../screens/Automate/AddNewAction/ChooseAction';
66
66
  import ScenarioName from '../screens/Automate/Scenario/ScenarioName';
67
67
  import ValueChangeName from '../screens/Automate/ValueChange/ValueChangeName';
68
68
  import AddAutomationTypeSmart from '../screens/Automate/AddNewAutoSmart/AddAutomationTypeSmart';
69
+ import SetupScriptNotify from '../screens/Automate/AddNewAction/SetupScriptNotify';
69
70
 
70
71
  const Stack = createStackNavigator();
71
72
 
@@ -331,7 +332,7 @@ export const UnitStack = memo((props) => {
331
332
  />
332
333
  <Stack.Screen
333
334
  name={Route.UnitMemberList}
334
- component={SharingMemberList}
335
+ component={UnitMemberList}
335
336
  options={{
336
337
  headerShown: false,
337
338
  }}
@@ -406,6 +407,13 @@ export const UnitStack = memo((props) => {
406
407
  headerShown: false,
407
408
  }}
408
409
  />
410
+ <Stack.Screen
411
+ name={Route.SetupScriptNotify}
412
+ component={SetupScriptNotify}
413
+ options={{
414
+ headerShown: false,
415
+ }}
416
+ />
409
417
  <Stack.Screen
410
418
  name={Route.AddAutomationTypeSmart}
411
419
  component={AddAutomationTypeSmart}
@@ -0,0 +1,92 @@
1
+ import React, { useCallback, useMemo, useState } from 'react';
2
+ import { View } from 'react-native';
3
+ import { useNavigation } from '@react-navigation/native';
4
+ import styles from './Styles/SetupScriptNotifyStyles';
5
+ import { HeaderCustom } from '../../../commons';
6
+ import { useTranslations } from '../../../hooks/Common/useTranslations';
7
+
8
+ import _TextInput from '../../../commons/Form/TextInput';
9
+ import AccessibilityLabel from '../../../configs/AccessibilityLabel';
10
+ import BottomButtonView from '../../../commons/BottomButtonView';
11
+ import { axiosPost } from '../../../utils/Apis/axios';
12
+ import { API } from '../../../configs';
13
+ import { ToastBottomHelper } from '../../../utils/Utils';
14
+ import Routes from '../../../utils/Route';
15
+ import moment from 'moment';
16
+
17
+ const SetupScriptNotify = ({ route }) => {
18
+ const t = useTranslations();
19
+ const { goBack, navigate } = useNavigation();
20
+ const { automate = {}, unitId } = route?.params || {};
21
+ const { id: automateId } = automate;
22
+ const [notify, setNotify] = useState({ unit: unitId });
23
+
24
+ const onChangeTitle = (value) => {
25
+ setNotify((state) => ({
26
+ ...state,
27
+ title: value,
28
+ }));
29
+ };
30
+ const onChangeMessage = (value) => {
31
+ setNotify((state) => ({
32
+ ...state,
33
+ message: value,
34
+ }));
35
+ };
36
+
37
+ const onNext = useCallback(async () => {
38
+ const { success } = await axiosPost(
39
+ API.AUTOMATE.ADD_SCRIPT_NOTIFY(automateId),
40
+ notify
41
+ );
42
+ if (success) {
43
+ ToastBottomHelper.success(t('text_done'));
44
+ navigate({
45
+ name: Routes.ScriptDetail,
46
+ merge: true,
47
+ params: { saveAt: moment().valueOf() },
48
+ });
49
+ } else {
50
+ ToastBottomHelper.error(t('text_done'));
51
+ }
52
+ }, [automateId, navigate, notify, t]);
53
+
54
+ const canSave = useMemo(() => {
55
+ const { title, message } = notify || {};
56
+ return !!title && !!message;
57
+ }, [notify]);
58
+
59
+ return (
60
+ <View style={styles.wrap}>
61
+ <HeaderCustom isShowClose onClose={goBack} title={t('notification')} />
62
+ <View style={styles.container}>
63
+ <_TextInput
64
+ placeholder={t('title_notification')}
65
+ onChange={onChangeTitle}
66
+ textInputStyle={styles.textTitle}
67
+ value={notify?.title}
68
+ accessibilityLabel={AccessibilityLabel.AUTOMATE_TITLE_NOTIFY}
69
+ autoFocus
70
+ />
71
+ <_TextInput
72
+ placeholder={t('message_notification')}
73
+ onChange={onChangeMessage}
74
+ textInputStyle={styles.textMessage}
75
+ value={notify?.message}
76
+ accessibilityLabel={AccessibilityLabel.AUTOMATE_MESSAGE_NOTIFY}
77
+ multiline={true}
78
+ maxLength={255}
79
+ />
80
+
81
+ <BottomButtonView
82
+ style={styles.bottomButtonView}
83
+ mainTitle={t('save')}
84
+ onPressMain={onNext}
85
+ typeMain={canSave ? 'primary' : 'disabled'}
86
+ />
87
+ </View>
88
+ </View>
89
+ );
90
+ };
91
+
92
+ export default SetupScriptNotify;
@@ -0,0 +1,57 @@
1
+ import { StyleSheet } from 'react-native';
2
+ import { Colors } from '../../../../configs';
3
+ import { getBottomSpace } from 'react-native-iphone-x-helper';
4
+
5
+ export default StyleSheet.create({
6
+ wrap: {
7
+ flex: 1,
8
+ backgroundColor: Colors.White,
9
+ },
10
+ titleCreate: {
11
+ fontStyle: 'normal',
12
+ fontWeight: '600',
13
+ color: Colors.Gray9,
14
+ },
15
+ titleChoose: {
16
+ fontStyle: 'normal',
17
+ fontWeight: '400',
18
+ color: Colors.Gray8,
19
+ },
20
+ container: {
21
+ flex: 1,
22
+ paddingHorizontal: 16,
23
+ paddingTop: 10,
24
+ paddingBottom: getBottomSpace() + 10,
25
+ },
26
+ textTitle: {
27
+ borderWidth: 1,
28
+ borderColor: Colors.Gray4,
29
+ borderStyle: 'solid',
30
+ borderRadius: 10,
31
+ },
32
+ textMessage: {
33
+ height: 500,
34
+ borderWidth: 1,
35
+ borderColor: Colors.Gray4,
36
+ borderStyle: 'solid',
37
+ borderRadius: 10,
38
+ },
39
+ bottomButtonView: {
40
+ paddingTop: 24,
41
+ paddingBottom: 32,
42
+
43
+ backgroundColor: Colors.White,
44
+ borderColor: Colors.ShadownTransparent,
45
+ borderTopWidth: 1,
46
+ },
47
+ bottomButton: {
48
+ borderWidth: 0,
49
+ borderColor: Colors.Gray4,
50
+ paddingTop: 24,
51
+ paddingBottom: 24,
52
+ borderTopWidth: 1,
53
+ borderStyle: 'solid',
54
+ position: 'absolute',
55
+ bottom: 0,
56
+ },
57
+ });
@@ -62,6 +62,7 @@ describe('Test SetupConfigCondition', () => {
62
62
  sensor_type: 'air_quality',
63
63
  value_evaluations: [
64
64
  {
65
+ id: 1,
65
66
  template: 'range',
66
67
  configuration: {
67
68
  ranges: [
@@ -83,6 +84,18 @@ describe('Test SetupConfigCondition', () => {
83
84
  ],
84
85
  },
85
86
  },
87
+ {
88
+ id: 2,
89
+ template: 'boolean',
90
+ configuration: {
91
+ on: {
92
+ text: 'On',
93
+ },
94
+ off: {
95
+ text: 'Off',
96
+ },
97
+ },
98
+ },
86
99
  ],
87
100
  },
88
101
  sensorData: [],