@eohjsc/react-native-smart-city 0.2.89 → 0.2.92

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 (37) hide show
  1. package/package.json +1 -1
  2. package/src/commons/ActionGroup/ColorPickerTemplate.js +30 -24
  3. package/src/commons/ActionGroup/OnOffSmartLock/OnOffSmartLock.js +60 -12
  4. package/src/commons/ActionGroup/OnOffSmartLock/PasscodeList/__test__/index.test.js +47 -0
  5. package/src/commons/ActionGroup/OnOffSmartLock/PasscodeList/index.js +2 -0
  6. package/src/commons/ActionGroup/OnOffTemplate/index.js +48 -28
  7. package/src/commons/ActionGroup/SliderRangeTemplate.js +19 -5
  8. package/src/commons/ActionGroup/__test__/ColorPickerTemplate.test.js +74 -0
  9. package/src/commons/ActionGroup/__test__/OnOffSmartLock.test.js +107 -0
  10. package/src/commons/ActionGroup/__test__/SliderRangeTemplate.test.js +71 -0
  11. package/src/commons/ActionGroup/index.js +1 -1
  12. package/src/commons/Calendar/index.js +5 -1
  13. package/src/commons/ConnectingProcess/__test__/Connecting.test.js +4 -1
  14. package/src/commons/Device/HorizontalBarChart.js +6 -2
  15. package/src/commons/SubUnit/Favorites/index.js +4 -35
  16. package/src/commons/SubUnit/ShortDetail.js +7 -41
  17. package/src/configs/Constants.js +5 -0
  18. package/src/hooks/Common/index.js +2 -0
  19. package/src/hooks/Common/useSensorsStatus.js +52 -0
  20. package/src/screens/AddNewGateway/PlugAndPlay/__test__/ConnectWifiWarning.test.js +1 -0
  21. package/src/screens/AddNewGateway/__test__/SelectGateway.test.js +61 -0
  22. package/src/screens/Device/__test__/DetailHistoryChart.test.js +40 -0
  23. package/src/screens/Device/detail.js +46 -29
  24. package/src/screens/HanetCamera/Detail.js +20 -13
  25. package/src/screens/HanetCamera/ManageAccess.js +10 -52
  26. package/src/screens/HanetCamera/MemberInfo.js +59 -13
  27. package/src/screens/HanetCamera/__test__/ManageAccess.test.js +19 -0
  28. package/src/screens/HanetCamera/__test__/MemberInfo.test.js +57 -10
  29. package/src/screens/HanetCamera/components/RequestFaceIDPopup.js +90 -0
  30. package/src/screens/HanetCamera/hooks/__test__/useHanetCheckinData.test.js +9 -12
  31. package/src/screens/HanetCamera/hooks/useHanetCheckinData.js +10 -7
  32. package/src/screens/HanetCamera/styles/manageAccessStyles.js +0 -14
  33. package/src/screens/Unit/Detail.js +1 -7
  34. package/src/screens/Unit/components/MyUnitDevice/index.js +13 -10
  35. package/src/screens/Unit/components/__test__/MyUnitDevice.test.js +2 -2
  36. package/src/utils/I18n/translations/en.json +1 -0
  37. package/src/utils/I18n/translations/vi.json +1 -0
@@ -1,4 +1,4 @@
1
- import React, { useState, useCallback } from 'react';
1
+ import React, { useState, useCallback, useEffect } from 'react';
2
2
  import { Image } from 'react-native';
3
3
  import { Calendar } from 'react-native-calendars';
4
4
  import moment from 'moment';
@@ -20,6 +20,10 @@ export default ({
20
20
  const t = useTranslations();
21
21
  const [dateSelected, setDateSelected] = useState(defaultDate);
22
22
 
23
+ useEffect(() => {
24
+ setDateSelected(defaultDate);
25
+ }, [defaultDate]);
26
+
23
27
  const onDateSelected = useCallback(
24
28
  (day) => {
25
29
  setDateSelected(moment(day.timestamp));
@@ -14,9 +14,12 @@ describe('Test ConnectingProcess', () => {
14
14
  let tree;
15
15
  test('create ConnectingProcess', () => {
16
16
  const scan_sensor_data = { imei: 'SENSOR-afasdfas' };
17
+ const devicePrefixName = 'SENSOR';
17
18
  const gateway = { id: 1, name: 'gateway' };
18
19
  const station = { id: 1, icon_kit: 'a', name: 'station' };
19
- const route = { params: { scan_sensor_data, gateway, station } };
20
+ const route = {
21
+ params: { scan_sensor_data, gateway, station, devicePrefixName },
22
+ };
20
23
  act(() => {
21
24
  tree = renderer.create(wrapComponent(route));
22
25
  });
@@ -105,7 +105,11 @@ const HorizontalBarChart = memo(({ datas, config }) => {
105
105
 
106
106
  const heightChart = useMemo(() => {
107
107
  const dataX = datas[0].data.map((item) => item.x);
108
- return dataX.length > 1 ? dataX.length * 55 : 90;
108
+ return dataX.length > 1
109
+ ? dataX.length === 2
110
+ ? dataX.length * 55 + 30
111
+ : dataX.length * 55
112
+ : 90;
109
113
  }, [datas]);
110
114
 
111
115
  useEffect(() => {
@@ -171,7 +175,7 @@ const styles = StyleSheet.create({
171
175
  },
172
176
  webviewStyle: {
173
177
  flex: 1,
174
- minHeight: 200,
178
+ minHeight: 0,
175
179
  height: 300,
176
180
  opacity: 0.99,
177
181
  },
@@ -1,55 +1,24 @@
1
- import React, { useState, useEffect, useRef } from 'react';
1
+ import React from 'react';
2
2
  import { View } from 'react-native';
3
3
  import { useTranslations } from '../../../hooks/Common/useTranslations';
4
- import { useIsFocused } from '@react-navigation/native';
4
+ import { useSensorsStatus } from '../../../hooks/Common';
5
5
 
6
6
  import { Section } from '../../Section';
7
7
  import ItemDevice from '../../Device/ItemDevice';
8
8
  import ItemOneTap from '../OneTap/ItemOneTap';
9
9
  import ItemAddNew from '../../Device/ItemAddNew';
10
10
  import styles from './styles';
11
- import { API } from '../../../configs';
12
- import { axiosGet } from '../../../utils/Apis/axios';
13
11
 
14
12
  const SubUnitFavorites = ({
15
13
  unit,
16
14
  isOwner,
17
15
  favorites,
18
- serverDown,
19
16
  isGGHomeConnected,
20
17
  wrapItemStyle,
21
18
  }) => {
22
19
  const t = useTranslations();
23
- const isFocused = useIsFocused();
24
- const intervalSensorStatus = useRef();
25
- const [sensorsStatus, setSensorsStatus] = useState([]);
26
20
 
27
- useEffect(() => {
28
- if (isFocused) {
29
- const getSensorsStatus = async () => {
30
- const params = new URLSearchParams();
31
- if (favorites?.devices?.length > 0) {
32
- favorites.devices.forEach((sensor) => {
33
- params.append('sensors', sensor.id);
34
- });
35
- const { success, data } = await axiosGet(
36
- API.UNIT.SENSORS_STATUS(unit.id),
37
- {
38
- params: params,
39
- }
40
- );
41
- if (success) {
42
- setSensorsStatus(data);
43
- }
44
- }
45
- };
46
- const updateInterval = setInterval(getSensorsStatus, 5000);
47
- intervalSensorStatus.current = updateInterval;
48
- return () => clearInterval(updateInterval);
49
- } else {
50
- clearInterval(intervalSensorStatus.current);
51
- }
52
- }, [isFocused, favorites?.devices, unit.id]);
21
+ const { getStatus, serverDown } = useSensorsStatus(unit, favorites?.devices);
53
22
 
54
23
  const handleOnAddNew = () => {
55
24
  alert(t('feature_under_development'));
@@ -74,7 +43,7 @@ const SubUnitFavorites = ({
74
43
  station={sensor.station}
75
44
  isGGHomeConnected={isGGHomeConnected}
76
45
  serverDown={serverDown}
77
- status={sensorsStatus.find((s) => s.id === sensor.id)}
46
+ status={getStatus(sensor)}
78
47
  wrapStyle={wrapItemStyle}
79
48
  />
80
49
  ))}
@@ -1,9 +1,10 @@
1
- import React, { useState, useEffect, useRef } from 'react';
1
+ import React from 'react';
2
2
  import { StyleSheet, View } from 'react-native';
3
- import { useNavigation, useIsFocused } from '@react-navigation/native';
3
+ import { useNavigation } from '@react-navigation/native';
4
4
  import { useTranslations } from '../../hooks/Common/useTranslations';
5
+ import { useSensorsStatus } from '../../hooks/Common';
5
6
 
6
- import { Images, Device, API } from '../../configs';
7
+ import { Images, Device } from '../../configs';
7
8
  import { DEVICE_TYPE, TESTID } from '../../configs/Constants';
8
9
  import { Section } from '../Section';
9
10
  import Text from '../Text';
@@ -14,51 +15,16 @@ import { standardizeCameraScreenSize } from '../../utils/Utils';
14
15
  import Routes from '../../utils/Route';
15
16
  import FastImage from 'react-native-fast-image';
16
17
  import MediaPlayerDetail from '../MediaPlayerDetail';
17
- import { axiosGet } from '../../utils/Apis/axios';
18
18
 
19
19
  const { standardizeWidth, standardizeHeight } = standardizeCameraScreenSize(
20
20
  Device.screenWidth - 32
21
21
  );
22
22
 
23
- const ShortDetailSubUnit = ({
24
- unit,
25
- station,
26
- serverDown,
27
- isGGHomeConnected,
28
- }) => {
23
+ const ShortDetailSubUnit = ({ unit, station, isGGHomeConnected }) => {
29
24
  const t = useTranslations();
30
- const isFocused = useIsFocused();
31
25
  const { navigate } = useNavigation();
32
- const intervalSensorStatus = useRef();
33
26
 
34
- const [sensorsStatus, setSensorsStatus] = useState([]);
35
-
36
- useEffect(() => {
37
- if (isFocused) {
38
- const getSensorsStatus = async () => {
39
- const params = new URLSearchParams();
40
- if (station?.sensors?.length > 0) {
41
- station.sensors.forEach((sensor) => {
42
- params.append('sensors', sensor.id);
43
- });
44
- const { success, data } = await axiosGet(
45
- API.UNIT.SENSORS_STATUS(unit.id),
46
- {
47
- params: params,
48
- }
49
- );
50
- if (success) {
51
- setSensorsStatus(data);
52
- }
53
- }
54
- };
55
- const updateInterval = setInterval(getSensorsStatus, 5000);
56
- intervalSensorStatus.current = updateInterval;
57
- return () => clearInterval(updateInterval);
58
- } else {
59
- clearInterval(intervalSensorStatus.current);
60
- }
61
- }, [isFocused, station?.sensors, unit.id]);
27
+ const { getStatus, serverDown } = useSensorsStatus(unit, station?.sensors);
62
28
 
63
29
  const renderCamera = () => {
64
30
  if (station?.camera) {
@@ -158,7 +124,7 @@ const ShortDetailSubUnit = ({
158
124
  station={station}
159
125
  isGGHomeConnected={isGGHomeConnected}
160
126
  serverDown={serverDown}
161
- status={sensorsStatus.find((s) => s.id === sensor.id)}
127
+ status={getStatus(sensor)}
162
128
  />
163
129
  );
164
130
  }
@@ -74,6 +74,7 @@ export const Constants = {
74
74
  export const DEVICE_TYPE = {
75
75
  LG_THINQ: 'LG_THINQ',
76
76
  HANET: 'HANET',
77
+ ZIGBEE: 'ZIGBEE',
77
78
  };
78
79
 
79
80
  const marginItem = 12;
@@ -393,6 +394,7 @@ export const TESTID = {
393
394
  BUTTON_TEMPLATE_2: 'BUTTON_TEMPLATE_2',
394
395
  BUTTON_TEMPLATE_3: 'BUTTON_TEMPLATE_3',
395
396
  TEXT_DOOR_LOOK_ON_OFF: 'TEXT_DOOR_LOOK_ON_OFF',
397
+ BUTTON_ON_OFF: 'BUTTON_ON_OFF',
396
398
 
397
399
  // Device Detail
398
400
  DEVICE_DETAIL_MEDIA_PLAYER: 'DEVICE_DETAIL_MEDIA_PLAYER',
@@ -679,6 +681,9 @@ export const TESTID = {
679
681
  GENERATE_PASSCODE_SET_TIME: 'GENERATE_PASSCODE_SET_TIME',
680
682
  GENERATE_PASSCODE_SET_DURATION: 'GENERATE_PASSCODE_SET_DURATION',
681
683
 
684
+ //Passcode
685
+ PASSCODE_LIST: 'PASSCODE_LIST',
686
+
682
687
  //AutoLock
683
688
  AUTO_LOCK_BUTTON_ENABLE: 'AUTO_LOCK_BUTTON_ENABLE',
684
689
  AUTO_LOCK_BUTTON_INSTANT: 'AUTO_LOCK_BUTTON_INSTANT',
@@ -4,6 +4,7 @@ import useForceUpdate from './useForceUpdate';
4
4
  import useKeyboardShow from './useKeyboardShow';
5
5
  import usePopover from './usePopover';
6
6
  import useTitleHeader from './useTitleHeader';
7
+ import useSensorsStatus from './useSensorsStatus';
7
8
  import { useBlockBackAndroid } from './useBlockBackAndroid';
8
9
  import { useIsOwnerOfUnit } from './useIsOwnerOfUnit';
9
10
  import { useStatusBar } from './useStatusBar';
@@ -20,4 +21,5 @@ export {
20
21
  useIsOwnerOfUnit,
21
22
  useStatusBar,
22
23
  useGetIdUser,
24
+ useSensorsStatus,
23
25
  };
@@ -0,0 +1,52 @@
1
+ import { useState, useEffect, useRef } from 'react';
2
+ import { useIsFocused } from '@react-navigation/native';
3
+ import { axiosGet } from '../../utils/Apis/axios';
4
+ import { API } from '../../configs';
5
+
6
+ const useSensorsStatus = (unit, sensors) => {
7
+ const isFocused = useIsFocused();
8
+ const intervalSensorStatus = useRef();
9
+ const [sensorsStatus, setSensorsStatus] = useState([]);
10
+ const [serverDown, setServerDown] = useState(false);
11
+
12
+ useEffect(() => {
13
+ if (isFocused) {
14
+ const getSensorsStatus = async () => {
15
+ const params = new URLSearchParams();
16
+ if (sensors?.length > 0) {
17
+ sensors.forEach((sensor) => {
18
+ params.append('sensors', sensor.id);
19
+ });
20
+ const { success, data, resp_status } = await axiosGet(
21
+ API.UNIT.SENSORS_STATUS(unit.id),
22
+ {
23
+ params: params,
24
+ }
25
+ );
26
+ if (success) {
27
+ setSensorsStatus(data);
28
+ setServerDown(false);
29
+ } else if (resp_status >= 500) {
30
+ setServerDown(true);
31
+ }
32
+ }
33
+ };
34
+ const updateInterval = setInterval(getSensorsStatus, 5000);
35
+ intervalSensorStatus.current = updateInterval;
36
+ return () => clearInterval(updateInterval);
37
+ } else {
38
+ clearInterval(intervalSensorStatus.current);
39
+ }
40
+ }, [isFocused, sensors, unit.id]);
41
+
42
+ const getStatus = (sensor) => {
43
+ sensorsStatus.find((s) => s.id === sensor.id);
44
+ };
45
+
46
+ return {
47
+ getStatus,
48
+ serverDown,
49
+ };
50
+ };
51
+
52
+ export default useSensorsStatus;
@@ -16,6 +16,7 @@ jest.mock('react', () => {
16
16
  useState: jest.fn((init) => [init, mockSetState]),
17
17
  };
18
18
  });
19
+
19
20
  jest.mock('react-native-udp', () => {
20
21
  return {
21
22
  createSocket: () => ({
@@ -0,0 +1,61 @@
1
+ import React from 'react';
2
+ import { act, create } from 'react-test-renderer';
3
+ import axios from 'axios';
4
+
5
+ import AddNewGatewaySelectGateway from '../SelectGateway';
6
+ import { SCProvider } from '../../../context';
7
+ import { mockSCStore } from '../../../context/mockStore';
8
+ import { SafeAreaView } from 'react-native';
9
+
10
+ const wrapComponent = (route) => (
11
+ <SCProvider initState={mockSCStore({})}>
12
+ <AddNewGatewaySelectGateway route={route} />
13
+ </SCProvider>
14
+ );
15
+
16
+ jest.mock('axios');
17
+
18
+ jest.mock('react', () => {
19
+ return { ...jest.requireActual('react'), memo: (x) => x };
20
+ });
21
+
22
+ const mockedNavigate = jest.fn();
23
+ const mockedGoBack = jest.fn();
24
+
25
+ jest.mock('@react-navigation/native', () => {
26
+ return {
27
+ ...jest.requireActual('@react-navigation/native'),
28
+ useNavigation: () => ({
29
+ navigate: mockedNavigate,
30
+ goBack: mockedGoBack,
31
+ }),
32
+ useIsFocused: () => true,
33
+ };
34
+ });
35
+
36
+ describe('Test AddNewGatewaySelectGateway', () => {
37
+ let tree;
38
+ let route;
39
+
40
+ afterEach(() => {
41
+ axios.get.mockClear();
42
+ mockedNavigate.mockClear();
43
+ });
44
+
45
+ beforeEach(() => {
46
+ route = {
47
+ params: {
48
+ unit_id: 1,
49
+ },
50
+ };
51
+ });
52
+
53
+ test('create AddNewGatewaySelectGateway', async () => {
54
+ await act(async () => {
55
+ tree = await create(wrapComponent(route));
56
+ });
57
+ const instance = tree.root;
58
+ const safeAreaView = instance.findAllByType(SafeAreaView);
59
+ expect(safeAreaView).toHaveLength(1);
60
+ });
61
+ });
@@ -0,0 +1,40 @@
1
+ import React from 'react';
2
+ import renderer, { act } from 'react-test-renderer';
3
+ import { DetailHistoryChart } from '../components/DetailHistoryChart';
4
+ import { SCProvider } from '../../../context';
5
+ import { mockSCStore } from '../../../context/mockStore';
6
+ import HistoryChart from '../../../commons/Device/HistoryChart';
7
+ const mockSetState = jest.fn();
8
+ jest.mock('react', () => {
9
+ return {
10
+ ...jest.requireActual('react'),
11
+ memo: (x) => x,
12
+ useState: jest.fn((init) => [init, mockSetState]),
13
+ };
14
+ });
15
+ const wrapComponent = (item, sensor) => (
16
+ <SCProvider initState={mockSCStore({})}>
17
+ <DetailHistoryChart item={item} sensor={sensor} />
18
+ </SCProvider>
19
+ );
20
+ describe('Test DetailHistoryChart', () => {
21
+ let tree;
22
+ test('create DetailHistoryChart', () => {
23
+ const item = {
24
+ configuration: {
25
+ configs: [0],
26
+ icon: 'slack',
27
+ },
28
+ };
29
+ const sensor = {
30
+ name: 'Sensor name',
31
+ is_managed_by_backend: false,
32
+ };
33
+ act(() => {
34
+ tree = renderer.create(wrapComponent(item, sensor));
35
+ });
36
+ const instance = tree.root;
37
+ const historyChart = instance.findAllByType(HistoryChart);
38
+ expect(historyChart).toHaveLength(1);
39
+ });
40
+ });
@@ -8,7 +8,6 @@ import React, {
8
8
  import { View, TouchableOpacity } from 'react-native';
9
9
  import { useTranslations } from '../../hooks/Common/useTranslations';
10
10
  import moment from 'moment';
11
- import _ from 'lodash';
12
11
  import { get } from 'lodash';
13
12
  import { useSelector } from 'react-redux';
14
13
  import { IconFill, IconOutline } from '@ant-design/icons-react-native';
@@ -463,10 +462,14 @@ const DeviceDetail = ({ route }) => {
463
462
  setDisplayValues((currentDisplayValues) => {
464
463
  for (const [configId, value] of Object.entries(configValues)) {
465
464
  const intId = parseInt(configId);
466
- const index = _.findIndex(currentDisplayValues, (o) => o.id === intId);
465
+ const index = currentDisplayValues.findIndex(
466
+ (element) => element.id === intId
467
+ );
468
+
469
+ const item = currentDisplayValues[index];
467
470
  if (index !== -1) {
468
471
  currentDisplayValues[index].value = value;
469
- currentDisplayValues[index].evaluate = null;
472
+ currentDisplayValues[index].evaluate = item.evaluate;
470
473
  } else {
471
474
  currentDisplayValues.push({
472
475
  id: intId,
@@ -496,7 +499,19 @@ const DeviceDetail = ({ route }) => {
496
499
  params: { unitId: unit?.id, group },
497
500
  });
498
501
  }, [navigation, unit?.group, unit?.id]);
499
-
502
+ const isHaveColorSliderTemplate = useMemo(() => {
503
+ let isFlag = false;
504
+ display?.items.some((item) => {
505
+ switch (item?.configuration?.template) {
506
+ case 'color_picker_template':
507
+ case 'slider_range_template':
508
+ return (isFlag = true);
509
+ default:
510
+ return (isFlag = false);
511
+ }
512
+ });
513
+ return isFlag;
514
+ }, [display]);
500
515
  // replace isConnected=True to see template
501
516
  const renderSensorConnected = () => {
502
517
  return (
@@ -536,31 +551,33 @@ const DeviceDetail = ({ route }) => {
536
551
  );
537
552
  }
538
553
  })}
539
- <Card title={t('controller')}>
540
- {display.items.map((item) => {
541
- switch (item?.configuration?.template) {
542
- case 'color_picker_template':
543
- case 'slider_range_template':
544
- return (
545
- <SensorDisplayItem
546
- testID={TESTID.SENSOR_DISPLAY_ITEM}
547
- key={item.id.toString()}
548
- item={item}
549
- emergency={onEmergencyButtonPress}
550
- sensor={sensor}
551
- getData={getData}
552
- maxValue={maxValue}
553
- offsetTitle={offsetTitle}
554
- setOffsetTitle={setOffsetTitle}
555
- setShowWindDirection={setShowWindDirection}
556
- background={station?.background}
557
- />
558
- );
559
- default:
560
- return <></>;
561
- }
562
- })}
563
- </Card>
554
+ {!!isHaveColorSliderTemplate && (
555
+ <Card title={t('controller')}>
556
+ {display.items.map((item) => {
557
+ switch (item?.configuration?.template) {
558
+ case 'color_picker_template':
559
+ case 'slider_range_template':
560
+ return (
561
+ <SensorDisplayItem
562
+ testID={TESTID.SENSOR_DISPLAY_ITEM}
563
+ key={item.id.toString()}
564
+ item={item}
565
+ emergency={onEmergencyButtonPress}
566
+ sensor={sensor}
567
+ getData={getData}
568
+ maxValue={maxValue}
569
+ offsetTitle={offsetTitle}
570
+ setOffsetTitle={setOffsetTitle}
571
+ setShowWindDirection={setShowWindDirection}
572
+ background={station?.background}
573
+ />
574
+ );
575
+ default:
576
+ return <></>;
577
+ }
578
+ })}
579
+ </Card>
580
+ )}
564
581
  </SensorConnectStatusViewHeader>
565
582
  );
566
583
  };
@@ -81,13 +81,18 @@ const HanetCameraDetail = ({ route }) => {
81
81
 
82
82
  const CheckInItem = useCallback(
83
83
  ({ item }) => {
84
- const textMask =
85
- item.detected_mask === 'MASK_OFF'
86
- ? t('mask_off')
87
- : item.detected_mask === 'MASK_ON'
88
- ? t('mask_on')
89
- : '';
90
- const isStranger = item.person_type === 'STRANGER';
84
+ const textMaskMapping = {
85
+ MASK_OFF: t('mask_off'),
86
+ MASK_ON: t('mask_on'),
87
+ };
88
+ const textNameMapping = {
89
+ STRANGER: t('stranger'),
90
+ IMAGE_FROM_CAMERA: t('image_from_camera'),
91
+ };
92
+ const textMask = textMaskMapping[item.detected_mask] || '';
93
+ const textName = textNameMapping[item.person_type] || item.person_name;
94
+ const isStranger = !['EMPLOYEE', 'CUSTOMER'].includes(item.person_type);
95
+
91
96
  return (
92
97
  <View style={styles.wrapItem}>
93
98
  <Text type="Body" color={Colors.Gray7} style={styles.timeCheckIn}>
@@ -103,13 +108,15 @@ const HanetCameraDetail = ({ route }) => {
103
108
  </View>
104
109
  <View style={styles.wrapItemInfo}>
105
110
  <Text type="Body" color={isStranger ? Colors.Red6 : Colors.Gray9}>
106
- {isStranger ? t('stranger') : item.person_name}
111
+ {textName}
107
112
  </Text>
108
- <View style={styles.itemDescription}>
109
- <Text type="Label" color={Colors.Gray7}>
110
- {textMask}
111
- </Text>
112
- </View>
113
+ {!!textMask && (
114
+ <View style={styles.itemDescription}>
115
+ <Text type="Label" color={Colors.Gray7}>
116
+ {textMask}
117
+ </Text>
118
+ </View>
119
+ )}
113
120
  </View>
114
121
  <View style={styles.wrapAvatar}>
115
122
  <Image
@@ -1,12 +1,11 @@
1
1
  import React, { useCallback, useMemo } from 'react';
2
2
  import { View, TouchableOpacity, Image, FlatList } from 'react-native';
3
3
  import { useNavigation } from '@react-navigation/native';
4
- import ImagePicker from 'react-native-image-crop-picker';
5
4
  import { Icon } from '@ant-design/react-native';
6
- import { IconOutline, IconFill } from '@ant-design/icons-react-native';
5
+ import { IconOutline } from '@ant-design/icons-react-native';
7
6
  import { HeaderCustom } from '../../commons/Header';
8
- import BottomSheet from '../../commons/BottomSheet';
9
7
  import Text from '../../commons/Text';
8
+ import RequestFaceIDPopup from './components/RequestFaceIDPopup';
10
9
  import styles from './styles/manageAccessStyles';
11
10
  import { useTranslations } from '../../hooks/Common/useTranslations';
12
11
  import { useHanetPlaceMembers } from './hooks';
@@ -14,7 +13,6 @@ import { useBoolean } from '../../hooks/Common';
14
13
  import { Colors } from '../../configs';
15
14
  import { TESTID } from '../../configs/Constants';
16
15
  import Routes from '../../utils/Route';
17
- import SmartPhoneSvg from '../../../assets/images/Common/SmartPhone.svg';
18
16
 
19
17
  const HanetManageAccess = ({ route }) => {
20
18
  const t = useTranslations();
@@ -40,7 +38,7 @@ const HanetManageAccess = ({ route }) => {
40
38
  const [showAddMemberModal, setShowAddMemberModal, setHideAddMemberModal] =
41
39
  useBoolean();
42
40
 
43
- const captureFaceID = () => {
41
+ const onCaptureFaceID = () => {
44
42
  navigate(Routes.HanetCaptureFaceID, {
45
43
  title: t('add_new_member'),
46
44
  hanetPlace: hanetPlace,
@@ -52,15 +50,7 @@ const HanetManageAccess = ({ route }) => {
52
50
  });
53
51
  };
54
52
 
55
- const chooseFile = async () => {
56
- const options = {
57
- mediaType: 'photo',
58
- compressImageMaxHeight: 1280,
59
- compressImageMaxWidth: 738,
60
- compressImageQuality: 0.7,
61
- forceJpg: true,
62
- };
63
- const result = await ImagePicker.openPicker(options);
53
+ const onChooseFile = (result) => {
64
54
  navigate(Routes.HanetMemberInfo, {
65
55
  hanetPlace: hanetPlace,
66
56
  hanetMember: {
@@ -72,25 +62,6 @@ const HanetManageAccess = ({ route }) => {
72
62
  });
73
63
  };
74
64
 
75
- const addMemberOptions = [
76
- {
77
- icon: <IconFill name="camera" color={Colors.Gray9} size={27} />,
78
- text: t('capture_image'),
79
- onChoose: () => {
80
- setHideAddMemberModal();
81
- captureFaceID();
82
- },
83
- },
84
- {
85
- icon: <SmartPhoneSvg />,
86
- text: t('pick_available_image_from_your_phone'),
87
- onChoose: () => {
88
- setHideAddMemberModal();
89
- chooseFile();
90
- },
91
- },
92
- ];
93
-
94
65
  const MemberItem = useCallback(
95
66
  ({ item }) => {
96
67
  return (
@@ -146,26 +117,13 @@ const HanetManageAccess = ({ route }) => {
146
117
  contentContainerStyle={styles.contentContainerStyle}
147
118
  scrollIndicatorInsets={{ right: 1 }}
148
119
  />
149
- <BottomSheet
150
- isVisible={showAddMemberModal}
151
- onBackdropPress={setHideAddMemberModal}
120
+ <RequestFaceIDPopup
152
121
  title={t('add_member')}
153
- style={styles.addMemberModal}
154
- >
155
- {addMemberOptions.map((option, i) => (
156
- <TouchableOpacity
157
- key={i}
158
- onPress={option.onChoose}
159
- style={styles.row}
160
- testID={`${TESTID.HANET_ADD_MEMBER_OPTION}_${i}`}
161
- >
162
- {option.icon}
163
- <Text type="H4" color={Colors.Gray9} style={styles.textOption}>
164
- {option.text}
165
- </Text>
166
- </TouchableOpacity>
167
- ))}
168
- </BottomSheet>
122
+ isVisible={showAddMemberModal}
123
+ setHide={setHideAddMemberModal}
124
+ onCaptureFaceID={onCaptureFaceID}
125
+ onChooseFile={onChooseFile}
126
+ />
169
127
  </View>
170
128
  );
171
129
  };