@eohjsc/react-native-smart-city 0.2.91 → 0.2.94
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.
- package/assets/images/Device/air-dry.svg +3 -0
- package/assets/images/Device/auto.svg +3 -0
- package/assets/images/Device/circulator.svg +4 -0
- package/assets/images/Device/clean.svg +5 -0
- package/assets/images/Device/current-state.svg +3 -0
- package/assets/images/Device/door-state.svg +3 -0
- package/assets/images/Device/wind-strength.svg +12 -0
- package/package.json +1 -1
- package/src/commons/Action/ItemQuickAction.js +1 -0
- package/src/commons/Action/__test__/ItemQuickAction.test.js +49 -2
- package/src/commons/ActionGroup/ColorPickerTemplate.js +30 -24
- package/src/commons/ActionGroup/OnOffSmartLock/OnOffSmartLock.js +60 -12
- package/src/commons/ActionGroup/OnOffSmartLock/PasscodeList/__test__/index.test.js +47 -0
- package/src/commons/ActionGroup/OnOffSmartLock/PasscodeList/index.js +2 -0
- package/src/commons/ActionGroup/OnOffTemplate/OnOffSimpleTemplateStyle.js +2 -1
- package/src/commons/ActionGroup/OnOffTemplate/index.js +48 -28
- package/src/commons/ActionGroup/OptionsDropdownActionTemplate.js +31 -11
- package/src/commons/ActionGroup/OptionsDropdownActionTemplateStyle.js +5 -2
- package/src/commons/ActionGroup/SliderRangeTemplate.js +19 -5
- package/src/commons/ActionGroup/StatesGridActionTemplate.js +42 -36
- package/src/commons/ActionGroup/StatesGridActionTemplateStyle.js +5 -10
- package/src/commons/ActionGroup/TimerActionTemplate.js +14 -10
- package/src/commons/ActionGroup/TimerActionTemplateStyles.js +12 -0
- package/src/commons/ActionGroup/TwoButtonTemplate/TwoButtonTemplateStyles.js +55 -0
- package/src/commons/ActionGroup/TwoButtonTemplate/index.js +170 -0
- package/src/commons/ActionGroup/__test__/ColorPickerTemplate.test.js +74 -0
- package/src/commons/ActionGroup/__test__/OnOffSmartLock.test.js +107 -0
- package/src/commons/ActionGroup/__test__/SliderRangeTemplate.test.js +71 -0
- package/src/commons/ActionGroup/__test__/TimerActionTemplate.test.js +1 -1
- package/src/commons/ActionGroup/__test__/TwoButtonTemplate.test.js +112 -0
- package/src/commons/ActionGroup/index.js +4 -1
- package/src/commons/Calendar/index.js +5 -1
- package/src/commons/CameraDevice/index.js +6 -1
- package/src/commons/ConnectingProcess/__test__/Connecting.test.js +4 -1
- package/src/commons/Device/HistoryChart.js +2 -2
- package/src/commons/Device/HorizontalBarChart.js +6 -2
- package/src/commons/Device/ItemDevice.js +3 -13
- package/src/commons/Explore/SearchBox/__test__/SearchBox.test.js +19 -0
- package/src/commons/Explore/SearchBox/index.js +2 -0
- package/src/commons/IconComponent/index.js +32 -26
- package/src/commons/MediaPlayerDetail/index.js +16 -4
- package/src/commons/MenuActionMore/index.js +14 -1
- package/src/commons/Modal/ModalCustom.js +9 -1
- package/src/commons/SubUnit/Favorites/index.js +11 -41
- package/src/commons/SubUnit/ShortDetail.js +7 -41
- package/src/commons/SubUnit/__test__/Favorites.test.js +33 -35
- package/src/configs/API.js +4 -0
- package/src/configs/Colors.js +1 -0
- package/src/configs/Constants.js +29 -0
- package/src/context/actionType.ts +17 -0
- package/src/context/mockStore.ts +18 -0
- package/src/context/reducer.ts +102 -0
- package/src/hooks/Common/index.js +2 -0
- package/src/hooks/Common/useSensorsStatus.js +52 -0
- package/src/iot/RemoteControl/Bluetooth.js +2 -0
- package/src/iot/RemoteControl/GoogleHome.js +1 -0
- package/src/navigations/AutomateStack.js +16 -1
- package/src/navigations/UnitStack.js +27 -0
- package/src/screens/AddCommon/SelectSubUnit.js +1 -0
- package/src/screens/AddCommon/__test__/SelectSubUnit.test.js +2 -0
- package/src/screens/AddNewAction/Device/__test__/index.test.js +1 -1
- package/src/screens/AddNewAction/SelectAction.js +13 -15
- package/src/screens/AddNewAction/__test__/SelectAction.test.js +0 -7
- package/src/screens/AddNewGateway/PlugAndPlay/ConnectWifiWarning.js +2 -0
- package/src/screens/AddNewGateway/PlugAndPlay/GatewayWifiList.js +2 -0
- package/src/screens/AddNewGateway/PlugAndPlay/__test__/ConnectWifiWarning.test.js +10 -0
- package/src/screens/AddNewGateway/PlugAndPlay/__test__/GatewayWifiList.test.js +15 -0
- package/src/screens/AddNewGateway/SetupGatewayWifi.js +6 -1
- package/src/screens/AddNewGateway/__test__/SelectGateway.test.js +61 -0
- package/src/screens/AddNewGateway/__test__/SetupGateway.test.js +34 -0
- package/src/screens/AllCamera/index.js +1 -0
- package/src/screens/Automate/MultiUnits.js +9 -9
- package/src/screens/Automate/index.js +21 -20
- package/src/screens/Device/__test__/DetailHistoryChart.test.js +40 -0
- package/src/screens/Device/__test__/detail.test.js +119 -86
- package/src/screens/Device/detail.js +38 -51
- package/src/screens/Device/hooks/useFavoriteDevice.js +38 -0
- package/src/screens/EmergencyContacts/EmergencyContactsList.js +1 -1
- package/src/screens/EmergencyContacts/EmergencyContactsSelectContacts.js +41 -44
- package/src/screens/EmergencyContacts/__test__/EmergencyContactList.test.js +1 -0
- package/src/screens/EmergencyContacts/__test__/EmergencyContactsSelectContacts.test.js +18 -19
- package/src/screens/HanetCamera/Detail.js +20 -13
- package/src/screens/HanetCamera/ManageAccess.js +10 -52
- package/src/screens/HanetCamera/MemberInfo.js +59 -13
- package/src/screens/HanetCamera/__test__/ManageAccess.test.js +19 -0
- package/src/screens/HanetCamera/__test__/MemberInfo.test.js +57 -10
- package/src/screens/HanetCamera/components/RequestFaceIDPopup.js +90 -0
- package/src/screens/HanetCamera/hooks/__test__/useHanetCheckinData.test.js +9 -12
- package/src/screens/HanetCamera/hooks/useHanetCheckinData.js +10 -7
- package/src/screens/HanetCamera/styles/manageAccessStyles.js +0 -14
- package/src/screens/MoveToAnotherSubUnit/index.js +3 -1
- package/src/screens/Notification/__test__/NotificationItem.test.js +64 -53
- package/src/screens/Notification/components/NotificationItem.js +13 -4
- package/src/screens/ScriptDetail/__test__/index.test.js +15 -4
- package/src/screens/ScriptDetail/hooks/useStarredScript.js +32 -0
- package/src/screens/ScriptDetail/index.js +11 -20
- package/src/screens/SharedUnit/__test__/TabHeader.test.js +5 -0
- package/src/screens/Sharing/SelectUser.js +3 -23
- package/src/screens/Sharing/__test__/SelectUser.test.js +12 -80
- package/src/screens/SmartIr/__test__/GroupButtonByType.test.js +33 -0
- package/src/screens/SmartIr/components/GroupButtonByType/GroupButtonByType.js +2 -0
- package/src/screens/Unit/ChooseLocation.js +5 -0
- package/src/screens/Unit/Detail.js +34 -44
- package/src/screens/Unit/ManageUnit.js +21 -20
- package/src/screens/Unit/ManageUnitStyles.js +1 -0
- package/src/screens/Unit/SelectAddress.js +8 -2
- package/src/screens/Unit/Summaries.js +12 -15
- package/src/screens/Unit/__test__/Detail.test.js +25 -0
- package/src/screens/Unit/components/MyUnitDevice/index.js +13 -10
- package/src/screens/Unit/components/__test__/Header.test.js +32 -0
- package/src/screens/Unit/components/__test__/MyUnitDevice.test.js +2 -2
- package/src/screens/Unit/hook/useFavorites.js +28 -0
- package/src/utils/Apis/axios.js +7 -2
- package/src/utils/I18n/translations/en.json +3 -5
- package/src/utils/I18n/translations/vi.json +2 -4
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { TouchableOpacity, StyleSheet } from 'react-native';
|
|
3
|
+
import ImagePicker from 'react-native-image-crop-picker';
|
|
4
|
+
import { IconFill } from '@ant-design/icons-react-native';
|
|
5
|
+
import Text from '../../../commons/Text';
|
|
6
|
+
import BottomSheet from '../../../commons/BottomSheet';
|
|
7
|
+
import { Colors } from '../../../configs';
|
|
8
|
+
import { useTranslations } from '../../../hooks/Common/useTranslations';
|
|
9
|
+
import SmartPhoneSvg from '../../../../assets/images/Common/SmartPhone.svg';
|
|
10
|
+
import { TESTID } from '../../../configs/Constants';
|
|
11
|
+
|
|
12
|
+
const RequestFaceIDPopup = ({
|
|
13
|
+
title,
|
|
14
|
+
isVisible,
|
|
15
|
+
setHide,
|
|
16
|
+
onCaptureFaceID,
|
|
17
|
+
onChooseFile,
|
|
18
|
+
}) => {
|
|
19
|
+
const t = useTranslations();
|
|
20
|
+
const options = [
|
|
21
|
+
{
|
|
22
|
+
icon: <IconFill name="camera" color={Colors.Gray9} size={27} />,
|
|
23
|
+
text: t('capture_image'),
|
|
24
|
+
onChoose: () => {
|
|
25
|
+
setHide();
|
|
26
|
+
onCaptureFaceID && onCaptureFaceID();
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
icon: <SmartPhoneSvg />,
|
|
31
|
+
text: t('pick_available_image_from_your_phone'),
|
|
32
|
+
onChoose: async () => {
|
|
33
|
+
setHide();
|
|
34
|
+
const options = {
|
|
35
|
+
mediaType: 'photo',
|
|
36
|
+
compressImageMaxHeight: 1280,
|
|
37
|
+
compressImageMaxWidth: 738,
|
|
38
|
+
compressImageQuality: 0.7,
|
|
39
|
+
forceJpg: true,
|
|
40
|
+
};
|
|
41
|
+
try {
|
|
42
|
+
const result = await ImagePicker.openPicker(options);
|
|
43
|
+
onChooseFile && onChooseFile(result);
|
|
44
|
+
} catch (e) {}
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<BottomSheet
|
|
51
|
+
isVisible={isVisible}
|
|
52
|
+
onBackdropPress={setHide}
|
|
53
|
+
title={title}
|
|
54
|
+
style={styles.wrap}
|
|
55
|
+
>
|
|
56
|
+
{options.map((option, i) => (
|
|
57
|
+
<TouchableOpacity
|
|
58
|
+
key={i}
|
|
59
|
+
onPress={option.onChoose}
|
|
60
|
+
style={styles.row}
|
|
61
|
+
testID={`${TESTID.HANET_ADD_MEMBER_OPTION}_${i}`}
|
|
62
|
+
>
|
|
63
|
+
{option.icon}
|
|
64
|
+
<Text type="H4" color={Colors.Gray9} style={styles.textOption}>
|
|
65
|
+
{option.text}
|
|
66
|
+
</Text>
|
|
67
|
+
</TouchableOpacity>
|
|
68
|
+
))}
|
|
69
|
+
</BottomSheet>
|
|
70
|
+
);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export default RequestFaceIDPopup;
|
|
74
|
+
|
|
75
|
+
const styles = StyleSheet.create({
|
|
76
|
+
wrap: {
|
|
77
|
+
paddingBottom: 50,
|
|
78
|
+
},
|
|
79
|
+
row: {
|
|
80
|
+
flexDirection: 'row',
|
|
81
|
+
alignItems: 'center',
|
|
82
|
+
paddingVertical: 16,
|
|
83
|
+
marginHorizontal: 16,
|
|
84
|
+
borderBottomColor: Colors.Gray3,
|
|
85
|
+
borderBottomWidth: 1,
|
|
86
|
+
},
|
|
87
|
+
textOption: {
|
|
88
|
+
marginLeft: 18,
|
|
89
|
+
},
|
|
90
|
+
});
|
|
@@ -38,6 +38,13 @@ describe('Test useHanetCheckinData', () => {
|
|
|
38
38
|
detected_mask: 'MASK_ON',
|
|
39
39
|
created_at: moment(),
|
|
40
40
|
},
|
|
41
|
+
{
|
|
42
|
+
id: 3,
|
|
43
|
+
person_type: 'IMAGE_FROM_CAMERA',
|
|
44
|
+
detected_image_uri: 'uri',
|
|
45
|
+
detected_mask: 'NOT_HANDLE',
|
|
46
|
+
created_at: moment(),
|
|
47
|
+
},
|
|
41
48
|
],
|
|
42
49
|
};
|
|
43
50
|
});
|
|
@@ -129,19 +136,9 @@ describe('Test useHanetCheckinData', () => {
|
|
|
129
136
|
expect(result.current.countMember).toBe(1);
|
|
130
137
|
expect(result.current.countStranger).toBe(1);
|
|
131
138
|
|
|
139
|
+
// send old data
|
|
132
140
|
await act(async () => {
|
|
133
|
-
await result.current.
|
|
134
|
-
});
|
|
135
|
-
const newData4 = {
|
|
136
|
-
id: 4,
|
|
137
|
-
person_name: 'name 2',
|
|
138
|
-
person_type: 'STRANGER',
|
|
139
|
-
detected_image_uri: 'uri',
|
|
140
|
-
detected_mask: 'MASK_ON',
|
|
141
|
-
created_at: moment(),
|
|
142
|
-
};
|
|
143
|
-
await act(async () => {
|
|
144
|
-
await result.current.onReceiveNewCheckinData(newData4);
|
|
141
|
+
await result.current.onReceiveNewCheckinData(newData2);
|
|
145
142
|
});
|
|
146
143
|
// no change
|
|
147
144
|
expect(result.current.checkinData).toHaveLength(2);
|
|
@@ -48,7 +48,7 @@ const useHanetCheckinData = (hanetCamera) => {
|
|
|
48
48
|
} else {
|
|
49
49
|
setCanLoadMore(page < Math.ceil(data.count / 20));
|
|
50
50
|
setCheckinData((prevData) =>
|
|
51
|
-
_.uniqBy(prevData.concat(data.results || []))
|
|
51
|
+
_.uniqBy(prevData.concat(data.results || []), 'id')
|
|
52
52
|
);
|
|
53
53
|
}
|
|
54
54
|
}
|
|
@@ -80,17 +80,20 @@ const useHanetCheckinData = (hanetCamera) => {
|
|
|
80
80
|
};
|
|
81
81
|
|
|
82
82
|
const onReceiveNewCheckinData = (data) => {
|
|
83
|
-
if (!moment(data.created_at).isSame(
|
|
83
|
+
if (!moment(data.created_at).isSame(moment(), 'date')) {
|
|
84
84
|
return;
|
|
85
85
|
}
|
|
86
86
|
setCheckinData((listData) => {
|
|
87
|
+
const existed = listData.find((i) => i.id === data.id);
|
|
88
|
+
if (!existed) {
|
|
89
|
+
if (['EMPLOYEE', 'CUSTOMER'].includes(data.person_type)) {
|
|
90
|
+
setCountMember((prevData) => prevData + 1);
|
|
91
|
+
} else {
|
|
92
|
+
setCountStranger((prevData) => prevData + 1);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
87
95
|
return _.uniqBy([data, ...listData], 'id');
|
|
88
96
|
});
|
|
89
|
-
if (['EMPLOYEE', 'CUSTOMER'].includes(data.person_type)) {
|
|
90
|
-
setCountMember((prevData) => prevData + 1);
|
|
91
|
-
} else {
|
|
92
|
-
setCountStranger((prevData) => prevData + 1);
|
|
93
|
-
}
|
|
94
97
|
};
|
|
95
98
|
|
|
96
99
|
useEffect(() => {
|
|
@@ -32,18 +32,4 @@ export default StyleSheet.create({
|
|
|
32
32
|
marginLeft: 16,
|
|
33
33
|
flex: 1,
|
|
34
34
|
},
|
|
35
|
-
addMemberModal: {
|
|
36
|
-
paddingBottom: 50,
|
|
37
|
-
},
|
|
38
|
-
row: {
|
|
39
|
-
flexDirection: 'row',
|
|
40
|
-
alignItems: 'center',
|
|
41
|
-
paddingVertical: 16,
|
|
42
|
-
marginHorizontal: 16,
|
|
43
|
-
borderBottomColor: Colors.Gray3,
|
|
44
|
-
borderBottomWidth: 1,
|
|
45
|
-
},
|
|
46
|
-
textOption: {
|
|
47
|
-
marginLeft: 18,
|
|
48
|
-
},
|
|
49
35
|
});
|
|
@@ -35,7 +35,9 @@ const MoveToAnotherSubUnit = memo(({ route }) => {
|
|
|
35
35
|
const { params = {} } = route;
|
|
36
36
|
const { unit, sensor, station } = params;
|
|
37
37
|
const { navigate } = useNavigation();
|
|
38
|
-
const [selectedSubUnit, setSelectedSubUnit] = useState(
|
|
38
|
+
const [selectedSubUnit, setSelectedSubUnit] = useState(
|
|
39
|
+
unit.stations?.find((subUnit) => subUnit.id === station.id)
|
|
40
|
+
);
|
|
39
41
|
|
|
40
42
|
const listStationUnit = useMemo(() => {
|
|
41
43
|
return unit.stations.slice(2);
|
|
@@ -36,7 +36,7 @@ describe('test NotificationItem', () => {
|
|
|
36
36
|
id: 1,
|
|
37
37
|
content_code: '',
|
|
38
38
|
is_read: true,
|
|
39
|
-
params:
|
|
39
|
+
params: "{'booking_id': 1, 'booking_id_new': 1}",
|
|
40
40
|
created_at: '',
|
|
41
41
|
icon: '',
|
|
42
42
|
};
|
|
@@ -49,62 +49,47 @@ describe('test NotificationItem', () => {
|
|
|
49
49
|
{
|
|
50
50
|
content_code: NOTIFICATION_TYPES.REMIND_TO_MAKE_PAYMENT,
|
|
51
51
|
screen: Routes.SmartParkingBookingDetails,
|
|
52
|
-
params: { id: 1 },
|
|
52
|
+
params: "{ 'id': 1 }",
|
|
53
53
|
},
|
|
54
54
|
{
|
|
55
55
|
content_code: NOTIFICATION_TYPES.EXPIRE_PARKING_SESSION,
|
|
56
56
|
screen: Routes.SmartParkingBookingDetails,
|
|
57
|
-
params: { id: 1 },
|
|
57
|
+
params: "{ 'id': 1 }",
|
|
58
58
|
},
|
|
59
59
|
{
|
|
60
60
|
content_code: NOTIFICATION_TYPES.REMIND_TO_SCAN_QR_CODE,
|
|
61
61
|
screen: Routes.SmartParkingBookingDetails,
|
|
62
|
-
params: { id: 1 },
|
|
63
|
-
},
|
|
64
|
-
{
|
|
65
|
-
content_code: NOTIFICATION_TYPES.USER_CANCEL,
|
|
66
|
-
screen: Routes.MyBookingList,
|
|
67
|
-
params: { tab: 1 },
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
content_code: NOTIFICATION_TYPES.SYSTEM_CANCEL_NO_PAYMENT,
|
|
71
|
-
screen: Routes.MyBookingList,
|
|
72
|
-
params: { tab: 1 },
|
|
62
|
+
params: "{ 'id': 1 }",
|
|
73
63
|
},
|
|
74
64
|
{
|
|
75
65
|
content_code: NOTIFICATION_TYPES.BOOKING_SUCCESSFULLY,
|
|
76
66
|
screen: Routes.SmartParkingBookingDetails,
|
|
77
|
-
params: { id: 1 },
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
content_code: NOTIFICATION_TYPES.PARKING_COMPLETED,
|
|
81
|
-
screen: Routes.MyBookingList,
|
|
82
|
-
params: { tab: 1 },
|
|
67
|
+
params: "{ 'id': 1 }",
|
|
83
68
|
},
|
|
84
69
|
{
|
|
85
70
|
content_code: NOTIFICATION_TYPES.BOOKING_EXPIRED_AND_VIOLATION_CREATED,
|
|
86
71
|
screen: Routes.SmartParkingBookingDetails,
|
|
87
|
-
params: { id: 1 },
|
|
72
|
+
params: "{ 'id': 1 }",
|
|
88
73
|
},
|
|
89
74
|
{
|
|
90
75
|
content_code: NOTIFICATION_TYPES.MOVE_CAR_WITHOUT_PAY_VIOLATION,
|
|
91
76
|
screen: Routes.SmartParkingBookingDetails,
|
|
92
|
-
params: { id: 1 },
|
|
77
|
+
params: "{ 'id': 1 }",
|
|
93
78
|
},
|
|
94
79
|
{
|
|
95
80
|
content_code: NOTIFICATION_TYPES.PAY_FINE_SUCCESSFULLY,
|
|
96
81
|
screen: Routes.SmartParkingBookingDetails,
|
|
97
|
-
params: { id: 1 },
|
|
82
|
+
params: "{ 'id': 1 }",
|
|
98
83
|
},
|
|
99
84
|
{
|
|
100
85
|
content_code: NOTIFICATION_TYPES.STOP_VIOLATION_FREE_PARKING_ZONE,
|
|
101
86
|
screen: Routes.SmartParkingBookingDetails,
|
|
102
|
-
params: { id: 1 },
|
|
87
|
+
params: "{ 'id': 1 }",
|
|
103
88
|
},
|
|
104
89
|
{
|
|
105
90
|
content_code: NOTIFICATION_TYPES.PAY_FINE_AND_EXTEND_SUCCESSFULLY,
|
|
106
91
|
screen: Routes.SmartParkingBookingDetails,
|
|
107
|
-
params: { id: 1 },
|
|
92
|
+
params: "{ 'id': 1 }",
|
|
108
93
|
},
|
|
109
94
|
];
|
|
110
95
|
|
|
@@ -121,7 +106,42 @@ describe('test NotificationItem', () => {
|
|
|
121
106
|
});
|
|
122
107
|
expect(mockNavigate).toHaveBeenCalledWith(Routes.SmartParkingStack, {
|
|
123
108
|
screen: notify.screen,
|
|
124
|
-
params:
|
|
109
|
+
params: { id: 1 },
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const listCaseSmartParking2 = [
|
|
115
|
+
{
|
|
116
|
+
content_code: NOTIFICATION_TYPES.USER_CANCEL,
|
|
117
|
+
screen: Routes.MyBookingList,
|
|
118
|
+
params: "{ 'tab': 1 }",
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
content_code: NOTIFICATION_TYPES.SYSTEM_CANCEL_NO_PAYMENT,
|
|
122
|
+
screen: Routes.MyBookingList,
|
|
123
|
+
params: "{ 'tab': 1 }",
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
content_code: NOTIFICATION_TYPES.PARKING_COMPLETED,
|
|
127
|
+
screen: Routes.MyBookingList,
|
|
128
|
+
params: "{ 'tab': 1 }",
|
|
129
|
+
},
|
|
130
|
+
];
|
|
131
|
+
for (const notify of listCaseSmartParking2) {
|
|
132
|
+
test(`create ItemNotification ${notify.content_code}`, () => {
|
|
133
|
+
item.content_code = notify.content_code;
|
|
134
|
+
act(() => {
|
|
135
|
+
tree = create(wrapComponent(item));
|
|
136
|
+
});
|
|
137
|
+
const instance = tree.root;
|
|
138
|
+
const button = instance.findByType(TouchableOpacity);
|
|
139
|
+
act(() => {
|
|
140
|
+
button.props.onPress();
|
|
141
|
+
});
|
|
142
|
+
expect(mockNavigate).toHaveBeenCalledWith(Routes.SmartParkingStack, {
|
|
143
|
+
screen: notify.screen,
|
|
144
|
+
params: { tab: 1 },
|
|
125
145
|
});
|
|
126
146
|
});
|
|
127
147
|
}
|
|
@@ -160,15 +180,7 @@ describe('test NotificationItem', () => {
|
|
|
160
180
|
for (const sensorType of listSensorType) {
|
|
161
181
|
test(`create ItemNotification NOTIFY_INDICATOR sensor_type ${sensorType}`, () => {
|
|
162
182
|
item.content_code = NOTIFICATION_TYPES.NOTIFY_INDICATOR;
|
|
163
|
-
item.params =
|
|
164
|
-
unit_name: 'EoH Office',
|
|
165
|
-
status: 'Very Poor',
|
|
166
|
-
sensor_type: sensorType,
|
|
167
|
-
unit_id: 5,
|
|
168
|
-
summary_id: 11,
|
|
169
|
-
sensor_id: '',
|
|
170
|
-
});
|
|
171
|
-
|
|
183
|
+
item.params = `{'sensor_type': '${sensorType}', 'unit_id': 5, 'summary_id': 11}`;
|
|
172
184
|
act(() => {
|
|
173
185
|
tree = create(wrapComponent(item));
|
|
174
186
|
});
|
|
@@ -196,14 +208,7 @@ describe('test NotificationItem', () => {
|
|
|
196
208
|
for (const sensorType of listSensorType2) {
|
|
197
209
|
test(`create ItemNotification NOTIFY_INDICATOR sensor_type ${sensorType}`, () => {
|
|
198
210
|
item.content_code = NOTIFICATION_TYPES.NOTIFY_INDICATOR;
|
|
199
|
-
item.params =
|
|
200
|
-
unit_name: 'Lavida Smart Home',
|
|
201
|
-
status: '',
|
|
202
|
-
sensor_type: sensorType,
|
|
203
|
-
unit_id: 70,
|
|
204
|
-
summary_id: '',
|
|
205
|
-
sensor_id: 394,
|
|
206
|
-
});
|
|
211
|
+
item.params = `{'sensor_type': '${sensorType}', 'unit_id': 70, 'sensor_id': 394}`;
|
|
207
212
|
|
|
208
213
|
act(() => {
|
|
209
214
|
tree = create(wrapComponent(item));
|
|
@@ -225,14 +230,8 @@ describe('test NotificationItem', () => {
|
|
|
225
230
|
|
|
226
231
|
test('test onClick Item Notify', () => {
|
|
227
232
|
item.content_code = NOTIFICATION_TYPES.NOTIFY_INDICATOR;
|
|
228
|
-
item.params =
|
|
229
|
-
|
|
230
|
-
status: 'Very Poor',
|
|
231
|
-
sensor_type: 'air_quality',
|
|
232
|
-
unit_id: 5,
|
|
233
|
-
summary_id: 11,
|
|
234
|
-
sensor_id: '',
|
|
235
|
-
});
|
|
233
|
+
item.params =
|
|
234
|
+
"{'sensor_type': 'air_quality', 'unit_id': 5, 'summary_id': 11}";
|
|
236
235
|
item.is_read = false;
|
|
237
236
|
act(() => {
|
|
238
237
|
tree = create(wrapComponent(item));
|
|
@@ -254,9 +253,21 @@ describe('test NotificationItem', () => {
|
|
|
254
253
|
|
|
255
254
|
test('test render Notify not in any case', () => {
|
|
256
255
|
item.content_code = 'NEW CASE';
|
|
257
|
-
item.params =
|
|
258
|
-
|
|
256
|
+
(item.params = "{ 'unit_id': 1 }"),
|
|
257
|
+
act(() => {
|
|
258
|
+
tree = create(wrapComponent(item));
|
|
259
|
+
});
|
|
260
|
+
const instance = tree.root;
|
|
261
|
+
const button = instance.findByType(TouchableOpacity);
|
|
262
|
+
act(() => {
|
|
263
|
+
button.props.onPress();
|
|
259
264
|
});
|
|
265
|
+
expect(mockNavigate).not.toHaveBeenCalledWith();
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
test('test render Notify params is object', () => {
|
|
269
|
+
item.content_code = 'NEW CASE';
|
|
270
|
+
item.params = { unit_id: 1 };
|
|
260
271
|
act(() => {
|
|
261
272
|
tree = create(wrapComponent(item));
|
|
262
273
|
});
|
|
@@ -22,14 +22,24 @@ const NotificationItem = memo(({ item }) => {
|
|
|
22
22
|
return /\B'|'\B/g;
|
|
23
23
|
}, []);
|
|
24
24
|
|
|
25
|
+
const paramsJSON = useMemo(() => {
|
|
26
|
+
if (typeof params === 'object') {
|
|
27
|
+
return params;
|
|
28
|
+
}
|
|
29
|
+
// TODO return this later
|
|
30
|
+
let stringParams = JSON.stringify(params);
|
|
31
|
+
stringParams = stringParams.replace(regex, '"');
|
|
32
|
+
stringParams = stringParams.substring(1, stringParams.length - 1);
|
|
33
|
+
return JSON.parse(stringParams);
|
|
34
|
+
}, [params, regex]);
|
|
35
|
+
|
|
25
36
|
let arrParams = useMemo(() => {
|
|
26
37
|
const values = [];
|
|
27
|
-
const paramsJSON = JSON.parse(params.replace(regex, '"'));
|
|
28
38
|
Object.entries(paramsJSON).forEach(([key, value]) => {
|
|
29
39
|
values.push(value);
|
|
30
40
|
});
|
|
31
41
|
return values;
|
|
32
|
-
}, [
|
|
42
|
+
}, [paramsJSON]);
|
|
33
43
|
|
|
34
44
|
const customColorText = (text, params) => {
|
|
35
45
|
return text.split('**').map((str, i) =>
|
|
@@ -46,7 +56,6 @@ const NotificationItem = memo(({ item }) => {
|
|
|
46
56
|
};
|
|
47
57
|
|
|
48
58
|
const renderItem = useCallback(() => {
|
|
49
|
-
const paramsJSON = JSON.parse(params.replace(regex, '"'));
|
|
50
59
|
const booking_id = paramsJSON.booking_id && paramsJSON.booking_id;
|
|
51
60
|
const unitId = paramsJSON?.unit_id;
|
|
52
61
|
const sensorId = paramsJSON?.sensor_id;
|
|
@@ -513,7 +522,7 @@ const NotificationItem = memo(({ item }) => {
|
|
|
513
522
|
iconContent: <Image source={Images.logo} style={styles.logo} />,
|
|
514
523
|
};
|
|
515
524
|
}
|
|
516
|
-
}, [arrParams, content_code, navigation,
|
|
525
|
+
}, [arrParams, content_code, navigation, paramsJSON, t]);
|
|
517
526
|
|
|
518
527
|
const { content, redirect, iconContent } = renderItem() || {};
|
|
519
528
|
|
|
@@ -73,6 +73,9 @@ describe('Test ScriptDetail', () => {
|
|
|
73
73
|
sensor_id: 73,
|
|
74
74
|
type: 'value_change',
|
|
75
75
|
value: 35,
|
|
76
|
+
script: {
|
|
77
|
+
id: 1,
|
|
78
|
+
},
|
|
76
79
|
},
|
|
77
80
|
},
|
|
78
81
|
};
|
|
@@ -171,7 +174,9 @@ describe('Test ScriptDetail', () => {
|
|
|
171
174
|
await act(async () => {
|
|
172
175
|
await buttonStar.props.onPress();
|
|
173
176
|
});
|
|
174
|
-
expect(axios.post).toHaveBeenCalledWith(
|
|
177
|
+
expect(axios.post).toHaveBeenCalledWith(
|
|
178
|
+
API.AUTOMATE.STAR_SCRIPT(route.params.automate.id)
|
|
179
|
+
);
|
|
175
180
|
|
|
176
181
|
axios.post.mockClear();
|
|
177
182
|
axios.post.mockImplementation(async () => {
|
|
@@ -180,7 +185,9 @@ describe('Test ScriptDetail', () => {
|
|
|
180
185
|
await act(async () => {
|
|
181
186
|
await buttonStar.props.onPress();
|
|
182
187
|
});
|
|
183
|
-
expect(axios.post).toHaveBeenCalledWith(
|
|
188
|
+
expect(axios.post).toHaveBeenCalledWith(
|
|
189
|
+
API.AUTOMATE.UNSTAR_SCRIPT(route.params.automate.id)
|
|
190
|
+
);
|
|
184
191
|
|
|
185
192
|
const menu = instance.findByType(MenuActionMore);
|
|
186
193
|
const addFavorite = menu.props.listMenuItem[1];
|
|
@@ -191,7 +198,9 @@ describe('Test ScriptDetail', () => {
|
|
|
191
198
|
await act(async () => {
|
|
192
199
|
await menu.props.onItemClick(addFavorite);
|
|
193
200
|
});
|
|
194
|
-
expect(axios.post).toHaveBeenCalledWith(
|
|
201
|
+
expect(axios.post).toHaveBeenCalledWith(
|
|
202
|
+
API.AUTOMATE.STAR_SCRIPT(route.params.automate.id)
|
|
203
|
+
);
|
|
195
204
|
|
|
196
205
|
const removeFavorite = menu.props.listMenuItem[1];
|
|
197
206
|
axios.post.mockClear();
|
|
@@ -201,7 +210,9 @@ describe('Test ScriptDetail', () => {
|
|
|
201
210
|
await act(async () => {
|
|
202
211
|
await menu.props.onItemClick(removeFavorite);
|
|
203
212
|
});
|
|
204
|
-
expect(axios.post).toHaveBeenCalledWith(
|
|
213
|
+
expect(axios.post).toHaveBeenCalledWith(
|
|
214
|
+
API.AUTOMATE.UNSTAR_SCRIPT(route.params.automate.id)
|
|
215
|
+
);
|
|
205
216
|
});
|
|
206
217
|
|
|
207
218
|
test('test activate one tap', async () => {
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { useCallback, useContext } from 'react';
|
|
2
|
+
import { SCContext, useSCContextSelector } from '../../../context';
|
|
3
|
+
import { Action } from '../../../context/actionType';
|
|
4
|
+
import { axiosPost } from '../../../utils/Apis/axios';
|
|
5
|
+
import { API } from '../../../configs';
|
|
6
|
+
|
|
7
|
+
export const useStarredScript = (automate) => {
|
|
8
|
+
const { setAction } = useContext(SCContext);
|
|
9
|
+
const starredScriptIds = useSCContextSelector(
|
|
10
|
+
(state) => state.automate.starredScriptIds
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
const isStarred = starredScriptIds.includes(automate?.script?.id);
|
|
14
|
+
|
|
15
|
+
const starScript = useCallback(async () => {
|
|
16
|
+
const { success } = await axiosPost(API.AUTOMATE.STAR_SCRIPT(automate?.id));
|
|
17
|
+
success && setAction(Action.STAR_SCRIPT, automate?.script?.id);
|
|
18
|
+
}, [automate, setAction]);
|
|
19
|
+
|
|
20
|
+
const unstarScript = useCallback(async () => {
|
|
21
|
+
const { success } = await axiosPost(
|
|
22
|
+
API.AUTOMATE.UNSTAR_SCRIPT(automate?.id)
|
|
23
|
+
);
|
|
24
|
+
success && setAction(Action.UNSTAR_SCRIPT, automate?.script?.id);
|
|
25
|
+
}, [automate, setAction]);
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
isStarred,
|
|
29
|
+
starScript,
|
|
30
|
+
unstarScript,
|
|
31
|
+
};
|
|
32
|
+
};
|
|
@@ -19,6 +19,7 @@ import WrapHeaderScrollable from '../../commons/Sharing/WrapHeaderScrollable';
|
|
|
19
19
|
import { API, Colors, Images } from '../../configs';
|
|
20
20
|
import { usePopover } from '../../hooks/Common';
|
|
21
21
|
import { useStateAlertAction } from './hooks';
|
|
22
|
+
import { useStarredScript } from './hooks/useStarredScript';
|
|
22
23
|
import MenuActionMore from '../../commons/MenuActionMore';
|
|
23
24
|
import Add from '../../../assets/images/Add.svg';
|
|
24
25
|
import { useNavigation } from '@react-navigation/native';
|
|
@@ -67,7 +68,6 @@ const ScriptDetail = ({ route }) => {
|
|
|
67
68
|
isCreateNewAction,
|
|
68
69
|
isMultiUnits,
|
|
69
70
|
} = params;
|
|
70
|
-
const [isStar, setIsStar] = useState(false);
|
|
71
71
|
const [scriptName, setScriptName] = useState(name);
|
|
72
72
|
const [inputName, setInputName] = useState(name);
|
|
73
73
|
const [
|
|
@@ -79,6 +79,8 @@ const ScriptDetail = ({ route }) => {
|
|
|
79
79
|
] = useStateAlertAction();
|
|
80
80
|
const [data, setData] = useState([]);
|
|
81
81
|
|
|
82
|
+
const { isStarred, starScript, unstarScript } = useStarredScript(automate);
|
|
83
|
+
|
|
82
84
|
const [transY] = useKeyboardAnimated(-16);
|
|
83
85
|
const animatedStyle = Platform.select({
|
|
84
86
|
ios: {
|
|
@@ -126,30 +128,20 @@ const ScriptDetail = ({ route }) => {
|
|
|
126
128
|
}
|
|
127
129
|
}, [stateAlertAction.isDelete, deleteScript, renameScript]);
|
|
128
130
|
|
|
129
|
-
const starScript = useCallback(async () => {
|
|
130
|
-
const { success } = await axiosPost(API.AUTOMATE.STAR_SCRIPT(id));
|
|
131
|
-
success && setIsStar(true);
|
|
132
|
-
}, [id]);
|
|
133
|
-
|
|
134
|
-
const unstarScript = useCallback(async () => {
|
|
135
|
-
const { success } = await axiosPost(API.AUTOMATE.UNSTAR_SCRIPT(id));
|
|
136
|
-
success && setIsStar(false);
|
|
137
|
-
}, [id]);
|
|
138
|
-
|
|
139
131
|
const onPressStar = useCallback(() => {
|
|
140
|
-
if (
|
|
132
|
+
if (isStarred) {
|
|
141
133
|
unstarScript();
|
|
142
134
|
} else {
|
|
143
135
|
starScript();
|
|
144
136
|
}
|
|
145
|
-
}, [
|
|
137
|
+
}, [isStarred, starScript, unstarScript]);
|
|
146
138
|
|
|
147
139
|
const listMenuItem = useMemo(
|
|
148
140
|
() => [
|
|
149
141
|
{ text: t('rename'), doAction: onShowRename(havePermission) },
|
|
150
142
|
{
|
|
151
|
-
text:
|
|
152
|
-
doAction:
|
|
143
|
+
text: isStarred ? t('remove_favorite') : t('add_favorite'),
|
|
144
|
+
doAction: isStarred ? unstarScript : starScript,
|
|
153
145
|
},
|
|
154
146
|
{
|
|
155
147
|
text: t('activity_log'),
|
|
@@ -170,7 +162,7 @@ const ScriptDetail = ({ route }) => {
|
|
|
170
162
|
unit,
|
|
171
163
|
onShowDelete,
|
|
172
164
|
scriptName,
|
|
173
|
-
|
|
165
|
+
isStarred,
|
|
174
166
|
starScript,
|
|
175
167
|
unstarScript,
|
|
176
168
|
]
|
|
@@ -189,7 +181,6 @@ const ScriptDetail = ({ route }) => {
|
|
|
189
181
|
const getScriptDetail = useCallback(async () => {
|
|
190
182
|
const { success, data } = await axiosGet(API.AUTOMATE.SCRIPT(id));
|
|
191
183
|
success && setData(data?.script_actions || []);
|
|
192
|
-
success && setIsStar(data?.is_star);
|
|
193
184
|
}, [id]);
|
|
194
185
|
|
|
195
186
|
const onPressEdit = useCallback(() => {
|
|
@@ -318,7 +309,7 @@ const ScriptDetail = ({ route }) => {
|
|
|
318
309
|
onPress={onPressStar}
|
|
319
310
|
testID={TESTID.HEADER_DEVICE_BUTTON_STAR}
|
|
320
311
|
>
|
|
321
|
-
{
|
|
312
|
+
{isStarred ? (
|
|
322
313
|
<IconFill name="star" size={25} color={Colors.Yellow6} />
|
|
323
314
|
) : (
|
|
324
315
|
<IconOutline name="star" size={25} />
|
|
@@ -326,7 +317,7 @@ const ScriptDetail = ({ route }) => {
|
|
|
326
317
|
</PreventDoubleTouch>
|
|
327
318
|
);
|
|
328
319
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
329
|
-
}, [
|
|
320
|
+
}, [isStarred]);
|
|
330
321
|
|
|
331
322
|
const rightComponent = useMemo(
|
|
332
323
|
() => (
|
|
@@ -342,7 +333,7 @@ const ScriptDetail = ({ route }) => {
|
|
|
342
333
|
</View>
|
|
343
334
|
),
|
|
344
335
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
345
|
-
[
|
|
336
|
+
[isStarred]
|
|
346
337
|
);
|
|
347
338
|
|
|
348
339
|
useEffect(() => {
|
|
@@ -35,6 +35,11 @@ describe('Test TabHeader', () => {
|
|
|
35
35
|
});
|
|
36
36
|
const instance = tree.root;
|
|
37
37
|
const touchableOpacity = instance.findAllByType(TouchableOpacity);
|
|
38
|
+
act(() => {
|
|
39
|
+
touchableOpacity[0].props.onPress();
|
|
40
|
+
touchableOpacity[1].props.onPress();
|
|
41
|
+
});
|
|
38
42
|
expect(touchableOpacity).toHaveLength(3);
|
|
43
|
+
expect(touchableOpacity).toBeDefined();
|
|
39
44
|
});
|
|
40
45
|
});
|
|
@@ -21,7 +21,6 @@ import {
|
|
|
21
21
|
import { axiosPost } from '../../utils/Apis/axios';
|
|
22
22
|
import { TESTID } from '../../configs/Constants';
|
|
23
23
|
import Text from '../../commons/Text';
|
|
24
|
-
import { ToastBottomHelper } from '../../utils/Utils';
|
|
25
24
|
|
|
26
25
|
const SelectUser = ({ route }) => {
|
|
27
26
|
const t = useTranslations();
|
|
@@ -33,6 +32,7 @@ const SelectUser = ({ route }) => {
|
|
|
33
32
|
|
|
34
33
|
const sharePermissions = useCallback(
|
|
35
34
|
async (phone, email) => {
|
|
35
|
+
Keyboard.dismiss();
|
|
36
36
|
let userSharedPermission = await users.filter(
|
|
37
37
|
(user) => user.phone_number === phone || user.email === email
|
|
38
38
|
);
|
|
@@ -45,29 +45,9 @@ const SelectUser = ({ route }) => {
|
|
|
45
45
|
unit: unit.id,
|
|
46
46
|
permissions,
|
|
47
47
|
});
|
|
48
|
-
|
|
49
|
-
setUsers([...users, data.user]);
|
|
50
|
-
} else {
|
|
51
|
-
if (data.non_field_errors) {
|
|
52
|
-
ToastBottomHelper.error(data.non_field_errors);
|
|
53
|
-
} else {
|
|
54
|
-
const textTemp = t(
|
|
55
|
-
data?.phone
|
|
56
|
-
? 'text_phone_share_permission'
|
|
57
|
-
: data?.email
|
|
58
|
-
? 'text_email_share_permission'
|
|
59
|
-
: ''
|
|
60
|
-
);
|
|
61
|
-
ToastBottomHelper.error(
|
|
62
|
-
t('error_share_permission', {
|
|
63
|
-
data: phone || email,
|
|
64
|
-
text: textTemp,
|
|
65
|
-
})
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
48
|
+
success && setUsers([...users, data.user]);
|
|
69
49
|
},
|
|
70
|
-
[users, unit.id, permissions
|
|
50
|
+
[users, unit.id, permissions]
|
|
71
51
|
);
|
|
72
52
|
|
|
73
53
|
const validate = useCallback(() => {
|