@ledvance/ui-biz-bundle 1.1.67 → 1.1.69

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 (240) hide show
  1. package/.babelrc +31 -31
  2. package/.eslintignore +5 -5
  3. package/.eslintrc.js +27 -27
  4. package/.prettierrc.js +1 -1
  5. package/.versionrc +5 -5
  6. package/package.json +74 -74
  7. package/rn-cli.config.js +8 -8
  8. package/src/hooks/DeviceDpStateHooks.d.ts +14 -14
  9. package/src/hooks/DeviceDpStateHooks.ts +50 -50
  10. package/src/modules/biorhythm/BiorhythmActions.d.ts +8 -8
  11. package/src/modules/biorhythm/BiorhythmActions.ts +324 -324
  12. package/src/modules/biorhythm/BiorhythmBean.d.ts +58 -58
  13. package/src/modules/biorhythm/BiorhythmBean.ts +230 -230
  14. package/src/modules/biorhythm/BiorhythmEditPage.d.ts +14 -14
  15. package/src/modules/biorhythm/BiorhythmEditPage.tsx +324 -324
  16. package/src/modules/biorhythm/BiorhythmPage.d.ts +10 -10
  17. package/src/modules/biorhythm/BiorhythmPage.tsx +796 -796
  18. package/src/modules/biorhythm/IconSelect.d.ts +2 -2
  19. package/src/modules/biorhythm/IconSelect.tsx +81 -81
  20. package/src/modules/biorhythm/Router.ts +34 -34
  21. package/src/modules/biorhythm/circular/ItemIcon.d.ts +22 -22
  22. package/src/modules/biorhythm/circular/ItemIcon.tsx +172 -172
  23. package/src/modules/biorhythm/circular/Progress.d.ts +24 -24
  24. package/src/modules/biorhythm/circular/Progress.tsx +411 -411
  25. package/src/modules/biorhythm/circular/TimeCircular.d.ts +11 -11
  26. package/src/modules/biorhythm/circular/TimeCircular.tsx +70 -70
  27. package/src/modules/biorhythm/iconListData.d.ts +7 -7
  28. package/src/modules/biorhythm/iconListData.ts +29 -29
  29. package/src/modules/biorhythm/pIdList.d.ts +2 -2
  30. package/src/modules/biorhythm/pIdList.ts +35 -35
  31. package/src/modules/biorhythm/res/BiologicalRes.d.ts +43 -43
  32. package/src/modules/biorhythm/res/BiologicalRes.ts +41 -41
  33. package/src/modules/config/ldvConfig.d.ts +2 -2
  34. package/src/modules/config/ldvConfig.tsx +18 -18
  35. package/src/modules/fixedTime/FixedTimeActions.ts +173 -173
  36. package/src/modules/fixedTime/FixedTimeDetailPage.tsx +372 -372
  37. package/src/modules/fixedTime/FixedTimePage.tsx +213 -213
  38. package/src/modules/fixedTime/Router.ts +26 -26
  39. package/src/modules/flags/FlagActions.ts +267 -267
  40. package/src/modules/flags/FlagEditPage.tsx +441 -441
  41. package/src/modules/flags/FlagInfo.tsx +563 -563
  42. package/src/modules/flags/FlagItem.tsx +90 -90
  43. package/src/modules/flags/FlagPage.tsx +277 -277
  44. package/src/modules/flags/Router.ts +25 -25
  45. package/src/modules/history/HistoryPage.d.ts +2 -2
  46. package/src/modules/history/HistoryPage.tsx +261 -261
  47. package/src/modules/history/Router.ts +16 -16
  48. package/src/modules/history/SwitchHistoryPageActions.d.ts +14 -14
  49. package/src/modules/history/SwitchHistoryPageActions.ts +76 -76
  50. package/src/modules/mood/AddMoodPage.d.ts +10 -10
  51. package/src/modules/mood/AddMoodPage.tsx +792 -792
  52. package/src/modules/mood/DynamicMoodEditorPage.d.ts +6 -6
  53. package/src/modules/mood/DynamicMoodEditorPage.tsx +561 -561
  54. package/src/modules/mood/FantasyMood.tsx +176 -176
  55. package/src/modules/mood/FantasyMoodEditPage.tsx +582 -582
  56. package/src/modules/mood/FantasyMoodItem.tsx +104 -104
  57. package/src/modules/mood/FantasyRouter.ts +35 -35
  58. package/src/modules/mood/MixMood/AddMixMoodPage.tsx +247 -247
  59. package/src/modules/mood/MixMood/MixMoodActions.ts +128 -128
  60. package/src/modules/mood/MixMood/MixMoodEditPage.tsx +721 -721
  61. package/src/modules/mood/MixMood/MixMoodItem.tsx +134 -134
  62. package/src/modules/mood/MixMood/MixMoodPage.tsx +326 -326
  63. package/src/modules/mood/MixMood/MixSceneBeans.ts +364 -364
  64. package/src/modules/mood/MixMood/RecommendMixMoodItem.tsx +69 -69
  65. package/src/modules/mood/MixMood/Router.ts +44 -44
  66. package/src/modules/mood/MoodItem.d.ts +11 -11
  67. package/src/modules/mood/MoodItem.tsx +114 -114
  68. package/src/modules/mood/MoodPage.d.ts +16 -16
  69. package/src/modules/mood/MoodPage.tsx +296 -296
  70. package/src/modules/mood/RecommendMoodItem.d.ts +13 -13
  71. package/src/modules/mood/RecommendMoodItem.tsx +74 -74
  72. package/src/modules/mood/Router.ts +53 -53
  73. package/src/modules/mood/StaticMoodEditorPage.d.ts +16 -16
  74. package/src/modules/mood/StaticMoodEditorPage.tsx +320 -320
  75. package/src/modules/mood/tools.d.ts +3 -3
  76. package/src/modules/mood/tools.ts +11 -11
  77. package/src/modules/music/MusicDataBean.d.ts +47 -47
  78. package/src/modules/music/MusicDataBean.ts +167 -167
  79. package/src/modules/music/MusicManager.d.ts +27 -27
  80. package/src/modules/music/MusicManager.ts +207 -207
  81. package/src/modules/music/MusicPage.d.ts +10 -10
  82. package/src/modules/music/MusicPage.tsx +347 -347
  83. package/src/modules/music/MusicPageActions.d.ts +35 -35
  84. package/src/modules/music/MusicPageActions.ts +317 -317
  85. package/src/modules/music/Router.ts +16 -16
  86. package/src/modules/music/SelecetGenre.d.ts +7 -7
  87. package/src/modules/music/SelecetGenre.tsx +63 -63
  88. package/src/modules/music/color.d.ts +2 -2
  89. package/src/modules/music/color.ts +73 -73
  90. package/src/modules/music/res/index.d.ts +10 -10
  91. package/src/modules/music/res/index.ts +9 -9
  92. package/src/modules/powerOnBehavior/PowerOnBehaviorActions.ts +11 -11
  93. package/src/modules/powerOnBehavior/PowerOnBehaviorPage.tsx +173 -173
  94. package/src/modules/powerOnBehavior/Router.ts +16 -16
  95. package/src/modules/randomTime/RandomTimeActions.ts +160 -160
  96. package/src/modules/randomTime/RandomTimeDetailPage.tsx +337 -337
  97. package/src/modules/randomTime/RandomTimePage.tsx +214 -214
  98. package/src/modules/randomTime/Router.ts +25 -25
  99. package/src/modules/randomTime/Summary.tsx +122 -122
  100. package/src/modules/scene/SceneAction.d.ts +13 -13
  101. package/src/modules/scene/SceneAction.ts +473 -473
  102. package/src/modules/scene/SceneDetailPage.d.ts +1 -1
  103. package/src/modules/scene/SceneDetailPage.tsx +421 -421
  104. package/src/modules/scene/SceneInfo.d.ts +72 -72
  105. package/src/modules/scene/SceneInfo.ts +1059 -1059
  106. package/src/modules/scene/ScenePage.d.ts +7 -7
  107. package/src/modules/scene/ScenePage.tsx +147 -147
  108. package/src/modules/select/SelectPage.d.ts +12 -12
  109. package/src/modules/select/SelectPage.tsx +137 -137
  110. package/src/modules/sleepWakeup/DeviceState.d.ts +9 -9
  111. package/src/modules/sleepWakeup/DeviceState.tsx +99 -99
  112. package/src/modules/sleepWakeup/LdvScheduleItem.d.ts +15 -15
  113. package/src/modules/sleepWakeup/LdvScheduleItem.tsx +176 -176
  114. package/src/modules/sleepWakeup/Router.ts +25 -25
  115. package/src/modules/sleepWakeup/SleepWakeUpActions.d.ts +2 -2
  116. package/src/modules/sleepWakeup/SleepWakeUpActions.ts +180 -180
  117. package/src/modules/sleepWakeup/SleepWakeUpDetailPage.d.ts +2 -2
  118. package/src/modules/sleepWakeup/SleepWakeUpDetailPage.tsx +616 -616
  119. package/src/modules/sleepWakeup/SleepWakeUpPage.d.ts +13 -13
  120. package/src/modules/sleepWakeup/SleepWakeUpPage.tsx +424 -424
  121. package/src/modules/sleepWakeup/utils.d.ts +44 -44
  122. package/src/modules/sleepWakeup/utils.ts +253 -253
  123. package/src/modules/timeSchedule/DeviceState.d.ts +17 -17
  124. package/src/modules/timeSchedule/DeviceState.tsx +94 -94
  125. package/src/modules/timeSchedule/LdvScheduleItem.d.ts +15 -15
  126. package/src/modules/timeSchedule/LdvScheduleItem.tsx +130 -130
  127. package/src/modules/timeSchedule/ManualSetting.d.ts +14 -14
  128. package/src/modules/timeSchedule/ManualSetting.tsx +219 -219
  129. package/src/modules/timeSchedule/MoodSetting.d.ts +11 -11
  130. package/src/modules/timeSchedule/MoodSetting.tsx +228 -228
  131. package/src/modules/timeSchedule/Router.ts +25 -25
  132. package/src/modules/timeSchedule/ScheduleScene.d.ts +6 -6
  133. package/src/modules/timeSchedule/ScheduleScene.tsx +144 -144
  134. package/src/modules/timeSchedule/SingleLightView.d.ts +12 -12
  135. package/src/modules/timeSchedule/SingleLightView.tsx +175 -175
  136. package/src/modules/timeSchedule/TimeScheduleBean.d.ts +14 -14
  137. package/src/modules/timeSchedule/TimeScheduleBean.ts +18 -18
  138. package/src/modules/timeSchedule/TimeScheduleEditpage.d.ts +6 -6
  139. package/src/modules/timeSchedule/TimeScheduleEditpage.tsx +765 -765
  140. package/src/modules/timeSchedule/TimeSchedulePage.d.ts +13 -13
  141. package/src/modules/timeSchedule/TimeSchedulePage.tsx +358 -358
  142. package/src/modules/timeSchedule/components/ColorList.ts +23 -23
  143. package/src/modules/timeSchedule/components/LampSwitchCard.tsx +106 -106
  144. package/src/modules/timeSchedule/mix/MixLightActions.d.ts +3 -3
  145. package/src/modules/timeSchedule/mix/MixLightActions.ts +49 -49
  146. package/src/modules/timeSchedule/mix/MixLightBean.d.ts +10 -10
  147. package/src/modules/timeSchedule/mix/MixLightBean.ts +9 -9
  148. package/src/modules/timeSchedule/mix/MixLightView.d.ts +7 -7
  149. package/src/modules/timeSchedule/mix/MixLightView.tsx +197 -197
  150. package/src/modules/timeSchedule/utils.d.ts +1 -1
  151. package/src/modules/timeSchedule/utils.ts +6 -6
  152. package/src/modules/timer/Router.ts +16 -16
  153. package/src/modules/timer/TimerPage.d.ts +11 -11
  154. package/src/modules/timer/TimerPage.tsx +384 -384
  155. package/src/modules/timer/TimerPageAction.d.ts +22 -22
  156. package/src/modules/timer/TimerPageAction.ts +131 -131
  157. package/src/navigation/Routers.d.ts +15 -15
  158. package/src/navigation/Routers.ts +46 -44
  159. package/src/navigation/tools.d.ts +9 -9
  160. package/src/navigation/tools.ts +21 -21
  161. package/src/newModules/biorhythm/BiorhythmActions.ts +374 -374
  162. package/src/newModules/biorhythm/BiorhythmBean.ts +230 -230
  163. package/src/newModules/biorhythm/BiorhythmEditPage.tsx +267 -267
  164. package/src/newModules/biorhythm/BiorhythmPage.tsx +642 -642
  165. package/src/newModules/biorhythm/IconSelect.tsx +84 -84
  166. package/src/newModules/biorhythm/Router.ts +33 -33
  167. package/src/newModules/biorhythm/circular/ItemIcon.d.ts +22 -22
  168. package/src/newModules/biorhythm/circular/ItemIcon.tsx +172 -172
  169. package/src/newModules/biorhythm/circular/Progress.d.ts +24 -24
  170. package/src/newModules/biorhythm/circular/Progress.tsx +371 -371
  171. package/src/newModules/biorhythm/circular/TimeCircular.d.ts +11 -11
  172. package/src/newModules/biorhythm/circular/TimeCircular.tsx +64 -64
  173. package/src/newModules/biorhythm/iconListData.ts +29 -29
  174. package/src/newModules/biorhythm/pIdList.ts +35 -35
  175. package/src/newModules/biorhythm/res/BiologicalRes.d.ts +43 -43
  176. package/src/newModules/biorhythm/res/BiologicalRes.ts +41 -41
  177. package/src/newModules/childLock/ChildLockPage.tsx +97 -97
  178. package/src/newModules/childLock/Router.ts +16 -16
  179. package/src/newModules/energyConsumption/EnergyConsumptionActions.ts +23 -23
  180. package/src/newModules/energyConsumption/EnergyConsumptionChart.tsx +84 -84
  181. package/src/newModules/energyConsumption/EnergyConsumptionDetail.tsx +322 -322
  182. package/src/newModules/energyConsumption/EnergyConsumptionPage.tsx +393 -393
  183. package/src/newModules/energyConsumption/Router.ts +34 -34
  184. package/src/newModules/energyConsumption/co2Data.ts +23655 -23655
  185. package/src/newModules/energyConsumption/component/BarChart.tsx +93 -93
  186. package/src/newModules/energyConsumption/component/EnergyModal.tsx +284 -284
  187. package/src/newModules/energyConsumption/component/Overview.tsx +118 -118
  188. package/src/newModules/fixedTime/FixedTimeActions.ts +241 -241
  189. package/src/newModules/fixedTime/FixedTimeDetailPage.tsx +345 -345
  190. package/src/newModules/fixedTime/FixedTimePage.tsx +302 -302
  191. package/src/newModules/fixedTime/Router.ts +25 -25
  192. package/src/newModules/lightMode/LightModePage.tsx +204 -204
  193. package/src/newModules/lightMode/Router.ts +16 -16
  194. package/src/newModules/mood/AddMoodPage.tsx +194 -194
  195. package/src/newModules/mood/DynamicMoodEditorPage.tsx +650 -650
  196. package/src/newModules/mood/Interface.ts +220 -220
  197. package/src/newModules/mood/MixDynamicMoodEditor.tsx +786 -786
  198. package/src/newModules/mood/MoodActions.ts +232 -232
  199. package/src/newModules/mood/MoodInfo.ts +2151 -2151
  200. package/src/newModules/mood/MoodItem.tsx +160 -160
  201. package/src/newModules/mood/MoodPage.tsx +386 -386
  202. package/src/newModules/mood/MoodParse.ts +443 -443
  203. package/src/newModules/mood/RecommendMoodItem.tsx +81 -81
  204. package/src/newModules/mood/Router.ts +43 -43
  205. package/src/newModules/mood/StaticMoodEditorPage.tsx +290 -290
  206. package/src/newModules/overchargeSwitch/OverchargeSwitchPage.tsx +96 -96
  207. package/src/newModules/overchargeSwitch/Router.ts +16 -16
  208. package/src/newModules/powerOnBehavior/LightBehaviorPage.tsx +266 -266
  209. package/src/newModules/powerOnBehavior/PlugBehaviorPage.tsx +173 -173
  210. package/src/newModules/powerOnBehavior/PowerOnBehaviorActions.ts +106 -106
  211. package/src/newModules/powerOnBehavior/Router.ts +27 -27
  212. package/src/newModules/randomTime/RandomTimeActions.ts +238 -238
  213. package/src/newModules/randomTime/RandomTimeDetailPage.tsx +325 -325
  214. package/src/newModules/randomTime/RandomTimePage.tsx +299 -299
  215. package/src/newModules/randomTime/Router.ts +25 -25
  216. package/src/newModules/randomTime/Summary.tsx +116 -116
  217. package/src/newModules/remoteControl/RemoteControlActions.ts +5 -5
  218. package/src/newModules/remoteControl/RemoteControlPage.tsx +51 -51
  219. package/src/newModules/remoteControl/Router.ts +15 -15
  220. package/src/newModules/select/Route.ts +16 -16
  221. package/src/newModules/select/SelectPage.d.ts +12 -12
  222. package/src/newModules/select/SelectPage.tsx +137 -137
  223. package/src/newModules/sleepWakeUp/Interface.ts +69 -69
  224. package/src/newModules/sleepWakeUp/Router.ts +24 -24
  225. package/src/newModules/sleepWakeUp/SleepWakeUpActions.ts +317 -317
  226. package/src/newModules/sleepWakeUp/SleepWakeUpDetailPage.tsx +661 -661
  227. package/src/newModules/sleepWakeUp/SleepWakeUpPage.tsx +455 -455
  228. package/src/newModules/sleepWakeUp/utils.ts +253 -253
  229. package/src/newModules/swithInching/Router.ts +16 -16
  230. package/src/newModules/swithInching/SwithInching.tsx +231 -231
  231. package/src/newModules/swithInching/SwithInchingAction.ts +55 -55
  232. package/src/newModules/swithInching/pickerView.tsx +91 -91
  233. package/src/newModules/timeSchedule/Interface.ts +142 -142
  234. package/src/newModules/timeSchedule/Router.ts +25 -25
  235. package/src/newModules/timeSchedule/TimeScheduleActions.ts +53 -53
  236. package/src/newModules/timeSchedule/TimeScheduleDetailPage.tsx +648 -648
  237. package/src/newModules/timeSchedule/TimeSchedulePage.tsx +253 -253
  238. package/src/newModules/timeSchedule/components/ManuaSettings.tsx +460 -460
  239. package/src/newModules/timeSchedule/components/ScheduleCard.tsx +125 -125
  240. package/tsconfig.json +50 -50
@@ -1,648 +1,648 @@
1
- import React, { useCallback, useEffect, useMemo } from 'react';
2
- import {
3
- FlatList,
4
- Image,
5
- ScrollView,
6
- StyleSheet,
7
- Text,
8
- TouchableOpacity,
9
- View,
10
- } from 'react-native';
11
- import { useNavigation } from '@react-navigation/core';
12
- import Page from '@ledvance/base/src/components/Page';
13
- import I18n from '@ledvance/base/src/i18n';
14
- import TextField from '@ledvance/base/src/components/TextField';
15
- import { cloneDeep, isEqual } from 'lodash';
16
- import { useReactive } from 'ahooks';
17
- import { SwitchButton, TimerPicker, Utils } from 'tuya-panel-kit';
18
- import Spacer from '@ledvance/base/src/components/Spacer';
19
- import LdvWeekView from '@ledvance/base/src/components/weekSelect';
20
- import { convertTo12HourFormat, loopText, showDialog } from '@ledvance/base/src/utils/common';
21
- import {
22
- ApplyForItem,
23
- ComponentConfig,
24
- DeviceType,
25
- TimeScheduleDetailState,
26
- Timer,
27
- TimerActions,
28
- } from './Interface';
29
- import res from '@ledvance/base/src/res';
30
- import {
31
- useDeviceId,
32
- useMoods,
33
- useSystemTimeFormate,
34
- } from '@ledvance/base/src/models/modules/NativePropsSlice';
35
- import { TimeSchedulePageParams } from './TimeSchedulePage';
36
- import { Result } from '@ledvance/base/src/models/modules/Result';
37
- import DeleteButton from '@ledvance/base/src/components/DeleteButton';
38
- import InfoText from '@ledvance/base/src/components/InfoText';
39
- import SegmentControl from '@ledvance/base/src/components/segmentControl';
40
- import { useParams } from '@ledvance/base/src/hooks/Hooks';
41
- import ManualSettings from './components/ManuaSettings';
42
- import { defDeviceData, defMixDeviceData, defStripDeviceData } from './TimeScheduleActions';
43
- import MoodItem from '../mood/MoodItem';
44
- import { getRemoteMoodList } from '../mood/MoodActions';
45
- import { MoodUIInfo } from '@ledvance/ui-biz-bundle/src/newModules/mood/Interface';
46
- import Summary from '@ledvance/base/src/components/Summary'
47
-
48
- const { convertX: cx } = Utils.RatioUtils;
49
- const { toFixedString } = Utils.NumberUtils;
50
- const { withTheme } = Utils.ThemeUtils
51
-
52
- interface TimeScheduleDetailPageParams extends TimeSchedulePageParams {
53
- mode: 'add' | 'update';
54
- timeSchedule: Timer;
55
- modDeleteTimeSchedule: (mode: TimerActions, timeSchedule: Timer) => Promise<Result<any>>;
56
- refreshFn: () => void;
57
- }
58
-
59
- const TimeScheduleDetailPage = (props: { theme?: any }) => {
60
- const is24HourClock = useSystemTimeFormate();
61
- const params = useParams<TimeScheduleDetailPageParams>();
62
- const navigation = useNavigation();
63
- const devId = useDeviceId();
64
- const [moods, setMoods] = useMoods();
65
- const state = useReactive<TimeScheduleDetailState>({
66
- timeSchedule: params.mode === 'add' ? newTimeSchedule() : cloneDeep(params.timeSchedule),
67
- dps: params.mode === 'add' ? {} : params.timeSchedule.dps,
68
- isManual: true, // manual ,mood
69
- initSelectedSkill: [] as ApplyForItem[],
70
- selectedSkill: [] as ApplyForItem[],
71
- unSelectedSkill: [] as ApplyForItem[],
72
- loading: false,
73
- moodLoading: false,
74
- manualData:
75
- params.mode === 'add'
76
- ? getDefaultManual(params)
77
- : params.manualDataDp2Obj(params.timeSchedule.dps).deviceData,
78
- mood: params.mode === 'add' ? undefined : params.manualDataDp2Obj(params.timeSchedule.dps)?.mood,
79
- moods: cloneDeep(moods),
80
- timerId: undefined,
81
- moodName: '',
82
- });
83
-
84
- useEffect(() => {
85
- const { applyForDisabled, timeSchedule, applyForList, mode } = params;
86
- const cannotChoose = applyForDisabled || applyForList.length === 1;
87
- const cloneApplyList =
88
- mode === 'add'
89
- ? cloneDeep(applyForList)
90
- : cloneDeep(applyForList).map(item => {
91
- if (params.isMixLight && state.manualData.type === DeviceType.MixLight) {
92
- return {
93
- ...item,
94
- enable:
95
- item.type === 'mainLight'
96
- ? state.manualData.deviceData.whiteLightSwitch
97
- : state.manualData.deviceData.colorLightSwitch,
98
- };
99
- }
100
- if (timeSchedule?.dps?.hasOwnProperty(item.dp)) {
101
- return {
102
- ...item,
103
- enable: timeSchedule?.dps[item.dp],
104
- };
105
- }
106
- return item;
107
- });
108
-
109
- if (cannotChoose) {
110
- state.selectedSkill = cloneApplyList;
111
- state.unSelectedSkill = [];
112
- } else {
113
- const selectedList = cloneApplyList.filter(item =>
114
- Object.keys(timeSchedule?.dps || {}).includes(item.dp)
115
- );
116
- const unSelectedList = cloneApplyList.filter(
117
- item => !Object.keys(timeSchedule?.dps || {}).includes(item.dp)
118
- );
119
- state.selectedSkill = mode === 'add' ? [] : selectedList;
120
- state.unSelectedSkill = mode === 'add' ? cloneApplyList : unSelectedList;
121
- }
122
- if (params.mode === 'update' && params.manualDataDp2Obj) {
123
- const { isManual, mood } = params.manualDataDp2Obj(params.timeSchedule.dps);
124
- state.isManual = isManual;
125
- state.mood = mood;
126
- }
127
-
128
- state.initSelectedSkill = cloneDeep(state.selectedSkill)
129
-
130
- if (!(Array.isArray(moods) && moods.length)) {
131
- state.timerId = setTimeout(() => {
132
- getRemoteMoodList(devId, params, params.featureId).then(res => {
133
- if (res.success && Array.isArray(res.data)) {
134
- state.moods = cloneDeep(res.data);
135
- setMoods(cloneDeep(res.data));
136
- if (!state.mood) state.mood = cloneDeep(res.data[0]);
137
- }
138
- });
139
- }, 250);
140
- return () => {
141
- if (state.timerId) clearTimeout(state.timerId);
142
- };
143
- } else {
144
- if (!state.mood) state.mood = cloneDeep(state.moods[0]);
145
- }
146
- }, []);
147
-
148
- useEffect(() => {
149
- if (state.moods?.length) {
150
- state.moodName =
151
- state.moods.find(m =>
152
- params.isCeilingLight
153
- ? m.mainLamp.id === state.mood?.mainLamp.id &&
154
- m.secondaryLamp.id === state.mood?.secondaryLamp.id
155
- : m.id === state.mood?.id
156
- )?.name || '';
157
- }
158
- }, [state.mood, state.moods]);
159
-
160
- const getFormateTime = useCallback((time: number | string) => {
161
- if (typeof time === 'number') {
162
- return `${toFixedString(Math.trunc(time / 60), 2)}:${toFixedString(time % 60, 2)}`;
163
- }
164
- if (typeof time === 'string') {
165
- const t = time.split(':');
166
- return Number(t[0]) * 60 + Number(t[1]);
167
- }
168
- return time;
169
- }, []);
170
-
171
- const isModify = useMemo(() => {
172
- const schedule = params.mode === 'add' ? newTimeSchedule() : params.timeSchedule;
173
- const manual = params.mode === 'add' ? getDefaultManual(params) : params.manualDataDp2Obj(params.timeSchedule?.dps).deviceData;
174
- const before = {
175
- ...schedule,
176
- selectedSkill: state.initSelectedSkill,
177
- dps: manual,
178
- isManual: params.mode === 'add' || params.manualDataDp2Obj(params.timeSchedule.dps).isManual,
179
- mood: params.mode === 'add' ? undefined : params.manualDataDp2Obj(params.timeSchedule?.dps).mood,
180
- id: 1,
181
- };
182
-
183
- const now = {
184
- ...state.timeSchedule,
185
- selectedSkill: state.selectedSkill,
186
- dps: state.manualData,
187
- isManual: state.isManual,
188
- mood: state.isManual ? undefined : state.mood,
189
- id: 1,
190
- };
191
- return isEqual(before, now);
192
- }, [JSON.stringify(state.timeSchedule), state.manualData, state.isManual, state.mood, JSON.stringify(state.selectedSkill)]);
193
-
194
- const showMoodFanSelectText = useMemo(() => {
195
- return (params.isUVCFan || params.isFanLight) && !state.isManual && state.selectedSkill.length < 2
196
- }, [params.isUVCFan, params.isFanLight, state.selectedSkill.length, state.isManual])
197
-
198
- const allowSubmit = useMemo(() => {
199
- return (
200
- !!(state.timeSchedule.name.length && state.timeSchedule.name.length < 33) &&
201
- !!state.selectedSkill.length &&
202
- (state.isManual || !!state.mood) &&
203
- !isModify &&
204
- !showMoodFanSelectText
205
- );
206
- }, [state.timeSchedule.name, state.selectedSkill, isModify, state.isManual, state.mood, showMoodFanSelectText]);
207
-
208
- const showSelectedIcon = useMemo(() => {
209
- return params.applyForList.length !== 1 && !params.applyForDisabled;
210
- }, [params.applyForList.length, params.applyForDisabled]);
211
-
212
- const getMoodItemEnable = useCallback((item: MoodUIInfo) => {
213
- return params.isCeilingLight ? ((item.mainLamp.id === state.mood?.mainLamp?.id) && (item.secondaryLamp.id === state.mood?.secondaryLamp?.id)) : item.id === state.mood?.id
214
- }, [state.mood, params.isCeilingLight])
215
-
216
- const styles = StyleSheet.create({
217
- cardContainer: {
218
- marginHorizontal: cx(24),
219
- },
220
- itemTitle: {
221
- color: props.theme.global.fontColor,
222
- fontSize: cx(16),
223
- fontWeight: 'bold',
224
- fontFamily: 'helvetica_neue_lt_std_bd',
225
- },
226
- applyContent: {
227
- backgroundColor: props.theme.card.board,
228
- borderRadius: 4,
229
- minHeight: cx(55),
230
- flex: 1,
231
- justifyContent: 'center',
232
- paddingTop: cx(10),
233
- paddingHorizontal: cx(10),
234
- },
235
- applyItem: {
236
- paddingLeft: cx(5),
237
- flexDirection: 'row',
238
- justifyContent: 'space-between',
239
- alignItems: 'center',
240
- backgroundColor: props.theme.global.background,
241
- height: cx(35),
242
- },
243
- moodScrollView: {
244
- maxHeight: cx(500),
245
- },
246
- summaryContainer: {
247
- flexDirection: 'row',
248
- justifyContent: 'flex-start',
249
- marginBottom: cx(10),
250
- marginHorizontal: cx(24),
251
- },
252
- summaryImg: {
253
- height: cx(12),
254
- width: cx(12),
255
- tintColor: props.theme.global.fontColor,
256
- },
257
- summaryLeft: {
258
- flexDirection: 'row',
259
- alignItems: 'center',
260
- minWidth: cx(90),
261
- },
262
- leftTitle: {
263
- fontSize: cx(14),
264
- color: props.theme.global.fontColor,
265
- marginTop: 0,
266
- },
267
- summaryRight: {
268
- flexDirection: 'column',
269
- backgroundColor: props.theme.card.background,
270
- borderRadius: cx(16),
271
- alignItems: 'center'
272
- },
273
-
274
- rightItem: {
275
- paddingHorizontal: cx(12),
276
- color: props.theme.global.fontColor,
277
- fontSize: cx(14)
278
- },
279
- switchButton: {
280
- flexDirection: 'row',
281
- alignItems: 'center',
282
- justifyContent: 'space-between',
283
- marginBottom: cx(10),
284
- },
285
- text: {
286
- color: props.theme.global.fontColor,
287
- fontSize: cx(14)
288
- },
289
- });
290
-
291
- return (
292
- <Page
293
- backText={I18n.getLang('motion_detection_add_time_schedule_system_back_text')}
294
- headlineText={I18n.getLang(
295
- params.mode === 'add'
296
- ? 'motion_detection_add_time_schedule_headline_text'
297
- : 'edit_timeschedule_headline_text'
298
- )}
299
- rightButtonIcon={allowSubmit ? res.ic_check : res.ic_uncheck}
300
- rightButtonIconClick={async () => {
301
- if (!allowSubmit || state.loading) return;
302
- state.loading = true;
303
- const res = await params.modDeleteTimeSchedule(params.mode, {
304
- ...state.timeSchedule,
305
- enable: true,
306
- dps: params.manualDataObj2Dp(
307
- {
308
- deviceData: state.manualData,
309
- isManual: state.isManual,
310
- mood: state.mood,
311
- },
312
- state.selectedSkill
313
- ),
314
- });
315
- console.log(res, '< ---- resss');
316
- state.loading = false;
317
- if (res.success) {
318
- navigation.goBack();
319
- }
320
- }}
321
- backDialogTitle={I18n.getLang('cancel_dialog_leave_unsaved_titel')}
322
- backDialogContent={I18n.getLang('cancel_dialog_leave_unsaved_timeschedule_note')}
323
- showBackDialog={!isModify}
324
- loading={state.loading}
325
- >
326
- <ScrollView nestedScrollEnabled={true}>
327
- <TextField
328
- style={styles.cardContainer}
329
- value={state.timeSchedule.name}
330
- showError={state.timeSchedule.name?.length > 32}
331
- maxLength={33}
332
- errorText={I18n.getLang('add_new_dynamic_mood_alert_text')}
333
- placeholder={I18n.getLang('add_new_trigger_time_inputfield_value_text')}
334
- onChangeText={(t: string) => {
335
- state.timeSchedule.name = t;
336
- }}
337
- />
338
-
339
- {/* pick */}
340
- <TimerPicker
341
- itemTextColor="#aeadb5"
342
- style={{ paddingVertical: cx(0), marginVertical: cx(0), backgroundColor: props.theme.global.background }}
343
- pickerFontColor={props.theme.global.fontColor}
344
- is12Hours={!is24HourClock}
345
- singlePicker={true}
346
- amText={I18n.getLang('manage_user_calendar_label_am')}
347
- pmText={I18n.getLang('manage_user_calendar_label_pm')}
348
- startTime={getFormateTime(state.timeSchedule.time) as number}
349
- symbol={''}
350
- onTimerChange={startTime => {
351
- state.timeSchedule.time = getFormateTime(startTime) as string;
352
- }}
353
- />
354
-
355
- <LdvWeekView
356
- value={state.timeSchedule.loops.split('').map(Number)}
357
- style={styles.cardContainer}
358
- onSelect={(index: number) => {
359
- const rawIndex = index - 1;
360
- const weeks = state.timeSchedule.loops.split('');
361
- weeks[rawIndex] = weeks[rawIndex] === '1' ? '0' : '1';
362
- state.timeSchedule.loops = weeks.join('');
363
- }}
364
- />
365
- <Spacer />
366
- <Text style={{ ...styles.cardContainer, color: props.theme.global.fontColor, fontSize: cx(14) }}>{loopText(state.timeSchedule.loops.split(''))}</Text>
367
- <Spacer height={cx(30)} />
368
-
369
- {/* Apply for */}
370
- <View style={styles.cardContainer}>
371
- <Text style={styles.itemTitle}>
372
- {I18n.getLang('timeschedule_add_schedule_subheadline_text')}
373
- </Text>
374
- <Spacer height={cx(10)} />
375
- <View style={[styles.applyContent, { paddingTop: state.selectedSkill.length ? cx(10) : 0 }]}>
376
- {state.selectedSkill.length === 0 ? (
377
- <Text>{I18n.getLang('timer_ceiling_fan_selectionfield_no_components_text')}</Text>
378
- ) : (
379
- state.selectedSkill.map(skill => (
380
- <View
381
- style={[styles.applyItem, { marginBottom: cx(10), borderRadius: 4 }]}
382
- key={skill.dp}
383
- >
384
- <Text style={{ color: props.theme.global.fontColor, fontSize: cx(12) }}>{skill.key}</Text>
385
- {showSelectedIcon && (
386
- <TouchableOpacity
387
- onPress={() => {
388
- state.selectedSkill = state.selectedSkill.filter(s => skill.dp !== s.dp);
389
- state.unSelectedSkill = [...state.unSelectedSkill, skill];
390
- }}
391
- style={{ paddingHorizontal: cx(5) }}
392
- >
393
- <Image
394
- style={{ width: cx(16), height: cx(16) }}
395
- source={res.ic_arrows_nav_clear}
396
- />
397
- </TouchableOpacity>
398
- )}
399
- </View>
400
- ))
401
- )}
402
- </View>
403
- {state.unSelectedSkill.map((item: ApplyForItem) => {
404
- return (
405
- <TouchableOpacity
406
- style={styles.applyItem}
407
- key={item.dp}
408
- onPress={() => {
409
- state.selectedSkill = [...state.selectedSkill, item];
410
- state.unSelectedSkill = state.unSelectedSkill.filter(s => item.dp !== s.dp);
411
- }}
412
- >
413
- <Text style={{ color: props.theme.global.fontColor, fontSize: cx(12) }}>{item.key}</Text>
414
- <Image
415
- style={{ width: cx(16), height: cx(16) }}
416
- source={res.device_panel_timer_add}
417
- />
418
- </TouchableOpacity>
419
- );
420
- })}
421
- <Spacer />
422
- </View>
423
-
424
- {/* device state */}
425
- <Text style={[styles.itemTitle, styles.cardContainer]}>
426
- {I18n.getLang('timeschedule_add_schedule_subheadline2_text')}
427
- </Text>
428
- <Spacer height={cx(10)} />
429
- {params.isSupportMood && (
430
- <>
431
- <SegmentControl
432
- title1={I18n.getLang('timeschedule_add_schedule_switch_tab_manual_text')}
433
- title2={I18n.getLang('timeschedule_add_schedule_switch_tab_mood_text')}
434
- isFirst={state.isManual}
435
- setIsFirst={(v: boolean) => (state.isManual = v)}
436
- />
437
- <Spacer height={cx(16)} />
438
- </>
439
- )}
440
- <Spacer height={cx(10)} />
441
- {(!state.selectedSkill.length && !showMoodFanSelectText) && <InfoText
442
- style={{ marginHorizontal: cx(24) }}
443
- icon={res.ic_warning_amber}
444
- contentColor="#FF9500"
445
- text={I18n.getLang('timeschedule_add_schedule_no_device_warning_text')}
446
- textStyle={{fontSize: cx(12)}}
447
- />}
448
- {showMoodFanSelectText && <InfoText
449
- style={{ marginHorizontal: cx(24) }}
450
- icon={res.ic_warning_amber}
451
- contentColor="#FF9500"
452
- text={I18n.getLang('timeschedule_add_schedule_devicestate_sec_warning_text')}
453
- textStyle={{fontSize: cx(12)}}
454
- />}
455
- {state.isManual ? (
456
- <ManualSettings
457
- dps={state.dps}
458
- applyForList={state.selectedSkill}
459
- isSupportColor={params.isSupportColor}
460
- isSupportBrightness={params.isSupportBrightness}
461
- isSupportTemperature={params.isSupportTemperature}
462
- isStripLight={params.isStripLight}
463
- manualData={state.manualData}
464
- onManualChange={manual => {
465
- state.manualData = {
466
- ...state.manualData,
467
- // @ts-ignore
468
- deviceData: cloneDeep(manual),
469
- };
470
- }}
471
- onApplyChange={apply => {
472
- state.selectedSkill = cloneDeep(apply);
473
- }}
474
- />
475
- ) : (
476
- !showMoodFanSelectText ? <FlatList
477
- data={state.moods}
478
- renderItem={({ item }) => {
479
- return (
480
- <MoodItem
481
- enable={getMoodItemEnable(item)}
482
- mood={item}
483
- isMix={!!(params.isMixLight || params.isCeilingLight)}
484
- onSwitch={_ => {
485
- state.mood = cloneDeep(item);
486
- }}
487
- />
488
- );
489
- }}
490
- ListHeaderComponent={() => <Spacer height={cx(10)} />}
491
- ItemSeparatorComponent={() => <Spacer />}
492
- ListFooterComponent={() => <Spacer />}
493
- keyExtractor={item => `${item.name}`}
494
- /> : <View></View>
495
- )}
496
- <Spacer />
497
-
498
- {/* settings */}
499
- <Text style={[styles.itemTitle, styles.cardContainer]}>
500
- {I18n.getLang('timeschedule_add_schedule_subheadline4_text')}
501
- </Text>
502
- <View style={[styles.switchButton, styles.cardContainer]}>
503
- <Text style={styles.text}>{I18n.getLang('timeschedule_add_schedule_text2')}</Text>
504
- <SwitchButton
505
- value={state.timeSchedule.notification}
506
- onValueChange={value => {
507
- state.timeSchedule.notification = value;
508
- }}
509
- />
510
- </View>
511
- <Spacer />
512
-
513
- {/* summary */}
514
- <Summary
515
- frequency={loopText(state.timeSchedule.loops.split(''), state.timeSchedule.time)}
516
- time={is24HourClock
517
- ? state.timeSchedule.time
518
- : convertTo12HourFormat(state.timeSchedule.time)}
519
- actions={<View style={{ flex: 1 }}>
520
- {state.isManual
521
- ? !!state.selectedSkill.length && (
522
- <>
523
- {!!state.selectedSkill.filter(skill => skill.enable).length && (
524
- <>
525
- <Text style={{ fontSize: cx(14), color: '#000' }}>
526
- {I18n.getLang('feature_summary_action_txt_1')}
527
- </Text>
528
- <View style={{ flexDirection: 'row', flexWrap: 'wrap' }}>
529
- {state.selectedSkill
530
- .filter(skill => skill.enable)
531
- .map(item => (
532
- <View
533
- style={[
534
- styles.summaryRight,
535
- { marginRight: cx(5), marginBottom: cx(5) },
536
- ]}
537
- key={item.dp}
538
- >
539
- <Text style={[styles.rightItem]}>{item.key}</Text>
540
- </View>
541
- ))}
542
- </View>
543
- </>
544
- )}
545
-
546
- {!!state.selectedSkill.filter(skill => !skill.enable).length && (
547
- <>
548
- <Text style={{ fontSize: cx(14) }}>
549
- {I18n.getLang('feature_summary_action_txt_2')}
550
- </Text>
551
- <View style={{ flexDirection: 'row', flexWrap: 'wrap' }}>
552
- {state.selectedSkill
553
- .filter(skill => !skill.enable)
554
- .map((item) => (
555
- <View
556
- style={[
557
- styles.summaryRight,
558
- { marginRight: cx(5), marginBottom: cx(5) },
559
- ]}
560
- key={item.dp}
561
- >
562
- <Text style={[styles.rightItem]}>{item.key}</Text>
563
- </View>
564
- ))}
565
- </View>
566
- </>
567
- )}
568
- </>
569
- )
570
- : !!state.moodName && (
571
- <View style={{ flexDirection: 'row', flexWrap: 'wrap' }}>
572
- <View style={[styles.summaryRight, { marginLeft: cx(5) }]}>
573
- <Text style={styles.rightItem}>{state.moodName}</Text>
574
- </View>
575
- </View>
576
- )}
577
- </View>}
578
- />
579
- <Spacer height={cx(30)} />
580
-
581
- {/* delete */}
582
- {params.mode === 'update' && (
583
- <View style={{ marginHorizontal: cx(24) }}>
584
- <DeleteButton
585
- text={I18n.getLang('edit_timeschedule_bttn_text')}
586
- onPress={() => {
587
- showDialog({
588
- method: 'confirm',
589
- title: I18n.getLang('cancel_dialog_delete_item_timeschedule_titel'),
590
- subTitle: I18n.getLang('cancel_dialog_delete_item_timeschedule_description'),
591
- onConfirm: async (_, { close }) => {
592
- state.loading = true;
593
- close();
594
- const res = await params.modDeleteTimeSchedule('delete', state.timeSchedule);
595
- state.loading = false;
596
- if (res.success) {
597
- navigation.goBack();
598
- }
599
- },
600
- });
601
- }}
602
- />
603
- <Spacer />
604
- </View>
605
- )}
606
- </ScrollView>
607
- </Page>
608
- );
609
- };
610
-
611
- const newTimeSchedule = () => {
612
- return {
613
- enable: true,
614
- loops: '0000000',
615
- notification: false,
616
- name: '',
617
- time: `${toFixedString(new Date().getHours(), 2)}:${toFixedString(new Date().getMinutes(), 2)}`,
618
- dps: {},
619
- id: -1,
620
- };
621
- };
622
-
623
- const getDefaultManual = (props: TimeScheduleDetailPageParams): ComponentConfig => {
624
- const deviceType =
625
- props.isStripLight || props.isCeilingLight
626
- ? DeviceType.StripLight
627
- : props.isMixLight
628
- ? DeviceType.MixLight
629
- : props.isPowerStrip
630
- ? DeviceType.PowerStrip
631
- : DeviceType.LightSource;
632
- const deviceData =
633
- deviceType === DeviceType.StripLight
634
- ? defStripDeviceData
635
- : deviceType === DeviceType.MixLight
636
- ? defMixDeviceData
637
- : defDeviceData;
638
- // @ts-ignore
639
- return {
640
- type: deviceType,
641
- deviceData: {
642
- ...deviceData,
643
- isColorMode: props.isSupportColor,
644
- },
645
- };
646
- };
647
-
648
- export default withTheme(TimeScheduleDetailPage)
1
+ import React, { useCallback, useEffect, useMemo } from 'react';
2
+ import {
3
+ FlatList,
4
+ Image,
5
+ ScrollView,
6
+ StyleSheet,
7
+ Text,
8
+ TouchableOpacity,
9
+ View,
10
+ } from 'react-native';
11
+ import { useNavigation } from '@react-navigation/core';
12
+ import Page from '@ledvance/base/src/components/Page';
13
+ import I18n from '@ledvance/base/src/i18n';
14
+ import TextField from '@ledvance/base/src/components/TextField';
15
+ import { cloneDeep, isEqual } from 'lodash';
16
+ import { useReactive } from 'ahooks';
17
+ import { SwitchButton, TimerPicker, Utils } from 'tuya-panel-kit';
18
+ import Spacer from '@ledvance/base/src/components/Spacer';
19
+ import LdvWeekView from '@ledvance/base/src/components/weekSelect';
20
+ import { convertTo12HourFormat, loopText, showDialog } from '@ledvance/base/src/utils/common';
21
+ import {
22
+ ApplyForItem,
23
+ ComponentConfig,
24
+ DeviceType,
25
+ TimeScheduleDetailState,
26
+ Timer,
27
+ TimerActions,
28
+ } from './Interface';
29
+ import res from '@ledvance/base/src/res';
30
+ import {
31
+ useDeviceId,
32
+ useMoods,
33
+ useSystemTimeFormate,
34
+ } from '@ledvance/base/src/models/modules/NativePropsSlice';
35
+ import { TimeSchedulePageParams } from './TimeSchedulePage';
36
+ import { Result } from '@ledvance/base/src/models/modules/Result';
37
+ import DeleteButton from '@ledvance/base/src/components/DeleteButton';
38
+ import InfoText from '@ledvance/base/src/components/InfoText';
39
+ import SegmentControl from '@ledvance/base/src/components/segmentControl';
40
+ import { useParams } from '@ledvance/base/src/hooks/Hooks';
41
+ import ManualSettings from './components/ManuaSettings';
42
+ import { defDeviceData, defMixDeviceData, defStripDeviceData } from './TimeScheduleActions';
43
+ import MoodItem from '../mood/MoodItem';
44
+ import { getRemoteMoodList } from '../mood/MoodActions';
45
+ import { MoodUIInfo } from '@ledvance/ui-biz-bundle/src/newModules/mood/Interface';
46
+ import Summary from '@ledvance/base/src/components/Summary'
47
+
48
+ const { convertX: cx } = Utils.RatioUtils;
49
+ const { toFixedString } = Utils.NumberUtils;
50
+ const { withTheme } = Utils.ThemeUtils
51
+
52
+ interface TimeScheduleDetailPageParams extends TimeSchedulePageParams {
53
+ mode: 'add' | 'update';
54
+ timeSchedule: Timer;
55
+ modDeleteTimeSchedule: (mode: TimerActions, timeSchedule: Timer) => Promise<Result<any>>;
56
+ refreshFn: () => void;
57
+ }
58
+
59
+ const TimeScheduleDetailPage = (props: { theme?: any }) => {
60
+ const is24HourClock = useSystemTimeFormate();
61
+ const params = useParams<TimeScheduleDetailPageParams>();
62
+ const navigation = useNavigation();
63
+ const devId = useDeviceId();
64
+ const [moods, setMoods] = useMoods();
65
+ const state = useReactive<TimeScheduleDetailState>({
66
+ timeSchedule: params.mode === 'add' ? newTimeSchedule() : cloneDeep(params.timeSchedule),
67
+ dps: params.mode === 'add' ? {} : params.timeSchedule.dps,
68
+ isManual: true, // manual ,mood
69
+ initSelectedSkill: [] as ApplyForItem[],
70
+ selectedSkill: [] as ApplyForItem[],
71
+ unSelectedSkill: [] as ApplyForItem[],
72
+ loading: false,
73
+ moodLoading: false,
74
+ manualData:
75
+ params.mode === 'add'
76
+ ? getDefaultManual(params)
77
+ : params.manualDataDp2Obj(params.timeSchedule.dps).deviceData,
78
+ mood: params.mode === 'add' ? undefined : params.manualDataDp2Obj(params.timeSchedule.dps)?.mood,
79
+ moods: cloneDeep(moods),
80
+ timerId: undefined,
81
+ moodName: '',
82
+ });
83
+
84
+ useEffect(() => {
85
+ const { applyForDisabled, timeSchedule, applyForList, mode } = params;
86
+ const cannotChoose = applyForDisabled || applyForList.length === 1;
87
+ const cloneApplyList =
88
+ mode === 'add'
89
+ ? cloneDeep(applyForList)
90
+ : cloneDeep(applyForList).map(item => {
91
+ if (params.isMixLight && state.manualData.type === DeviceType.MixLight) {
92
+ return {
93
+ ...item,
94
+ enable:
95
+ item.type === 'mainLight'
96
+ ? state.manualData.deviceData.whiteLightSwitch
97
+ : state.manualData.deviceData.colorLightSwitch,
98
+ };
99
+ }
100
+ if (timeSchedule?.dps?.hasOwnProperty(item.dp)) {
101
+ return {
102
+ ...item,
103
+ enable: timeSchedule?.dps[item.dp],
104
+ };
105
+ }
106
+ return item;
107
+ });
108
+
109
+ if (cannotChoose) {
110
+ state.selectedSkill = cloneApplyList;
111
+ state.unSelectedSkill = [];
112
+ } else {
113
+ const selectedList = cloneApplyList.filter(item =>
114
+ Object.keys(timeSchedule?.dps || {}).includes(item.dp)
115
+ );
116
+ const unSelectedList = cloneApplyList.filter(
117
+ item => !Object.keys(timeSchedule?.dps || {}).includes(item.dp)
118
+ );
119
+ state.selectedSkill = mode === 'add' ? [] : selectedList;
120
+ state.unSelectedSkill = mode === 'add' ? cloneApplyList : unSelectedList;
121
+ }
122
+ if (params.mode === 'update' && params.manualDataDp2Obj) {
123
+ const { isManual, mood } = params.manualDataDp2Obj(params.timeSchedule.dps);
124
+ state.isManual = isManual;
125
+ state.mood = mood;
126
+ }
127
+
128
+ state.initSelectedSkill = cloneDeep(state.selectedSkill)
129
+
130
+ if (!(Array.isArray(moods) && moods.length)) {
131
+ state.timerId = setTimeout(() => {
132
+ getRemoteMoodList(devId, params, params.featureId).then(res => {
133
+ if (res.success && Array.isArray(res.data)) {
134
+ state.moods = cloneDeep(res.data);
135
+ setMoods(cloneDeep(res.data));
136
+ if (!state.mood) state.mood = cloneDeep(res.data[0]);
137
+ }
138
+ });
139
+ }, 250);
140
+ return () => {
141
+ if (state.timerId) clearTimeout(state.timerId);
142
+ };
143
+ } else {
144
+ if (!state.mood) state.mood = cloneDeep(state.moods[0]);
145
+ }
146
+ }, []);
147
+
148
+ useEffect(() => {
149
+ if (state.moods?.length) {
150
+ state.moodName =
151
+ state.moods.find(m =>
152
+ params.isCeilingLight
153
+ ? m.mainLamp.id === state.mood?.mainLamp.id &&
154
+ m.secondaryLamp.id === state.mood?.secondaryLamp.id
155
+ : m.id === state.mood?.id
156
+ )?.name || '';
157
+ }
158
+ }, [state.mood, state.moods]);
159
+
160
+ const getFormateTime = useCallback((time: number | string) => {
161
+ if (typeof time === 'number') {
162
+ return `${toFixedString(Math.trunc(time / 60), 2)}:${toFixedString(time % 60, 2)}`;
163
+ }
164
+ if (typeof time === 'string') {
165
+ const t = time.split(':');
166
+ return Number(t[0]) * 60 + Number(t[1]);
167
+ }
168
+ return time;
169
+ }, []);
170
+
171
+ const isModify = useMemo(() => {
172
+ const schedule = params.mode === 'add' ? newTimeSchedule() : params.timeSchedule;
173
+ const manual = params.mode === 'add' ? getDefaultManual(params) : params.manualDataDp2Obj(params.timeSchedule?.dps).deviceData;
174
+ const before = {
175
+ ...schedule,
176
+ selectedSkill: state.initSelectedSkill,
177
+ dps: manual,
178
+ isManual: params.mode === 'add' || params.manualDataDp2Obj(params.timeSchedule.dps).isManual,
179
+ mood: params.mode === 'add' ? undefined : params.manualDataDp2Obj(params.timeSchedule?.dps).mood,
180
+ id: 1,
181
+ };
182
+
183
+ const now = {
184
+ ...state.timeSchedule,
185
+ selectedSkill: state.selectedSkill,
186
+ dps: state.manualData,
187
+ isManual: state.isManual,
188
+ mood: state.isManual ? undefined : state.mood,
189
+ id: 1,
190
+ };
191
+ return isEqual(before, now);
192
+ }, [JSON.stringify(state.timeSchedule), state.manualData, state.isManual, state.mood, JSON.stringify(state.selectedSkill)]);
193
+
194
+ const showMoodFanSelectText = useMemo(() => {
195
+ return (params.isUVCFan || params.isFanLight) && !state.isManual && state.selectedSkill.length < 2
196
+ }, [params.isUVCFan, params.isFanLight, state.selectedSkill.length, state.isManual])
197
+
198
+ const allowSubmit = useMemo(() => {
199
+ return (
200
+ !!(state.timeSchedule.name.length && state.timeSchedule.name.length < 33) &&
201
+ !!state.selectedSkill.length &&
202
+ (state.isManual || !!state.mood) &&
203
+ !isModify &&
204
+ !showMoodFanSelectText
205
+ );
206
+ }, [state.timeSchedule.name, state.selectedSkill, isModify, state.isManual, state.mood, showMoodFanSelectText]);
207
+
208
+ const showSelectedIcon = useMemo(() => {
209
+ return params.applyForList.length !== 1 && !params.applyForDisabled;
210
+ }, [params.applyForList.length, params.applyForDisabled]);
211
+
212
+ const getMoodItemEnable = useCallback((item: MoodUIInfo) => {
213
+ return params.isCeilingLight ? ((item.mainLamp.id === state.mood?.mainLamp?.id) && (item.secondaryLamp.id === state.mood?.secondaryLamp?.id)) : item.id === state.mood?.id
214
+ }, [state.mood, params.isCeilingLight])
215
+
216
+ const styles = StyleSheet.create({
217
+ cardContainer: {
218
+ marginHorizontal: cx(24),
219
+ },
220
+ itemTitle: {
221
+ color: props.theme.global.fontColor,
222
+ fontSize: cx(16),
223
+ fontWeight: 'bold',
224
+ fontFamily: 'helvetica_neue_lt_std_bd',
225
+ },
226
+ applyContent: {
227
+ backgroundColor: props.theme.card.board,
228
+ borderRadius: 4,
229
+ minHeight: cx(55),
230
+ flex: 1,
231
+ justifyContent: 'center',
232
+ paddingTop: cx(10),
233
+ paddingHorizontal: cx(10),
234
+ },
235
+ applyItem: {
236
+ paddingLeft: cx(5),
237
+ flexDirection: 'row',
238
+ justifyContent: 'space-between',
239
+ alignItems: 'center',
240
+ backgroundColor: props.theme.global.background,
241
+ height: cx(35),
242
+ },
243
+ moodScrollView: {
244
+ maxHeight: cx(500),
245
+ },
246
+ summaryContainer: {
247
+ flexDirection: 'row',
248
+ justifyContent: 'flex-start',
249
+ marginBottom: cx(10),
250
+ marginHorizontal: cx(24),
251
+ },
252
+ summaryImg: {
253
+ height: cx(12),
254
+ width: cx(12),
255
+ tintColor: props.theme.global.fontColor,
256
+ },
257
+ summaryLeft: {
258
+ flexDirection: 'row',
259
+ alignItems: 'center',
260
+ minWidth: cx(90),
261
+ },
262
+ leftTitle: {
263
+ fontSize: cx(14),
264
+ color: props.theme.global.fontColor,
265
+ marginTop: 0,
266
+ },
267
+ summaryRight: {
268
+ flexDirection: 'column',
269
+ backgroundColor: props.theme.card.background,
270
+ borderRadius: cx(16),
271
+ alignItems: 'center'
272
+ },
273
+
274
+ rightItem: {
275
+ paddingHorizontal: cx(12),
276
+ color: props.theme.global.fontColor,
277
+ fontSize: cx(14)
278
+ },
279
+ switchButton: {
280
+ flexDirection: 'row',
281
+ alignItems: 'center',
282
+ justifyContent: 'space-between',
283
+ marginBottom: cx(10),
284
+ },
285
+ text: {
286
+ color: props.theme.global.fontColor,
287
+ fontSize: cx(14)
288
+ },
289
+ });
290
+
291
+ return (
292
+ <Page
293
+ backText={I18n.getLang('motion_detection_add_time_schedule_system_back_text')}
294
+ headlineText={I18n.getLang(
295
+ params.mode === 'add'
296
+ ? 'motion_detection_add_time_schedule_headline_text'
297
+ : 'edit_timeschedule_headline_text'
298
+ )}
299
+ rightButtonIcon={allowSubmit ? res.ic_check : res.ic_uncheck}
300
+ rightButtonIconClick={async () => {
301
+ if (!allowSubmit || state.loading) return;
302
+ state.loading = true;
303
+ const res = await params.modDeleteTimeSchedule(params.mode, {
304
+ ...state.timeSchedule,
305
+ enable: true,
306
+ dps: params.manualDataObj2Dp(
307
+ {
308
+ deviceData: state.manualData,
309
+ isManual: state.isManual,
310
+ mood: state.mood,
311
+ },
312
+ state.selectedSkill
313
+ ),
314
+ });
315
+ console.log(res, '< ---- resss');
316
+ state.loading = false;
317
+ if (res.success) {
318
+ navigation.goBack();
319
+ }
320
+ }}
321
+ backDialogTitle={I18n.getLang('cancel_dialog_leave_unsaved_titel')}
322
+ backDialogContent={I18n.getLang('cancel_dialog_leave_unsaved_timeschedule_note')}
323
+ showBackDialog={!isModify}
324
+ loading={state.loading}
325
+ >
326
+ <ScrollView nestedScrollEnabled={true}>
327
+ <TextField
328
+ style={styles.cardContainer}
329
+ value={state.timeSchedule.name}
330
+ showError={state.timeSchedule.name?.length > 32}
331
+ maxLength={33}
332
+ errorText={I18n.getLang('add_new_dynamic_mood_alert_text')}
333
+ placeholder={I18n.getLang('add_new_trigger_time_inputfield_value_text')}
334
+ onChangeText={(t: string) => {
335
+ state.timeSchedule.name = t;
336
+ }}
337
+ />
338
+
339
+ {/* pick */}
340
+ <TimerPicker
341
+ itemTextColor="#aeadb5"
342
+ style={{ paddingVertical: cx(0), marginVertical: cx(0), backgroundColor: props.theme.global.background }}
343
+ pickerFontColor={props.theme.global.fontColor}
344
+ is12Hours={!is24HourClock}
345
+ singlePicker={true}
346
+ amText={I18n.getLang('manage_user_calendar_label_am')}
347
+ pmText={I18n.getLang('manage_user_calendar_label_pm')}
348
+ startTime={getFormateTime(state.timeSchedule.time) as number}
349
+ symbol={''}
350
+ onTimerChange={startTime => {
351
+ state.timeSchedule.time = getFormateTime(startTime) as string;
352
+ }}
353
+ />
354
+
355
+ <LdvWeekView
356
+ value={state.timeSchedule.loops.split('').map(Number)}
357
+ style={styles.cardContainer}
358
+ onSelect={(index: number) => {
359
+ const rawIndex = index - 1;
360
+ const weeks = state.timeSchedule.loops.split('');
361
+ weeks[rawIndex] = weeks[rawIndex] === '1' ? '0' : '1';
362
+ state.timeSchedule.loops = weeks.join('');
363
+ }}
364
+ />
365
+ <Spacer />
366
+ <Text style={{ ...styles.cardContainer, color: props.theme.global.fontColor, fontSize: cx(14) }}>{loopText(state.timeSchedule.loops.split(''))}</Text>
367
+ <Spacer height={cx(30)} />
368
+
369
+ {/* Apply for */}
370
+ <View style={styles.cardContainer}>
371
+ <Text style={styles.itemTitle}>
372
+ {I18n.getLang('timeschedule_add_schedule_subheadline_text')}
373
+ </Text>
374
+ <Spacer height={cx(10)} />
375
+ <View style={[styles.applyContent, { paddingTop: state.selectedSkill.length ? cx(10) : 0 }]}>
376
+ {state.selectedSkill.length === 0 ? (
377
+ <Text>{I18n.getLang('timer_ceiling_fan_selectionfield_no_components_text')}</Text>
378
+ ) : (
379
+ state.selectedSkill.map(skill => (
380
+ <View
381
+ style={[styles.applyItem, { marginBottom: cx(10), borderRadius: 4 }]}
382
+ key={skill.dp}
383
+ >
384
+ <Text style={{ color: props.theme.global.fontColor, fontSize: cx(12) }}>{skill.key}</Text>
385
+ {showSelectedIcon && (
386
+ <TouchableOpacity
387
+ onPress={() => {
388
+ state.selectedSkill = state.selectedSkill.filter(s => skill.dp !== s.dp);
389
+ state.unSelectedSkill = [...state.unSelectedSkill, skill];
390
+ }}
391
+ style={{ paddingHorizontal: cx(5) }}
392
+ >
393
+ <Image
394
+ style={{ width: cx(16), height: cx(16) }}
395
+ source={res.ic_arrows_nav_clear}
396
+ />
397
+ </TouchableOpacity>
398
+ )}
399
+ </View>
400
+ ))
401
+ )}
402
+ </View>
403
+ {state.unSelectedSkill.map((item: ApplyForItem) => {
404
+ return (
405
+ <TouchableOpacity
406
+ style={styles.applyItem}
407
+ key={item.dp}
408
+ onPress={() => {
409
+ state.selectedSkill = [...state.selectedSkill, item];
410
+ state.unSelectedSkill = state.unSelectedSkill.filter(s => item.dp !== s.dp);
411
+ }}
412
+ >
413
+ <Text style={{ color: props.theme.global.fontColor, fontSize: cx(12) }}>{item.key}</Text>
414
+ <Image
415
+ style={{ width: cx(16), height: cx(16) }}
416
+ source={res.device_panel_timer_add}
417
+ />
418
+ </TouchableOpacity>
419
+ );
420
+ })}
421
+ <Spacer />
422
+ </View>
423
+
424
+ {/* device state */}
425
+ <Text style={[styles.itemTitle, styles.cardContainer]}>
426
+ {I18n.getLang('timeschedule_add_schedule_subheadline2_text')}
427
+ </Text>
428
+ <Spacer height={cx(10)} />
429
+ {params.isSupportMood && (
430
+ <>
431
+ <SegmentControl
432
+ title1={I18n.getLang('timeschedule_add_schedule_switch_tab_manual_text')}
433
+ title2={I18n.getLang('timeschedule_add_schedule_switch_tab_mood_text')}
434
+ isFirst={state.isManual}
435
+ setIsFirst={(v: boolean) => (state.isManual = v)}
436
+ />
437
+ <Spacer height={cx(16)} />
438
+ </>
439
+ )}
440
+ <Spacer height={cx(10)} />
441
+ {(!state.selectedSkill.length && !showMoodFanSelectText) && <InfoText
442
+ style={{ marginHorizontal: cx(24) }}
443
+ icon={res.ic_warning_amber}
444
+ contentColor="#FF9500"
445
+ text={I18n.getLang('timeschedule_add_schedule_no_device_warning_text')}
446
+ textStyle={{fontSize: cx(12)}}
447
+ />}
448
+ {showMoodFanSelectText && <InfoText
449
+ style={{ marginHorizontal: cx(24) }}
450
+ icon={res.ic_warning_amber}
451
+ contentColor="#FF9500"
452
+ text={I18n.getLang('timeschedule_add_schedule_devicestate_sec_warning_text')}
453
+ textStyle={{fontSize: cx(12)}}
454
+ />}
455
+ {state.isManual ? (
456
+ <ManualSettings
457
+ dps={state.dps}
458
+ applyForList={state.selectedSkill}
459
+ isSupportColor={params.isSupportColor}
460
+ isSupportBrightness={params.isSupportBrightness}
461
+ isSupportTemperature={params.isSupportTemperature}
462
+ isStripLight={params.isStripLight}
463
+ manualData={state.manualData}
464
+ onManualChange={manual => {
465
+ state.manualData = {
466
+ ...state.manualData,
467
+ // @ts-ignore
468
+ deviceData: cloneDeep(manual),
469
+ };
470
+ }}
471
+ onApplyChange={apply => {
472
+ state.selectedSkill = cloneDeep(apply);
473
+ }}
474
+ />
475
+ ) : (
476
+ !showMoodFanSelectText ? <FlatList
477
+ data={state.moods}
478
+ renderItem={({ item }) => {
479
+ return (
480
+ <MoodItem
481
+ enable={getMoodItemEnable(item)}
482
+ mood={item}
483
+ isMix={!!(params.isMixLight || params.isCeilingLight)}
484
+ onSwitch={_ => {
485
+ state.mood = cloneDeep(item);
486
+ }}
487
+ />
488
+ );
489
+ }}
490
+ ListHeaderComponent={() => <Spacer height={cx(10)} />}
491
+ ItemSeparatorComponent={() => <Spacer />}
492
+ ListFooterComponent={() => <Spacer />}
493
+ keyExtractor={item => `${item.name}`}
494
+ /> : <View></View>
495
+ )}
496
+ <Spacer />
497
+
498
+ {/* settings */}
499
+ <Text style={[styles.itemTitle, styles.cardContainer]}>
500
+ {I18n.getLang('timeschedule_add_schedule_subheadline4_text')}
501
+ </Text>
502
+ <View style={[styles.switchButton, styles.cardContainer]}>
503
+ <Text style={styles.text}>{I18n.getLang('timeschedule_add_schedule_text2')}</Text>
504
+ <SwitchButton
505
+ value={state.timeSchedule.notification}
506
+ onValueChange={value => {
507
+ state.timeSchedule.notification = value;
508
+ }}
509
+ />
510
+ </View>
511
+ <Spacer />
512
+
513
+ {/* summary */}
514
+ <Summary
515
+ frequency={loopText(state.timeSchedule.loops.split(''), state.timeSchedule.time)}
516
+ time={is24HourClock
517
+ ? state.timeSchedule.time
518
+ : convertTo12HourFormat(state.timeSchedule.time)}
519
+ actions={<View style={{ flex: 1 }}>
520
+ {state.isManual
521
+ ? !!state.selectedSkill.length && (
522
+ <>
523
+ {!!state.selectedSkill.filter(skill => skill.enable).length && (
524
+ <>
525
+ <Text style={{ fontSize: cx(14), color: '#000' }}>
526
+ {I18n.getLang('feature_summary_action_txt_1')}
527
+ </Text>
528
+ <View style={{ flexDirection: 'row', flexWrap: 'wrap' }}>
529
+ {state.selectedSkill
530
+ .filter(skill => skill.enable)
531
+ .map(item => (
532
+ <View
533
+ style={[
534
+ styles.summaryRight,
535
+ { marginRight: cx(5), marginBottom: cx(5) },
536
+ ]}
537
+ key={item.dp}
538
+ >
539
+ <Text style={[styles.rightItem]}>{item.key}</Text>
540
+ </View>
541
+ ))}
542
+ </View>
543
+ </>
544
+ )}
545
+
546
+ {!!state.selectedSkill.filter(skill => !skill.enable).length && (
547
+ <>
548
+ <Text style={{ fontSize: cx(14) }}>
549
+ {I18n.getLang('feature_summary_action_txt_2')}
550
+ </Text>
551
+ <View style={{ flexDirection: 'row', flexWrap: 'wrap' }}>
552
+ {state.selectedSkill
553
+ .filter(skill => !skill.enable)
554
+ .map((item) => (
555
+ <View
556
+ style={[
557
+ styles.summaryRight,
558
+ { marginRight: cx(5), marginBottom: cx(5) },
559
+ ]}
560
+ key={item.dp}
561
+ >
562
+ <Text style={[styles.rightItem]}>{item.key}</Text>
563
+ </View>
564
+ ))}
565
+ </View>
566
+ </>
567
+ )}
568
+ </>
569
+ )
570
+ : !!state.moodName && (
571
+ <View style={{ flexDirection: 'row', flexWrap: 'wrap' }}>
572
+ <View style={[styles.summaryRight, { marginLeft: cx(5) }]}>
573
+ <Text style={styles.rightItem}>{state.moodName}</Text>
574
+ </View>
575
+ </View>
576
+ )}
577
+ </View>}
578
+ />
579
+ <Spacer height={cx(30)} />
580
+
581
+ {/* delete */}
582
+ {params.mode === 'update' && (
583
+ <View style={{ marginHorizontal: cx(24) }}>
584
+ <DeleteButton
585
+ text={I18n.getLang('edit_timeschedule_bttn_text')}
586
+ onPress={() => {
587
+ showDialog({
588
+ method: 'confirm',
589
+ title: I18n.getLang('cancel_dialog_delete_item_timeschedule_titel'),
590
+ subTitle: I18n.getLang('cancel_dialog_delete_item_timeschedule_description'),
591
+ onConfirm: async (_, { close }) => {
592
+ state.loading = true;
593
+ close();
594
+ const res = await params.modDeleteTimeSchedule('delete', state.timeSchedule);
595
+ state.loading = false;
596
+ if (res.success) {
597
+ navigation.goBack();
598
+ }
599
+ },
600
+ });
601
+ }}
602
+ />
603
+ <Spacer />
604
+ </View>
605
+ )}
606
+ </ScrollView>
607
+ </Page>
608
+ );
609
+ };
610
+
611
+ const newTimeSchedule = () => {
612
+ return {
613
+ enable: true,
614
+ loops: '0000000',
615
+ notification: false,
616
+ name: '',
617
+ time: `${toFixedString(new Date().getHours(), 2)}:${toFixedString(new Date().getMinutes(), 2)}`,
618
+ dps: {},
619
+ id: -1,
620
+ };
621
+ };
622
+
623
+ const getDefaultManual = (props: TimeScheduleDetailPageParams): ComponentConfig => {
624
+ const deviceType =
625
+ props.isStripLight || props.isCeilingLight
626
+ ? DeviceType.StripLight
627
+ : props.isMixLight
628
+ ? DeviceType.MixLight
629
+ : props.isPowerStrip
630
+ ? DeviceType.PowerStrip
631
+ : DeviceType.LightSource;
632
+ const deviceData =
633
+ deviceType === DeviceType.StripLight
634
+ ? defStripDeviceData
635
+ : deviceType === DeviceType.MixLight
636
+ ? defMixDeviceData
637
+ : defDeviceData;
638
+ // @ts-ignore
639
+ return {
640
+ type: deviceType,
641
+ deviceData: {
642
+ ...deviceData,
643
+ isColorMode: props.isSupportColor,
644
+ },
645
+ };
646
+ };
647
+
648
+ export default withTheme(TimeScheduleDetailPage)