加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
Calendar.js 10.13 KB
一键复制 编辑 原始数据 按行查看 历史
hanwenbo 提交于 2020-05-15 16:52 . no message
/**
* Created by TinySymphony on 2017-05-08.
*/
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import {
View,
Text,
Modal,
Image,
TouchableHighlight
} from 'react-native';
import Moment from 'moment';
import styles from './CalendarStyle';
import MonthList from './MonthList';
export default class Calendar extends Component {
static propTypes = {
i18n: PropTypes.string,
format: PropTypes.string,
customI18n: PropTypes.object,
color: PropTypes.object,
minDate: PropTypes.oneOfType([PropTypes.string, PropTypes.instanceOf(Date)]),
maxDate: PropTypes.oneOfType([PropTypes.string, PropTypes.instanceOf(Date)])
}
static defaultProps = {
format: 'YYYY-MM-DD',
i18n: 'en',
customI18n: {},
color: {}
}
static I18N_MAP = {
'zh': {
'w': ['', '', '', '', '', '', '', ''],
'weekday': ['', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日'],
'text': {
'start': '开 始',
'end': '结 束',
'date': '日 期',
'save': '保 存',
'clear': '清除'
},
'date': 'M月D日'
},
'en': {
'w': ['', 'Mon', 'Tues', 'Wed', 'Thur', 'Fri', 'Sat', 'Sun'],
'weekday': ['', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'],
'text': {
'start': 'Start',
'end': 'End',
'date': 'Date',
'save': 'Save',
'clear': 'Reset'
},
'date': 'DD / MM'
},
'jp': {
'w': ['', '', '', '', '', '', '', ''],
'weekday': ['', '月曜日', '火曜日', '水曜日', '木曜日', '金曜日', '土曜日', '日曜日'],
'text': {
'start': 'スタート',
'end': 'エンド',
'date': '時 間',
'save': '確 認',
'clear': 'クリア'
},
'date': 'M月D日'
}
}
constructor (props) {
super(props);
this.state = {
isModalVisible: false
};
this._today = Moment();
this._year = this._today.year();
this._i18n = this._i18n.bind(this);
this._getDateRange = this._getDateRange.bind(this);
this._onChoose = this._onChoose.bind(this);
this._resetCalendar = this._resetCalendar.bind(this);
this.close = this.close.bind(this);
this.cancel = this.cancel.bind(this);
this.open = this.open.bind(this);
this.clear = this.clear.bind(this);
this.confirm = this.confirm.bind(this);
this._getDateRange();
}
componentDidMount () {
this._resetCalendar();
}
_i18n (data, type) {
const {
i18n,
customI18n
} = this.props;
if (~['w', 'weekday', 'text'].indexOf(type)) {
return (customI18n[type] || {})[data] || Calendar.I18N_MAP[i18n][type][data];
}
if (type === 'date') {
return data.format(customI18n[type] || Calendar.I18N_MAP[i18n][type]);
}
}
_resetCalendar () {
const {
startDate,
endDate,
format
} = this.props;
let start = Moment(startDate, format);
let end = Moment(endDate, format);
let isStartValid = start.isValid() && start >= this._minDate && start <= this._maxDate;
let isEndValid = end.isValid() && end >= this._minDate && end <= this._maxDate;
this.setState({
startDate: isStartValid ? start : null,
startDateText: isStartValid ? this._i18n(start, 'date') : '',
startWeekdayText: isStartValid ? this._i18n(start.isoWeekday(), 'weekday') : '',
endDate: isEndValid ? end: null,
endDateText: isEndValid ? this._i18n(end, 'date') : '',
endWeekdayText: isEndValid ? this._i18n(end.isoWeekday(), 'weekday') : ''
});
}
_getDateRange () {
const {
maxDate,
minDate,
format
} = this.props;
let max = Moment(maxDate, format);
let min = Moment(minDate, format);
let maxValid = max.isValid();
let minValid = min.isValid();
if (!maxValid && !minValid) {
max = Moment().add(3, 'months');
min = Moment();
}
if (!maxValid && minValid) {
max = min.add(3, 'months');
}
if (maxValid && !minValid) {
min = max.subtract(3, 'months');
}
if (min.isSameOrAfter(max)) return {};
this._minDate = min;
this._maxDate = max;
}
_onChoose (day) {
const {
startDate,
endDate,
} = this.state;
const { range } = this.props
if(range){
if ((!startDate && !endDate) || day < startDate || (startDate && endDate)) {
this.setState({
startDate: day,
endDate: null,
startDateText: this._i18n(day, 'date'),
startWeekdayText: this._i18n(day.isoWeekday(), 'weekday'),
endDateText: '',
endWeekdayText: '',
});
} else if (startDate && !endDate && day > startDate) {
this.setState({
endDate: day,
endDateText: this._i18n(day, 'date'),
endWeekdayText: this._i18n(day.isoWeekday(), 'weekday')
});
}
}else {
this.setState({
startDate: day,
endDate: null,
startDateText: this._i18n(day, 'date'),
startWeekdayText: this._i18n(day.isoWeekday(), 'weekday'),
endDateText: '',
endWeekdayText: '',
})
}
}
cancel () {
this.close();
this._resetCalendar();
}
close () {
this.setState({
isModalVisible: false
});
}
open () {
this.setState({
isModalVisible: true
});
}
clear () {
this.setState({
startDate: null,
endDate: null,
startDateText: '',
startWeekdayText: '',
endDateText: '',
endWeekdayText: ''
});
}
confirm () {
const {
startDate,
endDate
} = this.state;
let startMoment = startDate ? startDate.clone() : null;
let endMoment = endDate ? endDate.clone() : null;
this.props.onConfirm && this.props.onConfirm({
startDate: startMoment ? startMoment.toDate() : null,
endDate: endMoment ? endMoment.toDate() : null,
startMoment,
endMoment
});
this.close();
}
render () {
const {
startDate,
endDate,
startDateText,
startWeekdayText,
endDateText,
endWeekdayText
} = this.state;
const {
mainColor = '#15aaaa',
subColor = '#fff',
borderColor = 'rgba(255, 255, 255, 0.50)'
} = this.props.color;
const {
disabledDate,
range
} = this.props
let color = {mainColor, subColor, borderColor};
let mainBack = {backgroundColor: mainColor};
let subBack = {backgroundColor: subColor};
let mainFontColor = {color: mainColor};
let subFontColor = {color: subColor};
let isValid = range ? (!startDate || endDate) : startDate;
let isClearVisible = startDate || endDate;
return (
<Modal
animationType={'slide'}
visible={this.state.isModalVisible}
onRequestClose={this.close}>
<View style={[styles.container, mainBack]}>
<View style={styles.ctrl}>
<TouchableHighlight
underlayColor="transparent"
onPress={this.cancel}
>
<Image
style={styles.closeIcon}
source={require('./close.png')}
resizeMode="cover"/>
</TouchableHighlight>
{isClearVisible && <TouchableHighlight
underlayColor="transparent"
activeOpacity={0.8}
onPress={this.clear}>
<Text style={[styles.clearText, subFontColor]}>{this._i18n('clear', 'text')}</Text>
</TouchableHighlight>}
</View>
<View style={styles.result}>
<View style={styles.resultPart}>
<Text style={[styles.resultText, styles.startText, subFontColor]}>
{startDateText || this._i18n('start', 'text')}
</Text>
<Text style={[styles.resultText, styles.startText, subFontColor]}>
{startWeekdayText || this._i18n('date', 'text')}
</Text>
</View>
<View style={[styles.resultSlash, subBack]}/>
<View style={styles.resultPart}>
<Text style={[styles.resultText, styles.endText, subFontColor]}>
{endDateText || this._i18n('end', 'text')}
</Text>
<Text style={[styles.resultText, styles.endText, subFontColor]}>
{endWeekdayText || this._i18n('date', 'text')}
</Text>
</View>
</View>
<View style={styles.week}>
{[7, 1, 2, 3, 4, 5, 6].map(item =>
<Text style={[styles.weekText, subFontColor]} key={item}>{this._i18n(item, 'w')}</Text>
)}
</View>
<View style={[styles.scroll, {borderColor}]}>
<MonthList
today={this._today}
minDate={this._minDate}
maxDate={this._maxDate}
startDate={this.state.startDate}
endDate={this.state.endDate}
onChoose={this._onChoose}
i18n={this.props.i18n}
color={color}
disabledDate={disabledDate}
/>
</View>
<View style={styles.btn}>
{isValid ?
<TouchableHighlight
underlayColor="rgba(255, 255, 255, 0.45)"
style={styles.confirmContainer}
onPress={this.confirm}>
<View style={styles.confirmBtn}>
<Text
ellipsisMode="tail" numberOfLines={1}
style={[styles.confirmText, subFontColor]}>
{this._i18n('save', 'text')}
</Text>
</View>
</TouchableHighlight> :
<View style={[styles.confirmContainer, styles.confirmContainerDisabled]}>
<View style={styles.confirmBtn}>
<Text
ellipsisMode="tail" numberOfLines={1}
style={[styles.confirmText, styles.confirmTextDisabled]}>
{this._i18n('save', 'text')}
</Text>
</View>
</View>
}
</View>
</View>
</Modal>
);
}
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化