@olea-bps/base 1.0.0

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 (268) hide show
  1. package/components/AppBar/index.js +84 -0
  2. package/components/AppBar/styles.js +27 -0
  3. package/components/BookDetail/index.js +268 -0
  4. package/components/BookDetail/styles.js +124 -0
  5. package/components/ComponentJobsFilter/index.js +188 -0
  6. package/components/ComponentJobsFilter/styles.js +12 -0
  7. package/components/ConnectivityWarning/index.js +65 -0
  8. package/components/ConnectivityWarning/styles.js +19 -0
  9. package/components/ContactDetail/index.js +232 -0
  10. package/components/ContactDetail/styles.js +32 -0
  11. package/components/CourseDetail/index.js +357 -0
  12. package/components/CourseDetail/styles.js +59 -0
  13. package/components/CourseDetailDialog/index.js +169 -0
  14. package/components/CourseDetailDialog/styles.js +116 -0
  15. package/components/CourseInfo/index.js +219 -0
  16. package/components/CourseInfo/styles.js +40 -0
  17. package/components/DevelopmentDialog/index.js +214 -0
  18. package/components/DevelopmentDialog/styles.js +10 -0
  19. package/components/EventCodeInput/index.js +149 -0
  20. package/components/EventCodeInput/styles.js +108 -0
  21. package/components/FlexMenuEntry/index.js +84 -0
  22. package/components/FlexMenuEntry/styles.js +27 -0
  23. package/components/MainMenuEntry/index.js +88 -0
  24. package/components/MainMenuEntry/styles.js +28 -0
  25. package/components/MealItem/index.js +87 -0
  26. package/components/MealItem/styles.js +84 -0
  27. package/components/MensaMenu/index.js +305 -0
  28. package/components/MensaMenu/styles.js +94 -0
  29. package/components/MensaSlider/index.js +188 -0
  30. package/components/MensaSlider/styles.js +53 -0
  31. package/components/Modal/index.js +106 -0
  32. package/components/Modal/styles.js +8 -0
  33. package/components/NewsDetail/index.js +377 -0
  34. package/components/NewsDetail/styles.js +77 -0
  35. package/components/NewsList/index.js +120 -0
  36. package/components/NewsList/styles.js +19 -0
  37. package/components/NewsListItem/index.js +89 -0
  38. package/components/NewsListItem/styles.js +32 -0
  39. package/components/OtherCourses/index.js +152 -0
  40. package/components/OtherCourses/styles.js +10 -0
  41. package/components/PtsDeparture/index.js +140 -0
  42. package/components/PtsDeparture/styles.js +7 -0
  43. package/components/PtsStation/index.js +186 -0
  44. package/components/PtsStation/styles.js +47 -0
  45. package/components/QuickLinks/index.js +127 -0
  46. package/components/QuickLinks/styles.js +45 -0
  47. package/components/RoomDetail/index.js +281 -0
  48. package/components/RoomDetail/styles.js +56 -0
  49. package/components/ScaledImage/index.js +92 -0
  50. package/components/SearchResults/index.js +362 -0
  51. package/components/SearchResults/styles.js +59 -0
  52. package/components/SettingSection/index.js +54 -0
  53. package/components/SettingSection/styles.js +15 -0
  54. package/components/SettingsDialog/index.js +52 -0
  55. package/components/SettingsDialog/styles.js +12 -0
  56. package/components/SettingsDialogRadio/index.js +66 -0
  57. package/components/SettingsDialogRadio/styles.js +7 -0
  58. package/components/SettingsDialogSelect/index.js +73 -0
  59. package/components/SettingsDialogSelect/styles.js +7 -0
  60. package/components/TimetableCodeInput/index.js +205 -0
  61. package/components/TimetableCodeInput/styles.js +28 -0
  62. package/components/TimetableDay/index.js +252 -0
  63. package/components/TimetableDay/styles.js +103 -0
  64. package/components/TimetableEvent/index.js +163 -0
  65. package/components/TimetableEvent/styles.js +108 -0
  66. package/components/TimetableList/index.js +180 -0
  67. package/components/TimetableList/styles.js +106 -0
  68. package/components/TimetableMonth/index.js +156 -0
  69. package/components/TimetableMonth/styles.js +29 -0
  70. package/components/TimetableWeek/index.js +230 -0
  71. package/components/TimetableWeek/styles.js +58 -0
  72. package/components/TopNews/index.js +282 -0
  73. package/components/TopNews/styles.js +125 -0
  74. package/components/TopNewsHtwk/index.js +279 -0
  75. package/components/TopNewsHtwk/styles.js +142 -0
  76. package/components/WebView/index.js +108 -0
  77. package/components/WebView/styles.js +11 -0
  78. package/context/context-callmanager/TucCallManager.js +74 -0
  79. package/context/context-callmanager/index.js +128 -0
  80. package/context/context-canteen/AsistServerApiProvider.js +126 -0
  81. package/context/context-canteen/CollektorVersion2ApiProvider.js +100 -0
  82. package/context/context-canteen/index.js +692 -0
  83. package/context/context-connectivity/index.js +85 -0
  84. package/context/context-event/AsistServerClient.js +82 -0
  85. package/context/context-event/index.js +205 -0
  86. package/context/context-flex-menu/AsistServerApiProvider.js +0 -0
  87. package/context/context-flex-menu/CollectorVersion2ApiProvider.js +32 -0
  88. package/context/context-flex-menu/index.js +160 -0
  89. package/context/context-info-dialog/CollektorVersion2ApiProvider.js +53 -0
  90. package/context/context-info-dialog/ProviderErrors.js +22 -0
  91. package/context/context-info-dialog/index.js +190 -0
  92. package/context/context-mails/MailService.js +147 -0
  93. package/context/context-mails/TucUnseenApiProvider.js +65 -0
  94. package/context/context-mails/index.js +131 -0
  95. package/context/context-news/CollektorVersion2ApiProvider.js +68 -0
  96. package/context/context-news/index.js +155 -0
  97. package/context/context-public-transport-ticket/CollektorVersion2ApiProvider.js +45 -0
  98. package/context/context-public-transport-ticket/ProviderErrors.js +11 -0
  99. package/context/context-public-transport-ticket/index.js +175 -0
  100. package/context/context-timetable/CollectorVersion2ApiProvider.js +102 -0
  101. package/context/context-timetable/ProviderErrors.js +22 -0
  102. package/context/context-timetable/TimetableService.js +357 -0
  103. package/context/context-timetable/index.js +215 -0
  104. package/context/context-user/index.js +586 -0
  105. package/index.js +178 -0
  106. package/libraries/base-api-provider/hooks.js +24 -0
  107. package/libraries/base-api-provider/http-api-provider.js +168 -0
  108. package/libraries/base-api-provider/index.js +20 -0
  109. package/libraries/core/api/canteens.js +88 -0
  110. package/libraries/core/api/corona.js +45 -0
  111. package/libraries/core/api/courses.js +54 -0
  112. package/libraries/core/api/device.js +98 -0
  113. package/libraries/core/api/feed.js +144 -0
  114. package/libraries/core/api/feedback.js +123 -0
  115. package/libraries/core/api/jobs.js +48 -0
  116. package/libraries/core/api/library.js +67 -0
  117. package/libraries/core/api/lostfound.js +77 -0
  118. package/libraries/core/api/occupancy.js +44 -0
  119. package/libraries/core/api/officehours.js +25 -0
  120. package/libraries/core/api/poi.js +25 -0
  121. package/libraries/core/api/pts.js +68 -0
  122. package/libraries/core/api/rooms.js +31 -0
  123. package/libraries/core/api/survey.js +121 -0
  124. package/libraries/core/api/telephone.js +32 -0
  125. package/libraries/core/api/tucrooms.js +31 -0
  126. package/libraries/core/constants/actions.js +75 -0
  127. package/libraries/core/constants/api.js +146 -0
  128. package/libraries/core/constants/enums.js +5 -0
  129. package/libraries/core/helper/date.js +9 -0
  130. package/libraries/core/helper/format.helper.js +2 -0
  131. package/libraries/core/index.js +60 -0
  132. package/libraries/core/redux/actions/notifications.js +6 -0
  133. package/libraries/core/redux/actions/setting.js +75 -0
  134. package/libraries/core/redux/actions/state.js +74 -0
  135. package/libraries/core/redux/asyncDispatch.js +27 -0
  136. package/libraries/core/redux/reducers/api.js +190 -0
  137. package/libraries/core/redux/reducers/index.js +32 -0
  138. package/libraries/core/redux/reducers/notifications.js +16 -0
  139. package/libraries/core/redux/reducers/setting.js +99 -0
  140. package/libraries/core/redux/reducers/state.js +122 -0
  141. package/libraries/core/redux/selectors.js +123 -0
  142. package/libraries/core/redux/store.js +40 -0
  143. package/libraries/core/services/data.js +96 -0
  144. package/libraries/core/services/root-navigation.js +36 -0
  145. package/libraries/core/services/search.js +175 -0
  146. package/libraries/core-plugins/enums/replaceTypes.js +53 -0
  147. package/libraries/core-plugins/index.js +21 -0
  148. package/libraries/core-plugins/redux/actions/plugin.js +13 -0
  149. package/libraries/core-plugins/redux/reducers/plugin.js +210 -0
  150. package/libraries/icons-openasist/index.js +143 -0
  151. package/libraries/notifications/index.js +268 -0
  152. package/libraries/notifications/services/subscriber.service.js +123 -0
  153. package/libraries/react-native-webview-autoheight/README.md +47 -0
  154. package/libraries/react-native-webview-autoheight/index.js +140 -0
  155. package/libraries/react-native-webview-autoheight/package.json +37 -0
  156. package/libraries/react-native-webview-autoheight/utils.js +268 -0
  157. package/libraries/redux-offline/.eslintignore +1 -0
  158. package/libraries/redux-offline/.github/ISSUE_TEMPLATE/redux-offline-core-issues-template.md +25 -0
  159. package/libraries/redux-offline/.prettierrc +6 -0
  160. package/libraries/redux-offline/LICENSE +21 -0
  161. package/libraries/redux-offline/README.md +133 -0
  162. package/libraries/redux-offline/flow-typed/npm/redux-logger_vx.x.x.js +109 -0
  163. package/libraries/redux-offline/flow-typed/npm/redux_v4.x.x.js +100 -0
  164. package/libraries/redux-offline/lib/actions.js +46 -0
  165. package/libraries/redux-offline/lib/config.js +15 -0
  166. package/libraries/redux-offline/lib/constants.js +17 -0
  167. package/libraries/redux-offline/lib/defaults/defaultCommit.js +11 -0
  168. package/libraries/redux-offline/lib/defaults/defaultRollback.js +11 -0
  169. package/libraries/redux-offline/lib/defaults/detectNetwork.js +33 -0
  170. package/libraries/redux-offline/lib/defaults/detectNetwork.native.js +211 -0
  171. package/libraries/redux-offline/lib/defaults/discard.js +18 -0
  172. package/libraries/redux-offline/lib/defaults/effect.js +87 -0
  173. package/libraries/redux-offline/lib/defaults/index.js +32 -0
  174. package/libraries/redux-offline/lib/defaults/offlineStateLens.js +24 -0
  175. package/libraries/redux-offline/lib/defaults/persist.js +9 -0
  176. package/libraries/redux-offline/lib/defaults/persist.native.js +17 -0
  177. package/libraries/redux-offline/lib/defaults/persistAutoRehydrate.js +8 -0
  178. package/libraries/redux-offline/lib/defaults/queue.js +27 -0
  179. package/libraries/redux-offline/lib/defaults/retry.js +29 -0
  180. package/libraries/redux-offline/lib/index.js +115 -0
  181. package/libraries/redux-offline/lib/middleware.js +56 -0
  182. package/libraries/redux-offline/lib/offlineActionTracker.js +43 -0
  183. package/libraries/redux-offline/lib/send.js +112 -0
  184. package/libraries/redux-offline/lib/types.js +3 -0
  185. package/libraries/redux-offline/lib/updater.js +111 -0
  186. package/libraries/redux-offline/package.json +69 -0
  187. package/libraries/redux-offline/src/__tests__/defaults/discard.js +22 -0
  188. package/libraries/redux-offline/src/__tests__/defaults/effect.js +118 -0
  189. package/libraries/redux-offline/src/__tests__/index.js +116 -0
  190. package/libraries/redux-offline/src/__tests__/middleware.js +185 -0
  191. package/libraries/redux-offline/src/__tests__/offlineActionTracker.js +54 -0
  192. package/libraries/redux-offline/src/__tests__/send.js +208 -0
  193. package/libraries/redux-offline/src/actions.js +36 -0
  194. package/libraries/redux-offline/src/config.js +9 -0
  195. package/libraries/redux-offline/src/constants.js +18 -0
  196. package/libraries/redux-offline/src/defaults/defaultCommit.js +7 -0
  197. package/libraries/redux-offline/src/defaults/defaultRollback.js +7 -0
  198. package/libraries/redux-offline/src/defaults/detectNetwork.js +16 -0
  199. package/libraries/redux-offline/src/defaults/detectNetwork.native.js +148 -0
  200. package/libraries/redux-offline/src/defaults/discard.js +19 -0
  201. package/libraries/redux-offline/src/defaults/effect.js +86 -0
  202. package/libraries/redux-offline/src/defaults/index.js +25 -0
  203. package/libraries/redux-offline/src/defaults/offlineStateLens.js +11 -0
  204. package/libraries/redux-offline/src/defaults/persist.js +4 -0
  205. package/libraries/redux-offline/src/defaults/persist.native.js +9 -0
  206. package/libraries/redux-offline/src/defaults/persistAutoRehydrate.js +4 -0
  207. package/libraries/redux-offline/src/defaults/queue.js +20 -0
  208. package/libraries/redux-offline/src/defaults/retry.js +18 -0
  209. package/libraries/redux-offline/src/index.js +138 -0
  210. package/libraries/redux-offline/src/middleware.js +52 -0
  211. package/libraries/redux-offline/src/offlineActionTracker.js +40 -0
  212. package/libraries/redux-offline/src/send.js +111 -0
  213. package/libraries/redux-offline/src/types.js +127 -0
  214. package/libraries/redux-offline/src/updater.js +141 -0
  215. package/libraries/redux-offline/typings.d.ts +150 -0
  216. package/libraries/redux-offline/yarn.lock +6460 -0
  217. package/libraries/stored-state/index.js +155 -0
  218. package/package.json +68 -0
  219. package/views/Callmanager/index.js +148 -0
  220. package/views/Callmanager/styles.js +62 -0
  221. package/views/Canteens/index.js +383 -0
  222. package/views/Canteens/styles.js +89 -0
  223. package/views/Dashboard/index.js +176 -0
  224. package/views/Dashboard/styles.js +16 -0
  225. package/views/DashboardHtwk/index.js +197 -0
  226. package/views/DashboardHtwk/styles.js +24 -0
  227. package/views/Event/index.js +373 -0
  228. package/views/Event/styles.js +63 -0
  229. package/views/FeedList/index.js +165 -0
  230. package/views/FeedList/styles.js +15 -0
  231. package/views/FeedNews/index.js +243 -0
  232. package/views/FeedNews/styles.js +32 -0
  233. package/views/Flexmenu/index.js +185 -0
  234. package/views/Flexmenu/styles.js +62 -0
  235. package/views/FlexmenuWebview/index.js +167 -0
  236. package/views/FlexmenuWebview/styles.js +16 -0
  237. package/views/Howhy/index.js +151 -0
  238. package/views/Howhy/styles.js +11 -0
  239. package/views/Jobs/index.js +217 -0
  240. package/views/Jobs/styles.js +41 -0
  241. package/views/MainMenu/index.js +283 -0
  242. package/views/MainMenu/styles.js +36 -0
  243. package/views/NewsTabbar/index.js +164 -0
  244. package/views/NewsTabbar/styles.js +27 -0
  245. package/views/Opal/index.js +136 -0
  246. package/views/Opal/styles.js +11 -0
  247. package/views/PublicTransportTicket/index.js +173 -0
  248. package/views/PublicTransportTicket/styles.js +17 -0
  249. package/views/Search/index.js +186 -0
  250. package/views/Search/styles.js +67 -0
  251. package/views/SettingsAccessibility/index.js +148 -0
  252. package/views/SettingsAccessibility/styles.js +13 -0
  253. package/views/SettingsAppInfo/index.js +86 -0
  254. package/views/SettingsAppInfo/styles.js +18 -0
  255. package/views/SettingsCanteens/index.js +249 -0
  256. package/views/SettingsCanteens/styles.js +33 -0
  257. package/views/SettingsGeneral/index.js +173 -0
  258. package/views/SettingsGeneral/styles.js +28 -0
  259. package/views/SettingsNotifications/index.js +204 -0
  260. package/views/SettingsNotifications/styles.js +38 -0
  261. package/views/SettingsUser/index.js +170 -0
  262. package/views/SettingsUser/styles.js +17 -0
  263. package/views/TimetableCalendar/index.js +387 -0
  264. package/views/TimetableCalendar/styles.js +121 -0
  265. package/views/TimetableList/index.js +402 -0
  266. package/views/TimetableList/styles.js +55 -0
  267. package/views/Webviews/index.js +158 -0
  268. package/views/Webviews/styles.js +11 -0
@@ -0,0 +1,692 @@
1
+ /**
2
+ * Licensed under the Apache License, Version 2.0 (the "License");
3
+ * you may not use this file except in compliance with the License.
4
+ * You may obtain a copy of the License at
5
+ *
6
+ * http://www.apache.org/licenses/LICENSE-2.0
7
+ *
8
+ * Unless required by applicable law or agreed to in writing, software
9
+ * distributed under the License is distributed on an "AS IS" BASIS,
10
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ * See the License for the specific language governing permissions and
12
+ * limitations under the License.
13
+ */
14
+
15
+ import { createContext, useCallback, useEffect, useContext, useReducer, useMemo } from 'react'
16
+ import { connect, useDispatch, useSelector } from 'react-redux'
17
+ import { useTheme } from 'react-native-paper';
18
+ import AsyncStorage from '@react-native-async-storage/async-storage'
19
+ import { DateTime } from 'luxon';
20
+
21
+ import { onSettingCanteenMerge, useStagingServer } from '../../libraries/core';
22
+ import { useUser } from '../context-user';
23
+ import { intersection } from 'lodash';
24
+
25
+ import CollektorVersion2ApiProvider, { NotModifiedResponse } from './CollektorVersion2ApiProvider.js';
26
+ import AsistServerApiProvider from './AsistServerApiProvider.js';
27
+
28
+ /**
29
+ * @typedef {Object} Canteen
30
+ * @property {string} id ID der Mensa
31
+ */
32
+
33
+ /**
34
+ * @typedef {Object.<string, Canteen>} CanteenState
35
+ */
36
+
37
+ const AsistServerProviderName = 'asist-server';
38
+ const CollectorVersion2ProviderName = 'hs-collector-v2';
39
+
40
+ // Create a context for the canteen data
41
+ const CanteenContext = createContext({
42
+ canteens: {},
43
+ });
44
+
45
+ const CanteensStoreKey = 'canteen:canteens';
46
+ const FavoriteCanteensStoreKey = 'canteen:favorite_canteens'
47
+
48
+ const RestoreCanteens = 'restore_canteens';
49
+ const SetMenuAction = 'set_menu';
50
+ const SetCanteenAction = 'set_canteen';
51
+ const RemoveUnusedCanteensAction = 'remove_unused_canteens'
52
+ const RemoveUnusedMenusAction = 'remove_unused_menus'
53
+
54
+ /**
55
+ *
56
+ * @param {CanteenState} state
57
+ * @param {Object} action
58
+ * @param {string} action.type
59
+ * @returns {CanteenState}
60
+ */
61
+ function CanteensStateReducer(state, action) {
62
+ switch (action.type) {
63
+
64
+ // Essensangebot einer Mensa zuordnen
65
+ case SetMenuAction: {
66
+ const canteenId = action.canteenId;
67
+ const menuDate = action.date;
68
+ const menu = action.menu;
69
+
70
+ // Einfügen des Essensangebot(menu) für eine Mensa(canteenId) an einem Tag(menuDate)
71
+ return {
72
+ // Kopieren der vorherigen Mensen
73
+ ...state ?? {},
74
+ //Mense mit id(canteenId) neu erstellen
75
+ [canteenId]: {
76
+ // Kopieren der vorherigen Daten der Mense
77
+ ...state?.[canteenId] ?? {},
78
+ // Essensangebote werden neu erstellt
79
+ menus: {
80
+ // Kopieren der alten Essensangebote
81
+ ...state?.[canteenId]?.menus ?? {},
82
+ // Es wird das Essensangebote(menu) für ein Datum(menuDate) hinterlegt
83
+ [menuDate]: menu,
84
+ }
85
+ }
86
+ };
87
+ }
88
+
89
+ // Anhand eines Datums werden alte Mensen entfernt
90
+ case RemoveUnusedMenusAction: {
91
+ const expiryDate = action.expiryDate;
92
+ const expiryTimestamp = Date.parse(expiryDate);
93
+
94
+ return Object.fromEntries(
95
+ Object.entries(state ?? {})
96
+ .map(
97
+ ([canteenId, canteenData]) =>
98
+ [
99
+ canteenId,
100
+ {
101
+ ...canteenData,
102
+ menus: Object.fromEntries(
103
+ Object.entries(canteenData?.menus ?? {})
104
+ .filter(([menuDate, menu]) => Date.parse(menuDate) >= expiryTimestamp)
105
+ )
106
+ }
107
+ ]
108
+ )
109
+ );
110
+ }
111
+
112
+ // Es werden die Basisdaten einer Mensa hinzugefügt oder aktualisiert
113
+ case SetCanteenAction: {
114
+ const canteen = action.canteen;
115
+
116
+ return {
117
+ ...state ?? {},
118
+ [canteen.id]: {
119
+ ...state?.[canteen.id] ?? {},
120
+ ...canteen,
121
+ }
122
+ };
123
+ }
124
+
125
+ // Anhand einer Liste von Mensa-IDs werden alte Mensen entfernt
126
+ case RemoveUnusedCanteensAction: {
127
+ const activeCanteenIds = action.activeCanteenIds;
128
+
129
+ return Object.fromEntries(
130
+ Object.entries(state ?? {})
131
+ .filter(([canteenId, canteenData]) => activeCanteenIds.includes(canteenId))
132
+ );
133
+ }
134
+
135
+ // Mensen und zugehörige Essensangebote aus dem Cache wiederherstellen
136
+ case RestoreCanteens: {
137
+ const restoredCanteens = action.canteens;
138
+
139
+ return state
140
+ ? { ...state }
141
+ : restoredCanteens;
142
+ }
143
+ }
144
+ }
145
+
146
+ const SetCanteensAction = 'set_canteens_ids';
147
+
148
+ /**
149
+ *
150
+ * @param {string[]} state
151
+ * @param {Object} action
152
+ * @param {string} action.type
153
+ * @returns {string[]}
154
+ */
155
+ function FavoriteCanteensStateReducer(state, action) {
156
+ switch (action.type) {
157
+
158
+ // Setzen der IDs der favoriten Mensen
159
+ case SetCanteensAction: {
160
+ const canteensIds = action?.canteensIds;
161
+
162
+ return canteensIds;
163
+ }
164
+
165
+ // Filtert IDs aus der Einstellung heraus, welche nicht mehr vom Kollektor übersendet werden
166
+ case RemoveUnusedCanteensAction: {
167
+ const activeCanteenIds = action?.activeCanteenIds;
168
+
169
+ const favoriteCanteensIds = intersection(state, activeCanteenIds);
170
+
171
+ return Array.isArray(favoriteCanteensIds) && favoriteCanteensIds.length > 0
172
+ ? favoriteCanteensIds
173
+ : null;
174
+ }
175
+
176
+ // Falls ein unbekannter Actionstyp übergeben wurde, wird nichts gemacht
177
+ default: {
178
+ return state;
179
+ }
180
+ }
181
+ }
182
+
183
+ //const providersInitializers = {
184
+ // 'hs-collector-v2': ({appSettings }) => {
185
+ // const baseUrl = appSettings?.modules?.canteen?.api?.baseUrl;
186
+ // CollektorVersion2ApiProvider.from(baseUrl,)
187
+ // },
188
+ // 'asist-server': ({ }) => {
189
+ //
190
+ // },
191
+ //}
192
+
193
+ // Define a provider component for the canteen context
194
+ function CanteenContextProvider({ children, settings, rootUrl, rootStgUrl, useStaging }) {
195
+ const componentName = CanteenContextProvider.name;
196
+
197
+ const reduxDispatch = useDispatch();
198
+ const [user] = useUser();
199
+ const theme = useTheme();
200
+
201
+ const appSettings = theme?.appSettings;
202
+ const groupsOfPersons = appSettings?.groupsOfPersons;
203
+ const language = settings.language;
204
+ const availableSelections = theme?.appSettings?.mealSelections;
205
+ const favoriteSelections = settings?.settingsCanteens?.favoriteSelection;
206
+
207
+ // Ermitteln des Preisgruppen-Codes des Nutzers
208
+ const priceGroupCode =
209
+ // Wenn der Nutzer selber eine Preisgruppe festgelegt hast, ist diese im Redux hinterlegt
210
+ // Prüfen ob im Redux eine Preisgruppe hinterlegt ist
211
+ useSelector(
212
+ (reduxState) =>
213
+ // Wenn der Preisgruppen-Code ein leerer String ist, wird stattdessen null zurückgegeben
214
+ reduxState?.settingReducer?.settingsCanteens?.favoritePrice
215
+ ? reduxState?.settingReducer?.settingsCanteens?.favoritePrice
216
+ : null
217
+ )
218
+ // Ist im Redux keine Preisgruppe hinterlegt, wird anhand des angemeldeten Nutzers die Preisgruppe ermittelt
219
+ // Dabei werden die Angehörigkeiten(user.member_types) des Nutzer mit den möglichen Personengruppen-Codes verglichen
220
+ // Ist eine Angehörigkeit, welche einem Code einer Personengruppe gleicht, vorhanden, wird die entsprechende Personengruppe verwendet
221
+ // Besitzt ein Nutzer mehrer Angehörigkeiten (z.B. Student, Mitarbeiter) wird anhand der Reihenfolge der Personengruppen in der Settings.js priorisiert.
222
+ // Dabei besetzt die erste bzw. oberste Personengruppe die höchste Priorität
223
+ ?? groupsOfPersons.find((personGroup) => user?.member_types?.includes?.(personGroup?.code))?.code
224
+ // Wenn der Nutzer nicht eingeloogt ist oder durch den Angehörigkeiten keine Personengruppe ermittelt werden konnt, wird die Standartgruppe ausgewählt
225
+ // Bei der Standartpersonengruppe ist in der Sttings.js das 'default'-Feld auf Wahr/true gesetzt.
226
+ ?? groupsOfPersons.find(personGroup => personGroup?.default)?.code;
227
+
228
+ // Daten für Essenstypen
229
+ const availableMealTypes = theme?.appSettings?.mealTypes;
230
+ const favoriteMealTypes = settings?.settingsCanteens?.favoriteMealTypes;
231
+
232
+ // Einstellung für Serverauswahl
233
+ const isStagingServerActive = useStagingServer();
234
+
235
+ // Einstellungen für Mensa-Modul
236
+ const canteenSettings = appSettings?.modules?.canteen;
237
+
238
+ // Einstellungen für Fallback API-Provider
239
+ const fallbackApiSettings = theme?.appSettings?.api;
240
+ const fallbackApiProvider = AsistServerProviderName;
241
+ const fallbackApiBaseUrl = (isStagingServerActive ? fallbackApiSettings.rootStgUrl : fallbackApiSettings.rootUrl) + 'app/';
242
+ const fallbbackApiUniversity = fallbackApiSettings?.university;
243
+
244
+ // Einstellungen für API-Provider
245
+ const canteenApiSettings = canteenSettings.api;
246
+ // Soll der Staging-Provider verwendet werden?
247
+ const canteenApiProviderSettings = isStagingServerActive
248
+ // Wenn ja, werden die Staging Provider-Einstellungen geladen
249
+ ? canteenApiSettings?.staging
250
+ // Wenn nein, werden die productiven Provider-Einstellungen geladen
251
+ : canteenApiSettings?.production;
252
+ const canteenApiProvider = canteenApiProviderSettings?.provider ?? fallbackApiProvider;
253
+ const canteenApiBaseUrl = canteenApiProviderSettings?.url ?? fallbackApiBaseUrl;
254
+ const canteenApiUniversity = canteenApiProviderSettings?.university ?? fallbbackApiUniversity;
255
+
256
+ const [canteens, dispatchCanteens] = useReducer(CanteensStateReducer, null);
257
+ const [favoriteCanteens, dispatchFavoriteCanteens] = useReducer(FavoriteCanteensStateReducer, null);
258
+
259
+ // Einmaliges Laden der gecachten Mensadaten und der zugehörigen Speisepläne aus dem Cache in den Kontext
260
+ useEffect(
261
+ () => {
262
+ AsyncStorage
263
+ .getItem(CanteensStoreKey)
264
+ .then(storedCanteens => {
265
+ dispatchCanteens({ type: RestoreCanteens, canteens: JSON.parse(storedCanteens) });
266
+ dispatchCanteens({ type: RemoveUnusedMenusAction, expiryDate: DateTime.now().minus({ weeks: 1 }).endOf('week').toISODate() });
267
+ })
268
+ .catch(reason => console.error(componentName, ':', 'can not restore canteens', ':', reason, 'key', ':', CanteensStoreKey));
269
+ }
270
+ , []
271
+ )
272
+
273
+ // Wenn die Mensa-Daten sich ändern, werden diese in den Cache zurückgespeichert
274
+ useEffect(
275
+ () => {
276
+ if (canteens) {
277
+ AsyncStorage
278
+ .setItem(CanteensStoreKey, JSON.stringify(canteens))
279
+ .catch(reason => console.error(componentName, ':', 'can`t store canteens: ', reason, 'key:', CanteensStoreKey, 'value:', canteens));
280
+ }
281
+ }
282
+ , [canteens]
283
+ )
284
+
285
+ // Einmaliges laden der favorisirten Mensen
286
+ useEffect(
287
+ () => {
288
+ AsyncStorage
289
+ .getItem(FavoriteCanteensStoreKey)
290
+ .then(storedFavoriteCanteens => {
291
+ console.debug(componentName, ':', 'restore favorite canteens ids', ':', storedFavoriteCanteens);
292
+ dispatchFavoriteCanteens({ type: SetCanteensAction, canteensIds: JSON.parse(storedFavoriteCanteens) });
293
+ })
294
+ .catch(reason => console.error(componentName, ':', 'can not restore favorite canteens ids', ':', reason, 'key', ':', FavoriteCanteensStoreKey));
295
+ },
296
+ []
297
+ )
298
+
299
+ // Wenn die favorisirten Mensen sich ändern, werden diese in den Cache zurückgespeichert
300
+ useEffect(
301
+ () => {
302
+ if (Array.isArray(favoriteCanteens)) {
303
+ console.debug(componentName, ':', 'store favorite canteens', favoriteCanteens);
304
+ AsyncStorage
305
+ .setItem(FavoriteCanteensStoreKey, JSON.stringify(favoriteCanteens))
306
+ .catch(reason => console.error(componentName, ':', 'can`t store canteens: ', reason, 'key:', FavoriteCanteensStoreKey, 'value:', favoriteCanteens));
307
+ }
308
+ },
309
+ [favoriteCanteens]
310
+ )
311
+
312
+ console.debug(componentName, ':', 'favorite selections', ':', favoriteSelections);
313
+ console.debug(componentName, ':', 'available selections', ':', availableSelections);
314
+
315
+ const activeSelections = useMemo(
316
+ () => {
317
+ if (Array.isArray(favoriteSelections) && favoriteSelections.length > 0 && Array.isArray(availableSelections)) {
318
+ return availableSelections
319
+ .filter(availableSelection => favoriteSelections.includes(availableSelection.code));
320
+ } else {
321
+ return null;
322
+ }
323
+ },
324
+ [favoriteSelections, availableSelections]
325
+ );
326
+
327
+ console.debug(componentName, ':', 'active selections', ':', activeSelections);
328
+
329
+ const activeSelectionFilters = useMemo(
330
+ () => {
331
+ if (Array.isArray(activeSelections) && activeSelections.length > 0) {
332
+ return [
333
+ ...new Set(
334
+ activeSelections
335
+ .flatMap(activeSelection => activeSelection?.filters)
336
+ )
337
+ ];
338
+ } else {
339
+ return null;
340
+ }
341
+ },
342
+ [activeSelections]
343
+ )
344
+
345
+ console.debug(componentName, ':', 'active selection filter', ':', activeSelectionFilters);
346
+
347
+
348
+ console.debug(componentName, ':', 'available meal typeas', ':', availableMealTypes);
349
+ console.debug(componentName, ':', 'favorite meal types', ':', favoriteMealTypes);
350
+
351
+ const activeMealtypes = useMemo(
352
+ () => {
353
+ if (Array.isArray(favoriteMealTypes) && favoriteMealTypes.length > 0 && Array.isArray(availableMealTypes)) {
354
+ return availableMealTypes
355
+ .filter(activeMealtype => favoriteMealTypes.includes(activeMealtype.code));
356
+ }
357
+ else {
358
+ return null;
359
+ }
360
+ },
361
+ [favoriteMealTypes, availableMealTypes]
362
+ )
363
+
364
+ console.debug(componentName, ':', 'active meal types', ':', activeMealtypes);
365
+
366
+ const activeMealtypeFilters = useMemo(
367
+ () => {
368
+ if (Array.isArray(activeMealtypes) && activeMealtypes.length > 0) {
369
+ return [
370
+ ... new Set(
371
+ activeMealtypes
372
+ .flatMap(activeMealtype => activeMealtype?.filters ?? activeMealtype?.code ?? [])
373
+ )
374
+ ];
375
+ } else {
376
+ return null;
377
+ }
378
+ }
379
+ )
380
+
381
+ console.debug(componentName, ':', 'active meal type filters', ':', activeMealtypeFilters);
382
+
383
+ // Estellen des API-Providers bzw. erneuern wenn sich Einstellungen sich ändern.
384
+ const apiProvider = useMemo(
385
+ () => {
386
+ switch (canteenApiProvider?.toLowerCase()) {
387
+ case AsistServerProviderName:
388
+ console.debug(componentName, ': use asist server api');
389
+ return new AsistServerApiProvider.from(canteenApiBaseUrl, canteenApiUniversity, language);
390
+ case CollectorVersion2ProviderName:
391
+ console.debug(componentName, ': use collector v2 api');
392
+ return new CollektorVersion2ApiProvider.from(canteenApiBaseUrl, language);
393
+ default:
394
+ console.log(`${componentName}: Can't build api provider: ${canteenApiProvider}`)
395
+ return null;
396
+ }
397
+ },
398
+ [canteenApiSettings, canteenApiProvider, canteenApiBaseUrl, canteenApiUniversity, language]
399
+ );
400
+
401
+ // Sobald der Mensa-Context erstellt wird, werden die Mensen vom Server geholt
402
+ useEffect(
403
+ () => {
404
+ if (apiProvider) {
405
+ apiProvider.getCanteens()
406
+ .then(
407
+ canteens => {
408
+ // Jede Mensa wird einzeln in den Mensa-State hineinreduziert
409
+ canteens.forEach(canteen => dispatchCanteens({ type: SetCanteenAction, canteen }));
410
+
411
+ // Danach werden die alten Mensen, die nicht in der Serverantwort sind, herausreduziert
412
+ // Liste der IDs der in der Serverantwort enthaltenen Mensen erstellen
413
+ const activeCanteenIds = canteens.map(canteen => canteen?.id);
414
+ // Alte Mensen aus den gecachten Mensa-Daten löschen
415
+ dispatchCanteens(
416
+ {
417
+ type: RemoveUnusedCanteensAction,
418
+ activeCanteenIds: activeCanteenIds,
419
+ }
420
+ );
421
+ // Alte Mensen aus den favorisierten Mensen löschen
422
+ dispatchFavoriteCanteens(
423
+ {
424
+ type: RemoveUnusedCanteensAction,
425
+ activeCanteenIds: activeCanteenIds,
426
+ }
427
+ );
428
+ }
429
+ );
430
+ }
431
+ },
432
+ [apiProvider]
433
+ );
434
+
435
+ /**
436
+ * Refresh a menu in canteens object.
437
+ *
438
+ * @param {String} canteenId ID of the canteen of the menu to be refreshing
439
+ * @param {String} date Date of the menu to be refreshing
440
+ * @returns {Promise<void>} Promise as an indicator of whether the refresh is in progress
441
+ */
442
+ function refreshMenu(canteenId, date) {
443
+ return apiProvider.getMenu(canteenId, date)
444
+ .then(
445
+ menu =>
446
+ dispatchCanteens(
447
+ {
448
+ type: SetMenuAction,
449
+ menu,
450
+ canteenId: canteenId,
451
+ date: date,
452
+ }
453
+ ),
454
+ reason => {
455
+ if (reason instanceof NotModifiedResponse) {
456
+ console.debug(componentName, ':', 'Meal from', date, 'and canteen', canteenId, 'not modified');
457
+ } else {
458
+ throw reason;
459
+ }
460
+ }
461
+ );
462
+ }
463
+
464
+ /**
465
+ * Setz den vom Nutzer gewünschen Mensapreis, anhand des Codes der entsprechnden Personengruppe.
466
+ * @function
467
+ * @param {string} personGroupCode Code der Personengruppe, welche für die Mensapreise zu verwenden ist
468
+ */
469
+ const setPriceGroupCode = useCallback(
470
+ /**
471
+ * @param {string} personGroupCode Code der Personengruppe, welche für die Mensapreise zu verwenden ist
472
+ */
473
+ (personGroupCode) =>
474
+ reduxDispatch(
475
+ onSettingCanteenMerge(
476
+ "canteenSettings",
477
+ { favoritePrice: personGroupCode }
478
+ )
479
+ ),
480
+ [reduxDispatch]
481
+ );
482
+
483
+ /**
484
+ * Setzt die favorsierten Mensen, anhand einer Liste der IDs
485
+ */
486
+ const setFavoriteCanteens = useCallback(
487
+ /**
488
+ * @param {string[]} favoriteCanteens IDs der Mensen, die als favorisiert gesetzt werden sollen
489
+ */
490
+ (favoriteCanteens) => {
491
+ console.debug(componentName, ':', 'set favorite canteens', ':', favoriteCanteens);
492
+ dispatchFavoriteCanteens(
493
+ {
494
+ type: SetCanteensAction,
495
+ canteensIds: favoriteCanteens,
496
+ }
497
+ );
498
+ },
499
+ [dispatchFavoriteCanteens, SetCanteensAction]
500
+ );
501
+
502
+ // Render the provider component with the filtered canteens and canteens data
503
+ return (
504
+ <CanteenContext.Provider
505
+ value={{
506
+ canteens: canteens ?? {},
507
+ favoriteCanteens: favoriteCanteens ?? Object.keys(canteens ?? {}),
508
+ setFavoriteCanteens,
509
+ priceGroupCode,
510
+ setPriceGroupCode,
511
+ activeSelections,
512
+ activeSelectionFilters,
513
+ activeMealtypes,
514
+ activeMealtypeFilters,
515
+ refreshMenu,
516
+ }}
517
+ >
518
+ {children}
519
+ </CanteenContext.Provider>
520
+ );
521
+ }
522
+
523
+ // Map the Redux state to props
524
+ const mapStateToProps = storeState => {
525
+ return {
526
+ settings: storeState.settingReducer,
527
+ rootUrl: storeState.settingReducer.api.rootUrl,
528
+ rootStgUrl: storeState.settingReducer.api.rootStgUrl,
529
+ useStaging: storeState.settingReducer.settingsDevelop.useStaging,
530
+ };
531
+ };
532
+
533
+ // Connect the CanteenContextProvider component to Redux
534
+ const ConnectedCanteenContextProvider = connect(mapStateToProps)(CanteenContextProvider);
535
+
536
+
537
+ // Custom hook to use the CanteenContext
538
+ function useCanteenContext() {
539
+ const context = useContext(CanteenContext);
540
+ if (context === undefined) {
541
+ throw new Error('useCanteenContext must be used within a CanteenContextProvider')
542
+ }
543
+ return context;
544
+ }
545
+
546
+ /**
547
+ * Dieser Hook gibt die Mensen und eine Aktualisierungsfunktion für Tagesangebote zurück.
548
+ * @returns {[?Object, (canteenId: String, menuDate: String) => Promise<void>]} Ein aus 2 Elementen bestehendes Array. Das erste Element ist ein Objekt, welches die Mensen enthält. Das zweite Element ist die Aktualisierungsfunktion.
549
+ * @example
550
+ * [canteens, refreshMenu] = useCanteen();
551
+ * canteen = canteens['1'];
552
+ * menu = canteen.menus['2024-12-31'];
553
+ * meal = menu[0];
554
+ *
555
+ * refreshMenu('1', '2024-12-31');
556
+ */
557
+ function useCanteens() {
558
+ const canteenContext = useCanteenContext();
559
+
560
+ return [canteenContext.canteens ?? null, canteenContext.refreshMenu];
561
+ }
562
+
563
+ /**
564
+ *
565
+ *
566
+ * @param {String} canteenId
567
+ * @returns {[?Object, (menuDate: String) => Promise<void>]}
568
+ */
569
+ function useCanteen(canteenId) {
570
+ const [canteens, refreshMenu] = useCanteens();
571
+
572
+ return [
573
+ canteens?.[canteenId] ?? null, // Holt die Mensa mit der ID canteenId aus dem Mensa-Objekt
574
+ (menuDate) => refreshMenu(canteenId, menuDate), // Erstellt eine Funktion, die das Essen ohne angeben der canteenId aktualisiert
575
+ ];
576
+ }
577
+
578
+ /**
579
+ *
580
+ *
581
+ * @param {String} canteenId
582
+ * @param {String} menuDate
583
+ * @returns {[?Object[], () => Promise<void>]}
584
+ */
585
+ function useMenu(canteenId, menuDate) {
586
+ const [canteen, refreshMenu] = useCanteen(canteenId);
587
+
588
+ return [
589
+ canteen?.menus?.[menuDate] ?? null, // Holt das Essen aus der Mensa mit der ID canteenId
590
+ () => refreshMenu(menuDate), // Erstellt eine Funktion, die das Essen ohne angeben von canteenId und menuDate aktualisiert
591
+ ];
592
+ }
593
+
594
+ /**
595
+ *
596
+ *
597
+ * @param {String} canteenId
598
+ * @param {String} menuDate
599
+ * @returns {[?Object, () => Promise<void>]}
600
+ */
601
+ function useFilteredMenu(canteenId, menuDate) {
602
+ //const hookName = arguments.callee.name;
603
+ //const hookCall = `${hookName}(canteenId: ${canteenId}, menuDate: ${menuDate})`;
604
+
605
+ const {
606
+ activeSelections,
607
+ activeSelectionFilters,
608
+ activeMealtypes,
609
+ activeMealtypeFilters
610
+ } = useCanteenContext();
611
+ const [menu, refreshMenu] = useMenu(canteenId, menuDate);
612
+
613
+ let filteredMenu = menu;
614
+
615
+ if (activeSelectionFilters) {
616
+ filteredMenu = filteredMenu?.filter(
617
+ meal => activeSelectionFilters.every(
618
+ activeSelectionFilter => meal.selections.includes(activeSelectionFilter)
619
+ )
620
+ );
621
+ }
622
+
623
+ if (activeMealtypeFilters) {
624
+ filteredMenu = filteredMenu
625
+ ?.filter(
626
+ meal =>
627
+ meal?.type
628
+ ? activeMealtypeFilters.includes(meal.type)
629
+ : true
630
+ );
631
+ }
632
+
633
+ const mealAmount = menu?.length ?? 0;
634
+ const filteredMealAmount = filteredMenu?.length ?? 0;
635
+
636
+ return [
637
+ filteredMenu,
638
+ refreshMenu,
639
+ mealAmount,
640
+ filteredMealAmount,
641
+ activeSelections,
642
+ activeMealtypes,
643
+ ];
644
+ }
645
+
646
+ /**
647
+ * Gibt ein Array zurück, welches als erstes Element den Coder der aktuellen Preisgruppe für Mensaessen enthält.
648
+ * Als Zweites wird eine Funktion zum setzen der Preisgruppe in dem Rückgabearray gespeichert.
649
+ *
650
+ * Es werden 3 Quellen zum ermitteln der Preisgruppe verwendet.
651
+ * Zuerst wird geprüft, ob der Nutzer selber einen Preis gesetzt hat, dann wird dieser verwendet.
652
+ * Ansonsten wird geprüft, ob ein Nutzer eingeloggt ist und dessen Angehörigkeitsstatus ausgewertet.
653
+ * Treffen diese beiden Fälle nicht zu, wird die als Standartgruppe gesetzte Gruppe verwendet.
654
+ * @returns {[priceGroupCode: string, (priceGroupCode:string) => void ]}
655
+ * @example
656
+ * const [priceGroupCode, setPriceGroupCode] = usePriceGroupCode();
657
+ *
658
+ * console.log(priceGroupCode);
659
+ * setPriceGroupCode('guest');
660
+ */
661
+ function usePriceGroupCode() {
662
+ const { priceGroupCode, setPriceGroupCode } = useCanteenContext();
663
+
664
+ return [priceGroupCode, setPriceGroupCode];
665
+ }
666
+
667
+ /**
668
+ * Gibt die favorisierten Mensen und eine Set-Funktion für diese in einem Array zurück.
669
+ *
670
+ * @returns {[favoriteCanteens: string[], setFavoriteCanteens: (favoriteCanteens: string[]) => void]}
671
+ * @example
672
+ * const [favoriteCanteens, setFavoriteCanteens] = useFavoriteCanteens();
673
+ *
674
+ * setFavoriteCanteens(['canteen1', 'canteen2']);
675
+ */
676
+ function useFavoriteCanteens() {
677
+ const { favoriteCanteens, setFavoriteCanteens } = useCanteenContext();
678
+
679
+ return [favoriteCanteens, setFavoriteCanteens];
680
+ }
681
+
682
+ export {
683
+ ConnectedCanteenContextProvider as CanteenContextProvider,
684
+ CanteenContext as default,
685
+ useCanteenContext,
686
+ useCanteens,
687
+ useCanteen,
688
+ useMenu,
689
+ useFilteredMenu,
690
+ usePriceGroupCode,
691
+ useFavoriteCanteens,
692
+ };