Commit 8368f1ef authored by Sébastiaan Versteeg's avatar Sébastiaan Versteeg
Browse files

Add registrations to event detail

parent 80dcd3f8
......@@ -9,3 +9,5 @@ export const CALENDARRETREIVED = 'CALENDARRETREIVED';
export const CALENDARERROR = 'CALENDARERROR';
export const LOADEVENTSUCCESS = 'LOADEVENTSUCCESS';
export const LOADEVENTFAILURE = 'LOADEVENTFAILURE';
export const LOADEVENTREGISTRATIONSSUCCESS = 'LOADEVENTREGISTRATIONSSUCCESS';
export const LOADEVENTREGISTRATIONSFAILURE = 'LOADEVENTREGISTRATIONSFAILURE';
......@@ -2,16 +2,16 @@ import * as types from './actionTypes';
import { navigate } from './navigation';
import { url } from '../url';
export function success(data) {
export function success(type, data) {
return {
type: types.LOADEVENTSUCCESS,
type,
data,
};
}
export function fail() {
export function fail(type) {
return {
type: types.LOADEVENTFAILURE,
type,
};
}
......@@ -31,15 +31,42 @@ export function loadEvent(id, token) {
)
.then(
(response) => {
dispatch(success(response));
dispatch(success(types.LOADEVENTSUCCESS, response));
dispatch(navigate('event'));
},
)
.catch(
() => {
dispatch(fail());
dispatch(fail(types.LOADEVENTFAILURE));
dispatch(navigate('event'));
},
);
};
}
export function loadRegistrations(id, token) {
return (dispatch) => {
const data = {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Token ${token}`,
},
};
return fetch(`${url}/api/events/${id}/registrations`, data)
.then(
response => response.json(),
)
.then(
(response) => {
dispatch(success(types.LOADEVENTREGISTRATIONSSUCCESS, response));
},
)
.catch(
() => {
dispatch(fail(types.LOADEVENTREGISTRATIONSFAILURE));
},
);
};
}
import React from 'react';
import {Image, ScrollView, Text, View} from 'react-native';
import { Image, ScrollView, Text, View } from 'react-native';
import { connect } from 'react-redux';
import Moment from 'moment';
import 'moment/locale/nl';
import styles from './style/event';
import * as actions from '../actions/events';
import MemberView from './MemberView';
const REGISTRATION_NOT_NEEDED = -1;
const REGISTRATION_NOT_YET_OPEN = 0;
......@@ -16,6 +18,8 @@ const REGISTRATION_CLOSED_CANCEL_ONLY = 4;
const Event = (props) => {
if (props.success) {
props.loadRegistrations(props.data.pk, props.token);
const eventDesc = (data) => {
const startDate = Moment(data.start).format('D MMM YYYY, HH:mm');
const endDate = Moment(data.end).format('D MMM YYYY, HH:mm');
......@@ -125,6 +129,49 @@ const Event = (props) => {
return (<View />);
};
const registrationsGrid = (registrations) => {
if (registrations !== undefined && registrations.length > 0) {
return (
<View>
<View style={styles.divider} />
<Text style={styles.registrationsTitle}>Aanmeldingen</Text>
<View style={styles.registrationsView}>
{ props.registrations.map((item, index) => {
if (index % 3 === 0) {
return props.registrations.slice(index, index + 3);
}
return null;
}).filter(item => item)
.map((list) => {
while (list.length < 3) {
list.push({});
}
return (
<View style={styles.registrationsRow}>
{list.map((reg, i) => {
const style = i === 1 ? styles.registrationsItemMargin :
styles.registrationsItem;
if (reg.name) {
return (
<MemberView member={reg} style={style} />
);
}
return (
<View style={style} />
);
})}
</View>
);
})
}
</View>
</View>
);
}
return (<View />);
};
return (
<ScrollView contentContainerStyle={styles.eventView}>
<Image style={styles.locationImage} source={{ uri: `https://maps.googleapis.com/maps/api/staticmap?center=${props.data.map_location}&zoom=13&size=450x250&markers=${props.data.map_location}` }} />
......@@ -134,20 +181,22 @@ const Event = (props) => {
</Text>
{eventActions(props.data)}
{eventInfo(props.data)}
{/* <Button color={colors.magenta} style={styles.registerButton}
title="Aanmelden" onPress={() => {}} />*/}
<View style={styles.divider} />
<Text style={styles.descText}>{props.data.description}</Text>
{registrationsGrid(props.registrations)}
</ScrollView>
);
}
return (
<Text>Kon het evenement niet laden...</Text>
<ScrollView contentContainerStyle={styles.eventView}>
<Text>Kon het evenement niet laden...</Text>
</ScrollView>
);
};
Event.propTypes = {
data: React.PropTypes.shape({
pk: React.PropTypes.number.isRequired,
title: React.PropTypes.string.isRequired,
description: React.PropTypes.string.isRequired,
start: React.PropTypes.string.isRequired,
......@@ -173,12 +222,24 @@ Event.propTypes = {
}),
no_registration_message: React.PropTypes.string,
}).isRequired,
registrations: React.PropTypes.arrayOf(React.PropTypes.shape({
member: React.PropTypes.number,
name: React.PropTypes.string.isRequired,
})).isRequired,
success: React.PropTypes.bool.isRequired,
token: React.PropTypes.string.isRequired,
loadRegistrations: React.PropTypes.func.isRequired,
};
const mapStateToProps = state => ({
data: state.events.data,
registrations: state.events.registrations,
success: state.events.success,
token: state.session.token,
});
const mapDispatchToProps = dispatch => ({
loadRegistrations: (id, token) => dispatch(actions.loadRegistrations(id, token)),
});
export default connect(mapStateToProps, () => ({}))(Event);
export default connect(mapStateToProps, mapDispatchToProps)(Event);
import React from 'react';
import { Image, Text, ViewPropTypes, StyleSheet } from 'react-native';
import { connect } from 'react-redux';
import styles from './style/memberView';
import SquareView from './SquareView';
const MemberView = props => (
<SquareView style={props.style}>
<Image style={styles.image} source={{ uri: props.member.photo }} />
<Text style={styles.nameText}>{props.member.name}</Text>
</SquareView>
);
MemberView.propTypes = {
member: React.PropTypes.shape({
name: React.PropTypes.string,
photo: React.PropTypes.string,
}).isRequired,
style: ViewPropTypes.style,
};
const defaultStyles = StyleSheet.create({
});
MemberView.defaultProps = {
style: defaultStyles,
};
export default connect(() => ({}), () => ({}))(MemberView);
import React, { Component } from 'react';
import { View, ViewPropTypes, StyleSheet } from 'react-native';
class SquareView extends Component {
constructor(props) {
super(props);
this.state = {
width: 0,
height: 0,
direction: 'column', // 'column' and 'row'
};
}
render() {
const square = (
<View
{...this.props}
style={[this.props.style, { width: this.state.width, height: this.state.height }]}
onLayout={(event) => {
const { width, height } = event.nativeEvent.layout;
const sideLength = Math.max(width, height);
if (sideLength) {
this.setState({ width: sideLength, height: sideLength });
} else {
this.setState({ direction: 'column' });
}
}}
>
{this.props.children}
</View>
);
switch (this.state.direction) {
case 'column':
return square;
case 'row':
// eslint-disable-next-line react-native/no-inline-styles,react-native/no-color-literals
return (<View style={{ backgroundColor: 'transparent' }}>{square}</View>);
default:
return null;
}
}
}
SquareView.propTypes = {
children: React.PropTypes.node.isRequired,
style: ViewPropTypes.style,
};
const styles = StyleSheet.create({
});
SquareView.defaultProps = {
style: styles,
};
export default SquareView;
......@@ -3,6 +3,7 @@ import { create, colors } from '../../style';
const styles = create({
eventView: {
padding: 16,
backgroundColor: colors.backgroundColour,
},
locationImage: {
height: 150,
......@@ -40,6 +41,33 @@ const styles = create({
lineHeight: 24.0,
color: colors.black,
},
registrationsTitle: {
fontFamily: 'sans-serif-medium',
fontSize: 14,
color: colors.darkGrey,
marginBottom: 16,
},
registrationsView: {
flex: 1,
flexDirection: 'column',
alignItems: 'stretch',
justifyContent: 'space-between',
},
registrationsRow: {
flex: 1,
flexDirection: 'row',
alignSelf: 'stretch',
justifyContent: 'space-between',
marginBottom: 16,
},
registrationsItem: {
flex: 1,
},
registrationsItemMargin: {
flex: 1,
marginLeft: 16,
marginRight: 16,
},
divider: {
marginLeft: -16,
marginRight: -16,
......@@ -47,7 +75,7 @@ const styles = create({
marginBottom: 16,
alignSelf: 'stretch',
borderStyle: 'solid',
borderWidth: 1,
borderWidth: 0.5,
borderColor: colors.dividerGrey,
},
italicText: {
......
import { StyleSheet } from 'react-native';
import { colors } from '../../style';
const styles = StyleSheet.create({
nameText: {
fontSize: 11,
color: colors.white,
position: 'absolute',
left: 6,
bottom: 4,
right: 6,
},
image: {
flex: 1,
},
});
export default styles;
......@@ -13,6 +13,7 @@ const initialState = {
status: -1,
registered: false,
},
registrations: [],
success: false,
};
......@@ -20,6 +21,7 @@ export default function loadEvent(state = initialState, action = {}) {
switch (action.type) {
case types.LOADEVENTSUCCESS:
return {
...state,
data: action.data,
success: true,
};
......@@ -28,6 +30,16 @@ export default function loadEvent(state = initialState, action = {}) {
...state,
success: false,
};
case types.LOADEVENTREGISTRATIONSSUCCESS:
return {
...state,
registrations: action.data,
};
case types.LOADEVENTREGISTRATIONSFAILURE:
return {
...state,
registrations: action.data,
};
default:
return state;
}
......
......@@ -9,6 +9,7 @@ export const colors = {
textColour: '#313131',
darkGrey: '#373737',
dividerGrey: 'rgba(0, 0, 0, 0.12)',
backgroundColour: '#FAFAFA',
};
export function create(styles) {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment