@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.
- package/AppBar/index.js +83 -0
- package/AppBar/styles.js +27 -0
- package/BookDetail/index.js +268 -0
- package/BookDetail/styles.js +124 -0
- package/Component/342/200/216JobsFilter/index.js +188 -0
- package/Component/342/200/216JobsFilter/styles.js +12 -0
- package/ConnectivityWarning/index.js +65 -0
- package/ConnectivityWarning/styles.js +19 -0
- package/ContactDetail/index.js +232 -0
- package/ContactDetail/styles.js +32 -0
- package/CourseDetail/index.js +357 -0
- package/CourseDetail/styles.js +59 -0
- package/CourseDetailDialog/index.js +169 -0
- package/CourseDetailDialog/styles.js +116 -0
- package/CourseInfo/index.js +219 -0
- package/CourseInfo/styles.js +40 -0
- package/DevelopmentDialog/index.js +208 -0
- package/DevelopmentDialog/styles.js +10 -0
- package/EventCodeInput/index.js +146 -0
- package/EventCodeInput/styles.js +108 -0
- package/FlexMenuEntry/index.js +84 -0
- package/FlexMenuEntry/styles.js +27 -0
- package/MainMenuEntry/index.js +88 -0
- package/MainMenuEntry/styles.js +28 -0
- package/MealItem/index.js +87 -0
- package/MealItem/styles.js +73 -0
- package/MensaMenu/index.js +307 -0
- package/MensaMenu/styles.js +94 -0
- package/MensaSlider/index.js +184 -0
- package/MensaSlider/styles.js +53 -0
- package/Modal/index.js +106 -0
- package/Modal/styles.js +8 -0
- package/NewsDetail/index.js +377 -0
- package/NewsDetail/styles.js +77 -0
- package/NewsList/index.js +120 -0
- package/NewsList/styles.js +19 -0
- package/NewsListItem/index.js +89 -0
- package/NewsListItem/styles.js +32 -0
- package/OtherCourses/index.js +152 -0
- package/OtherCourses/styles.js +10 -0
- package/PtsDeparture/index.js +140 -0
- package/PtsDeparture/styles.js +7 -0
- package/PtsStation/index.js +183 -0
- package/PtsStation/styles.js +47 -0
- package/QuickLinks/index.js +127 -0
- package/QuickLinks/styles.js +45 -0
- package/RoomDetail/index.js +281 -0
- package/RoomDetail/styles.js +56 -0
- package/ScaledImage/index.js +92 -0
- package/SearchResults/index.js +362 -0
- package/SearchResults/styles.js +59 -0
- package/SettingSection/index.js +54 -0
- package/SettingSection/styles.js +15 -0
- package/SettingsDialog/index.js +52 -0
- package/SettingsDialog/styles.js +12 -0
- package/SettingsDialogRadio/index.js +66 -0
- package/SettingsDialogRadio/styles.js +7 -0
- package/SettingsDialogSelect/index.js +73 -0
- package/SettingsDialogSelect/styles.js +7 -0
- package/TimetableCodeInput/index.js +201 -0
- package/TimetableCodeInput/styles.js +28 -0
- package/TimetableDay/index.js +266 -0
- package/TimetableDay/styles.js +103 -0
- package/TimetableEvent/index.js +163 -0
- package/TimetableEvent/styles.js +108 -0
- package/TimetableList/index.js +116 -0
- package/TimetableList/styles.js +109 -0
- package/TimetableMonth/index.js +156 -0
- package/TimetableMonth/styles.js +29 -0
- package/TimetableWeek/index.js +245 -0
- package/TimetableWeek/styles.js +58 -0
- package/TopNews/index.js +282 -0
- package/TopNews/styles.js +125 -0
- package/TopNewsHtwk/index.js +279 -0
- package/TopNewsHtwk/styles.js +142 -0
- package/WebView/index.js +108 -0
- package/WebView/styles.js +11 -0
- package/index.js +39 -0
- package/package.json +37 -0
package/AppBar/index.js
ADDED
|
@@ -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)
|
package/AppBar/styles.js
ADDED
|
@@ -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)))
|