diff --git a/README.md b/README.md index a502536..f747fc5 100644 --- a/README.md +++ b/README.md @@ -27,3 +27,7 @@ # Output is in android/app/build/outputs/apk + +## Libraries + +We use https://nativebase.io/ for generic UI components diff --git a/src/modules/events/EventList.js b/src/modules/events/EventList.js index f67d593..d2ba341 100644 --- a/src/modules/events/EventList.js +++ b/src/modules/events/EventList.js @@ -1,41 +1,76 @@ -import {Platform, StyleSheet, FlatList, Text, View, Linking, TouchableOpacity, ActivityIndicator} from "react-native"; +import {StyleSheet, Linking, ActivityIndicator, View, SectionList} from "react-native"; +import {Card, ListItem, CardItem, Body, Text as Text, Left, Right, Icon, Button, Content} from 'native-base'; import React, { Component } from 'react'; import moment from "moment"; import 'moment/locale/nb'; export default class EventList extends Component { - _keyExtractor = (item, index) => item.id; - _renderItem = ({item}) => ( - - { this._onPressItem(item); }} style={[styles.listItem, styles.card]}> - - {item.title.rendered} - {this._formatTime(item.start_time)} - - - + { this._onPressItem(item); }} style={styles.listItem}> + + {item.title.decoded} + {this._formatTime(item.start_time)} + + + + + ); + _renderSectionHeader = ({section}) => { + return ( + + {section.title} + + ); + }; + + _renderFooter = () => { + if(!this.props.loading) { + return null; + } + + return ( + + ); + }; + _onPressItem = (item) => { Linking.openURL(item.link); }; + _formatTime(time) { moment.locale('nb'); return moment(time).format('llll'); } render() { - if(this.props.loading) { - return (Loading...) + if (this.props.error) { + return ( + + { this._onPressItem(item); }}> + Kunne ikke hente programmet... + + + + + + ) } - return ( item.id} refreshing={this.props.refreshing} + onRefresh={this.props.handleRefresh} + onEndReached={this.props.handleLoadMore} + onEndReachedThreshould={10} + initialNumToRender={10} + ListFooterComponent={this._renderFooter} + style={styles.list} />); } } @@ -43,40 +78,24 @@ export default class EventList extends Component { const styles = StyleSheet.create({ listItem: { - height: 86, + marginLeft: 0 }, listItemTitle: { - fontSize: 16, - fontWeight: 'bold', - color: 'black' + fontSize: 14, }, listItemTime: { - fontSize: 16, - color: 'black' + fontSize: 14, + color: '#666' }, - container: { - flex: 1, - }, - card: { - borderColor: '#e1e8ee', - borderWidth: 1, - ...Platform.select({ - ios: { - shadowColor: 'rgba(0,0,0, .2)', - shadowOffset: { height: 0, width: 0 }, - shadowOpacity: 1, - shadowRadius: 1, - }, - android: { - elevation: 1, - }, - }), - padding: 8, - margin: 8, - backgroundColor: '#fff', + listItemSectionTitle: { + fontSize: 14, + fontWeight: 'bold', }, loadingText: { textAlign: 'center', paddingBottom: 8 + }, + list: { + backgroundColor: 'white' } }); \ No newline at end of file diff --git a/src/modules/events/EventListContainer.js b/src/modules/events/EventListContainer.js index 9fc14b1..8f2573f 100644 --- a/src/modules/events/EventListContainer.js +++ b/src/modules/events/EventListContainer.js @@ -2,6 +2,8 @@ import {connect} from "react-redux"; import EventList from "./EventList"; import React from 'react'; +import moment from "moment"; +import 'moment/locale/nb'; /* Ref: https://medium.com/react-native-development/how-to-use-the-flatlist-component-react-native-basics-92c482816fe6 */ @@ -12,26 +14,81 @@ class EventListContainer extends React.Component { this.state = { loading: false, events: [], + eventsSectioned: [], page: 1, + noMorePages: false, error: null, refreshing: false, }; } + _formatDate(time) { + moment.locale('nb'); + return moment(time).format('ll'); + } + + _toSectionFormat(events) { + let sectioned = {}; + events.map((event) => { + const title = this._formatDate(event.start_time); + if( title in sectioned ) { + sectioned[title].push(event); + } else { + sectioned[title] = [event]; + } + }); + + let sectionedList = []; + Object.entries(sectioned).forEach(([title, section]) => { + sectionedList.push({data: section, title: title}); + }); + + return sectionedList; + } + + handleRefresh = () => { + this.setState({ + page: 1, + refreshing: true, + noMorePages: false, + }, () => { + this.fetchEvents() + }); + }; + + handleLoadMore = () => { + if(this.state.noMorePages || this.state.loading) { + return; + } + this.setState({ + page: this.state.page + 1, + }, () => { + this.fetchEvents(); + }) + }; + fetchEvents() { const { page } = this.state; - const url = `https://studentersamfundet.no/wp-json/wp/v2/events?future=1`; //&page=${page}&results=20`; + const url = `https://studentersamfundet.no/wp-json/wp/v2/events?page=${page}&future=1`; this.setState({ loading: true }); + fetch(url) .then(res => res.json()) .then(res => { - console.log(res); + if(res.code === 'rest_post_invalid_page_number') { + this.setState({ + noMorePages: true + }); + } + this.setState({ events: page === 1 ? res : [...this.state.events, ...res], + eventsSectioned: page === 1 ? this._toSectionFormat(res) : this._toSectionFormat([...this.state.events, ...res]), error: res.error || null, loading: false, refreshing: false }); + }) .catch(error => { this.setState({ error, loading: false }); @@ -43,7 +100,7 @@ class EventListContainer extends React.Component { } render() { - return () + return () } }