@olea-bps/components 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 (79) hide show
  1. package/AppBar/index.js +83 -0
  2. package/AppBar/styles.js +27 -0
  3. package/BookDetail/index.js +268 -0
  4. package/BookDetail/styles.js +124 -0
  5. package/Component/342/200/216JobsFilter/index.js +188 -0
  6. package/Component/342/200/216JobsFilter/styles.js +12 -0
  7. package/ConnectivityWarning/index.js +65 -0
  8. package/ConnectivityWarning/styles.js +19 -0
  9. package/ContactDetail/index.js +232 -0
  10. package/ContactDetail/styles.js +32 -0
  11. package/CourseDetail/index.js +357 -0
  12. package/CourseDetail/styles.js +59 -0
  13. package/CourseDetailDialog/index.js +169 -0
  14. package/CourseDetailDialog/styles.js +116 -0
  15. package/CourseInfo/index.js +219 -0
  16. package/CourseInfo/styles.js +40 -0
  17. package/DevelopmentDialog/index.js +208 -0
  18. package/DevelopmentDialog/styles.js +10 -0
  19. package/EventCodeInput/index.js +146 -0
  20. package/EventCodeInput/styles.js +108 -0
  21. package/FlexMenuEntry/index.js +84 -0
  22. package/FlexMenuEntry/styles.js +27 -0
  23. package/MainMenuEntry/index.js +88 -0
  24. package/MainMenuEntry/styles.js +28 -0
  25. package/MealItem/index.js +87 -0
  26. package/MealItem/styles.js +73 -0
  27. package/MensaMenu/index.js +307 -0
  28. package/MensaMenu/styles.js +94 -0
  29. package/MensaSlider/index.js +184 -0
  30. package/MensaSlider/styles.js +53 -0
  31. package/Modal/index.js +106 -0
  32. package/Modal/styles.js +8 -0
  33. package/NewsDetail/index.js +377 -0
  34. package/NewsDetail/styles.js +77 -0
  35. package/NewsList/index.js +120 -0
  36. package/NewsList/styles.js +19 -0
  37. package/NewsListItem/index.js +89 -0
  38. package/NewsListItem/styles.js +32 -0
  39. package/OtherCourses/index.js +152 -0
  40. package/OtherCourses/styles.js +10 -0
  41. package/PtsDeparture/index.js +140 -0
  42. package/PtsDeparture/styles.js +7 -0
  43. package/PtsStation/index.js +183 -0
  44. package/PtsStation/styles.js +47 -0
  45. package/QuickLinks/index.js +127 -0
  46. package/QuickLinks/styles.js +45 -0
  47. package/RoomDetail/index.js +281 -0
  48. package/RoomDetail/styles.js +56 -0
  49. package/ScaledImage/index.js +92 -0
  50. package/SearchResults/index.js +362 -0
  51. package/SearchResults/styles.js +59 -0
  52. package/SettingSection/index.js +54 -0
  53. package/SettingSection/styles.js +15 -0
  54. package/SettingsDialog/index.js +52 -0
  55. package/SettingsDialog/styles.js +12 -0
  56. package/SettingsDialogRadio/index.js +66 -0
  57. package/SettingsDialogRadio/styles.js +7 -0
  58. package/SettingsDialogSelect/index.js +73 -0
  59. package/SettingsDialogSelect/styles.js +7 -0
  60. package/TimetableCodeInput/index.js +201 -0
  61. package/TimetableCodeInput/styles.js +28 -0
  62. package/TimetableDay/index.js +266 -0
  63. package/TimetableDay/styles.js +103 -0
  64. package/TimetableEvent/index.js +163 -0
  65. package/TimetableEvent/styles.js +108 -0
  66. package/TimetableList/index.js +116 -0
  67. package/TimetableList/styles.js +109 -0
  68. package/TimetableMonth/index.js +156 -0
  69. package/TimetableMonth/styles.js +29 -0
  70. package/TimetableWeek/index.js +245 -0
  71. package/TimetableWeek/styles.js +58 -0
  72. package/TopNews/index.js +282 -0
  73. package/TopNews/styles.js +125 -0
  74. package/TopNewsHtwk/index.js +279 -0
  75. package/TopNewsHtwk/styles.js +142 -0
  76. package/WebView/index.js +108 -0
  77. package/WebView/styles.js +11 -0
  78. package/index.js +39 -0
  79. package/package.json +37 -0
@@ -0,0 +1,83 @@
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, { useMemo } from 'react';
16
+ import { StyleSheet } from 'react-native';
17
+ import PropTypes from 'prop-types';
18
+
19
+ import { Appbar, useTheme } from 'react-native-paper';
20
+ import { useTranslation } from 'react-i18next';
21
+ import { useNavigation } from '@react-navigation/native';
22
+
23
+ import { connect } from 'react-redux';
24
+
25
+ import IconsOpenasist from '@olea-bps/icons-openasist';
26
+
27
+ import componentStyles from './styles';
28
+
29
+ function AppbarComponent({ settings, title, leftAction, rightAction, subtitle, style }) {
30
+ const theme = useTheme();
31
+ const { t } = useTranslation();
32
+ const { colors } = theme;
33
+ const navigation = useNavigation();
34
+ const isBigFont = settings?.settingsAccessibility?.increaseFontSize ?? false;
35
+
36
+ // Styles of this component
37
+ const styles = useMemo(
38
+ () => StyleSheet.create(componentStyles(theme)),
39
+ [theme]
40
+ )
41
+
42
+ return (
43
+ <Appbar.Header style={[{ elevation: 0 }, isBigFont ? { height: 70 } : null, style]} statusBarHeight={0}>
44
+ {
45
+ leftAction
46
+ ? leftAction
47
+ : <Appbar.Action
48
+ icon={(props) => <IconsOpenasist {...props} icon={'back'} color={colors.appbarIconColor} />}
49
+ onPress={() => navigation.goBack(null)}
50
+ accessible={true}
51
+ accessibilityHint={t('accessibility:appbar.back')}
52
+ />
53
+ }
54
+ <Appbar.Content
55
+ style={isBigFont ? styles.contentStyleBigFont : {}}
56
+ title={title}
57
+ titleStyle={[styles.titleStyle, isBigFont ? styles.titleBigFont : null]}
58
+ subtitle={subtitle}
59
+ subtitleStyle={[styles.subtitle, isBigFont ? styles.subtitleBigFont : null]} />
60
+ {
61
+ rightAction
62
+ ? rightAction
63
+ : null
64
+ }
65
+ </Appbar.Header>
66
+ );
67
+ }
68
+
69
+ //DEPRECATED: Proptypes werden in React 19 nicht mehr unterstützt, stattdessen wird TypeScript empfohlen.
70
+ AppbarComponent.propTypes = {
71
+ title: PropTypes.string,
72
+ rightAction: PropTypes.any,
73
+ leftAction: PropTypes.any,
74
+ style: PropTypes.object
75
+ };
76
+
77
+ const mapStateToProps = state => {
78
+ return {
79
+ settings: state.settingReducer
80
+ };
81
+ };
82
+
83
+ export default connect(mapStateToProps, null)(AppbarComponent)
@@ -0,0 +1,27 @@
1
+ export default function(theme) {
2
+ return {
3
+ contentStyleBigFont: {
4
+ paddingHorizontal: 0
5
+ },
6
+ titleStyle: {
7
+ fontSize: theme.fontSizes.xxl,
8
+ lineHeight: theme.lineHeights.l,
9
+ ...theme.fonts.medium
10
+ },
11
+ titleBigFont: {
12
+ fontSize: theme.fontSizes.xl,
13
+ lineHeight: theme.lineHeights.l,
14
+ ...theme.fonts.medium
15
+ },
16
+ subtitle: {
17
+ fontSize: theme.fontSizes.l,
18
+ lineHeight: theme.lineHeights.s,
19
+ color: theme.colors.appbarSubtitle
20
+ },
21
+ subtitleBigFont: {
22
+ fontSize: theme.fontSizes.s,
23
+ lineHeight: theme.lineHeights.xxs,
24
+ color: theme.colors.appbarSubtitle
25
+ }
26
+ };
27
+ }
@@ -0,0 +1,268 @@
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 PropTypes from 'prop-types';
17
+
18
+ import {
19
+ Image, ScrollView, StyleSheet, Text,
20
+ View, SafeAreaView, ActivityIndicator, Share
21
+ } from 'react-native';
22
+ import {Appbar, Badge, Headline, List, Surface, withTheme} from "react-native-paper";
23
+
24
+ import { connect } from 'react-redux'
25
+ import {withTranslation} from "react-i18next";
26
+ import merge from 'lodash/merge';
27
+ import unescape from 'lodash/unescape';
28
+ import uniqBy from 'lodash/uniqBy';
29
+ import {libraryApi} from '@olea-bps/core';
30
+
31
+
32
+ import componentStyles from "./styles"
33
+ import { AppBar as AppbarComponent } from '@olea-bps/components';
34
+ import {handleHtmlEntities} from "@olea-bps/core/helper/format.helper";
35
+
36
+
37
+ class BookDetailComponent extends React.Component {
38
+ static propTypes = {
39
+ book: PropTypes.object.isRequired
40
+ };
41
+
42
+ // Styles of this component
43
+ styles;
44
+
45
+ book = null;
46
+
47
+ constructor(props) {
48
+ super(props);
49
+ this.state = {
50
+ inProgress: true
51
+ };
52
+ // ------------------------------------------------------------------------
53
+ // PLUGIN FUNCTIONALITY
54
+ // ------------------------------------------------------------------------
55
+
56
+ const { pluginStyles,theme } = this.props;
57
+ this.styles = componentStyles(theme);
58
+
59
+ if(pluginStyles) {
60
+ this.styles = merge(componentStyles, pluginStyles);
61
+ }
62
+
63
+ this.styles = StyleSheet.create(this.styles);
64
+
65
+ // ------------------------------------------------------------------------
66
+ };
67
+
68
+ /**
69
+ * Share function for book
70
+ *
71
+ * @returns {Promise<void>}
72
+ * @private
73
+ */
74
+ async _onShare() {
75
+ const { t } = this.props;
76
+ try {
77
+ let holdings = "";
78
+ this.book.details.holdings.forEach((holding) => {
79
+ holdings +=
80
+ t('books:library') + ": " + holding.branch + "\n" +
81
+ t('books:status') + ": " + holding.status + "\n" +
82
+ t('books:shelf') + ": " + holding.shelf + "\n" +
83
+ t('books:location') + ": " + holding.type + "\n\n\n";
84
+ });
85
+ let title = this.book.title.replace(/&#(\d+);/g, (match, dec) => String.fromCharCode(dec));
86
+ const result = await Share.share({
87
+ message: '"' + title + '" ' + t('books:from') + ' ' + this.book.author + '\n\n' +
88
+ ((holdings.length > 0) ? t('books:availability') + '\n' + holdings : '')
89
+ });
90
+
91
+ if (result.action === Share.sharedAction) {
92
+ if (result.activityType) {
93
+ // shared with activity type of result.activityType
94
+ } else {
95
+ // shared
96
+ }
97
+ } else if (result.action === Share.dismissedAction) {
98
+ // dismissed
99
+ }
100
+ } catch (error) {
101
+ alert(error.message);
102
+ }
103
+ };
104
+
105
+
106
+ /**
107
+ * Render holdings and availability
108
+ *
109
+ * @returns {*}
110
+ * @private
111
+ */
112
+ _renderHoldings = () => {
113
+ if(!this.book.details || !this.book.details.holdings) {
114
+ return null;
115
+ }
116
+ const { t } = this.props;
117
+ const holdings = [];
118
+ let index = 0;
119
+ this.book.details.holdings.forEach((holding) => {
120
+ if(holding.branch && holding.status && holding.shelf && holding.type) {
121
+ holdings.push(
122
+ <Surface key={holding.branch + '_' + index} style={this.styles.holdingContainer}>
123
+ <List.Accordion title={<Text style={this.styles.holdingTitle}>{holding.branch}</Text>}
124
+ style={this.styles.holdingBranch}>
125
+ <List.Item title={t('books:status')} description={holding.status} titleStyle={this.styles.holdingTitle}
126
+ descriptionStyle={this.styles.holdingDescription}/>
127
+ <List.Item title={t('books:shelf')} description={holding.shelf} titleStyle={this.styles.holdingTitle}
128
+ descriptionStyle={this.styles.holdingDescription}/>
129
+ <List.Item title={t('books:location')} description={holding.type} titleStyle={this.styles.holdingTitle}
130
+ descriptionStyle={this.styles.holdingDescription}/>
131
+ </List.Accordion>
132
+ </Surface>
133
+ );
134
+ index++;
135
+ }
136
+ });
137
+
138
+ if(holdings.length > 0) {
139
+ return (
140
+ <ScrollView style={[this.styles.bookDetails, {marginBottom: 100}]}>
141
+ {holdings}
142
+ </ScrollView>
143
+ )
144
+ } else {
145
+ return null;
146
+ }
147
+ };
148
+
149
+ /**
150
+ * Render book details content
151
+ *
152
+ * @returns {*}
153
+ * @private
154
+ */
155
+ _renderContent = () => {
156
+ const { colors } = this.props.theme;
157
+ const { t } = this.props;
158
+
159
+ if(this.state.inProgress) {
160
+ return (<ActivityIndicator style={this.styles.activity} size="large" color={colors.loadingIndicator} />);
161
+
162
+ } else {
163
+ let buzzwords = this.book.details ? uniqBy(this.book.details.buzzwords) : [];
164
+ let badges = [];
165
+ buzzwords.forEach((word) => {
166
+ badges.push(<Badge key={word} style={this.styles.badge}>{word}</Badge>)
167
+ });
168
+
169
+ let publisher = '';
170
+ if(this.book.details && this.book.details.publisher) {
171
+ publisher = handleHtmlEntities(this.book.details.publisher)
172
+ }
173
+
174
+
175
+ let format = this.book.format;
176
+ let edition = this.book.details && this.book.details.edition;
177
+ let language = this.book.details && this.book.details.language;
178
+
179
+ let availableCount = (this.book.details && this.book.details.holdings) ? this.book.details.holdings.length : 0;
180
+ let holdings = this._renderHoldings();
181
+
182
+ // Handle html entities
183
+ let title = handleHtmlEntities(this.book.title);
184
+
185
+ return (
186
+ <ScrollView style={this.styles.containerInner}>
187
+ <Text style={this.styles.availableCount}>{availableCount > 0 ? availableCount + t('books:availableCount') : t('books:notAvailable')}</Text>
188
+ <Surface style={this.styles.bookHeader}>
189
+ { this.book.details && this.book.details.imageUrl &&
190
+ <Image source={{uri: this.book.details.imageUrl }}
191
+ resizeMode="cover"
192
+ style={this.styles.bookImage}/> }
193
+ <View style={this.book.details && this.book.details.imageUrl ? this.styles.bookTitle : this.styles.bookTitleFull}>
194
+ <Headline style={this.styles.bookTitleHeadline}>{unescape(title)}</Headline>
195
+ <Text style={this.styles.bookTitleSubline}>{this.book.pubdate}</Text>
196
+ </View>
197
+ </Surface>
198
+ <View style={this.styles.badges}>
199
+ {format !== null && format !== '' && <Text style={this.styles.badgeLabel}>{t('books:format')}</Text>}
200
+ {format !== null && format !== '' && <Badge style={this.styles.badge}>{format}</Badge>}
201
+ {edition !== null && edition !== '' && <Text style={this.styles.badgeLabel}>{t('books:edition')}</Text>}
202
+ {edition !== null && edition !== '' && <Badge style={this.styles.badge}>{edition}</Badge>}
203
+ {language !== null && language !== '' && <Text style={this.styles.badgeLabel}>{t('books:language')}</Text>}
204
+ {language !== null && language !== '' && <Badge style={this.styles.badge}>{language}</Badge>}
205
+ {publisher !== null && publisher !== '' && <Text style={this.styles.badgeLabel}>{t('books:publisher')}</Text>}
206
+ {publisher !== null && publisher !== '' && <Badge style={[this.styles.badge, this.styles.badgeFullWidth]}>{publisher}</Badge>}
207
+ </View>
208
+ <Text style={this.styles.badgeLabel}>{t('books:availability')}</Text>
209
+ {holdings === null && <Text style={[this.styles.notAvailable]}>{t('books:noLibraryFound')}</Text>}
210
+ {holdings !== null && holdings}
211
+ </ScrollView>
212
+ );
213
+ }
214
+ };
215
+
216
+ render() {
217
+ // ------------------------------------------------------------------------
218
+ // PLUGIN FUNCTIONALITY
219
+ // ------------------------------------------------------------------------
220
+ const PluginComponent = this.props.pluginComponent;
221
+ if (PluginComponent) {
222
+ return <PluginComponent />;
223
+ }
224
+ // ------------------------------------------------------------------------
225
+
226
+
227
+ const {themeStyles} = this.props.theme;
228
+ const { book, t } = this.props;
229
+
230
+ if(!book){
231
+ return (
232
+ <SafeAreaView style={[this.styles.container, themeStyles.safeAreaContainer]}>
233
+ <AppbarComponent {...this.props}
234
+ title={t('search:title')}/>
235
+ <Text>{t('books:couldNotLoad')}</Text>
236
+ </SafeAreaView>);
237
+ } else if(!this.book) {
238
+ try {
239
+ libraryApi.getSearchDetailsByBookId(book.bookId, (bookDetails) => {
240
+ this.book = merge(book, {details: bookDetails});
241
+
242
+ this.setState({
243
+ inProgress: false
244
+ });
245
+ });
246
+ } catch {}
247
+ }
248
+
249
+ return (
250
+ <SafeAreaView style={[this.styles.container, themeStyles.safeAreaContainer]}>
251
+ <AppbarComponent {...this.props}
252
+ title={t('search:title')}
253
+ rightAction={<Appbar.Action icon="share-variant" onPress={this._onShare.bind(this)}/>}/>
254
+ {this._renderContent()}
255
+ </SafeAreaView>
256
+ );
257
+ }
258
+ }
259
+
260
+
261
+ const mapStateToProps = state => {
262
+ return {
263
+ pluginComponent: state.pluginReducer.bookDetail.component,
264
+ pluginStyles: state.pluginReducer.bookDetail.styles
265
+ };
266
+ };
267
+
268
+ export default connect(mapStateToProps, null)(withTranslation()(withTheme(BookDetailComponent)))
@@ -0,0 +1,124 @@
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
+ },
9
+ containerInner: {
10
+ flex: 1,
11
+ paddingHorizontal: 20,
12
+ paddingVertical: 20
13
+ },
14
+ activity: {
15
+ marginTop: 20
16
+ },
17
+ badges: {
18
+ flexDirection: 'row',
19
+ flexWrap: 'wrap',
20
+ paddingHorizontal: 0
21
+ },
22
+ badge: {
23
+ backgroundColor: theme.colors.categoryBadgeBackgroundColor,
24
+ color: theme.colors.categoryBadgeColor,
25
+ ...theme.fonts.regular,
26
+ fontSize: theme.fontSizes.m,
27
+ lineHeight: theme.lineHeights.xs,
28
+ paddingHorizontal: theme.paddings.default,
29
+ paddingVertical: theme.paddings.xsmall,
30
+ marginRight: theme.paddings.default,
31
+ marginBottom: theme.paddings.default,
32
+ borderRadius: 0,
33
+ minWidth: 80,
34
+ height: 'auto'
35
+ },
36
+ badgeFullWidth: {
37
+ flex: 1,
38
+ textAlign: 'left',
39
+ marginRight: 0
40
+ },
41
+ badgeLabel: {
42
+ flex: 0,
43
+ ...theme.fonts.regular,
44
+ fontSize: theme.fontSizes.m,
45
+ lineHeight: theme.lineHeights.xs,
46
+ width: width,
47
+ marginBottom: theme.paddings.xsmall
48
+ },
49
+ bookHeader: {
50
+ flex: 0,
51
+ flexDirection: 'row',
52
+ elevation: 1,
53
+ marginBottom: theme.paddings.default
54
+ },
55
+ bookImage: {
56
+ flex: 0.4,
57
+ minHeight: 200
58
+ },
59
+ bookTitle: {
60
+ flex: 0.6,
61
+ padding: theme.paddings.small
62
+ },
63
+ bookTitleFull: {
64
+ flex: 1,
65
+ padding: theme.paddings.small
66
+ },
67
+ bookTitleHeadline: {
68
+ ...theme.fonts.medium,
69
+ fontSize: theme.fontSizes.xl,
70
+ lineHeight: theme.lineHeights.l,
71
+ marginBottom: theme.paddings.small
72
+ },
73
+ bookTitleSubline: {
74
+ ...theme.fonts.medium,
75
+ fontSize: theme.fontSizes.m,
76
+ lineHeight: theme.lineHeights.s,
77
+ color: theme.colors.subtitle
78
+ },
79
+ bookDetails: {
80
+ flex: 1,
81
+ flexDirection: 'column'
82
+ },
83
+ holdingBranch: {
84
+ paddingHorizontal: theme.paddings.xsmall,
85
+ paddingVertical: theme.paddings.xsmall,
86
+ flexWrap: 'wrap',
87
+ padding: 0,
88
+ backgroundColor: theme.colors.bookHoldingBackgroundColor,
89
+
90
+ },
91
+ holdingTitle: {
92
+ ...theme.fonts.medium,
93
+ fontSize: theme.fontSizes.m,
94
+ lineHeight: theme.lineHeights.xs,
95
+ color: theme.colors.bookHoldingColor
96
+ },
97
+ holdingDescription: {
98
+ ...theme.fonts.regular,
99
+ fontSize: theme.fontSizes.m,
100
+ lineHeight: theme.lineHeights.xs,
101
+ color: theme.colors.subtitle
102
+ },
103
+ holdingContainer: {
104
+ elevation: 0,
105
+ marginBottom: 10
106
+ },
107
+ notAvailable: {
108
+ backgroundColor: theme.colors.categoryBadgeBackgroundColor,
109
+ color: theme.colors.categoryBadgeColor,
110
+ paddingHorizontal: theme.paddings.default,
111
+ paddingVertical: theme.paddings.xsmall,
112
+ ...theme.fonts.regular,
113
+ fontSize: theme.fontSizes.m,
114
+ lineHeight: theme.lineHeights.xs,
115
+ },
116
+ availableCount: {
117
+ textAlign: 'right',
118
+ textTransform: 'none',
119
+ ...theme.fonts.regular,
120
+ color: theme.colors.grayLight1,
121
+ fontSize: theme.fontSizes.m
122
+ }
123
+ };
124
+ }
@@ -0,0 +1,188 @@
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 {FlatList, SafeAreaView, StyleSheet, View} from 'react-native';
17
+ import {connect} from 'react-redux'
18
+ import {withTranslation} from "react-i18next";
19
+ import {Appbar, withTheme} from "react-native-paper";
20
+ import { CheckBox } from 'react-native-elements'
21
+
22
+ import merge from 'lodash/merge';
23
+ import componentStyles from "./styles";
24
+ import { AppBar as AppbarComponent } from '@olea-bps/components';
25
+ import IconsOpenasist from "@olea-bps/icons-openasist";
26
+
27
+
28
+
29
+ /**
30
+ * JobPortalFilter View
31
+ *
32
+ * Shows the Job Portal Category Filter
33
+ *
34
+ * Parameters:
35
+ * - none
36
+ *
37
+ * Navigation-Parameters:
38
+ * - none
39
+ */
40
+ class JobFilterComponent extends React.Component {
41
+ static navigationOptions = {
42
+ header: null
43
+ };
44
+
45
+ state = {
46
+ data: null,
47
+ selectedIds: [],
48
+ checked: []
49
+ };
50
+
51
+ // Styles of this component
52
+ styles;
53
+
54
+ checked;
55
+
56
+ selectedIds;
57
+
58
+ catData;
59
+
60
+ constructor(props) {
61
+ super(props);
62
+ // ------------------------------------------------------------------------
63
+ // PLUGIN FUNCTIONALITY
64
+ // ------------------------------------------------------------------------
65
+ const {pluginStyles, theme} = this.props;
66
+ this.styles = componentStyles(theme);
67
+ if (pluginStyles) {
68
+ this.styles = merge(this.styles, pluginStyles);
69
+ }
70
+ this.styles = StyleSheet.create(this.styles);
71
+ // ------------------------------------------------------------------------
72
+
73
+ }
74
+
75
+ componentDidMount(){
76
+ this.setState({
77
+ checked: this.props.route.params.checked,
78
+ selectedIds: this.props.route.params.selectedIds,
79
+ data: this.props.route.params.catData
80
+ });
81
+ }
82
+
83
+ goBack() {
84
+ const { navigation, route } = this.props;
85
+ navigation.navigate('Job', {
86
+ selectedIds: this.state.selectedIds,
87
+ checked: this.state.checked
88
+ });
89
+ }
90
+
91
+
92
+
93
+ handleChange = (index) => {
94
+ let checked = [...this.state.checked];
95
+ let selectedIds = [...this.state.selectedIds];
96
+ var data = this.state.data;
97
+ selectedIds = this.addOrRemSelectedIds(data, index, selectedIds);
98
+ checked[index] = !checked[index];
99
+ this.setState({ checked, selectedIds });
100
+ }
101
+
102
+ addOrRemSelectedIds = (data, index, selectedIds) => {
103
+ for(var i = 0; i < data[index].id.length; i++){
104
+ let value = data[index].id[i];
105
+ if(selectedIds.indexOf(value) === -1){
106
+ selectedIds.push(value);
107
+ }else{
108
+ selectedIds.splice(selectedIds.indexOf(value), 1);
109
+ }
110
+ }
111
+ return selectedIds;
112
+ }
113
+
114
+ _keyExtractor = (item, index) => {
115
+ return item?.name ?? index.toString();
116
+ };
117
+
118
+ _renderListView = () => {
119
+ const { colors } = this.props.theme;
120
+ let { data, checked } = this.state;
121
+
122
+ return(
123
+ <FlatList
124
+ data={this.state.data}
125
+ extraData={this.state}
126
+ renderItem={({item, index}) =>
127
+ <CheckBox
128
+ checked={checked[index]}
129
+ title={item.name}
130
+ textStyle={this.styles.title}
131
+ onPress={() => this.handleChange(index)}
132
+ checkedColor={colors.primary}
133
+ />
134
+ }
135
+ keyExtractor={this._keyExtractor}
136
+ />
137
+ )
138
+ }
139
+
140
+ /**
141
+ * Tab for services
142
+ * @returns {*}
143
+ * @constructor
144
+ */
145
+
146
+ render() {
147
+
148
+ // ------------------------------------------------------------------------
149
+ // PLUGIN FUNCTIONALITY
150
+ // ------------------------------------------------------------------------
151
+ const PluginComponent = this.props.pluginComponent;
152
+ if (PluginComponent) {
153
+ return <PluginComponent />;
154
+ }
155
+ // ------------------------------------------------------------------------
156
+ const {colors, themeStyles} = this.props.theme;
157
+
158
+ return (
159
+ <SafeAreaView style={[this.styles.container, themeStyles.appSafeAreaContainer]}>
160
+ <View>
161
+ <AppbarComponent {...this.props}
162
+ title="Filter"
163
+ leftAction={
164
+ <Appbar.Action
165
+ icon={props => <IconsOpenasist {...props} icon={'back'} color={colors.primaryText} /> }
166
+ onPress={() => {
167
+ this.goBack();
168
+ }} />
169
+ }
170
+ />
171
+ </View>
172
+ <View style={themeStyles.container}>
173
+ {this._renderListView()}
174
+ </View>
175
+ </SafeAreaView>
176
+ );
177
+ }
178
+ }
179
+
180
+
181
+ const mapStateToProps = state => {
182
+ return {
183
+ pluginComponent: state.pluginReducer.jobFilter.component,
184
+ pluginStyles: state.pluginReducer.jobFilter.styles,
185
+ };
186
+ };
187
+
188
+ export default connect(mapStateToProps, null)(withTranslation()(withTheme(JobFilterComponent)))