Skip to content

Instantly share code, notes, and snippets.

@varunon9
Created February 24, 2019 19:41
Show Gist options
  • Save varunon9/8b2a97394da92fd66f914c43c7945afe to your computer and use it in GitHub Desktop.
Save varunon9/8b2a97394da92fd66f914c43c7945afe to your computer and use it in GitHub Desktop.
react-native-toggle-calendar- customized calendar built on top of react-native-calendars to support horizontal and grid calendar view
import React from 'react';
import { View, Text, StyleSheet, TouchableOpacity } from 'react-native';
import PropTypes from 'prop-types';
const weekDaysNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
class CalendarDayComponent extends React.Component {
constructor(props) {
super(props);
this.onDayPress = this.onDayPress.bind(this);
}
getContentStyle() {
const { state, marking = {}, date, current } = this.props;
const style= {
content: {},
text: {
color: '#181c26'
}
};
if (marking.soldOut) {
style.text.color = '#fff';
style.content.backgroundColor = '#e35052';
style.content.borderRadius = 50;
} else if (marking.blocked) {
style.text.color = '#fff';
style.content.backgroundColor = '#c1c2c1';
style.content.borderRadius = 50;
} else if (state === 'disabled') {
style.text.color = '#c1c2c1';
} else if (state === 'today') {
style.text.color = '#fff';
style.content.backgroundColor = '#216bc9';
style.content.borderRadius = 50;
} else if (current === date.dateString) {
style.content.borderRadius = 50;
style.content.borderWidth = 1;
style.content.borderColor = '#216bc9';
}
return style;
}
getFooterTextStyle() {
const { marking = {} } = this.props;
const style = {
color: '#c1c2c1'
};
if (marking.inventory > 0) {
style.color = '#4caf50';
}
return style;
}
getInventoryCount() {
const { marking = {} } = this.props;
if (typeof marking === 'object') {
if (marking.inventory >= 0) {
return marking.inventory;
}
}
return 'NA';
}
onDayPress() {
this.props.onPress(this.props.date);
}
render() {
const contentStyle = this.getContentStyle();
return (
<View style={styles.container}>
<View style={styles.header}>
{
this.props.horizontal ?
<Text style={styles.weekName} numberOfLines={1}>
{
weekDaysNames[this.props.date.weekDay]
}
</Text>
:
null
}
</View>
<TouchableOpacity
style={[styles.content, contentStyle.content]}
onPress={this.onDayPress}
>
<Text style={[styles.contentText, contentStyle.text]}>
{String(this.props.children)}
</Text>
</TouchableOpacity>
<View>
<Text style={this.getFooterTextStyle()}>
{this.getInventoryCount()}
</Text>
</View>
</View>
);
}
}
CalendarDayComponent.propTypes = {
children: PropTypes.any,
state: PropTypes.string,
marking: PropTypes.any,
horizontal: PropTypes.bool,
date: PropTypes.object,
onPress: PropTypes.func.isRequired,
current: PropTypes.string
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
marginLeft: 7,
marginRight: 7
},
weekName: {
width: 32,
textAlign: 'center',
fontSize: 12,
textTransform: 'uppercase',
fontWeight: 'bold',
color: '#7c7c7c'
},
content: {
width: 36,
height: 36,
justifyContent: 'center',
alignItems: 'center'
},
contentText: {
fontSize: 18
}
});
export default CalendarDayComponent;
import React from 'react';
import {
View, Text, StyleSheet, Image, TouchableOpacity
} from 'react-native';
import PropTypes from 'prop-types';
const weekDaysNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
class CalendarHeaderComponent extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<View style={styles.container}>
<View style={styles.header}>
<Text style={styles.dateText}>
{this.props.headerData.calendarDate}
</Text>
<TouchableOpacity
style={styles.iconContainer}
onPress={this.props.onPressArrowLeft}
>
<Image
style={[styles.icon, styles.leftIcon]}
source={require('../../images/arrow.png')}
/>
</TouchableOpacity>
<TouchableOpacity
style={styles.iconContainer}
onPress={this.props.onPressArrowRight}
>
<Image
style={styles.icon}
source={require('../../images/arrow.png')}
/>
</TouchableOpacity>
<TouchableOpacity
style={[
styles.iconContainer, {
opacity: this.props.horizontal ? 0.2 : 1
}
]}
onPress={this.props.onPressListView}
disabled={this.props.horizontal}
>
<Image
style={styles.icon}
source={require('../../images/list.png')}
/>
</TouchableOpacity>
<TouchableOpacity
style={[
styles.iconContainer, {
opacity: this.props.horizontal ? 1 : 0.2
}
]}
onPress={this.props.onPressGridView}
disabled={!this.props.horizontal}
>
<Image
style={styles.icon}
source={require('../../images/grid.png')}
/>
</TouchableOpacity>
</View>
{
// not showing week day in case of horizontal calendar, this will be handled by day component
this.props.horizontal ?
null
:
<View style={styles.week}>
{weekDaysNames.map((day, index) => (
<Text key={index} style={styles.weekName} numberOfLines={1}>
{day}
</Text>
))}
</View>
}
</View>
);
}
}
CalendarHeaderComponent.propTypes = {
headerData: PropTypes.object.isRequired,
horizontal: PropTypes.bool,
onPressArrowRight: PropTypes.func.isRequired,
onPressArrowLeft: PropTypes.func.isRequired,
onPressListView: PropTypes.func.isRequired,
onPressGridView: PropTypes.func.isRequired
};
const styles = StyleSheet.create({
container: {
flex: 1
},
header: {
flexDirection: 'row',
padding: 12,
backgroundColor: '#eceef1'
},
week: {
marginTop: 7,
flexDirection: 'row',
justifyContent: 'space-around'
},
weekName: {
marginTop: 2,
marginBottom: 7,
width: 32,
textAlign: 'center',
fontSize: 12,
textTransform: 'uppercase',
fontWeight: 'bold',
color: '#7c7c7c'
},
dateText: {
flex: 6,
fontSize: 18
},
iconContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
leftIcon: {
transform: [{ rotate: '180deg' }]
},
icon: {
width: 24,
height: 24
}
});
export default CalendarHeaderComponent;
import React, { Component } from 'react';
import { View } from 'react-native';
import { Calendar } from 'react-native-calendars';
import moment from 'moment';
import CalendarDayComponent from './CalendarDayComponent';
import CalendarHeaderComponent from './CalendarHeaderComponent';
let calendarDate = moment();
class ViewInventoryMain extends Component {
constructor(props) {
super(props);
this.state = {
calendarDate: calendarDate.format('YYYY-MM-DD'),
horizontal: false
};
this.onPressArrowLeft = this.onPressArrowLeft.bind(this);
this.onPressArrowRight = this.onPressArrowRight.bind(this);
this.onPressListView = this.onPressListView.bind(this);
this.onPressGridView = this.onPressGridView.bind(this);
this.onDayPress = this.onDayPress.bind(this);
}
onPressArrowLeft() {
calendarDate = calendarDate.add(-1, 'month');
this.updateCalendarDate();
}
onPressArrowRight() {
calendarDate = calendarDate.add(1, 'month');
this.updateCalendarDate();
}
onPressListView() {
this.setState({ horizontal: true });
}
onPressGridView() {
this.setState({ horizontal: false });
}
onDayPress(date) {
calendarDate = moment(date.dateString);
this.updateCalendarDate();
}
updateCalendarDate() {
this.setState({
calendarDate: calendarDate.format('YYYY-MM-DD')
});
}
render() {
return (
<View style={{ flex: 1 }}>
<Calendar
current={this.state.calendarDate}
dayComponent={CalendarDayComponent}
calendarHeaderComponent={CalendarHeaderComponent}
headerData={{
calendarDate: calendarDate.format('DD MMM, YYYY')
}}
style={{
paddingLeft: 0, paddingRight: 0
}}
onPressArrowLeft={this.onPressArrowLeft}
onPressArrowRight={this.onPressArrowRight}
onPressListView={this.onPressListView}
onPressGridView={this.onPressGridView}
markedDates={{
'2019-02-23': {soldOut: false, blocked: false, inventory: 2},
'2019-02-24': {soldOut: false, blocked: false, inventory: 2},
'2019-02-25': {soldOut: false, blocked: true, inventory: 0},
'2019-02-26': {soldOut: true, blocked: true, inventory: 2}
}}
horizontal={this.state.horizontal}
onDayPress={this.onDayPress}
/>
</View>
);
}
}
export default ViewInventoryMain;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment