@eohjsc/react-native-smart-city 0.2.61 → 0.2.62

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 (56) hide show
  1. package/README.md +115 -68
  2. package/package.json +1 -1
  3. package/src/commons/ActionGroup/CurtainButtonTemplate.js +10 -2
  4. package/src/commons/ActionGroup/__test__/CurtainButtonTemplate.test.js +1 -1
  5. package/src/commons/ActionGroup/__test__/MenuActionAddSchedule.test.js +71 -0
  6. package/src/commons/ActionGroup/hooks/AccessScheduleDetailStyles.js +41 -0
  7. package/src/commons/ActionGroup/hooks/MenuActionAddSchedule.js +110 -0
  8. package/src/commons/ActionGroup/hooks/MenuActionAddScheduleStyle.js +69 -0
  9. package/src/commons/ActionGroup/hooks/RecurringDetail.js +97 -0
  10. package/src/commons/DateTimeRangeChange/DateTimeButton.js +6 -1
  11. package/src/commons/Device/HistoryChart.js +2 -1
  12. package/src/commons/Device/HorizontalBarChart.js +2 -1
  13. package/src/commons/Device/LinearChart.js +28 -1
  14. package/src/commons/Form/CurrencyInput.js +1 -0
  15. package/src/commons/SubUnit/OneTap/OneTapStyles.js +20 -1
  16. package/src/commons/SubUnit/OneTap/__test__/SubUnitAutomate.test.js +151 -40
  17. package/src/commons/SubUnit/OneTap/index.js +64 -12
  18. package/src/configs/Constants.js +9 -0
  19. package/src/iot/RemoteControl/Bluetooth.js +6 -3
  20. package/src/iot/RemoteControl/GoogleHome.js +5 -2
  21. package/src/iot/RemoteControl/Internet.js +1 -0
  22. package/src/iot/RemoteControl/LG.js +2 -1
  23. package/src/iot/RemoteControl/index.js +13 -6
  24. package/src/navigations/SharedStack.js +11 -9
  25. package/src/navigations/UnitStack.js +10 -2
  26. package/src/screens/ActivityLog/hooks/index.js +1 -1
  27. package/src/screens/AddNewAction/SelectSensorDevices.js +18 -11
  28. package/src/screens/AddNewAction/Styles/SelectSensorDevicesStyles.js +5 -1
  29. package/src/screens/AddNewAction/__test__/SelectSensorDevices.test.js +6 -1
  30. package/src/screens/Automate/MultiUnits.js +7 -4
  31. package/src/screens/Automate/__test__/MultiUnits.test.js +1 -1
  32. package/src/screens/Automate/__test__/index.test.js +12 -0
  33. package/src/screens/ConfirmUnitDeletion/__test__/ConfirmUnitDeletion.test.js +61 -0
  34. package/src/screens/ConfirmUnitDeletion/index.js +64 -0
  35. package/src/screens/ConfirmUnitDeletion/styles.js +37 -0
  36. package/src/screens/EmergencySetting/index.js +2 -0
  37. package/src/screens/EmergencySetting/styles.js +8 -2
  38. package/src/screens/ScriptDetail/index.js +1 -0
  39. package/src/screens/SubUnit/EditSubUnit.js +8 -1
  40. package/src/screens/SubUnit/EditSubUnitStyles.js +2 -3
  41. package/src/screens/TDSGuide/index.js +1 -1
  42. package/src/screens/Unit/Detail.js +16 -6
  43. package/src/screens/Unit/ManageUnit.js +9 -12
  44. package/src/screens/Unit/SmartAccount.js +25 -41
  45. package/src/screens/Unit/SmartAccountItem.js +2 -1
  46. package/src/screens/Unit/SmartAccountStyles.js +0 -1
  47. package/src/screens/Unit/__test__/ManageUnit.test.js +0 -6
  48. package/src/screens/Unit/__test__/SmartAccount.test.js +24 -0
  49. package/src/screens/Unit/__test__/SmartAccountItem.test.js +72 -0
  50. package/src/screens/UnitSummary/components/3PPowerConsumption/index.js +2 -1
  51. package/src/screens/UnitSummary/components/PowerConsumption/index.js +1 -1
  52. package/src/screens/UnitSummary/components/Temperature/ItemTemperature/index.js +2 -2
  53. package/src/utils/I18n/translations/en.json +15 -3
  54. package/src/utils/I18n/translations/vi.json +15 -3
  55. package/src/utils/Route/index.js +1 -0
  56. package/src/utils/Utils.js +4 -0
package/README.md CHANGED
@@ -1,101 +1,148 @@
1
- # react-native-smart-city
1
+ ## react-native-smart-city
2
2
 
3
3
  ## Getting started
4
+ 1. Install package dependencies:
5
+ - Using [Yarn](https://yarnpkg.com/): `yarn add react-native-reanimated@^1.10.1`
4
6
 
5
- `$ npm install @eohjsc/react-native-smart-city --save`
7
+ 2. Install:
8
+ - Using [npm](https://www.npmjs.com/#getting-started): `npm install @eohjsc/react-native-smart-city --save`
9
+ - Using [Yarn](https://yarnpkg.com/): `yarn add @eohjsc/react-native-smart-city`
6
10
 
11
+ 3. Compile application using react-native run-android
7
12
  ### Mostly automatic installation
8
-
9
13
  `$ react-native link @eohjsc/react-native-smart-city`
10
14
 
11
15
  ## Usage
12
-
13
- Make sure that SmartCity
14
- Example:
15
-
16
+ 1. StackNavigator
16
17
  ```javascript
17
- import SmartCity, {
18
- AddSubUnitStack,
19
- EmergencyContactsStack,
18
+ import {
19
+ UnitStack,
20
20
  AddMemberStack,
21
- AddGatewayStack,
21
+ AddSubUnitStack,
22
22
  AddDeviceStack,
23
- UnitStack,
24
- AddUnitStack,
25
- SharedStack,
26
- Explore,
27
- SCProvider,
23
+ AddGatewayStack,
28
24
  SCContext,
29
25
  AddLGDeviceStack,
30
26
  initSCConfig,
27
+ AddUnitStack,
31
28
  AutomateStack,
32
29
  NotificationStack,
33
- MyPinnedSharedUnit,
34
- SharedUnit,
35
- MyUnit,
36
30
  } from '@eohjsc/react-native-smart-city';
37
31
  import { createStackNavigator } from '@react-navigation/stack';
38
32
 
39
33
  // TODO: What to do with the module?
40
- const Stack = creatStackNavigation();
34
+ const Stack = createStackNavigator();
41
35
 
42
36
  const YourStack = () => {
43
37
  // Declare yourAuthObject and params
44
38
  return (
45
- <SmartCity auth={yourAuthObject}>
46
- <NavigationContainer>
47
- <Stack.Navigator>
48
- <Stack.Screen
49
- name={'MainTab'}
50
- component={MainTab}
51
- options={{
52
- headerShown: false,
53
- }}
54
- />
55
- <Stack.Screen
56
- name={'UnitStack'}
57
- component={UnitStack}
58
- initialParams={params}
59
- options={{
60
- headerShown: false,
61
- }}
62
- />
63
- <Stack.Screen
64
- name={'AddGatewayStack'}
65
- component={AddGatewayStack}
66
- options={{ headerShown: false }}
67
- />
68
- <Stack.Screen
69
- name={'AddDeviceStack'}
70
- component={AddDeviceStack}
71
- options={{ headerShown: false }}
72
- />
73
- <Stack.Screen
74
- name={'AddMemberStack'}
75
- component={AddMemberStack}
76
- options={{ headerShown: false }}
77
- />
78
- <Stack.Screen
79
- name={'AddSubUnitStack'}
80
- component={AddSubUnitStack}
81
- options={{ headerShown: false }}
82
- />
83
- <Stack.Screen
84
- name={'EmergencyContactsStack'}
85
- component={EmergencyContactsStack}
86
- options={{ headerShown: false }}
87
- />
88
- </Stack.Navigator>
89
- </NavigationContainer>
90
- </SmartCity>
39
+ <Stack.Navigator>
40
+ <Stack.Screen
41
+ name={'MainTab'}
42
+ component={MainTab}
43
+ options={{
44
+ headerShown: false,
45
+ }}
46
+ />
47
+ <Stack.Screen
48
+ name={'UnitStack'}
49
+ component={UnitStack}
50
+ initialParams={params}
51
+ options={{
52
+ headerShown: false,
53
+ }}
54
+ />
55
+ <Stack.Screen
56
+ name={'AddGatewayStack'}
57
+ component={AddGatewayStack}
58
+ options={{ headerShown: false }}
59
+ />
60
+ <Stack.Screen
61
+ name={'AddDeviceStack'}
62
+ component={AddDeviceStack}
63
+ options={{ headerShown: false }}
64
+ />
65
+ <Stack.Screen
66
+ name={'AddMemberStack'}
67
+ component={AddMemberStack}
68
+ options={{ headerShown: false }}
69
+ />
70
+ <Stack.Screen
71
+ name={'AddSubUnitStack'}
72
+ component={AddSubUnitStack}
73
+ options={{ headerShown: false }}
74
+ />
75
+ </Stack.Navigator>
91
76
  );
92
77
  };
93
78
  const MainTab = () => {
94
79
  return (
95
80
  <Tab.Navigator>
96
- <Tab.Screen name={'SharedStack'} component={SharedStack} />
97
- <Tab.Screen name={'Search'} component={Explore} />
81
+ <Tab.Screen name={'AutomateStack'} component={AutomateStack} />
82
+ <Tab.Screen name={'NotificationStack'} component={NotificationStack} />
98
83
  </Tab.Navigator>
99
84
  );
100
85
  };
101
86
  ```
87
+ 2. Use components
88
+ ```javascript
89
+ import React from 'react';
90
+ import { View } from 'react-native';
91
+ import { MyPinnedSharedUnit, MyUnit } from '@eohjsc/react-native-smart-city';
92
+
93
+ const MyScreen = () => {
94
+ return (
95
+ <View>
96
+ <MyUnit />
97
+ <MyPinnedSharedUnit />
98
+ </View>
99
+ );
100
+ };
101
+ ```
102
+ 3. Trigger quick action
103
+ ```javascript
104
+ import React from 'react';
105
+ import { View, Button } from 'react-native';
106
+ import { sendRemoteCommand } from '@eohjsc/react-native-smart-city/src/iot/RemoteControl';
107
+
108
+ export const MyFunctionalComponent = () => {
109
+ const sensor = {
110
+ id: 1,
111
+ remote_control_options: {
112
+ internet: {},
113
+ bluetooth: {},
114
+ },
115
+ };
116
+ const action = {
117
+ color: '#00979D',
118
+ command_prefer_over_bluetooth: true,
119
+ command_prefer_over_googlehome: false,
120
+ command_prefer_over_internet: false,
121
+ googlehome_actions: [],
122
+ icon: 'caret-up',
123
+ icon_kit: null,
124
+ id: 1,
125
+ key: '24240de0-5c8e-11ec-bf63-0242ac130002',
126
+ lg_actions: [],
127
+ name: 'Garage Up',
128
+ };
129
+ const handleQuickAction = async() => {
130
+ const result = await sendRemoteCommand(sensor, action); // Action Garage Up
131
+ if (result){
132
+ console.log('Successful control')
133
+ }else {
134
+ console.log('Control failed')
135
+ }
136
+ };
137
+ return (
138
+ <View>
139
+ <Button onPress={handleQuickAction} title="Example trigger quick action control Garage Up" />
140
+ </View>
141
+ );
142
+ };
143
+ ```
144
+ - sendRemoteCommand user needs to `have permission to control the device`, you pass in the `sensor and action` to it and it will run after calling render.
145
+ - `sensor` is a device in your Unit and action is the `action` key of the device..
146
+ - You can take out the sensor and action from your Unit when calling the `API.UNIT.UNIT_DETAIL(unitId)` it will return all devices in 1 unit.
147
+ - Or get sensor from `API.SENSOR.DISPLAY(sensor.id)` returns all actions of 1 device.
148
+ - Refer YourProjectPath /node_modules/@eohjsc/react-native-smart-city/src/screens/Unit/Detail.js
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.2.61",
4
+ "version": "0.2.62",
5
5
  "description": "TODO",
6
6
  "main": "index.js",
7
7
  "files": [
@@ -8,11 +8,14 @@ import { TESTID } from '../../configs/Constants';
8
8
  import { Colors, Images } from '../../configs';
9
9
  import { Section } from '../../commons/Section';
10
10
  import { IconOutline } from '@ant-design/icons-react-native';
11
+ import MenuActionAddSchedule from './hooks/MenuActionAddSchedule';
12
+ import { useBoolean } from '../../hooks/Common';
11
13
 
12
14
  const CurtainButtonTemplate = memo(({ actionGroup, doAction }) => {
13
15
  const t = useTranslations();
14
16
  const { configuration } = actionGroup;
15
17
  const [lock, setLock] = useState(false);
18
+ const [isShowModal, setShowModal, setHideModal] = useBoolean(false);
16
19
 
17
20
  const onButtonOpenPress = useCallback(
18
21
  () => doAction(configuration.open_action_data),
@@ -120,17 +123,22 @@ const CurtainButtonTemplate = memo(({ actionGroup, doAction }) => {
120
123
  <Text type="H4" color={Colors.Gray8}>
121
124
  {t('schedule')}
122
125
  </Text>
123
- <TouchableOpacity>
126
+ <TouchableOpacity onPress={setShowModal}>
124
127
  <IconOutline name="plus" size={20} />
125
128
  </TouchableOpacity>
126
129
  </View>
127
130
  <View>
128
- <TouchableOpacity style={styles.tapToAddSchedule}>
131
+ <TouchableOpacity
132
+ onPress={setShowModal}
133
+ style={styles.tapToAddSchedule}
134
+ >
129
135
  <Text type="Body" color={Colors.Gray6} center>
130
136
  {t('tap_to_add_new_schedule')}
131
137
  </Text>
132
138
  </TouchableOpacity>
133
139
  </View>
140
+
141
+ <MenuActionAddSchedule visible={isShowModal} hideModal={setHideModal} />
134
142
  </Section>
135
143
  </>
136
144
  );
@@ -67,6 +67,6 @@ describe('Test CurtainButtonTemplate', () => {
67
67
  });
68
68
  const instance = wrapper.root;
69
69
  const touchableOpacities = instance.findAllByType(TouchableOpacity);
70
- expect(touchableOpacities.length).toEqual(5);
70
+ expect(touchableOpacities.length).toEqual(18);
71
71
  });
72
72
  });
@@ -0,0 +1,71 @@
1
+ import React from 'react';
2
+ import renderer, { act } from 'react-test-renderer';
3
+
4
+ import MenuActionAddSchedule from '../hooks/MenuActionAddSchedule';
5
+ import { SCProvider } from '../../../context';
6
+ import { mockSCStore } from '../../../context/mockStore';
7
+ import RecurringDetail from '../hooks/RecurringDetail';
8
+ import WheelDateTimePicker from '../../WheelDateTimePicker';
9
+
10
+ const mockSetState = jest.fn();
11
+ jest.mock('react', () => {
12
+ return {
13
+ ...jest.requireActual('react'),
14
+ memo: (x) => x,
15
+ useState: jest.fn((init) => [init, mockSetState]),
16
+ };
17
+ });
18
+
19
+ const wrapComponent = (actionGroup) => (
20
+ <SCProvider initState={mockSCStore({})}>
21
+ <MenuActionAddSchedule />
22
+ </SCProvider>
23
+ );
24
+
25
+ const mockedNavigate = jest.fn();
26
+
27
+ jest.mock('@react-navigation/native', () => {
28
+ return {
29
+ ...jest.requireActual('@react-navigation/native'),
30
+ useNavigation: () => ({
31
+ goBack: mockedNavigate,
32
+ }),
33
+ };
34
+ });
35
+
36
+ jest.mock('react', () => {
37
+ return {
38
+ ...jest.requireActual('react'),
39
+ memo: (x) => x,
40
+ };
41
+ });
42
+
43
+ jest.mock('axios');
44
+
45
+ describe('Test MenuActionAddSchedule', () => {
46
+ let tree;
47
+
48
+ test('test render MenuActionAddSchedule', async () => {
49
+ await act(async () => {
50
+ tree = await renderer.create(wrapComponent());
51
+ });
52
+ const instance = tree.root;
53
+
54
+ const recurringDetail = instance.findByType(RecurringDetail);
55
+ await act(async () => {
56
+ recurringDetail.props.onShowSetDateTime();
57
+ });
58
+
59
+ const wheelDateTimePicker = instance.findByType(WheelDateTimePicker);
60
+
61
+ await act(async () => {
62
+ wheelDateTimePicker.props.onPicked();
63
+ });
64
+
65
+ await act(async () => {
66
+ wheelDateTimePicker.props.onCancel();
67
+ });
68
+
69
+ expect(wheelDateTimePicker.props.isVisible).toEqual(false);
70
+ });
71
+ });
@@ -0,0 +1,41 @@
1
+ import { StyleSheet } from 'react-native';
2
+ import { Colors } from '../../../configs';
3
+
4
+ export default StyleSheet.create({
5
+ title: {
6
+ marginTop: 16,
7
+ },
8
+ value: {
9
+ marginTop: 8,
10
+ marginBottom: 12,
11
+ },
12
+ repeatWrap: {
13
+ flexDirection: 'row',
14
+ justifyContent: 'space-around',
15
+ marginTop: 16,
16
+ },
17
+ repeatItem: {
18
+ width: 24,
19
+ height: 24,
20
+ justifyContent: 'center',
21
+ alignItems: 'center',
22
+ borderRadius: 12,
23
+ borderWidth: 0,
24
+ borderColor: Colors.Orange,
25
+ },
26
+ repeatItemSelected: {
27
+ borderWidth: 1,
28
+ },
29
+ repeatText: {
30
+ lineHeight: 16,
31
+ },
32
+ curtainText: {
33
+ fontSize: 17,
34
+ marginTop: 12,
35
+ color: Colors.Gray9,
36
+ },
37
+ boder: {
38
+ borderBottomWidth: 1,
39
+ borderColor: Colors.Gray4,
40
+ },
41
+ });
@@ -0,0 +1,110 @@
1
+ import React, { memo, useCallback, useState } from 'react';
2
+ import { View } from 'react-native';
3
+ import { useTranslations } from '../../../hooks/Common/useTranslations';
4
+
5
+ import Text from '../../Text';
6
+ import { ModalCustom } from '../../Modal';
7
+ import ViewButtonBottom from '../../ViewButtonBottom';
8
+ import WheelDateTimePicker from '../../WheelDateTimePicker';
9
+ import moment from 'moment';
10
+ import { useBoolean } from '../../../hooks/Common';
11
+ import RecurringDetail from './RecurringDetail';
12
+ import _TextInput from '../../../commons/Form/TextInput';
13
+ import styles from './MenuActionAddScheduleStyle';
14
+
15
+ const MenuActionAddSchedule = memo(({ visible, hideModal, onItemClick }) => {
16
+ const t = useTranslations();
17
+
18
+ const [stateDateTimePicker, setStateDateTimePicker] = useState({
19
+ isVisible: false,
20
+ mode: 'time',
21
+ defaultValue: moment().valueOf(),
22
+ setter: null,
23
+ });
24
+
25
+ const [lockShowing, releaseLockShowing, acquireLockShowing] =
26
+ useBoolean(true);
27
+ const [recurringTimeStart, setRecurringTimeStart] = useState('');
28
+ const [recurringTimeEnd, setRecurringTimeEnd] = useState('');
29
+ const [recurringTimeRepeat, setRecurringTimeRepeat] = useState('');
30
+
31
+ const onShowSetDateTime = useCallback(
32
+ (currentValue, setter, mode) => {
33
+ acquireLockShowing();
34
+ setStateDateTimePicker((state) => ({
35
+ ...state,
36
+ isVisible: true,
37
+ mode: mode,
38
+ defaultValue: currentValue,
39
+ setter: setter,
40
+ }));
41
+ },
42
+ [setStateDateTimePicker, acquireLockShowing]
43
+ );
44
+
45
+ const onDateTimePicked = useCallback(
46
+ (timeData) => {
47
+ const setter = stateDateTimePicker.setter;
48
+ setter && setter(moment(timeData));
49
+ },
50
+ [stateDateTimePicker]
51
+ );
52
+
53
+ const onHideSetDateTime = useCallback(() => {
54
+ acquireLockShowing();
55
+ setStateDateTimePicker((state) => ({
56
+ ...state,
57
+ isVisible: false,
58
+ }));
59
+ }, [setStateDateTimePicker, acquireLockShowing]);
60
+
61
+ return (
62
+ <ModalCustom
63
+ isVisible={visible}
64
+ onBackButtonPress={hideModal}
65
+ onBackdropPress={hideModal}
66
+ style={styles.container}
67
+ >
68
+ <View style={styles.popoverStyle}>
69
+ <View style={styles.modalWrapper}>
70
+ <View style={styles.modalHeader}>
71
+ <Text style={styles.modalHeaderText}>{t('add_schedule')}</Text>
72
+ <View style={styles.boder} />
73
+ <RecurringDetail
74
+ onShowSetDateTime={onShowSetDateTime}
75
+ recurringTimeStart={recurringTimeStart}
76
+ recurringTimeEnd={recurringTimeEnd}
77
+ recurringTimeRepeat={recurringTimeRepeat}
78
+ setRecurringTimeStart={setRecurringTimeStart}
79
+ setRecurringTimeEnd={setRecurringTimeEnd}
80
+ setRecurringTimeRepeat={setRecurringTimeRepeat}
81
+ />
82
+
83
+ <Text style={styles.subName}>{t('schedule_name')}</Text>
84
+ <_TextInput
85
+ placeholder={t('enter_name')}
86
+ wrapStyle={styles.noMarginTop}
87
+ textInputStyle={styles.textInput}
88
+ />
89
+ <View style={styles.ViewButtonBottom}>
90
+ <ViewButtonBottom
91
+ leftTitle={t('cancel')}
92
+ onLeftClick={hideModal}
93
+ rightTitle={t('done')}
94
+ />
95
+ </View>
96
+ <WheelDateTimePicker
97
+ mode={stateDateTimePicker.mode}
98
+ isVisible={stateDateTimePicker.isVisible && lockShowing}
99
+ defaultValue={stateDateTimePicker.defaultValue}
100
+ onPicked={onDateTimePicked}
101
+ onCancel={onHideSetDateTime}
102
+ onHide={releaseLockShowing}
103
+ />
104
+ </View>
105
+ </View>
106
+ </View>
107
+ </ModalCustom>
108
+ );
109
+ });
110
+ export default MenuActionAddSchedule;
@@ -0,0 +1,69 @@
1
+ import { Colors } from '../../../configs';
2
+ import { StyleSheet } from 'react-native';
3
+
4
+ export default StyleSheet.create({
5
+ container: {
6
+ flex: 1,
7
+ margin: 0,
8
+ },
9
+ popoverStyle: {
10
+ width: '100%',
11
+ backgroundColor: Colors.White,
12
+ bottom: 0,
13
+ left: 0,
14
+ position: 'absolute',
15
+ borderRadius: 10,
16
+ },
17
+ modalWrapper: {
18
+ flex: 1,
19
+ flexDirection: 'column',
20
+ backgroundColor: Colors.White,
21
+ borderRadius: 10,
22
+ },
23
+ modalHeader: {
24
+ padding: 16,
25
+ backgroundColor: Colors.White,
26
+ justifyContent: 'flex-start',
27
+ },
28
+ modalHeaderText: {
29
+ fontSize: 17,
30
+ lineHeight: 24,
31
+ color: Colors.Gray9,
32
+ fontWeight: 'bold',
33
+ borderTopLeftRadius: 20,
34
+ borderTopRightRadius: 20,
35
+ marginVertical: 20,
36
+ },
37
+ boder: {
38
+ borderBottomWidth: 1,
39
+ borderColor: Colors.Gray4,
40
+ },
41
+ subName: {
42
+ color: Colors.Gray8,
43
+ marginTop: 12,
44
+ },
45
+ ViewButtonBottom: {
46
+ borderTopWidth: 1,
47
+ borderTopColor: Colors.Gray4,
48
+ },
49
+ scheduleName: {
50
+ fontSize: 17,
51
+ marginTop: 12,
52
+ color: Colors.Gray9,
53
+ marginBottom: 12,
54
+ },
55
+ noMarginTop: {
56
+ marginTop: 0,
57
+ backgroundColor: Colors.White,
58
+ },
59
+ textInput: {
60
+ marginTop: 0,
61
+ borderWidth: 0,
62
+ borderBottomWidth: 1,
63
+ borderBottomColor: Colors.Gray4,
64
+ paddingLeft: 0,
65
+ backgroundColor: Colors.White,
66
+ fontSize: 17,
67
+ color: Colors.Gray9,
68
+ },
69
+ });
@@ -0,0 +1,97 @@
1
+ import React, { useCallback } from 'react';
2
+ import { View, TouchableOpacity } from 'react-native';
3
+ import { useTranslations } from '../../../hooks/Common/useTranslations';
4
+
5
+ import Text from '../../../commons/Text';
6
+ import { Colors } from '../../../configs';
7
+ import { REPEAT_ITEMS } from '../../../screens/GuestInfo/constant';
8
+ import styles from './AccessScheduleDetailStyles';
9
+
10
+ const RecurringDetail = ({
11
+ onShowSetDateTime,
12
+ recurringTimeStart,
13
+ recurringTimeEnd,
14
+ recurringTimeRepeat,
15
+ setRecurringTimeStart,
16
+ setRecurringTimeEnd,
17
+ setRecurringTimeRepeat,
18
+ }) => {
19
+ const t = useTranslations();
20
+ const onSetTimeStart = useCallback(() => {
21
+ onShowSetDateTime();
22
+ }, [onShowSetDateTime]);
23
+
24
+ const onSetTimeEnd = useCallback(() => {
25
+ onShowSetDateTime();
26
+ }, [onShowSetDateTime]);
27
+
28
+ const onSetRepeat = useCallback(
29
+ (item) => {
30
+ const index = recurringTimeRepeat.indexOf(item.value);
31
+ if (index !== -1) {
32
+ setRecurringTimeRepeat([
33
+ ...recurringTimeRepeat.slice(0, index),
34
+ ...recurringTimeRepeat.slice(index + 1),
35
+ ]);
36
+ } else {
37
+ setRecurringTimeRepeat([...recurringTimeRepeat, item.value]);
38
+ }
39
+ },
40
+ [recurringTimeRepeat, setRecurringTimeRepeat]
41
+ );
42
+
43
+ const renderRepeatItem = useCallback(
44
+ (item, index, isSelected) => {
45
+ return (
46
+ <TouchableOpacity
47
+ key={index}
48
+ style={[styles.repeatItem, isSelected && styles.repeatItemSelected]}
49
+ onPress={() => onSetRepeat(item)}
50
+ >
51
+ <Text
52
+ type="Body"
53
+ lineHeight={16}
54
+ color={isSelected ? Colors.Orange : item.color}
55
+ style={styles.repeatText}
56
+ >
57
+ {item.text}
58
+ </Text>
59
+ </TouchableOpacity>
60
+ );
61
+ },
62
+ [onSetRepeat]
63
+ );
64
+
65
+ return (
66
+ <View>
67
+ <Text style={styles.curtainText}>{t('curtain_opens')}</Text>
68
+ <TouchableOpacity onPress={onSetTimeStart}>
69
+ <Text type="Body" color={Colors.Orange} style={styles.value}>
70
+ 07:00 AM
71
+ </Text>
72
+ </TouchableOpacity>
73
+ <View style={styles.boder} />
74
+ <Text style={styles.curtainText}>{t('curtain_closes')}</Text>
75
+ <TouchableOpacity onPress={onSetTimeEnd}>
76
+ <Text type="Body" color={Colors.Orange} style={styles.value}>
77
+ 12:00 AM
78
+ </Text>
79
+ </TouchableOpacity>
80
+ <View style={styles.boder} />
81
+ <Text type="Body" color={Colors.Gray8} style={styles.title}>
82
+ {t('repeat')}
83
+ </Text>
84
+ <View style={styles.repeatWrap}>
85
+ {REPEAT_ITEMS.map((item, index) =>
86
+ renderRepeatItem(
87
+ item,
88
+ index,
89
+ recurringTimeRepeat.includes(item.value)
90
+ )
91
+ )}
92
+ </View>
93
+ </View>
94
+ );
95
+ };
96
+
97
+ export default RecurringDetail;
@@ -16,7 +16,7 @@ const DateTimeButton = memo(({ onPress, time, date, formatType, style }) => {
16
16
  <Text type={'Label'} color={Colors.Gray8} style={styles.txtTime}>
17
17
  {moment(time).format(format)}
18
18
  </Text>
19
- <IconOutline name={'calendar'} size={16} color={Colors.Gray8} />
19
+ <IconOutline style={styles.iconDateTime} name={'calendar'} />
20
20
  </TouchableOpacity>
21
21
  );
22
22
  });
@@ -40,4 +40,9 @@ const styles = StyleSheet.create({
40
40
  txtTime: {
41
41
  marginRight: 4,
42
42
  },
43
+ iconDateTime: {
44
+ marginBottom: 4,
45
+ fontSize: 16,
46
+ color: Colors.Gray8,
47
+ },
43
48
  });