@eohjsc/react-native-smart-city 0.7.8 → 0.7.9
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/AddNewDevice/add-scan-device-icon.svg +13 -0
- package/assets/images/Email.svg +9 -0
- package/assets/images/lan.svg +3 -0
- package/assets/images/wifi-open.svg +3 -0
- package/package.json +2 -1
- package/src/commons/ActionGroup/StatesGridActionTemplate.js +7 -3
- package/src/commons/ActionGroup/__test__/StatesGridActionTemplate.test.js +7 -3
- package/src/commons/AlertAction/index.js +1 -0
- package/src/commons/Auth/AccountItem.js +17 -3
- package/src/commons/Auth/AccountList.js +3 -7
- package/src/commons/ConnectWifi/__test__/ConnectWifi.test.js +373 -0
- package/src/commons/ConnectWifi/index.js +201 -0
- package/src/commons/ConnectWifi/styles.js +69 -0
- package/src/commons/Form/TextInputPassword.js +1 -1
- package/src/commons/OneTapTemplate/StatesGridActionTemplate.js +6 -2
- package/src/configs/API.js +12 -0
- package/src/configs/AccessibilityLabel.js +7 -0
- package/src/configs/Constants.js +1 -0
- package/src/hooks/Common/index.js +2 -2
- package/src/hooks/Common/useBlockBack.js +36 -0
- package/src/hooks/useMqtt.js +10 -5
- package/src/navigations/AddGatewayStack.js +2 -0
- package/src/navigations/AllGatewayStack.js +4 -0
- package/src/navigations/Main.js +2 -2
- package/src/navigations/UnitStack.js +32 -0
- package/src/screens/AddNewGateway/ConnectingWifiDevice.js +7 -6
- package/src/screens/AddNewGateway/ScanDeviceLocal.js +267 -0
- package/src/screens/AddNewGateway/ScanDeviceLocalStyles.js +58 -0
- package/src/screens/AddNewGateway/SelectDeviceSubUnit.js +10 -2
- package/src/screens/AddNewGateway/SelectDeviceType.js +19 -2
- package/src/screens/AddNewGateway/__test__/ScanDeviceLocal.test.js +475 -0
- package/src/screens/AddNewGateway/__test__/SelectDeviceType.test.js +2 -2
- package/src/screens/AddNewGateway/configs/API.js +8 -0
- package/src/screens/AddNewGateway/hooks/useConnectDevice.js +59 -0
- package/src/screens/AllGateway/GatewayInfo/__test__/index.test.js +58 -1
- package/src/screens/AllGateway/GatewayInfo/index.js +8 -6
- package/src/screens/AllGateway/GatewayWifi/__test__/index.test.js +319 -0
- package/src/screens/AllGateway/GatewayWifi/index.js +107 -0
- package/src/screens/AllGateway/Successfully/__test__/index.test.js +77 -0
- package/src/screens/AllGateway/Successfully/index.js +66 -0
- package/src/screens/AllGateway/Successfully/styles.js +35 -0
- package/src/screens/AllGateway/components/Information/index.js +17 -1
- package/src/screens/AllGateway/components/RowItem/index.js +12 -1
- package/src/screens/AllGateway/hooks/__test__/index.test.js +18 -0
- package/src/screens/AllGateway/hooks/useGateway.js +13 -0
- package/src/screens/Automate/AddNewAction/SetupConfigCondition.js +3 -3
- package/src/screens/Automate/AddNewAction/SetupScriptEmail.js +79 -0
- package/src/screens/Automate/AddNewAction/SetupScriptReceiverEmail.js +166 -0
- package/src/screens/Automate/AddNewAction/Styles/SetupScriptEmailStyles.js +37 -0
- package/src/screens/Automate/AddNewAction/Styles/SetupScriptReceiverEmailStyles.js +79 -0
- package/src/screens/Automate/AddNewAction/__test__/ChooseAction.test.js +1 -1
- package/src/screens/Automate/AddNewAction/__test__/SetupConfigCondition.test.js +13 -5
- package/src/screens/Automate/AddNewAction/__test__/SetupScriptEmail.test.js +76 -0
- package/src/screens/Automate/AddNewAction/__test__/SetupScriptReceiverEmail.test.js +105 -0
- package/src/screens/Automate/EditActionsList/Styles/UpdateReceiverEmailScriptStyles.js +78 -0
- package/src/screens/Automate/EditActionsList/UpdateEmailScript.js +80 -0
- package/src/screens/Automate/EditActionsList/UpdateReceiverEmailScript.js +179 -0
- package/src/screens/Automate/EditActionsList/__tests__/UpdateEmailScript.test.js +81 -0
- package/src/screens/Automate/EditActionsList/__tests__/UpdateReceiverEmailScript.test.js +83 -0
- package/src/screens/Automate/EditActionsList/__tests__/index.test.js +38 -5
- package/src/screens/Automate/EditActionsList/index.js +59 -2
- package/src/screens/Automate/ScriptDetail/Components/AddActionScript.js +20 -0
- package/src/screens/Automate/ScriptDetail/Styles/indexStyles.js +5 -3
- package/src/screens/Automate/ScriptDetail/__test__/index.test.js +127 -21
- package/src/screens/Automate/ScriptDetail/index.js +57 -14
- package/src/screens/SharedUnit/index.js +2 -2
- package/src/screens/Sharing/SelectUser.js +47 -47
- package/src/screens/Sharing/__test__/SelectUser.test.js +57 -103
- package/src/screens/SubUnit/ManageSubUnit.js +94 -90
- package/src/screens/SubUnit/ManageSubUnitStyles.js +4 -6
- package/src/screens/SubUnit/RearrageSubUnit.js +90 -0
- package/src/screens/SubUnit/RearrrageSubUnitStyle.js +65 -0
- package/src/screens/SubUnit/__test__/ManageSubUnit.test.js +35 -19
- package/src/screens/SubUnit/__test__/RearrangeSubUnit.test.js +129 -0
- package/src/screens/SubUnit/hooks/__test__/useManageSubUnit.test.js +6 -7
- package/src/screens/SubUnit/hooks/useManageSubUnit.js +8 -16
- package/src/screens/Unit/Detail.js +2 -6
- package/src/screens/Unit/ManageUnit.js +1 -1
- package/src/utils/Functions/__test__/ShortEmail.test.js +5 -0
- package/src/utils/I18n/translations/en.js +46 -8
- package/src/utils/I18n/translations/vi.js +37 -4
- package/src/utils/Route/index.js +7 -0
- package/src/commons/Auth/__test__/AccountItem.test.js +0 -31
- package/src/hooks/Common/useBlockBackAndroid.js +0 -21
- package/src/screens/SubUnit/DetailStyles.js +0 -46
|
@@ -2,7 +2,6 @@ import React from 'react';
|
|
|
2
2
|
import { create, act } from 'react-test-renderer';
|
|
3
3
|
import MockAdapter from 'axios-mock-adapter';
|
|
4
4
|
|
|
5
|
-
import { AccessibilityLabel } from '../../../configs/Constants';
|
|
6
5
|
import { ViewButtonBottom, Button } from '../../../commons';
|
|
7
6
|
import _TextInput from '../../../commons/Form/TextInput';
|
|
8
7
|
import AccountList from '../../../commons/Auth/AccountList';
|
|
@@ -11,8 +10,9 @@ import { getTranslate } from '../../../utils/I18n';
|
|
|
11
10
|
import { SCProvider } from '../../../context';
|
|
12
11
|
import { mockSCStore } from '../../../context/mockStore';
|
|
13
12
|
import api from '../../../utils/Apis/axios';
|
|
14
|
-
import { Text } from 'react-native';
|
|
15
13
|
import SharingInviteMembers from '../SelectUser';
|
|
14
|
+
import { ToastBottomHelper } from '../../../utils/Utils';
|
|
15
|
+
import { IconOutline } from '@ant-design/icons-react-native';
|
|
16
16
|
|
|
17
17
|
const wrapComponent = (route) => (
|
|
18
18
|
<SCProvider initState={mockSCStore({})}>
|
|
@@ -40,62 +40,7 @@ describe('test SharingInviteMembers container', () => {
|
|
|
40
40
|
};
|
|
41
41
|
});
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
return instance.find((el) => el.props.accessibilityLabel === id);
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
it('create', async () => {
|
|
48
|
-
await act(async () => {
|
|
49
|
-
tree = await create(wrapComponent(route));
|
|
50
|
-
});
|
|
51
|
-
const instance = tree.root;
|
|
52
|
-
const textTitle = findByTestId(
|
|
53
|
-
instance,
|
|
54
|
-
AccessibilityLabel.SELECT_USER_ADD_USER_TITLE
|
|
55
|
-
);
|
|
56
|
-
const textSubTitle = findByTestId(
|
|
57
|
-
instance,
|
|
58
|
-
AccessibilityLabel.SELECT_USER_ADD_USER_SUB_TITLE
|
|
59
|
-
);
|
|
60
|
-
expect(textTitle.props.children).toEqual(
|
|
61
|
-
getTranslate('en', 'add_user_title')
|
|
62
|
-
);
|
|
63
|
-
expect(textSubTitle.props.children).toEqual(
|
|
64
|
-
getTranslate('en', 'add_user_sub_title')
|
|
65
|
-
);
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
it('viewButtonBottom and onLeftClick', async () => {
|
|
69
|
-
await act(async () => {
|
|
70
|
-
tree = await create(wrapComponent(route));
|
|
71
|
-
});
|
|
72
|
-
const instance = tree.root;
|
|
73
|
-
const viewButtonBottom = instance.findByType(ViewButtonBottom);
|
|
74
|
-
expect(viewButtonBottom.props.leftTitle).toEqual(
|
|
75
|
-
getTranslate('en', 'back')
|
|
76
|
-
);
|
|
77
|
-
expect(viewButtonBottom.props.rightTitle).toEqual(
|
|
78
|
-
getTranslate('en', 'done')
|
|
79
|
-
);
|
|
80
|
-
await act(async () => {
|
|
81
|
-
viewButtonBottom.props.onLeftClick();
|
|
82
|
-
});
|
|
83
|
-
expect(global.mockedGoBack).toHaveBeenCalled();
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it('viewButtonBottom onRightClick', async () => {
|
|
87
|
-
await act(async () => {
|
|
88
|
-
tree = await create(wrapComponent(route));
|
|
89
|
-
});
|
|
90
|
-
const instance = tree.root;
|
|
91
|
-
const viewButtonBottom = instance.findByType(ViewButtonBottom);
|
|
92
|
-
await act(async () => {
|
|
93
|
-
viewButtonBottom.props.onRightClick();
|
|
94
|
-
});
|
|
95
|
-
expect(global.mockedNavigate).toHaveBeenCalled();
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
it('_TextInput onChange phone, invalidate and not call api sharedPermission', async () => {
|
|
43
|
+
it('input phone invalid', async () => {
|
|
99
44
|
mock.onPost(API.SHARE.SHARE()).reply(200);
|
|
100
45
|
await act(async () => {
|
|
101
46
|
tree = await create(wrapComponent(route));
|
|
@@ -118,83 +63,92 @@ describe('test SharingInviteMembers container', () => {
|
|
|
118
63
|
expect(textInput.props.errorText).toEqual(
|
|
119
64
|
getTranslate('en', 'invalid_phone_number_or_email')
|
|
120
65
|
);
|
|
66
|
+
const viewButtonBottom = instance.findByType(ViewButtonBottom);
|
|
67
|
+
expect(viewButtonBottom.props.rightDisabled).toBeTruthy();
|
|
121
68
|
});
|
|
122
69
|
|
|
123
|
-
it('
|
|
70
|
+
it('input phone valid and call api share permission', async () => {
|
|
71
|
+
const phone = '0909123456';
|
|
72
|
+
const spyToast = jest.spyOn(ToastBottomHelper, 'success');
|
|
73
|
+
mock.onGet(API.SHARE.SEARCH_USER_BY_PHONE(phone)).reply(200, {
|
|
74
|
+
id: 3,
|
|
75
|
+
name: 'user add',
|
|
76
|
+
phone_number: phone,
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
mock.onPost(API.SHARE.SHARE_V2()).reply(200);
|
|
124
80
|
await act(async () => {
|
|
125
81
|
tree = await create(wrapComponent(route));
|
|
126
82
|
});
|
|
127
83
|
const instance = tree.root;
|
|
128
84
|
const textInput = instance.findByType(_TextInput);
|
|
129
|
-
const
|
|
85
|
+
const buttonCheckUser = instance.findByType(Button);
|
|
130
86
|
let accountList = instance.findAllByType(AccountList);
|
|
131
87
|
expect(accountList).toHaveLength(0);
|
|
132
88
|
await act(async () => {
|
|
133
|
-
await textInput.props.onChange(
|
|
134
|
-
});
|
|
135
|
-
mock.onPost(API.SHARE.SHARE()).reply(200, {
|
|
136
|
-
user: {
|
|
137
|
-
id: 3,
|
|
138
|
-
name: 'user add',
|
|
139
|
-
phone_number: '0909123456',
|
|
140
|
-
},
|
|
89
|
+
await textInput.props.onChange(phone);
|
|
141
90
|
});
|
|
142
91
|
await act(async () => {
|
|
143
|
-
await
|
|
92
|
+
await buttonCheckUser.props.onPress();
|
|
93
|
+
await buttonCheckUser.props.onPress(); // case user double click
|
|
144
94
|
});
|
|
145
|
-
|
|
95
|
+
|
|
146
96
|
accountList = instance.findAllByType(AccountList);
|
|
147
97
|
expect(accountList).toHaveLength(1);
|
|
148
98
|
expect(accountList[0].props.accounts).toHaveLength(1);
|
|
149
99
|
|
|
100
|
+
const viewButtonBottom = instance.findByType(ViewButtonBottom);
|
|
150
101
|
await act(async () => {
|
|
151
|
-
|
|
152
|
-
});
|
|
153
|
-
mock.onPost(API.SHARE.SHARE()).reply(400);
|
|
154
|
-
await act(async () => {
|
|
155
|
-
await button.props.onPress();
|
|
102
|
+
viewButtonBottom.props.onRightClick();
|
|
156
103
|
});
|
|
157
|
-
expect(
|
|
104
|
+
expect(spyToast).toBeCalledWith('Invited user');
|
|
105
|
+
});
|
|
158
106
|
|
|
159
|
-
|
|
160
|
-
|
|
107
|
+
it('input 2 email valid and remove 1 email then call api share permission', async () => {
|
|
108
|
+
const email_1 = 'test1@gmail.com';
|
|
109
|
+
const email_2 = 'test2@gmail.com';
|
|
110
|
+
const spyToast = jest.spyOn(ToastBottomHelper, 'success');
|
|
111
|
+
mock.onGet(API.SHARE.SEARCH_USER_BY_EMAIL(email_1)).reply(200, {
|
|
112
|
+
id: 1,
|
|
113
|
+
email: email_1,
|
|
161
114
|
});
|
|
162
|
-
mock.
|
|
163
|
-
|
|
164
|
-
|
|
115
|
+
mock.onGet(API.SHARE.SEARCH_USER_BY_EMAIL(email_2)).reply(200, {
|
|
116
|
+
id: 2,
|
|
117
|
+
email: email_2,
|
|
165
118
|
});
|
|
166
|
-
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
it('_TextInput onChange email, validated and call api sharedPermission', async () => {
|
|
119
|
+
mock.onPost(API.SHARE.SHARE_V2()).reply(200);
|
|
170
120
|
await act(async () => {
|
|
171
121
|
tree = await create(wrapComponent(route));
|
|
172
122
|
});
|
|
173
123
|
const instance = tree.root;
|
|
174
124
|
const textInput = instance.findByType(_TextInput);
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
expect(accountList).toHaveLength(0);
|
|
125
|
+
const buttonCheckUser = instance.findByType(Button);
|
|
126
|
+
expect(instance.findAllByType(AccountList)).toHaveLength(0);
|
|
178
127
|
await act(async () => {
|
|
179
|
-
await textInput.props.onChange(
|
|
128
|
+
await textInput.props.onChange(email_1);
|
|
129
|
+
await buttonCheckUser.props.onPress();
|
|
180
130
|
});
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
},
|
|
131
|
+
|
|
132
|
+
expect(instance.findByType(AccountList).props.accounts).toHaveLength(1);
|
|
133
|
+
|
|
134
|
+
await act(async () => {
|
|
135
|
+
await textInput.props.onChange(email_2);
|
|
136
|
+
await buttonCheckUser.props.onPress();
|
|
188
137
|
});
|
|
138
|
+
|
|
139
|
+
expect(instance.findByType(AccountList).props.accounts).toHaveLength(2);
|
|
140
|
+
|
|
141
|
+
const iconRemoves = instance.findAllByType(IconOutline);
|
|
189
142
|
await act(async () => {
|
|
190
|
-
await
|
|
143
|
+
await iconRemoves[0].props.onPress();
|
|
191
144
|
});
|
|
192
145
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
146
|
+
expect(instance.findByType(AccountList).props.accounts).toHaveLength(1);
|
|
147
|
+
|
|
148
|
+
const viewButtonBottom = instance.findByType(ViewButtonBottom);
|
|
149
|
+
await act(async () => {
|
|
150
|
+
viewButtonBottom.props.onRightClick();
|
|
151
|
+
});
|
|
152
|
+
expect(spyToast).toBeCalledWith('Invited user');
|
|
199
153
|
});
|
|
200
154
|
});
|
|
@@ -1,42 +1,93 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
import {
|
|
3
|
-
View,
|
|
4
|
-
TouchableOpacity,
|
|
5
|
-
Image,
|
|
6
|
-
ScrollView,
|
|
7
|
-
RefreshControl,
|
|
8
|
-
} from 'react-native';
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
|
+
import { View, TouchableOpacity, Image } from 'react-native';
|
|
9
3
|
import { useIsFocused, useNavigation } from '@react-navigation/native';
|
|
10
4
|
import { Colors } from '../../configs';
|
|
11
5
|
import { useTranslations } from '../../hooks/Common/useTranslations';
|
|
12
|
-
|
|
13
6
|
import WrapHeaderScrollable from '../../commons/Sharing/WrapHeaderScrollable';
|
|
14
7
|
import Text from '../../commons/Text';
|
|
15
|
-
|
|
16
8
|
import styles from './ManageSubUnitStyles';
|
|
17
9
|
import { IconOutline } from '@ant-design/icons-react-native';
|
|
18
10
|
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
|
|
19
11
|
import Routes from '../../utils/Route';
|
|
20
|
-
import { RowItem } from '../../commons/RowItem';
|
|
21
12
|
import NoSubUnitImage from '../../../assets/images/Illustrations.svg';
|
|
22
13
|
import useManageSubUnit from './hooks/useManageSubUnit';
|
|
23
14
|
import { AccessibilityLabel } from '../../configs/Constants';
|
|
15
|
+
import { RowItem } from '../../commons/RowItem';
|
|
16
|
+
|
|
17
|
+
const RightComponent = ({ onAddSubUnit, onRearrangeSubUnit }) => (
|
|
18
|
+
<View style={styles.rightComponent}>
|
|
19
|
+
<TouchableOpacity
|
|
20
|
+
accessibilityLabel={AccessibilityLabel.ADD_SUB_UNIT}
|
|
21
|
+
onPress={onAddSubUnit}
|
|
22
|
+
style={styles.headerButton}
|
|
23
|
+
>
|
|
24
|
+
<IconOutline name={'plus'} size={27} color={Colors.Black} />
|
|
25
|
+
</TouchableOpacity>
|
|
26
|
+
<TouchableOpacity
|
|
27
|
+
accessibilityLabel={AccessibilityLabel.REARRANGE_SUB_UNIT}
|
|
28
|
+
onPress={onRearrangeSubUnit}
|
|
29
|
+
style={[styles.headerButton, styles.moreButton]}
|
|
30
|
+
>
|
|
31
|
+
<MaterialIcons name={'reorder'} size={27} color={Colors.Black} />
|
|
32
|
+
</TouchableOpacity>
|
|
33
|
+
</View>
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
const StationList = ({ stations, onEditSubUnit }) => {
|
|
37
|
+
const t = useTranslations();
|
|
38
|
+
return (
|
|
39
|
+
<>
|
|
40
|
+
{stations.map((item, index) => (
|
|
41
|
+
<RowItem
|
|
42
|
+
type={'noneBG'}
|
|
43
|
+
key={index.toString()}
|
|
44
|
+
index={index}
|
|
45
|
+
leftIcon={
|
|
46
|
+
<Image
|
|
47
|
+
source={{ uri: item.background }}
|
|
48
|
+
style={styles.image}
|
|
49
|
+
resizeMode="cover"
|
|
50
|
+
/>
|
|
51
|
+
}
|
|
52
|
+
text={item.name}
|
|
53
|
+
subtext={`${item.devices.length} ${t('devices').toLowerCase()}`}
|
|
54
|
+
onPress={() => onEditSubUnit(item)}
|
|
55
|
+
rightComponent={
|
|
56
|
+
<IconOutline name="right" size={20} color={Colors.Gray6} />
|
|
57
|
+
}
|
|
58
|
+
/>
|
|
59
|
+
))}
|
|
60
|
+
</>
|
|
61
|
+
);
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const NoSubUnit = ({ noSubUnitText, addSubUnitText }) => (
|
|
65
|
+
<View style={styles.noSubUnit}>
|
|
66
|
+
<NoSubUnitImage />
|
|
67
|
+
<Text semibold type="H4" center>
|
|
68
|
+
{noSubUnitText}
|
|
69
|
+
</Text>
|
|
70
|
+
<Text type="Body" center>
|
|
71
|
+
{addSubUnitText}
|
|
72
|
+
</Text>
|
|
73
|
+
</View>
|
|
74
|
+
);
|
|
24
75
|
|
|
25
76
|
const ManageSubUnit = ({ route }) => {
|
|
26
77
|
const t = useTranslations();
|
|
27
78
|
const { unit } = route.params;
|
|
28
79
|
const navigation = useNavigation();
|
|
29
80
|
const isFocused = useIsFocused();
|
|
30
|
-
const { stations,
|
|
81
|
+
const { stations, refreshing, onRefresh } = useManageSubUnit(unit.id);
|
|
31
82
|
|
|
32
|
-
const
|
|
83
|
+
const handleAddSubUnit = () => {
|
|
33
84
|
navigation.navigate(Routes.AddSubUnitStack, {
|
|
34
85
|
screen: Routes.AddSubUnit,
|
|
35
86
|
params: { unit },
|
|
36
87
|
});
|
|
37
|
-
}
|
|
88
|
+
};
|
|
38
89
|
|
|
39
|
-
const
|
|
90
|
+
const handleEditSubUnit = (station) => {
|
|
40
91
|
navigation.navigate(Routes.UnitStack, {
|
|
41
92
|
screen: Routes.EditSubUnit,
|
|
42
93
|
params: {
|
|
@@ -46,29 +97,15 @@ const ManageSubUnit = ({ route }) => {
|
|
|
46
97
|
});
|
|
47
98
|
};
|
|
48
99
|
|
|
49
|
-
const
|
|
50
|
-
(
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
</TouchableOpacity>
|
|
59
|
-
<TouchableOpacity
|
|
60
|
-
// onPress={handleShowMenuAction}
|
|
61
|
-
// ref={refMenuAction}
|
|
62
|
-
style={[styles.headerButton, styles.moreButton]}
|
|
63
|
-
>
|
|
64
|
-
<MaterialIcons name={'more-vert'} size={27} color={Colors.Black} />
|
|
65
|
-
</TouchableOpacity>
|
|
66
|
-
</View>
|
|
67
|
-
),
|
|
68
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
69
|
-
[]
|
|
70
|
-
);
|
|
71
|
-
|
|
100
|
+
const handleRearrageSubUnit = () => {
|
|
101
|
+
navigation.navigate(Routes.UnitStack, {
|
|
102
|
+
screen: Routes.RearrangeSubUnit,
|
|
103
|
+
params: {
|
|
104
|
+
stations,
|
|
105
|
+
unit,
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
};
|
|
72
109
|
useEffect(() => {
|
|
73
110
|
isFocused && onRefresh();
|
|
74
111
|
}, [onRefresh, isFocused]);
|
|
@@ -80,60 +117,27 @@ const ManageSubUnit = ({ route }) => {
|
|
|
80
117
|
>
|
|
81
118
|
<WrapHeaderScrollable
|
|
82
119
|
title={t('manage_sub_unit')}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
120
|
+
rightComponent={
|
|
121
|
+
<RightComponent
|
|
122
|
+
onAddSubUnit={handleAddSubUnit}
|
|
123
|
+
onRearrangeSubUnit={handleRearrageSubUnit}
|
|
124
|
+
/>
|
|
125
|
+
}
|
|
126
|
+
onRefresh={onRefresh}
|
|
127
|
+
loading={refreshing}
|
|
86
128
|
>
|
|
87
129
|
<View style={styles.container}>
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
<
|
|
95
|
-
{
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
type={'noneBG'}
|
|
100
|
-
key={index.toString()}
|
|
101
|
-
index={index}
|
|
102
|
-
leftIcon={
|
|
103
|
-
<Image
|
|
104
|
-
source={{ uri: item.background }}
|
|
105
|
-
style={styles.image}
|
|
106
|
-
resizeMode="cover"
|
|
107
|
-
/>
|
|
108
|
-
}
|
|
109
|
-
text={item.name}
|
|
110
|
-
subtext={`${
|
|
111
|
-
item.devices ? item.devices.length : '0'
|
|
112
|
-
} devices`}
|
|
113
|
-
onPress={() => goToEditSubUnit(item, unit)}
|
|
114
|
-
rightComponent={
|
|
115
|
-
<IconOutline
|
|
116
|
-
name="right"
|
|
117
|
-
size={20}
|
|
118
|
-
color={Colors.Gray6}
|
|
119
|
-
/>
|
|
120
|
-
}
|
|
121
|
-
/>
|
|
122
|
-
);
|
|
123
|
-
})}
|
|
124
|
-
{!stations.length && !isRefresh && !isLoading && (
|
|
125
|
-
<View style={styles.NoSubUnit}>
|
|
126
|
-
<NoSubUnitImage />
|
|
127
|
-
<Text semibold type="H4" center>
|
|
128
|
-
{t('no_sub_unit_yet')}
|
|
129
|
-
</Text>
|
|
130
|
-
<Text type="Body" center>
|
|
131
|
-
{t('tap_+_to_add_new_sub_unit')}
|
|
132
|
-
</Text>
|
|
133
|
-
</View>
|
|
134
|
-
)}
|
|
135
|
-
</View>
|
|
136
|
-
</ScrollView>
|
|
130
|
+
{!!stations.length ? (
|
|
131
|
+
<StationList
|
|
132
|
+
stations={stations}
|
|
133
|
+
onEditSubUnit={handleEditSubUnit}
|
|
134
|
+
/>
|
|
135
|
+
) : (
|
|
136
|
+
<NoSubUnit
|
|
137
|
+
noSubUnitText={t('no_sub_unit_yet')}
|
|
138
|
+
addSubUnitText={t('tap_+_to_add_new_sub_unit')}
|
|
139
|
+
/>
|
|
140
|
+
)}
|
|
137
141
|
</View>
|
|
138
142
|
</WrapHeaderScrollable>
|
|
139
143
|
</View>
|
|
@@ -3,16 +3,12 @@ import { Colors } from '../../configs';
|
|
|
3
3
|
import { Constants } from '../../configs';
|
|
4
4
|
|
|
5
5
|
export default StyleSheet.create({
|
|
6
|
-
headerAniStyle: {
|
|
7
|
-
paddingBottom: 16,
|
|
8
|
-
borderBottomWidth: 0,
|
|
9
|
-
},
|
|
10
6
|
rightComponent: {
|
|
11
7
|
flexDirection: 'row',
|
|
12
8
|
alignItems: 'flex-end',
|
|
13
9
|
},
|
|
14
10
|
headerButton: {
|
|
15
|
-
marginRight:
|
|
11
|
+
marginRight: 16,
|
|
16
12
|
},
|
|
17
13
|
moreButton: {
|
|
18
14
|
marginLeft: -5,
|
|
@@ -23,11 +19,12 @@ export default StyleSheet.create({
|
|
|
23
19
|
},
|
|
24
20
|
container: {
|
|
25
21
|
paddingTop: 0,
|
|
22
|
+
flex: 1,
|
|
26
23
|
},
|
|
27
24
|
paddingLeft16: {
|
|
28
25
|
paddingLeft: 16,
|
|
29
26
|
},
|
|
30
|
-
|
|
27
|
+
noSubUnit: {
|
|
31
28
|
alignSelf: 'center',
|
|
32
29
|
marginTop: Constants.height * 0.2,
|
|
33
30
|
fontSize: 16,
|
|
@@ -36,5 +33,6 @@ export default StyleSheet.create({
|
|
|
36
33
|
width: 40,
|
|
37
34
|
height: 40,
|
|
38
35
|
borderRadius: 40 / 2,
|
|
36
|
+
backgroundColor: Colors.White,
|
|
39
37
|
},
|
|
40
38
|
});
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { View, TouchableOpacity } from 'react-native';
|
|
3
|
+
import { isEqual } from 'lodash';
|
|
4
|
+
import { API } from '../../configs';
|
|
5
|
+
import { axiosPost } from '../../utils/Apis/axios';
|
|
6
|
+
import styles from './RearrrageSubUnitStyle';
|
|
7
|
+
import Text from '../../commons/Text';
|
|
8
|
+
import FlatListDnD from '../../commons/FlatListDnD';
|
|
9
|
+
import ViewButtonBottom from '../../commons/ViewButtonBottom';
|
|
10
|
+
import { HeaderCustom } from '../../commons/Header';
|
|
11
|
+
import Rearrange from '../../../assets/images/Rearrange.svg';
|
|
12
|
+
import { ToastBottomHelper } from '../../utils/Utils';
|
|
13
|
+
import { useNavigation } from '@react-navigation/native';
|
|
14
|
+
import { useTranslations } from '../../hooks/Common/useTranslations';
|
|
15
|
+
|
|
16
|
+
const RearrangeSubUnit = ({ route }) => {
|
|
17
|
+
const { stations, unit } = route.params;
|
|
18
|
+
const t = useTranslations();
|
|
19
|
+
const { goBack } = useNavigation();
|
|
20
|
+
const [reorderItems, setReorderItems] = useState(stations);
|
|
21
|
+
const handleOnSave = async () => {
|
|
22
|
+
const idOrderSubUnits = reorderItems.map((i) => i.id);
|
|
23
|
+
const { success } = await axiosPost(API.SUB_UNIT.ORDER_SUB_UNITS(unit.id), {
|
|
24
|
+
id_order_sub_units: idOrderSubUnits,
|
|
25
|
+
});
|
|
26
|
+
if (success) {
|
|
27
|
+
ToastBottomHelper.success(t('updated_sub_unit_order'));
|
|
28
|
+
goBack();
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const renderItem = ({ item, getIndex, drag, isActive }) => {
|
|
33
|
+
const index = getIndex() + 1;
|
|
34
|
+
return (
|
|
35
|
+
<View style={styles.itemWrapper}>
|
|
36
|
+
<TouchableOpacity
|
|
37
|
+
style={[
|
|
38
|
+
styles.border,
|
|
39
|
+
styles.indexWrapper,
|
|
40
|
+
/* istanbul ignore next */
|
|
41
|
+
isActive && styles.isDragging,
|
|
42
|
+
]}
|
|
43
|
+
onPressIn={drag}
|
|
44
|
+
>
|
|
45
|
+
<Text style={styles.indexText}>{`${index}`.padStart(2, '0')}</Text>
|
|
46
|
+
<Rearrange />
|
|
47
|
+
</TouchableOpacity>
|
|
48
|
+
<View
|
|
49
|
+
style={[
|
|
50
|
+
styles.border,
|
|
51
|
+
styles.subUnitWrapper,
|
|
52
|
+
/* istanbul ignore next */
|
|
53
|
+
isActive && styles.isDragging,
|
|
54
|
+
]}
|
|
55
|
+
>
|
|
56
|
+
<Text style={styles.indexText}>{item.name}</Text>
|
|
57
|
+
<Text style={styles.deviceText}>
|
|
58
|
+
{`${item.devices.length} ${t('devices').toLowerCase()}`}
|
|
59
|
+
</Text>
|
|
60
|
+
</View>
|
|
61
|
+
</View>
|
|
62
|
+
);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
return (
|
|
66
|
+
<View style={styles.container}>
|
|
67
|
+
<HeaderCustom title={t('rearrange_sub_unit')} isShowSeparator />
|
|
68
|
+
<Text style={styles.hintText}>{t('rearrange_sub_unit_hint')}</Text>
|
|
69
|
+
<View style={styles.flatList}>
|
|
70
|
+
<FlatListDnD
|
|
71
|
+
data={reorderItems}
|
|
72
|
+
extraData={reorderItems}
|
|
73
|
+
setData={setReorderItems}
|
|
74
|
+
renderItem={renderItem}
|
|
75
|
+
/>
|
|
76
|
+
</View>
|
|
77
|
+
<ViewButtonBottom
|
|
78
|
+
leftTitle={t('cancel')}
|
|
79
|
+
onLeftClick={() => goBack()}
|
|
80
|
+
rightTitle={t('save')}
|
|
81
|
+
rightDisabled={isEqual(stations, reorderItems)}
|
|
82
|
+
onRightClick={handleOnSave}
|
|
83
|
+
isPreventDoubleTouch
|
|
84
|
+
wrapStyle={styles.bottomButtonWrapper}
|
|
85
|
+
/>
|
|
86
|
+
</View>
|
|
87
|
+
);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export default RearrangeSubUnit;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { Colors } from '../../configs';
|
|
2
|
+
import { StyleSheet } from 'react-native';
|
|
3
|
+
|
|
4
|
+
export default StyleSheet.create({
|
|
5
|
+
container: {
|
|
6
|
+
flex: 1,
|
|
7
|
+
backgroundColor: Colors.White,
|
|
8
|
+
},
|
|
9
|
+
border: {
|
|
10
|
+
borderRadius: 5,
|
|
11
|
+
borderColor: Colors.Gray6,
|
|
12
|
+
borderWidth: 1,
|
|
13
|
+
padding: 20,
|
|
14
|
+
backgroundColor: Colors.White,
|
|
15
|
+
shadowColor: Colors.Black,
|
|
16
|
+
shadowOffset: {
|
|
17
|
+
width: 0,
|
|
18
|
+
height: 10,
|
|
19
|
+
},
|
|
20
|
+
shadowOpacity: 0.23,
|
|
21
|
+
shadowRadius: 11.27,
|
|
22
|
+
elevation: 4,
|
|
23
|
+
},
|
|
24
|
+
flatList: {
|
|
25
|
+
flex: 0.95,
|
|
26
|
+
marginBottom: 10,
|
|
27
|
+
},
|
|
28
|
+
isDragging: {
|
|
29
|
+
borderBottomWidth: 1,
|
|
30
|
+
borderColor: Colors.Red,
|
|
31
|
+
},
|
|
32
|
+
itemWrapper: {
|
|
33
|
+
flexDirection: 'row',
|
|
34
|
+
marginBottom: 20,
|
|
35
|
+
marginHorizontal: 16,
|
|
36
|
+
backgroundColor: Colors.White,
|
|
37
|
+
},
|
|
38
|
+
indexWrapper: {
|
|
39
|
+
flexDirection: 'column',
|
|
40
|
+
justifyContent: 'center',
|
|
41
|
+
alignItems: 'center',
|
|
42
|
+
},
|
|
43
|
+
subUnitWrapper: {
|
|
44
|
+
flex: 1,
|
|
45
|
+
marginLeft: 10,
|
|
46
|
+
justifyContent: 'center',
|
|
47
|
+
},
|
|
48
|
+
hintText: {
|
|
49
|
+
marginHorizontal: 16,
|
|
50
|
+
marginTop: 10,
|
|
51
|
+
},
|
|
52
|
+
indexText: {
|
|
53
|
+
fontSize: 16,
|
|
54
|
+
lineHeight: 24,
|
|
55
|
+
fontWeight: 'bold',
|
|
56
|
+
},
|
|
57
|
+
deviceText: {
|
|
58
|
+
fontSize: 14,
|
|
59
|
+
lineHeight: 20,
|
|
60
|
+
color: Colors.Gray7,
|
|
61
|
+
},
|
|
62
|
+
bottomButtonWrapper: {
|
|
63
|
+
backgroundColor: Colors.White,
|
|
64
|
+
},
|
|
65
|
+
});
|