UNPKG

zy-react-native-calendars

Version:
223 lines (201 loc) 6.85 kB
import React, {Component} from 'react'; import {FlatList, ActivityIndicator, View} from 'react-native'; import Reservation from './reservation'; import PropTypes from 'prop-types'; import XDate from 'xdate'; import dateutils from '../../dateutils'; import styleConstructor from './style'; class ReservationList extends Component { static displayName = 'IGNORE'; static propTypes = { // specify your item comparison function for increased performance rowHasChanged: PropTypes.func, // specify how each item should be rendered in agenda renderItem: PropTypes.func, // specify how each date should be rendered. day can be undefined if the item is not first in that day. renderDay: PropTypes.func, // specify how empty date content with no items should be rendered renderEmptyDate: PropTypes.func, // callback that gets called when day changes while scrolling agenda list onDayChange: PropTypes.func, // onScroll ListView event onScroll: PropTypes.func, // the list of items that have to be displayed in agenda. If you want to render item as empty date // the value of date key kas to be an empty array []. If there exists no value for date key it is // considered that the date in question is not yet loaded reservations: PropTypes.object, selectedDay: PropTypes.instanceOf(XDate), topDay: PropTypes.instanceOf(XDate), refreshControl: PropTypes.element, refreshing: PropTypes.bool, onRefresh: PropTypes.func, onScrollBeginDrag: PropTypes.func, onScrollEndDrag: PropTypes.func, onMomentumScrollBegin: PropTypes.func, onMomentumScrollEnd: PropTypes.func }; constructor(props) { super(props); this.styles = styleConstructor(props.theme); this.state = { reservations: [] }; this.heights=[]; this.selectedDay = this.props.selectedDay; this.scrollOver = true; } UNSAFE_componentWillMount() { this.updateDataSource(this.getReservations(this.props).reservations); } updateDataSource(reservations) { this.setState({ reservations }); } updateReservations(props) { const reservations = this.getReservations(props); if (this.list && !dateutils.sameDate(props.selectedDay, this.selectedDay)) { let scrollPosition = 0; for (let i = 0; i < reservations.scrollPosition; i++) { scrollPosition += this.heights[i] || 0; } this.scrollOver = false; this.list.scrollToOffset({offset: scrollPosition, animated: true}); } this.selectedDay = props.selectedDay; this.updateDataSource(reservations.reservations); } UNSAFE_componentWillReceiveProps(props) { if (!dateutils.sameDate(props.topDay, this.props.topDay)) { this.setState({ reservations: [] }, () => { this.updateReservations(props); }); } else { this.updateReservations(props); } } onScroll(event) { const yOffset = event.nativeEvent.contentOffset.y; this.props.onScroll(yOffset); let topRowOffset = 0; let topRow; for (topRow = 0; topRow < this.heights.length; topRow++) { if (topRowOffset + this.heights[topRow] / 2 >= yOffset) { break; } topRowOffset += this.heights[topRow]; } const row = this.state.reservations[topRow]; if (!row) return; const day = row.day; const sameDate = dateutils.sameDate(day, this.selectedDay); if (!sameDate && this.scrollOver) { this.selectedDay = day.clone(); this.props.onDayChange(day.clone()); } } onRowLayoutChange(ind, event) { this.heights[ind] = event.nativeEvent.layout.height; } renderRow({item, index}) { return ( <View onLayout={this.onRowLayoutChange.bind(this, index)}> <Reservation item={item} renderItem={this.props.renderItem} renderDay={this.props.renderDay} renderEmptyDate={this.props.renderEmptyDate} theme={this.props.theme} rowHasChanged={this.props.rowHasChanged} /> </View> ); } getReservationsForDay(iterator, props) { const day = iterator.clone(); const res = props.reservations[day.toString('yyyy-MM-dd')]; if (res && res.length) { return res.map((reservation, i) => { return { reservation, date: i ? false : day, day }; }); } else if (res) { return [{ date: iterator.clone(), day }]; } else { return false; } } onListTouch() { this.scrollOver = true; } getReservations(props) { if (!props.reservations || !props.selectedDay) { return {reservations: [], scrollPosition: 0}; } let reservations = []; if (this.state.reservations && this.state.reservations.length) { const iterator = this.state.reservations[0].day.clone(); while (iterator.getTime() < props.selectedDay.getTime()) { const res = this.getReservationsForDay(iterator, props); if (!res) { reservations = []; break; } else { reservations = reservations.concat(res); } iterator.addDays(1); } } const scrollPosition = reservations.length; const iterator = props.selectedDay.clone(); for (let i = 0; i < 31; i++) { const res = this.getReservationsForDay(iterator, props); if (res) { reservations = reservations.concat(res); } iterator.addDays(1); } return {reservations, scrollPosition}; } render() { const {reservations} = this.props; if (!reservations || !reservations[this.props.selectedDay.toString('yyyy-MM-dd')]) { if (this.props.renderEmptyData) { return this.props.renderEmptyData(); } return ( <ActivityIndicator style={{marginTop: 80}} color={this.props.theme && this.props.theme.indicatorColor}/> ); } return ( <FlatList ref={(c) => this.list = c} style={this.props.style} contentContainerStyle={this.styles.content} renderItem={this.renderRow.bind(this)} data={this.state.reservations} onScroll={this.onScroll.bind(this)} showsVerticalScrollIndicator={false} scrollEventThrottle={200} onMoveShouldSetResponderCapture={() => {this.onListTouch(); return false;}} keyExtractor={(item, index) => String(index)} refreshControl={this.props.refreshControl} refreshing={this.props.refreshing || false} onRefresh={this.props.onRefresh} onScrollBeginDrag={this.props.onScrollBeginDrag} onScrollEndDrag={this.props.onScrollEndDrag} onMomentumScrollBegin={this.props.onMomentumScrollBegin} onMomentumScrollEnd={this.props.onMomentumScrollEnd} /> ); } } export default ReservationList;