diff --git a/app/ui/components/floatingActionButton/FloatingActionButton.js b/app/ui/components/floatingActionButton/FloatingActionButton.js
new file mode 100644
index 0000000..d72307b
--- /dev/null
+++ b/app/ui/components/floatingActionButton/FloatingActionButton.js
@@ -0,0 +1,71 @@
+import React from 'react';
+import { FloatingAction } from 'react-native-floating-action';
+import Icon from 'react-native-vector-icons/MaterialIcons';
+import PropTypes from 'prop-types';
+import { Text, View } from 'react-native';
+import Colors from '../../style/Colors';
+import styles from './style/FloatingActionButton';
+
+const renderText = (text) => (
+
+ {text}
+
+);
+
+const renderIcon = (iconName) => {
+ if (iconName) {
+ return (
+
+
+
+ );
+ }
+ return null;
+};
+
+const renderItem = (item) => (
+
+ {renderText(item.text)}
+ {renderIcon(item.iconName)}
+
+);
+
+const FloatingActionButton = (props) => {
+ const actions = props.actions.map((action, index) => ({
+ text: action.text,
+ icon: ,
+ name: index.toString(),
+ color: Colors.magenta,
+ buttonSize: 46,
+ textColor: Colors.white,
+ textBackground: Colors.magenta,
+ render: () => renderItem(action),
+ }));
+
+ const onPress = (index) => {
+ props.actions[index].onPress();
+ };
+
+ return (
+ }
+ />
+ );
+};
+
+FloatingActionButton.propTypes = {
+ iconName: PropTypes.string.isRequired,
+ actions: PropTypes.arrayOf(
+ PropTypes.shape({
+ iconName: PropTypes.string,
+ text: PropTypes.string,
+ onPress: PropTypes.func.isRequired,
+ })
+ ).isRequired,
+};
+
+export default FloatingActionButton;
diff --git a/app/ui/components/floatingActionButton/style/FloatingActionButton.js b/app/ui/components/floatingActionButton/style/FloatingActionButton.js
new file mode 100644
index 0000000..1717d0e
--- /dev/null
+++ b/app/ui/components/floatingActionButton/style/FloatingActionButton.js
@@ -0,0 +1,34 @@
+import Colors from '../../../style/Colors';
+import StyleSheet from '../../../style/StyleSheet';
+
+const styles = StyleSheet.create({
+ floatingActionButtonItem: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ },
+ floatingActionButtonItemIcon: {
+ backgroundColor: Colors.magenta,
+ width: 46,
+ height: 46,
+ marginLeft: 14,
+ borderRadius: 23,
+ justifyContent: 'center',
+ alignItems: 'center',
+ elevation: 5,
+ },
+ floatingActionButtonItemTextWrapper: {
+ backgroundColor: Colors.magenta,
+ paddingHorizontal: 10,
+ elevation: 5,
+ borderRadius: 6,
+ height: 28,
+ flexDirection: 'row',
+ alignItems: 'center',
+ },
+ floatingActionButtonItemText: {
+ color: Colors.white,
+ fontSize: 16,
+ },
+});
+
+export default styles;
diff --git a/app/ui/screens/admin/AdminScreen.js b/app/ui/screens/admin/AdminScreen.js
index 332b4aa..7ca16d6 100644
--- a/app/ui/screens/admin/AdminScreen.js
+++ b/app/ui/screens/admin/AdminScreen.js
@@ -1,15 +1,6 @@
import React, { Component } from 'react';
-import {
- FlatList,
- RefreshControl,
- Switch,
- Text,
- TouchableHighlight,
- View,
-} from 'react-native';
+import { FlatList, RefreshControl, Switch, Text, View } from 'react-native';
import PropTypes from 'prop-types';
-import Icon from 'react-native-vector-icons/MaterialIcons';
-import Snackbar from 'react-native-snackbar';
import unorm from 'unorm';
import styles from './style/AdminScreen';
@@ -17,15 +8,21 @@ import Colors from '../../style/Colors';
import SearchHeader from '../../components/searchHeader/SearchHeaderConnector';
import Button from '../../components/button/Button';
+import FloatingActionButton from '../../components/floatingActionButton/FloatingActionButton';
class AdminScreen extends Component {
+ actions = this.props.filterTypes.map((filterType) => ({
+ text: filterType.label,
+ onPress: () => this.updateFilter(filterType.checkItem),
+ }));
+
constructor(props) {
super(props);
this.state = {
items: {},
searchKey: '',
- currentFilter: 0,
+ currentFilter: props.filterTypes[0].checkItem,
};
for (let i = 0; i < this.props.items.length; i += 1) {
@@ -76,12 +73,11 @@ class AdminScreen extends Component {
};
applyFilter = (keys) => {
- const { filterTypes } = this.props;
const { currentFilter } = this.state;
return keys
.filter(this.containsSearchKey)
- .filter((pk) => filterTypes[currentFilter].checkItem(this.state.items[pk]));
+ .filter((pk) => currentFilter(this.state.items[pk]));
};
cleanSearchTerm = (term) =>
@@ -104,14 +100,10 @@ class AdminScreen extends Component {
return 0;
};
- updateFilter = () => {
+ updateFilter = (newFilter) => {
const { currentFilter } = this.state;
- const { filterTypes } = this.props;
-
- const newFilter = (currentFilter + 1) % filterTypes.length;
if (newFilter !== currentFilter) {
- Snackbar.show({ text: filterTypes[newFilter].label });
this.setState({ currentFilter: newFilter });
}
};
@@ -183,11 +175,7 @@ class AdminScreen extends Component {
);
const filterButton = this.props.filterTypes.length > 1 && (
-
-
-
-
-
+
);
if (keys.length === 0) {
diff --git a/app/ui/screens/admin/style/AdminScreen.js b/app/ui/screens/admin/style/AdminScreen.js
index 4fc4649..a205e0a 100644
--- a/app/ui/screens/admin/style/AdminScreen.js
+++ b/app/ui/screens/admin/style/AdminScreen.js
@@ -63,29 +63,6 @@ const styles = StyleSheet.create({
selected: {
backgroundColor: Colors.magenta,
},
- filterButton: {
- position: 'absolute',
- bottom: 16,
- right: 16,
- borderRadius: 28,
- overflow: 'hidden',
- backgroundColor: Colors.grey,
- android: {
- elevation: 4,
- },
- ios: {
- borderColor: Colors.lightGray,
- borderStyle: 'solid',
- borderWidth: 0.5,
- },
- },
- filterButtonWrapper: {
- width: 56,
- height: 56,
- justifyContent: 'center',
- alignItems: 'center',
- backgroundColor: Colors.magenta,
- },
noResultsMessage: {
fontSize: 18,
padding: 16,
diff --git a/app/ui/screens/events/CalendarScreen.js b/app/ui/screens/events/CalendarScreen.js
index 8eb3f03..1b345d2 100644
--- a/app/ui/screens/events/CalendarScreen.js
+++ b/app/ui/screens/events/CalendarScreen.js
@@ -9,6 +9,13 @@ import ErrorScreen from '../../components/errorScreen/ErrorScreen';
import styles from './style/CalendarScreen';
import SearchHeader from '../../components/searchHeader/SearchHeaderConnector';
import DismissKeyboardView from '../../components/dismissKeyboardView/DismissKeyboardView';
+import FloatingActionButton from '../../components/floatingActionButton/FloatingActionButton';
+
+const filters = {
+ all: () => true,
+ registered: (item) => item.registered,
+ open: (item) => item.registration_allowed,
+};
/* eslint no-param-reassign: ["error", { "props": false }] */
const addEventToSection = (sections, date, event) => {
@@ -119,6 +126,31 @@ const renderItem = (item) => {
};
class CalendarScreen extends Component {
+ actions = [
+ {
+ text: 'All',
+ iconName: 'reorder',
+ onPress: () => this.updateFilter(filters.all),
+ },
+ {
+ text: 'Your registrations',
+ iconName: 'account-circle',
+ onPress: () => this.updateFilter(filters.registered),
+ },
+ {
+ text: 'Open registrations',
+ iconName: 'event-available',
+ onPress: () => this.updateFilter(filters.open),
+ },
+ ];
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ activeFilter: filters.all,
+ };
+ }
+
componentDidMount() {
const { keywords } = this.props;
this.props.events(keywords);
@@ -136,7 +168,22 @@ class CalendarScreen extends Component {
}, 500);
};
+ filteredEvents = () => {
+ const { activeFilter } = this.state;
+ const { eventList } = this.props;
+
+ return eventList.filter(activeFilter);
+ };
+
+ updateFilter = (filter) => {
+ this.setState({
+ activeFilter: filter,
+ });
+ };
+
render() {
+ const items = this.filteredEvents();
+
const header = (
(
{itemHeader.section.key}
)}
- sections={eventListToSections(this.props.eventList)}
+ sections={eventListToSections(items)}
keyExtractor={(item) => item.dayNumber}
stickySectionHeadersEnabled
onRefresh={this.handleRefresh}
@@ -199,6 +246,7 @@ class CalendarScreen extends Component {
{content}
+
);
}
@@ -217,6 +265,7 @@ CalendarScreen.propTypes = {
start: PropTypes.string,
end: PropTypes.string,
location: PropTypes.string,
+ registration_allowed: PropTypes.bool.isRequired,
price: PropTypes.string,
registered: PropTypes.bool,
pizza: PropTypes.bool,
diff --git a/app/ui/screens/events/EventAdminScreen.js b/app/ui/screens/events/EventAdminScreen.js
index 24e6c6f..5e7483a 100644
--- a/app/ui/screens/events/EventAdminScreen.js
+++ b/app/ui/screens/events/EventAdminScreen.js
@@ -50,15 +50,15 @@ class EventAdminScreen extends Component {
const filterTypes = [
{
- label: 'Disabled filter',
+ label: 'Show all',
checkItem: () => true,
},
{
- label: 'Filtering on payment',
+ label: 'Hide paid',
checkItem: (item) => item.select.value === PAYMENT_TYPES.NONE,
},
{
- label: 'Filtering on presence',
+ label: 'Hide present',
checkItem: (item) => !item.checkbox,
},
];
diff --git a/app/ui/screens/pizza/PizzaAdminScreen.js b/app/ui/screens/pizza/PizzaAdminScreen.js
index b369aa1..bce51d9 100644
--- a/app/ui/screens/pizza/PizzaAdminScreen.js
+++ b/app/ui/screens/pizza/PizzaAdminScreen.js
@@ -48,11 +48,11 @@ class PizzaAdminScreen extends Component {
const filterTypes = [
{
- label: 'Disabled filter',
+ label: 'Show all',
checkItem: () => true,
},
{
- label: 'Filtering on payment',
+ label: 'Hide paid',
checkItem: (item) => item.select.value === PAYMENT_TYPES.NONE,
},
];
diff --git a/package.json b/package.json
index 900b5cb..691defa 100644
--- a/package.json
+++ b/package.json
@@ -41,7 +41,7 @@
"/__tests__/setup.js"
],
"transformIgnorePatterns": [
- "node_modules/(?!(react-native|@react-native-community|react-navigation|react-navigation-drawer|react-navigation-stack|@sentry|react-native-gesture-handler|react-native-vector-icons|react-native-linear-gradient|@react-native-firebase|react-native-image-crop-picker|react-native-reanimated|react-native-iphone-x-helper|react-native-render-html|react-native-webview|react-native-share|react-native-image-zoom-viewer|react-native-image-pan-zoom|react-native-add-calendar-event)/)"
+ "node_modules/(?!(react-native|@react-native-community|react-navigation|react-navigation-drawer|react-navigation-stack|@sentry|react-native-gesture-handler|react-native-vector-icons|react-native-linear-gradient|@react-native-firebase|react-native-image-crop-picker|react-native-reanimated|react-native-iphone-x-helper|react-native-render-html|react-native-webview|react-native-share|react-native-image-zoom-viewer|react-native-image-pan-zoom|react-native-add-calendar-event|react-native-floating-action)/)"
]
},
"prettier": {
@@ -67,6 +67,7 @@
"react-native-cli": "^2.0.1",
"react-native-device-info": "^7.0.2",
"react-native-dotenv": "^2.4.2",
+ "react-native-floating-action": "^1.21.0",
"react-native-fs": "^2.16.6",
"react-native-gesture-handler": "^1.8.0",
"react-native-image-crop-picker": "^0.35.1",
@@ -75,8 +76,8 @@
"react-native-reanimated": "^1.13.1",
"react-native-render-html": "^4.2.4",
"react-native-safe-area-context": "^3.1.8",
- "react-native-share": "^4.0.4",
"react-native-screens": "^2.12.0",
+ "react-native-share": "^4.0.4",
"react-native-snackbar": "^2.2.3",
"react-native-vector-icons": "^7.1.0",
"react-native-webview": "^10.10.0",
diff --git a/yarn.lock b/yarn.lock
index 1bb7cfa..e6f5dc7 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -7467,6 +7467,11 @@ react-native-dotenv@^2.4.2:
dependencies:
dotenv "^8.0.0"
+react-native-floating-action@^1.21.0:
+ version "1.21.0"
+ resolved "https://registry.yarnpkg.com/react-native-floating-action/-/react-native-floating-action-1.21.0.tgz#cb1e8349fec5b9aed06c8053c07372822c64b22f"
+ integrity sha512-ozd/iaJunrEYc4eGUWkP+4UI8yoIL0nQsToI3hnJRste/3LPhBkyu0eG3RTjc6aFY+q++JpRmgO469Ck8jJOwg==
+
react-native-fs@^2.16.6:
version "2.16.6"
resolved "https://registry.yarnpkg.com/react-native-fs/-/react-native-fs-2.16.6.tgz#2901789a43210a35a0ef0a098019bbef3af395fd"