@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,197 @@
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 React from 'react';
16
+ import {
17
+ Animated,
18
+ StyleSheet,
19
+ View,
20
+ RefreshControl,
21
+ SafeAreaView
22
+ } from 'react-native';
23
+ import {connect} from 'react-redux'
24
+ import { withTheme } from "react-native-paper";
25
+ import {withTranslation} from "react-i18next";
26
+
27
+ import merge from 'lodash/merge';
28
+
29
+ import { onUpdateRefreshing, DataService } from '../../libraries/core';
30
+ import TopNewsComponent from '../../components/TopNewsHtwk';
31
+ import MensaSliderComponent from '../../components/MensaSlider';
32
+ import CourseInfoComponent from '../../components/CourseInfo';
33
+ import QuickLinksComponent from '../../components/QuickLinks';
34
+
35
+ import componentStyles from "./styles"
36
+ export const scrollRangeForAnimation = 160;
37
+
38
+
39
+ /**
40
+ * Dashboard View
41
+ *
42
+ * The home screen of the app. Shows different informations like the top news, weather,
43
+ * current mensa menus and informations of the next course (if the student has imported his timtetable)
44
+ *
45
+ * Parameters:
46
+ * - none
47
+ *
48
+ * Navigation-Parameters:
49
+ * - none
50
+ */
51
+ class DashboardView extends React.Component {
52
+ static navigationOptions = {
53
+ header: null
54
+ };
55
+
56
+ // Styles of this component
57
+ styles;
58
+
59
+ dataService = null;
60
+ _scrollView = null;
61
+
62
+
63
+ constructor(props) {
64
+ super(props);
65
+
66
+ // ------------------------------------------------------------------------
67
+ // PLUGIN FUNCTIONALITY
68
+ // ------------------------------------------------------------------------
69
+
70
+ const { pluginStyles,theme } = this.props;
71
+ this.styles = componentStyles(theme);
72
+
73
+ if(pluginStyles) {
74
+ this.styles = merge(this.styles, pluginStyles);
75
+ }
76
+
77
+ this.styles = StyleSheet.create(this.styles);
78
+
79
+ // ------------------------------------------------------------------------
80
+
81
+ this.dataService = new DataService();
82
+ this.props.onUpdateRefreshing(false);
83
+
84
+ this.state = {
85
+ scrollY: new Animated.Value(0)
86
+ };
87
+ }
88
+
89
+ /**
90
+ * User has dragged down the view to update the informations
91
+ *
92
+ * @private
93
+ */
94
+ _onRefresh = () => {
95
+ this.props.onUpdateRefreshing(true);
96
+ this.dataService.refresh();
97
+ };
98
+
99
+ /**
100
+ * User has scrolled down. If the header animation isn't fully finished,
101
+ * scroll up or down (depends on how far the user has scrolled) to finish the animation.
102
+ * This prevents that the top view looks like its stuck.
103
+ *
104
+ * @param event
105
+ *
106
+ * @private
107
+ */
108
+ _onScrollEndSnapToEdge = event => {
109
+ /* TODO Disabled at the moment. On smaller devices the user isn't able to
110
+ use the course component because of the scroll back
111
+
112
+ const y = event.nativeEvent.contentOffset.y;
113
+ if (0 < y && y < this._scrollRangeForAnimation / 2) {
114
+ if (this._scrollView) {
115
+ this._scrollView.scrollTo({y: 0});
116
+ }
117
+ } else if (this._scrollRangeForAnimation / 2 <= y && y < this._scrollRangeForAnimation) {
118
+ if (this._scrollView) {
119
+ this._scrollView.scrollTo({y: this._scrollRangeForAnimation});
120
+ }
121
+ }*/
122
+ };
123
+
124
+ render() {
125
+ // ------------------------------------------------------------------------
126
+ // PLUGIN FUNCTIONALITY
127
+ // ------------------------------------------------------------------------
128
+ const PluginComponent = this.props.pluginComponent;
129
+ if (PluginComponent) {
130
+ return <PluginComponent />;
131
+ }
132
+ // ------------------------------------------------------------------------
133
+
134
+ const { t } = this.props;
135
+ const { themeStyles } = this.props.theme;
136
+
137
+ const scrollY = Animated.add(
138
+ this.state.scrollY,
139
+ 0,
140
+ );
141
+ const headerTranslate = scrollY.interpolate({
142
+ inputRange: [0, scrollRangeForAnimation],
143
+ outputRange: [0, 1],
144
+ extrapolate: 'clamp',
145
+ });
146
+
147
+ return (
148
+ <SafeAreaView style={[this.styles.container, themeStyles.appSafeAreaContainer]}>
149
+ <Animated.ScrollView
150
+ ref={scrollView => {
151
+ this._scrollView = scrollView ? scrollView._component : null;
152
+ }}
153
+ style={this.styles.container}
154
+ contentContainerStyle={this.styles.contentContainer}
155
+ scrollEventThrottle={2}
156
+ onScrollEndDrag={this._onScrollEndSnapToEdge}
157
+ onMomentumScrollEnd={this._onScrollEndSnapToEdge}
158
+ onScroll={Animated.event(
159
+ [
160
+ {
161
+ nativeEvent: {contentOffset: {y: this.state.scrollY}},
162
+ },
163
+ ],
164
+ {
165
+ useNativeDriver: true,
166
+ }
167
+ )}
168
+ refreshControl={
169
+ <RefreshControl
170
+ refreshing={this.props.refreshing}
171
+ onRefresh={this._onRefresh}
172
+ />
173
+ }>
174
+ <View>
175
+ <TopNewsComponent {...this.props} animationRange={headerTranslate}/>
176
+ <QuickLinksComponent {...this.props} />
177
+ <MensaSliderComponent {...this.props} />
178
+ <CourseInfoComponent {...this.props} />
179
+ </View>
180
+ </Animated.ScrollView>
181
+ </SafeAreaView>
182
+ );
183
+ }
184
+ }
185
+
186
+ const mapStateToProps = state => {
187
+ return {
188
+ pluginComponent: state.pluginReducer.dashboard.component,
189
+ pluginStyles: state.pluginReducer.dashboard.styles,
190
+ view : state.stateReducer.view,
191
+ feedItems: state.stateReducer.feedItems,
192
+ feeds: state.stateReducer.feeds,
193
+ refreshing: state.stateReducer.refreshing
194
+ };
195
+ };
196
+
197
+ export default connect(mapStateToProps, {onUpdateRefreshing})(withTranslation()(withTheme(DashboardView)))
@@ -0,0 +1,24 @@
1
+ import {Dimensions} from 'react-native';
2
+
3
+ export default function(theme) {
4
+ const width = Dimensions.get('window').width;
5
+ return {
6
+ container: {
7
+ flex: 1,
8
+ backgroundColor: theme.colors.background,
9
+ },
10
+ contentContainer: {
11
+ paddingTop: 0
12
+ },
13
+ titleStyle: {
14
+ ...theme.fonts.medium,
15
+ fontSize: theme.fontSizes.xxl,
16
+ alignSelf: 'center'
17
+ },
18
+ universityIcon: {
19
+ width: width * .40,
20
+ height: (width * .40) * .5625, // 56.25% = 16:9 Ratio
21
+ margin: theme.paddings.default
22
+ }
23
+ }
24
+ };
@@ -0,0 +1,373 @@
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 { useState, useMemo, useEffect, useCallback } from 'react';
16
+ import {
17
+ ActivityIndicator,
18
+ Dimensions,
19
+ SafeAreaView,
20
+ ScrollView,
21
+ StyleSheet,
22
+ Text,
23
+ View,
24
+ } from 'react-native';
25
+
26
+ import { useTranslation } from 'react-i18next';
27
+ import { Appbar, useTheme } from 'react-native-paper';
28
+ import { AccordionList } from 'accordion-collapse-react-native';
29
+ import { TabView, TabBar, SceneMap } from 'react-native-tab-view';
30
+ import { useNavigation } from '@react-navigation/native';
31
+
32
+ import moment from 'moment';
33
+ import { DateTime } from 'luxon';
34
+
35
+ import EventContextProvider, { usePersonalEvents, usePersonalEventsCode, useEvents } from '../../context/context-event';
36
+ import AppbarComponent from '../../components/AppBar';
37
+ import IconsOpenasist from '../../libraries/icons-openasist';
38
+ import EventCodeInputComponent from '../../components/EventCodeInput';
39
+ import TimetableEventComponent from '../../components/TimetableEvent';
40
+
41
+ import componentStyles from './styles';
42
+
43
+ /**
44
+ * @param {*} allEvents List of events
45
+ * @param {*} start Startingpoint of the timeslot-list/start of the event-day
46
+ * @param {*} end Endpoint of the timeslot-list/end of the event-day
47
+ * @param {*} length length of the single timeslots
48
+ * @returns a list of objects for each timeslot including start(startTs), end(endTs) and a list(events) of events for that timeslot
49
+ * startTs and endTs are moment().js-elements/modified date-time-elements while events will contain the event-objects for this timeslot
50
+ */
51
+ function generateTimeslots(allEvents, start, end, length) {
52
+
53
+ const timeslotList = [];
54
+ /*
55
+ For-Loop that loops from the start to the end in increments provided by length
56
+ So that there are timeslots from the start to the end of the event day
57
+ */
58
+ for (let timeSlot = moment(start); timeSlot.isSameOrBefore(end); timeSlot.add(length, 'hours')) {
59
+ // Define start and end(start + length) for each timeslot
60
+ var timeslotStart = moment(timeSlot);
61
+ var timeslotEnd = moment(timeSlot).add(length, 'hours');
62
+
63
+ /*
64
+ Use the build in filter()-Method to find all events in the given timeslot, so between timeslotStart and timeslotEnd
65
+ The timeslotStart and timeslotEnd are defined in the yyyy-MM-ddTHH:mm:ssZ-format in order to be able to compare them directly to the
66
+ start and end-prop in the event-Objects
67
+ A event will be sorted in the current timeslot, if the value of the start prop is between the start and end of the current timeslot
68
+ This is due to also include events that start in one timeslot and end in another timeslot
69
+ */
70
+ var eventsInTimeslot = allEvents.filter(
71
+ currentEvent =>
72
+ moment(currentEvent.begin).isSameOrAfter(timeslotStart)
73
+ &&
74
+ moment(currentEvent.begin).isBefore(timeslotEnd)
75
+ );
76
+
77
+ // If there are any Event-objects in the given timeslot, the event have to be sorted in the correct order
78
+ if (eventsInTimeslot.length > 0) {
79
+ // After that, push the current timeslot-object into the timeslotList
80
+ timeslotList.push({ startTs: timeslotStart.format('HH:mm'), endTs: timeslotEnd.format('HH:mm'), eventsTs: eventsInTimeslot })
81
+ }
82
+ }
83
+
84
+ return timeslotList;
85
+ }
86
+
87
+ /**
88
+ * Event View
89
+ *
90
+ * Parameters:
91
+ * - none
92
+ *
93
+ * Navigation-Parameters:
94
+ * - none
95
+ */
96
+
97
+ /**
98
+ * Die Funktion erzeugt einen Header für die jeweilige Liste, der eine Kurzbezeichnung und ein Icon zur Identifikation beinhaltet
99
+ *
100
+ * @param {object} props beinhaltet styles, themes und weitere props
101
+ * @param {boolean} props.isExpanded Flag das signalisiert, ob die aktuelle Liste geöffnet ist oder nicht
102
+ * @param {string} props.startTime Startzeit der Liste
103
+ * @param {string} props.endTime Endzeit der Liste
104
+ */
105
+ function TimeslotAccordionHeader({ startTime, endTime, styles, isExpanded }) {
106
+ const { t } = useTranslation();
107
+ const theme = useTheme();
108
+ const { colors, themeStyles } = theme;
109
+
110
+ return (
111
+ <View style={styles.header}>
112
+ <View style={[themeStyles.cardLeftIcon, { marginStart: 5 }]}>
113
+ <IconsOpenasist icon={('info')} size={25} color={colors.icon} />
114
+ </View>
115
+ <Text style={styles.headerText}>{`${startTime} ${t('event:type.to')} ${endTime} ${t('event:type.oclock')}`}</Text>
116
+ <View style={styles.arrowIcon}>
117
+ <IconsOpenasist icon={isExpanded ? 'up' : 'down'} size={20} color={colors.grayLight5} />
118
+ </View>
119
+ </View>
120
+ );
121
+ }
122
+
123
+ /**
124
+ * @param {object} props beinhaltet styles, themes und weitere props
125
+ * @param {Array} props.items Die Liste von Events vom aktuellen Tab
126
+ * @return eine Scrollview, welche eine Liste von TimeTableEventComponent enthält
127
+ */
128
+ function EventList({ items: events = [], styles }) {
129
+ const { t } = useTranslation();
130
+
131
+ return (
132
+ <ScrollView>
133
+ {
134
+ events
135
+ ?.map(
136
+ (event) => {
137
+ const startTime = DateTime.fromISO(event.begin).toLocaleString(DateTime.TIME_24_SIMPLE);
138
+ const endTime = DateTime.fromISO(event.end).toLocaleString(DateTime.TIME_24_SIMPLE);
139
+
140
+ return (
141
+ <TimetableEventComponent
142
+ key={event.id}
143
+ type={event?.type ? t(`event:type:${event.type}`) : null}
144
+ title={event?.title}
145
+ location={event?.location}
146
+ locationUrl={event?.locationUrl}
147
+ description={event?.description}
148
+ times={{ start: startTime, end: endTime }} />
149
+ );
150
+ }
151
+ )
152
+ ?? null
153
+ }
154
+ </ScrollView>
155
+ );
156
+ }
157
+
158
+ /***
159
+ * Hook-Component welche eine Accordionliste mit dem entsprechenden Inhalt generiert. Inklusive Header.
160
+ *
161
+ * @param props beinhaltet styles, themes und weitere props
162
+ */
163
+ function EventTimeslotList() {
164
+ const componentName = EventTimeslotList.name;
165
+ const theme = useTheme();
166
+ const [events, refreshEvents] = useEvents();
167
+
168
+ const styles = useMemo(
169
+ () => StyleSheet.create(componentStyles(theme)),
170
+ [theme, componentStyles]
171
+ );
172
+
173
+ const timeslots = useMemo(
174
+ () => {
175
+ if (Array.isArray(events) && events.length > 0) {
176
+ // get the value of the start-prop of the earliest-event
177
+ const earliestEvent = events.reduce((previousEvent, currentEvent) => { return currentEvent.begin < previousEvent.begin ? currentEvent : previousEvent });
178
+ // get the value of the end-prop of the latest-event
179
+ const latestEvent = events.reduce((previousEvent, currentEvent) => { return currentEvent.end > previousEvent.end ? currentEvent : previousEvent });
180
+ return generateTimeslots(events, earliestEvent.begin, latestEvent.end, 1.5);
181
+
182
+ } else if (Array.isArray(events) && events.length === 0) {
183
+ return [];
184
+
185
+ } else {
186
+ console.debug(componentName, ':', 'No events to Generate timeslots');
187
+ return null;
188
+ }
189
+ },
190
+ [events, generateTimeslots]
191
+ );
192
+
193
+ useEffect(
194
+ () => {
195
+ refreshEvents();
196
+ },
197
+ [refreshEvents]
198
+ );
199
+
200
+ return Array.isArray(timeslots)
201
+ ? timeslots.length > 0
202
+ ? <AccordionList
203
+ list={timeslots}
204
+ header={
205
+ (timeslot, index, isExpanded) => <TimeslotAccordionHeader startTime={timeslot.startTs} endTime={timeslot.endTs} styles={styles} isExpanded={isExpanded} />
206
+ }
207
+ body={
208
+ (timeslot) => <EventList items={timeslot.eventsTs} styles={styles} />
209
+ }
210
+ />
211
+ : <View style={styles.content}>
212
+ <Text>
213
+ Es werden gerade keine Veranstalltungen angeboten
214
+ </Text>
215
+ </View>
216
+ : <View style={styles.content}>
217
+ <Text>{t('canteen:notAvailable')}</Text>
218
+ <ActivityIndicator style={styles.activity} size='large' color={theme.colors.loadingIndicator} />
219
+ </View>
220
+
221
+ }
222
+
223
+ function SelectedEventList() {
224
+ const componentName = SelectedEventList.name;
225
+ const theme = useTheme();
226
+
227
+ const [personalEvents, refreshPersonalEvents] = usePersonalEvents();
228
+
229
+ const styles = useMemo(
230
+ () => StyleSheet.create(componentStyles(theme)),
231
+ [theme, componentStyles]
232
+ );
233
+
234
+ useEffect(
235
+ () => {
236
+ refreshPersonalEvents();
237
+ },
238
+ [refreshPersonalEvents]
239
+ )
240
+
241
+ return (
242
+ <EventList
243
+ styles={styles}
244
+ items={personalEvents}
245
+ />
246
+ )
247
+ }
248
+
249
+ const TabViewScenes = SceneMap({
250
+ all_events: EventTimeslotList,
251
+ personal_events: SelectedEventList,
252
+ });
253
+
254
+
255
+ export default function EventsView(props) {
256
+
257
+ const [personalEventsCode] = usePersonalEventsCode();
258
+ const theme = useTheme();
259
+ const { colors, themeStyles } = theme;
260
+ const { t } = useTranslation();
261
+ const navigation = useNavigation();
262
+
263
+ const [showCodeInput, setShowCodeInput] = useState(personalEventsCode ? false : true);
264
+ const [tabIndex, setTabIndex] = useState(0);
265
+
266
+ const tabRoutes = useMemo(
267
+ () =>
268
+ [
269
+ {
270
+ key: 'personal_events',
271
+ title: t('event:tabs.selected'),
272
+ accessibilityLabel: t('accessibility:event.selected'),
273
+ },
274
+ {
275
+ key: 'all_events',
276
+ title: t('event:tabs.all'),
277
+ accessibilityLabel: t('accessibility:event.all'),
278
+ }
279
+ ],
280
+ [t]
281
+ );
282
+
283
+
284
+ const styles = useMemo(
285
+ () => StyleSheet.create(componentStyles(theme)),
286
+ [theme]
287
+ )
288
+
289
+ const leftAction = useMemo(
290
+ () => (
291
+ <Appbar.Action
292
+ icon={props => <IconsOpenasist {...props} icon={'back'} color={colors.primaryText} />}
293
+ onPress={() => {
294
+ navigation.goBack();
295
+ }} />
296
+ ),
297
+ [colors, navigation]
298
+ )
299
+
300
+ const rightAction = useMemo(
301
+ () => (
302
+ <Appbar.Action
303
+ icon={showCodeInput ? 'table' : 'table-plus'}
304
+ color={colors.appbarIconColor}
305
+ onPress={() => setShowCodeInput(showCodeInput => !showCodeInput)}
306
+ />
307
+ ),
308
+ [showCodeInput, setShowCodeInput, colors]
309
+ )
310
+
311
+ const closeCodeInput = useCallback(
312
+ () => setShowCodeInput(false),
313
+ [setShowCodeInput]
314
+ );
315
+
316
+ const closeCodeInputAndShowPersonalEvents = useCallback(
317
+ () => {
318
+ setTabIndex(tabRoutes.findIndex(route => route.key === 'personal_events'));
319
+ setShowCodeInput(false);
320
+ },
321
+ [tabRoutes, setShowCodeInput, setTabIndex]
322
+ );
323
+
324
+
325
+ return (
326
+ <SafeAreaView style={[styles.container, themeStyles.appSafeAreaContainer]}>
327
+ <View>
328
+ <AppbarComponent {...props}
329
+ title={t('menu:titles.event')}
330
+ leftAction={leftAction}
331
+ rightAction={rightAction}
332
+ />
333
+ </View>
334
+ {
335
+ showCodeInput
336
+ ? <EventCodeInputComponent {...props}
337
+ onClose={closeCodeInput}
338
+ onPersonalEventsImported={closeCodeInputAndShowPersonalEvents}
339
+ />
340
+ : <View style={themeStyles.container}>
341
+ <TabView
342
+ index={tabIndex}
343
+ navigationState={{ index: tabIndex, routes: tabRoutes }}
344
+ initialLayout={{ height: 0, width: Dimensions.get('window').width }}
345
+ onIndexChange={setTabIndex}
346
+ renderTabBar={props =>
347
+ <TabBar
348
+ {...props}
349
+ style={themeStyles.tabs}
350
+ labelStyle={themeStyles.tab}
351
+ activeColor={themeStyles.tabs.activeColor}
352
+ inactiveColor={themeStyles.tabs.inactiveColor}
353
+ indicatorStyle={themeStyles.tabIndicator}
354
+ tabStyle={{ paddingHorizontal: 20 }}
355
+ />
356
+ }
357
+ renderScene={TabViewScenes}
358
+ />
359
+ </View>
360
+ }
361
+ </SafeAreaView>
362
+ );
363
+ }
364
+
365
+ export function APIProvidetEventsView(props) {
366
+ return (
367
+ <EventContextProvider>
368
+ <EventsView
369
+ {...props}
370
+ />
371
+ </EventContextProvider>
372
+ )
373
+ }
@@ -0,0 +1,63 @@
1
+ export default function(theme) {
2
+ return {
3
+ activity: {
4
+ padding: 20
5
+ },
6
+ arrowIcon: {
7
+ marginStart: 'auto',
8
+ marginEnd: 10,
9
+ },
10
+ companyCity:{
11
+ fontSize: theme.fontSizes.s,
12
+ paddingTop: theme.paddings.xsmall,
13
+ color: theme.colors.secondaryText
14
+ },
15
+ container: {
16
+ flex: 1,
17
+ backgroundColor: theme.colors.background,
18
+ },
19
+ containerErrorMsg: {
20
+ flex: 1,
21
+ justifyContent: 'center',
22
+ alignContent: 'center',
23
+ alignItems: 'center',
24
+ margin: theme.paddings.default,
25
+ },
26
+ content: {
27
+ backgroundColor: theme.colors.background,
28
+ flex: 1,
29
+ padding: "2%",
30
+ },
31
+ date:{
32
+ fontSize: theme.fontSizes.s,
33
+ paddingTop: theme.paddings.xsmall
34
+ },
35
+ header: {
36
+ backgroundColor: theme.colors.background,
37
+ padding: 10,
38
+ flexDirection: "row",
39
+ justifyContent: 'flex-start',
40
+ alignItems: 'center',
41
+ },
42
+ headerText: {
43
+ fontSize: theme.fontSizes.l,
44
+ ...theme.fonts.light,
45
+ marginTop: 10,
46
+ marginBottom: 10
47
+ },
48
+ innerContainer: {
49
+ padding: 40,
50
+ marginTop: 200
51
+ },
52
+ title:{
53
+ fontSize: theme.fontSizes.xxl,
54
+ color: theme.colors.jobsTitleColor
55
+ },
56
+ titleNoJobs:{
57
+ fontSize: theme.fontSizes.xxl,
58
+ color: theme.colors.jobsTitleColor,
59
+ textAlign: 'center',
60
+ marginBottom: theme.paddings.default
61
+ },
62
+ }
63
+ };