@momo-kits/calendar 0.0.41-beta → 0.0.41-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -1,3 +1,4 @@
1
1
  import Calendar from './src/Calendar';
2
+ import CalendarPicker from './src/calendarPicker/index';
2
3
 
3
- export default Calendar;
4
+ export { Calendar, CalendarPicker };
package/package.json CHANGED
@@ -1,14 +1,16 @@
1
1
  {
2
2
  "name": "@momo-kits/calendar",
3
- "version": "0.0.41-beta",
3
+ "version": "0.0.41-beta.10",
4
4
  "private": false,
5
5
  "main": "index.js",
6
- "dependencies": {},
6
+ "dependencies": {
7
+ "@momo-kits/date-picker": "latest",
8
+ "moment": "^2.24.0"
9
+ },
7
10
  "peerDependencies": {
8
11
  "react": "16.9.0",
9
12
  "react-native": ">=0.55",
10
13
  "prop-types": "^15.7.2",
11
- "moment": "^2.24.0",
12
14
  "@momo-kits/core": ">=0.0.5-beta"
13
15
  },
14
16
  "devDependencies": {},
package/src/Day/index.js CHANGED
@@ -1,193 +1,210 @@
1
- import React, { Component } from 'react';
1
+ import React, {Component} from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
 
4
- import {
5
- View,
6
- TouchableHighlight,
7
- Text
8
- } from 'react-native';
9
- import { Colors, SwitchLanguage } from '@momo-kits/core';
4
+ import {View, TouchableHighlight, Text} from 'react-native';
5
+ import {Colors, SwitchLanguage} from '@momo-kits/core';
10
6
  import style from './style';
11
7
 
12
8
  class Day extends Component {
13
- constructor(props) {
14
- super(props);
15
- this.statusCheck();
16
- }
9
+ constructor(props) {
10
+ super(props);
11
+ this.statusCheck();
12
+ }
17
13
 
18
- chooseDay = () => {
19
- const { onChoose, date } = this.props;
20
- onChoose && onChoose(date);
21
- };
14
+ chooseDay = () => {
15
+ const {onChoose, date} = this.props;
16
+ onChoose && onChoose(date);
17
+ };
22
18
 
23
- findHoliday = (date, holidays) => {
24
- if (date && holidays && holidays.length > 0) {
25
- const day = date.date();
26
- const month = date.month() + 1;
27
- return holidays.find((item) => item.day === day && item.month === month);
28
- }
29
- return null;
30
- };
19
+ findHoliday = (date, holidays) => {
20
+ if (date && holidays && holidays.length > 0) {
21
+ const day = date.date();
22
+ const month = date.month() + 1;
23
+ return holidays.find(item => item.day === day && item.month === month);
24
+ }
25
+ return null;
26
+ };
31
27
 
32
- checkHoliday = (date, holidays) => {
33
- const holiday = this.findHoliday(date, holidays);
34
- return {
35
- solarHoliday: !!(holiday && !holiday.lunar),
36
- lunarHoliday: !!(holiday && holiday.lunar)
37
- };
28
+ checkHoliday = (date, holidays) => {
29
+ const holiday = this.findHoliday(date, holidays);
30
+ return {
31
+ solarHoliday: !!(holiday && !holiday.lunar),
32
+ lunarHoliday: !!(holiday && holiday.lunar),
38
33
  };
34
+ };
39
35
 
40
- statusCheck = (props) => {
41
- const {
42
- startDate,
43
- endDate,
44
- date = null,
45
- minDate,
46
- maxDate,
47
- empty,
48
- index,
49
- isShowLunar,
50
- tabSelected,
51
- isDoubleDateMode,
52
- lunarDate,
53
- isSolarHoliday,
54
- isLunarHoliday,
55
- price
56
- } = props || this.props;
57
- this.isValid = date && (date >= minDate || date.isSame(minDate, 'day')) && (date <= maxDate || date.isSame(maxDate, 'day'));
58
- this.isMid = isDoubleDateMode && date > startDate && date < endDate
59
- || (!date && empty >= startDate && empty <= endDate);
60
- this.isStart = date && date.isSame(startDate, 'd');
61
- this.isStartPart = this.isStart && endDate;
62
- this.isEnd = isDoubleDateMode && date && date.isSame(endDate, 'day');
63
- this.isFocus = this.isMid || this.isStart || this.isEnd;
64
- this.isWeekEnd = index === 6 || index === 5;
65
- this.showLunar = isShowLunar;
66
- this.lunarDate = lunarDate;
67
- this.isDoubleDateMode = isDoubleDateMode;
68
- this.isLunarHoliday = isLunarHoliday;
69
- this.isLunarDayStart = this.lunarDate && this.lunarDate.lunarDay === 1;
70
- this.isSolarHoliday = isSolarHoliday;
71
- this.isInScope = isDoubleDateMode ? (tabSelected === 0 || (tabSelected === 1 && startDate && date && date.isSameOrAfter(startDate, 'day'))) : true;
72
- return this.isFocus || this.diffPrice;
73
- };
36
+ statusCheck = props => {
37
+ const {
38
+ startDate,
39
+ endDate,
40
+ date = null,
41
+ minDate,
42
+ maxDate,
43
+ empty,
44
+ index,
45
+ isShowLunar,
46
+ tabSelected,
47
+ isDoubleDateMode,
48
+ lunarDate,
49
+ isSolarHoliday,
50
+ isLunarHoliday,
51
+ price,
52
+ } = props || this.props;
53
+ this.isValid =
54
+ date &&
55
+ (date >= minDate || date.isSame(minDate, 'day')) &&
56
+ (date <= maxDate || date.isSame(maxDate, 'day'));
57
+ this.isMid =
58
+ (isDoubleDateMode && date > startDate && date < endDate) ||
59
+ (!date && empty >= startDate && empty <= endDate);
60
+ this.isStart = date && date.isSame(startDate, 'd');
61
+ this.isStartPart = this.isStart && endDate;
62
+ this.isEnd = isDoubleDateMode && date && date.isSame(endDate, 'day');
63
+ this.isFocus = this.isMid || this.isStart || this.isEnd;
64
+ this.isWeekEnd = index === 6 || index === 5;
65
+ this.showLunar = isShowLunar;
66
+ this.lunarDate = lunarDate;
67
+ this.isDoubleDateMode = isDoubleDateMode;
68
+ this.isLunarHoliday = isLunarHoliday;
69
+ this.isLunarDayStart = this.lunarDate && this.lunarDate.lunarDay === 1;
70
+ this.isSolarHoliday = isSolarHoliday;
71
+ this.isInScope = isDoubleDateMode
72
+ ? tabSelected === 0 ||
73
+ (tabSelected === 1 &&
74
+ startDate &&
75
+ date &&
76
+ date.isSameOrAfter(startDate, 'day'))
77
+ : true;
78
+ return this.isFocus || this.diffPrice;
79
+ };
74
80
 
75
- shouldComponentUpdate(nextProps) {
76
- const {
77
- isDoubleDateMode, isShowLunar, tabSelected, isSolarHoliday,
78
- isLunarHoliday,
79
- price,
80
- isBestPrice,
81
- startDate,
82
- endDate
83
- } = this.props;
84
- const prevStatus = this.isFocus;
85
- const selectionModeChange = isDoubleDateMode !== nextProps.isDoubleDateMode;
86
- const lunarChange = isShowLunar !== nextProps.isShowLunar;
87
- const nextStatus = this.statusCheck(nextProps);
88
- const tabChange = tabSelected !== nextProps.tabSelected;
89
- const solarHoliday = isSolarHoliday !== nextProps.isSolarHoliday;
90
- const lunarHoliday = isLunarHoliday !== nextProps.isLunarHoliday;
91
- const diffPrice = price !== nextProps.price && isBestPrice !== nextProps.isBestPrice;
92
- const startDateChange = startDate && !startDate?.isSame?.(nextProps.startDate, 'day');
93
- const endDateChange = endDate && !endDate?.isSame?.(nextProps.endDate, 'day');
94
- return !!(prevStatus !== nextStatus || selectionModeChange || lunarChange || tabChange || solarHoliday || lunarHoliday || diffPrice || startDateChange || endDateChange);
95
- }
81
+ shouldComponentUpdate(nextProps) {
82
+ const {
83
+ isDoubleDateMode,
84
+ isShowLunar,
85
+ tabSelected,
86
+ isSolarHoliday,
87
+ isLunarHoliday,
88
+ price,
89
+ isBestPrice,
90
+ startDate,
91
+ endDate,
92
+ } = this.props;
93
+ const prevStatus = this.isFocus;
94
+ const selectionModeChange = isDoubleDateMode !== nextProps.isDoubleDateMode;
95
+ const lunarChange = isShowLunar !== nextProps.isShowLunar;
96
+ const nextStatus = this.statusCheck(nextProps);
97
+ const tabChange = tabSelected !== nextProps.tabSelected;
98
+ const solarHoliday = isSolarHoliday !== nextProps.isSolarHoliday;
99
+ const lunarHoliday = isLunarHoliday !== nextProps.isLunarHoliday;
100
+ const diffPrice =
101
+ price !== nextProps.price && isBestPrice !== nextProps.isBestPrice;
102
+ const startDateChange =
103
+ startDate && !startDate?.isSame?.(nextProps.startDate, 'day');
104
+ const endDateChange =
105
+ endDate && !endDate?.isSame?.(nextProps.endDate, 'day');
106
+ return !!(
107
+ prevStatus !== nextStatus ||
108
+ selectionModeChange ||
109
+ lunarChange ||
110
+ tabChange ||
111
+ solarHoliday ||
112
+ lunarHoliday ||
113
+ diffPrice ||
114
+ startDateChange ||
115
+ endDateChange
116
+ );
117
+ }
96
118
 
97
- render() {
98
- const {
99
- date, empty, isDoubleDateMode, price, isBestPrice, isShowPrice, labelFrom, labelTo, isHideLabel
100
- } = this.props;
101
- const text = date ? date.date() : '';
102
- return (
103
- <View style={style.dayContainer}>
104
- <View style={[
105
- this.isMid && !empty && style.mid,
106
- this.isStartPart && style.dayStartContainer,
107
- this.isEnd && style.dayEndContainer
108
-
109
- ]}
110
- >
111
- {this.isValid && this.isInScope
112
- ? (
113
- <TouchableHighlight
114
- style={[
115
- style.day,
116
- (this.isStart || this.isEnd) && style.focused
117
- ]}
118
- underlayColor="rgba(255, 255, 255, 0.35)"
119
- onPress={this.chooseDay}
120
- >
121
- <>
122
- <Text style={[
123
- style.dayText,
124
- this.isWeekEnd && style.weekendDay,
125
- this.isSolarHoliday && style.weekendDay,
126
- (this.isStart || this.isEnd) && style.focusedText,
127
- ]}
128
- >
129
- {text}
130
- </Text>
131
- {
132
- this.lunarDate && this.showLunar && (
133
- <Text style={[
134
- style.lunarDayText,
135
- (this.isLunarHoliday || this.isLunarDayStart) && style.weekendDay,
136
- (this.isStart || this.isEnd) && style.focusedText,
137
- ]}
138
- >
139
- {this.lunarDate.lunarDay === 1 ? `${this.lunarDate.lunarDay}/${this.lunarDate.lunarMonth}` : this.lunarDate.lunarDay}
140
- </Text>
141
- )
142
- }
143
- </>
144
- </TouchableHighlight>
145
- )
146
- : (
147
- <View style={[style.day]}>
148
- <Text style={[
149
- style.dayText,
150
- style.dayTextDisabled,
151
- ]}
152
- >
153
- {text}
154
- </Text>
155
- {
156
- this.lunarDate && this.showLunar && text ? (
157
- <Text style={[
158
- style.lunarDayText,
159
- style.dayTextDisabled,
160
- ]}
161
- >
162
- {this.lunarDate.lunarDay === 1 ? `${this.lunarDate.lunarDay}/${this.lunarDate.lunarMonth}` : this.lunarDate.lunarDay}
163
- </Text>
164
- ) : <View />
165
- }
166
- </View>
167
- )}
168
- </View>
169
-
170
- {(isDoubleDateMode && this.isStart && !isHideLabel) && (
171
- <View style={style.txtGo}>
172
- <Text style={{ fontSize: 8, color: 'white' }}>
173
- {labelFrom || SwitchLanguage.departing}
174
- </Text>
175
- </View>
176
- )}
177
- {(isDoubleDateMode && this.isEnd && !isHideLabel) && (
178
- <View style={style.txtBack}>
179
- <Text style={{ fontSize: 8, color: 'white' }}>
180
- {labelTo || SwitchLanguage.returning}
181
- </Text>
182
- </View>
119
+ render() {
120
+ const {
121
+ date,
122
+ empty,
123
+ isDoubleDateMode,
124
+ price,
125
+ isBestPrice,
126
+ isShowPrice,
127
+ labelFrom,
128
+ labelTo,
129
+ isHideLabel,
130
+ } = this.props;
131
+ const text = date ? date.date() : '';
132
+ return (
133
+ <View style={style.dayContainer}>
134
+ <View
135
+ style={[
136
+ this.isMid && !empty && style.mid,
137
+ this.isStartPart && style.dayStartContainer,
138
+ this.isEnd && style.dayEndContainer,
139
+ ]}>
140
+ {this.isValid && this.isInScope ? (
141
+ <TouchableHighlight
142
+ style={[style.day, (this.isStart || this.isEnd) && style.focused]}
143
+ underlayColor="rgba(255, 255, 255, 0.35)"
144
+ onPress={this.chooseDay}>
145
+ <>
146
+ <Text
147
+ style={[
148
+ style.dayText,
149
+ this.isWeekEnd && style.weekendDay,
150
+ this.isSolarHoliday && style.weekendDay,
151
+ (this.isStart || this.isEnd) && style.focusedText,
152
+ ]}>
153
+ {text}
154
+ </Text>
155
+ {this.lunarDate && this.showLunar && (
156
+ <Text
157
+ style={[
158
+ style.lunarDayText,
159
+ (this.isLunarHoliday || this.isLunarDayStart) &&
160
+ style.weekendDay,
161
+ (this.isStart || this.isEnd) && style.focusedText,
162
+ ]}>
163
+ {this.lunarDate.lunarDay === 1
164
+ ? `${this.lunarDate.lunarDay}/${this.lunarDate.lunarMonth}`
165
+ : this.lunarDate.lunarDay}
166
+ </Text>
183
167
  )}
184
- {this.isValid
185
- && this.isInScope
186
- && !!(price)
187
- && <Text style={[style.price, isBestPrice && { color: Colors.pink_05_b }]}>{price}</Text>}
168
+ </>
169
+ </TouchableHighlight>
170
+ ) : (
171
+ <View style={[style.day]}>
172
+ <Text style={[style.dayText, style.dayTextDisabled]}>{text}</Text>
173
+ {this.lunarDate && this.showLunar && text ? (
174
+ <Text style={[style.lunarDayText, style.dayTextDisabled]}>
175
+ {this.lunarDate.lunarDay === 1
176
+ ? `${this.lunarDate.lunarDay}/${this.lunarDate.lunarMonth}`
177
+ : this.lunarDate.lunarDay}
178
+ </Text>
179
+ ) : (
180
+ <View />
181
+ )}
188
182
  </View>
189
- );
190
- }
183
+ )}
184
+ </View>
185
+
186
+ {isDoubleDateMode && this.isStart && !isHideLabel && (
187
+ <View style={style.txtGo}>
188
+ <Text style={{fontSize: 8, color: 'white'}}>
189
+ {labelFrom || SwitchLanguage.departing}
190
+ </Text>
191
+ </View>
192
+ )}
193
+ {isDoubleDateMode && this.isEnd && !isHideLabel && (
194
+ <View style={style.txtBack}>
195
+ <Text style={{fontSize: 8, color: 'white'}}>
196
+ {labelTo || SwitchLanguage.returning}
197
+ </Text>
198
+ </View>
199
+ )}
200
+ {this.isValid && this.isInScope && !!price && (
201
+ <Text style={[style.price, isBestPrice && {color: Colors.pink_05_b}]}>
202
+ {price}
203
+ </Text>
204
+ )}
205
+ </View>
206
+ );
207
+ }
191
208
  }
192
209
 
193
210
  export default Day;
@@ -0,0 +1,154 @@
1
+ import React, { Component, } from 'react';
2
+ import { TouchableOpacity, View } from 'react-native';
3
+ import PropTypes from 'prop-types';
4
+ import { Text } from '@momo-kits/core';
5
+ import styles from './styles';
6
+
7
+ export default class Day extends Component {
8
+ processMinDate() {
9
+ const { minDate } = this.props;
10
+ if (minDate) {
11
+ minDate.setHours(0, 0, 0, 0);
12
+ if (this.date < minDate) {
13
+ this.disableTouch = true;
14
+ }
15
+ }
16
+ }
17
+
18
+ processMaxDate() {
19
+ const { maxDate } = this.props;
20
+ if (maxDate) {
21
+ maxDate.setHours(0, 0, 0, 0);
22
+ if (this.date > maxDate) {
23
+ this.disableTouch = true;
24
+ }
25
+ }
26
+ }
27
+
28
+ processDoubleDate() {
29
+ const {
30
+ mode, otherMonth, firstDate, secondDate, tabSelected
31
+ } = this.props;
32
+ const { date } = this;
33
+ if (mode === 'doubleDate' && !otherMonth) {
34
+ if (firstDate && tabSelected === 1) {
35
+ firstDate.setHours(0, 0, 0, 0);
36
+ if (date < firstDate) {
37
+ this.disableTouch = true;
38
+ this.styleDouble = {};
39
+ } else if (date.getTime() === firstDate.getTime()) {
40
+ this.colorCanTouch = '#2eb3e8';
41
+ this.colorText = 'white';
42
+ this.styleDouble = {};
43
+ }
44
+ }
45
+ if (secondDate && firstDate) {
46
+ secondDate.setHours(0, 0, 0, 0);
47
+ if (date > firstDate && date < secondDate) {
48
+ this.colorCanTouch = '#90d6f3';
49
+
50
+ this.styleDouble = styles.styleBetween;
51
+
52
+ this.colorText = 'white';
53
+ }
54
+ if (secondDate.getTime() !== firstDate.getTime()) {
55
+ if (date.getTime() === firstDate.getTime()) {
56
+ this.colorCanTouch = '#2eb3e8';
57
+ this.colorText = 'white';
58
+ this.styleDouble = styles.styleFirstDate;
59
+ }
60
+ if (date.getTime() === secondDate.getTime()) {
61
+ this.styleDouble = styles.styleSecondDate;
62
+ this.colorCanTouch = '#2eb3e8';
63
+ this.colorText = 'white';
64
+ }
65
+ }
66
+ }
67
+ }
68
+ }
69
+
70
+ processSelected() {
71
+ const { selected } = this.props;
72
+ if (selected && !this.disableTouch) {
73
+ this.colorCanTouch = '#2eb3e8';
74
+ this.colorText = 'white';
75
+ }
76
+ }
77
+
78
+ processDateNow() {
79
+ const { selected } = this.props;
80
+ if (!selected && this.date.getTime() === this.dateNow.getTime()) {
81
+ this.colorCanTouch = '#8F8E94';
82
+ this.colorText = 'white';
83
+ }
84
+ }
85
+
86
+ processOtherMonth() {
87
+ const { otherMonth } = this.props;
88
+ if (otherMonth) {
89
+ this.colorTextDisable = 'white';
90
+ }
91
+ }
92
+
93
+ processRender() {
94
+ this.processMinDate();
95
+ this.processMaxDate();
96
+ // this.processDateNow()
97
+ this.processDoubleDate();
98
+ this.processSelected();
99
+ this.processOtherMonth();
100
+ }
101
+
102
+ render() {
103
+ const {
104
+ day, month, year, otherMonth, onDayChange
105
+ } = this.props;
106
+ this.colorCanTouch = 'white';
107
+ this.colorText = '#393939';
108
+ this.colorTextDisable = '#DADADA';
109
+ this.styleDouble = {};
110
+ this.disableTouch = false;
111
+ this.dateNow = new Date();
112
+ this.dateNow.setHours(0, 0, 0, 0);
113
+ this.date = new Date(year, month, day);
114
+ this.date.setHours(0, 0, 0, 0);
115
+ this.processRender();
116
+ return (
117
+
118
+ <View style={styles.dayWrapper}>
119
+ <View style={this.styleDouble} />
120
+ {
121
+ this.disableTouch || otherMonth
122
+ ? (
123
+ <View style={styles.dayButton}>
124
+ <Text.Title style={[styles.dayLabel, { color: this.colorTextDisable }]}>
125
+ {day}
126
+ </Text.Title>
127
+ </View>
128
+ )
129
+ : (
130
+ <View style={[styles.dayButtonSelected, { backgroundColor: this.colorCanTouch }]}>
131
+ <TouchableOpacity
132
+ style={styles.dayButton}
133
+ onPress={() => onDayChange(day, month, year)}
134
+ >
135
+ <Text.Title style={[styles.dayLabel, { color: this.colorText }]}>
136
+ {day}
137
+ </Text.Title>
138
+ </TouchableOpacity>
139
+
140
+ </View>
141
+ )
142
+
143
+ }
144
+ </View>
145
+ );
146
+ }
147
+ }
148
+ Day.propTypes = {
149
+ day: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
150
+ month: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
151
+ year: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
152
+ otherMonth: PropTypes.bool,
153
+ onDayChange: PropTypes.func,
154
+ };
@@ -0,0 +1,203 @@
1
+ import React, { Component, } from 'react';
2
+ import { View, } from 'react-native';
3
+ import styles from './styles';
4
+ import { getDaysInMonth, MAX_COLUMNS, MAX_ROWS, } from './util';
5
+ import Day from './Day';
6
+
7
+ export default class Days extends Component {
8
+ constructor(props) {
9
+ super(props);
10
+ this.state = {
11
+ selectedDay: 0,
12
+ selectedMonth: 0,
13
+ selectedYear: 0,
14
+ };
15
+ this.selectedDate = null;
16
+ }
17
+
18
+ componentDidMount() {
19
+ const { selectedDate } = this.props;
20
+ if (selectedDate) {
21
+ const temp = selectedDate;
22
+ if (typeof temp.getDate === 'function') {
23
+ this.selectedDate = temp;
24
+ } else {
25
+ this.selectedDate = new Date(temp);
26
+ }
27
+ this.updateSelectedStates(
28
+ this.selectedDate.getDate(),
29
+ this.selectedDate.getMonth(),
30
+ this.selectedDate.getFullYear(),
31
+ );
32
+ }
33
+ }
34
+
35
+ updateSelectedStates = (day, month, year) => {
36
+ const { onDayChange } = this.props;
37
+ // const monthTmp = month + 1;
38
+ this.setState({
39
+ selectedDay: day,
40
+ selectedMonth: month,
41
+ selectedYear: year,
42
+ });
43
+ if (onDayChange) {
44
+ onDayChange(day, month, year);
45
+ }
46
+ }
47
+
48
+ onPressDay = (day, month, year) => {
49
+ const { minDate, maxDate } = this.props;
50
+ const selectDate = new Date(year, month, day);
51
+ selectDate.setHours(0, 0, 0, 0);
52
+ if (minDate) {
53
+ minDate.setHours(0, 0, 0, 0);
54
+ if (selectDate < minDate) {
55
+ return;
56
+ }
57
+ }
58
+
59
+ if (maxDate) {
60
+ maxDate.setHours(0, 0, 0, 0);
61
+ if (selectDate > maxDate) {
62
+ return;
63
+ }
64
+ }
65
+ this.updateSelectedStates(day, month, year);
66
+ }
67
+
68
+ getCalendarDays = () => {
69
+ const {
70
+ month, year, mode, minDate, maxDate, firstDate, secondDate, tabSelected
71
+ } = this.props;
72
+ const { selectedMonth, selectedDay, selectedYear } = this.state;
73
+ let columns;
74
+ const matrix = [];
75
+ let i;
76
+ let j;
77
+ let currentDay = 0;
78
+ const thisMonthFirstDay = new Date(year, month, 1);
79
+ let slotsAccumulator = 1;
80
+
81
+ let goNextMonth = false;
82
+ for (i = 0; i < MAX_ROWS; i += 1) { // Week rows
83
+ columns = [];
84
+ if (goNextMonth) { break; }
85
+ for (j = 0; j < MAX_COLUMNS; j += 1) { // Day columns
86
+ // HungHC: getDay() Sunday is 0, Monday is 1, and so on.
87
+ let tmp = thisMonthFirstDay.getDay();
88
+ if (tmp === 0) { tmp = 7; }
89
+ if (slotsAccumulator >= tmp) {
90
+ if (currentDay < getDaysInMonth(month, year)) {
91
+ const day = currentDay + 1;
92
+ const selected = (selectedDay === day
93
+ && selectedMonth === month
94
+ && selectedYear === year);
95
+ const date = Date(year, month, day);
96
+
97
+ columns.push(<Day
98
+ mode={mode}
99
+ key={j.toString()}
100
+ column={j}
101
+ day={day}
102
+ month={month}
103
+ year={year}
104
+ selected={selected}
105
+ date={date}
106
+ minDate={minDate}
107
+ maxDate={maxDate}
108
+ firstDate={firstDate}
109
+ secondDate={secondDate}
110
+ tabSelected={tabSelected}
111
+
112
+ otherMonth={false}
113
+ onDayChange={this.onPressDay}
114
+ />);
115
+ currentDay += 1;
116
+ } else {
117
+ // HungHC: show next month
118
+ goNextMonth = true;
119
+ if (j === 0) {
120
+ break;
121
+ }
122
+
123
+ let nextMonth = month + 1;
124
+ const day = currentDay + 1 - getDaysInMonth(month, year);
125
+ let yearTmp = year;
126
+ if (nextMonth > 11) {
127
+ nextMonth = 0;
128
+ yearTmp = year + 1;
129
+ }
130
+ const date = Date(yearTmp, nextMonth, day);
131
+ const selected = (selectedDay === day
132
+ && selectedMonth === nextMonth
133
+ && selectedYear === yearTmp);
134
+ columns.push(<Day
135
+ mode={mode}
136
+ key={j.toString()}
137
+ column={j}
138
+ day={day}
139
+ month={nextMonth}
140
+ year={yearTmp}
141
+ selected={selected}
142
+ date={date}
143
+ minDate={minDate}
144
+ maxDate={maxDate}
145
+ firstDate={firstDate}
146
+ secondDate={secondDate}
147
+ tabSelected={tabSelected}
148
+ otherMonth
149
+ onDayChange={this.onPressDay}
150
+ />);
151
+ currentDay += 1;
152
+ }
153
+ } else {
154
+ // HungHC: show prev month
155
+ let prevMonth = month - 1;
156
+ let yearTmp = year;
157
+ if (prevMonth < 0) {
158
+ prevMonth = 11;
159
+ yearTmp = year - 1;
160
+ }
161
+ const daysPrev = getDaysInMonth(prevMonth, yearTmp);
162
+ let tmpDay = thisMonthFirstDay.getDay();
163
+ if (tmpDay === 0) { tmpDay = 7; }
164
+ const delta = (slotsAccumulator - tmpDay + 1);
165
+ const day = daysPrev + delta;
166
+
167
+ const selected = (selectedDay === day
168
+ && selectedMonth === prevMonth
169
+ && selectedYear === yearTmp);
170
+
171
+ const date = Date(yearTmp, prevMonth, day);
172
+ columns.push(<Day
173
+ mode={mode}
174
+ key={j.toString()}
175
+ column={j}
176
+ day={day}
177
+ month={prevMonth}
178
+ year={yearTmp}
179
+ selected={selected}
180
+ date={date}
181
+ minDate={minDate}
182
+ maxDate={maxDate}
183
+ firstDate={firstDate}
184
+ secondDate={secondDate}
185
+ tabSelected={tabSelected}
186
+ otherMonth
187
+ onDayChange={this.onPressDay}
188
+ />);
189
+ }
190
+
191
+ slotsAccumulator += 1;
192
+ }
193
+ matrix[i] = [];
194
+ matrix[i].push(<View key={i.toString()} style={styles.weekRow}>{columns}</View>);
195
+ }
196
+
197
+ return matrix;
198
+ }
199
+
200
+ render() {
201
+ return <View style={styles.daysWrapper}>{ this.getCalendarDays()}</View>;
202
+ }
203
+ }
@@ -0,0 +1,158 @@
1
+ /* eslint-disable no-param-reassign */
2
+ import React, { Component, } from 'react';
3
+ import {
4
+ Text, TouchableOpacity, View
5
+ } from 'react-native';
6
+ import PropTypes from 'prop-types';
7
+ import { IconSource, Image } from '@momo-kits/core';
8
+ import { DatePicker } from '@momo-kits/date-picker';
9
+ import styles from './styles';
10
+ import { MONTHS } from './util';
11
+
12
+ const padding = (input) => `${input > 9 ? input : `0${input}`}`;
13
+
14
+ const formatDate = (date) => {
15
+ if (date && typeof date.getDate === 'function') {
16
+ return `${padding(date.getMonth() + 1)}/${(date.getFullYear()).toString()}`;
17
+ }
18
+ return null;
19
+ };
20
+
21
+ const makeRange = (min = 0, max = 9999, step = 1) => {
22
+ const range = [];
23
+ let entry = `${0}`;
24
+
25
+ for (min; min <= max; min += step) {
26
+ entry = `${min}`;
27
+ range.push(entry);
28
+ }
29
+
30
+ return range;
31
+ };
32
+ export default class HeaderControls extends Component {
33
+ constructor(props) {
34
+ super(props);
35
+ const { month } = this.props;
36
+ this.state = {
37
+ selectedMonth: month
38
+ };
39
+
40
+ const minYear = 1900 + (new Date()).getYear();
41
+ const maxYear = minYear + 5;
42
+ this.months = makeRange(1, 12);
43
+ this.years = makeRange(minYear, maxYear);
44
+ this.momoDatePicker = React.createRef();
45
+ }
46
+
47
+ setMonth = (month) => {
48
+ this.setState({
49
+ selectedMonth: month,
50
+ });
51
+ }
52
+
53
+ getNext = () => {
54
+ const { selectedMonth } = this.state;
55
+ const { getNextYear, onMonthChange } = this.props;
56
+ let next = selectedMonth + 1;
57
+ if (next > 11) {
58
+ next = 0;
59
+ this.setState({ selectedMonth: next });
60
+ getNextYear();
61
+ } else {
62
+ this.setState({ selectedMonth: next });
63
+ }
64
+
65
+ onMonthChange(next);
66
+ }
67
+
68
+ getPrevious = () => {
69
+ const { selectedMonth } = this.state;
70
+ const {
71
+ onMonthChange, year, minDate, getPrevYear
72
+ } = this.props;
73
+
74
+ let prev = selectedMonth - 1;
75
+ if (prev < 0) {
76
+ prev = 11;
77
+ this.setState({ selectedMonth: prev });
78
+ getPrevYear();
79
+ onMonthChange(prev);
80
+ } else if (year <= minDate.getFullYear() && prev < minDate.getMonth()) {
81
+ return null;
82
+ } else {
83
+ this.setState({ selectedMonth: prev });
84
+ onMonthChange(prev);
85
+ }
86
+ }
87
+
88
+ pickMonthYear = () => {
89
+ const { navigator, minDate, maxDate } = this.props;
90
+ navigator.showBottom({
91
+ screen: DatePicker,
92
+ params: {
93
+ dragDisabled: true,
94
+ onSelected: this.onMonthYearChange,
95
+ onClose: () => { },
96
+ selectedDate: formatDate(minDate),
97
+ minDate: formatDate(minDate),
98
+ maxDate: formatDate(maxDate),
99
+ format: 'MM/YYYY',
100
+ }
101
+ });
102
+ };
103
+
104
+ onMonthYearChange = (date) => {
105
+ const { onMonthYearChange } = this.props;
106
+ const splitDate = date.split('/');
107
+ const idM = +splitDate[0];
108
+ const idY = +splitDate[1];
109
+ this.setState({
110
+ selectedMonth: idM - 1
111
+ });
112
+ if (onMonthYearChange) {
113
+ onMonthYearChange(idM - 1, idY);
114
+ }
115
+ }
116
+
117
+ render() {
118
+ const { selectedMonth } = this.state;
119
+ const { year, minDate } = this.props;
120
+ const previous = selectedMonth - 1 < 0 ? 11 : selectedMonth - 1;
121
+ const opacity = (previous < minDate.getMonth() && minDate.getFullYear() === year) ? 0.2 : 1;
122
+ // const monthNow = (new Date()).getMonth() + 1;
123
+ // const yearNow = (new Date()).getYear() + 1900;
124
+ return (
125
+ <View style={styles.headerWrapper}>
126
+
127
+ <TouchableOpacity onPress={() => this.getPrevious()} style={{ paddingHorizontal: 20, }}>
128
+ <Image style={{ width: 20, height: 20, opacity }} source={IconSource.ic_back_arrow} />
129
+ </TouchableOpacity>
130
+
131
+ <TouchableOpacity onPress={this.pickMonthYear}>
132
+ <Text style={styles.monthLabel}>
133
+ { MONTHS[selectedMonth] }
134
+ /
135
+ { year }
136
+ </Text>
137
+ </TouchableOpacity>
138
+
139
+ <TouchableOpacity onPress={() => this.getNext()} style={{ paddingHorizontal: 20, }}>
140
+ <Image style={{ width: 20, height: 20, }} source={IconSource.ic_arrow_next} />
141
+ </TouchableOpacity>
142
+ </View>
143
+ );
144
+ }
145
+ }
146
+
147
+ HeaderControls.propTypes = {
148
+ getNextYear: PropTypes.func,
149
+ onMonthChange: PropTypes.func,
150
+ onMonthYearChange: PropTypes.func,
151
+ getPrevYear: PropTypes.func,
152
+ year: PropTypes.number,
153
+ minDate: PropTypes.any,
154
+ };
155
+
156
+ HeaderControls.defaultProps = {
157
+
158
+ };
@@ -0,0 +1,22 @@
1
+ import React from 'react';
2
+ import { View } from 'react-native';
3
+
4
+ import { Text } from '@momo-kits/core';
5
+ import styles from './styles';
6
+ import { WEEKDAYS, } from './util';
7
+
8
+ const colorDay = '#9199a2';
9
+ const WeekDaysLabels = () => (
10
+ <View style={styles.dayLabelsWrapper}>
11
+ { WEEKDAYS.map((day, key) => (
12
+ <Text.Title
13
+ key={key.toString()}
14
+ style={[styles.dayLabels, { color: colorDay, fontSize: 16 }]}
15
+ >
16
+ {day}
17
+ </Text.Title>
18
+ )) }
19
+ </View>
20
+ );
21
+
22
+ export default WeekDaysLabels;
@@ -0,0 +1,125 @@
1
+ /* eslint-disable react/no-typos */
2
+ import React, { Component, } from 'react';
3
+ import { View, } from 'react-native';
4
+ import PropTypes from 'prop-types';
5
+ import styles from './styles';
6
+ import HeaderControls from './HeaderControls';
7
+ import Days from './Days';
8
+ import WeekDaysLabels from './WeekDaysLabels';
9
+
10
+ class CalendarPicker extends Component {
11
+ constructor(props) {
12
+ super(props);
13
+
14
+ this.selectedDate = null;
15
+ const temp = props.selectedDate;
16
+ try {
17
+ if (typeof temp.getDate === 'function') {
18
+ this.selectedDate = temp;
19
+ } else {
20
+ this.selectedDate = new Date(temp);
21
+ }
22
+ } catch (e) {
23
+ this.selectedDate = new Date();
24
+ }
25
+ this.state = {
26
+ // date: this.selectedDate,
27
+ month: this.selectedDate.getMonth(),
28
+ day: this.selectedDate.getDate(),
29
+ year: this.selectedDate.getFullYear(),
30
+ // selectedDay: [],
31
+ tabSelected: 0,
32
+ };
33
+ }
34
+
35
+ onDayChange = (day, month, year) => {
36
+ const { onDateChange } = this.props;
37
+ const date = new Date(year, month, day);
38
+ if (onDateChange) { onDateChange(date); }
39
+ if (this.refs.header) { this.refs.header.setMonth(month); }
40
+ this.setState({
41
+ year,
42
+ month,
43
+ day,
44
+ });
45
+ }
46
+
47
+ onMonthYearChange = (month, year) => {
48
+ this.setState({
49
+ month,
50
+ year
51
+ });
52
+ }
53
+
54
+ onMonthChange = (month) => {
55
+ this.setState({ month, });
56
+ }
57
+
58
+
59
+ getNextYear = () => {
60
+ const { year } = this.state;
61
+ this.setState({ year: parseInt(year) + 1, });
62
+ }
63
+
64
+ getPrevYear =() => {
65
+ const { year } = this.state;
66
+ this.setState({ year: parseInt(year) - 1, });
67
+ }
68
+
69
+ setDoubleDateAndTabIndex = (first, second, tabSelected) => {
70
+ this.setState({
71
+ firstDate: first,
72
+ secondDate: second,
73
+ tabSelected
74
+ });
75
+ }
76
+
77
+ render() {
78
+ const {
79
+ day, year, month, firstDate, secondDate, tabSelected
80
+ } = this.state;
81
+ const {
82
+ minDate, maxDate, mode, navigator
83
+ } = this.props;
84
+ return (
85
+ <View style={styles.calendar}>
86
+ <HeaderControls
87
+ ref="header"
88
+ year={year}
89
+ month={month}
90
+ navigator={navigator}
91
+ onMonthYearChange={this.onMonthYearChange}
92
+ onMonthChange={this.onMonthChange}
93
+ getNextYear={this.getNextYear}
94
+ getPrevYear={this.getPrevYear}
95
+ minDate={minDate || null}
96
+ />
97
+ <WeekDaysLabels />
98
+
99
+ <Days
100
+ mode={mode}
101
+ firstDate={firstDate}
102
+ secondDate={secondDate}
103
+ tabSelected={tabSelected}
104
+ month={month}
105
+ year={year}
106
+ day={day}
107
+ minDate={minDate || new Date()}
108
+ maxDate={maxDate}
109
+ selectedDate={this.selectedDate}
110
+ onDayChange={this.onDayChange}
111
+ />
112
+ </View>
113
+ );
114
+ }
115
+ }
116
+ export default CalendarPicker;
117
+
118
+ CalendarPicker.propTypes = {
119
+ navigator: PropTypes.object.isRequired,
120
+ minDate: PropTypes.any,
121
+ maxDate: PropTypes.any,
122
+ mode: PropTypes.oneOf(['doubleDate', 'signleDate']),
123
+ selectedDate: PropTypes.any,
124
+ onDateChange: PropTypes.func,
125
+ };
@@ -0,0 +1,184 @@
1
+ import { Dimensions, StyleSheet } from 'react-native';
2
+
3
+ const widthScreen = Dimensions.get('window').width;
4
+
5
+ const styles = StyleSheet.create({
6
+ calendar: {
7
+ // height:widthScreen - 20,
8
+ backgroundColor: 'white',
9
+ borderColor: '#DADADA',
10
+ borderBottomWidth: 1,
11
+ borderTopWidth: 1,
12
+ },
13
+ dayWrapper: {
14
+ width: widthScreen / 7,
15
+ height: 40,
16
+ backgroundColor: 'rgba(0,0,0,0.0)'
17
+
18
+ },
19
+
20
+ dayButton: {
21
+ width: 50,
22
+ height: 50,
23
+ alignSelf: 'center'
24
+ },
25
+
26
+ styleFirstDate: {
27
+ position: 'absolute',
28
+ // width:45,
29
+ height: 40,
30
+ top: 0,
31
+ left: widthScreen / 14,
32
+ right: -1,
33
+ backgroundColor: '#90d6f3',
34
+ borderRadius: 0
35
+ },
36
+ styleSecondDate: {
37
+ position: 'absolute',
38
+ // width:45,
39
+ height: 40,
40
+ top: 0,
41
+ right: widthScreen / 14,
42
+ left: 0,
43
+ backgroundColor: '#90d6f3',
44
+ borderRadius: 0
45
+ },
46
+ styleBetween: {
47
+ height: 40,
48
+ // width:60,
49
+ top: 0,
50
+ left: 0,
51
+ right: -1,
52
+ position: 'absolute',
53
+ backgroundColor: '#90d6f3',
54
+ borderRadius: 0
55
+ },
56
+ dayButtonSelected: {
57
+ width: 40,
58
+ height: 40,
59
+ borderRadius: 20,
60
+ backgroundColor: '#2eb3e8',
61
+ alignSelf: 'center'
62
+ },
63
+
64
+ dayButtonNow: {
65
+ width: 40,
66
+ height: 40,
67
+ borderRadius: 20,
68
+ backgroundColor: '#8F8E94',
69
+ alignSelf: 'center'
70
+ },
71
+
72
+ dayLabel: {
73
+ fontSize: 16,
74
+ color: '#393939',
75
+ marginTop: 10,
76
+ alignSelf: 'center'
77
+ },
78
+
79
+ dayLabelsWrapper: {
80
+ width: widthScreen,
81
+ flexDirection: 'row',
82
+ marginBottom: 10,
83
+ paddingTop: 5,
84
+ paddingBottom: 5,
85
+ borderColor: '#DADADA',
86
+ borderBottomWidth: 1,
87
+ borderTopWidth: 1,
88
+ },
89
+
90
+ daysWrapper: {
91
+ alignSelf: 'center',
92
+ },
93
+
94
+ dayLabels: {
95
+ width: widthScreen / 7,
96
+ fontSize: 12,
97
+ color: '#000',
98
+ textAlign: 'center',
99
+ },
100
+
101
+ selectedDay: {
102
+ width: 60,
103
+ height: 60,
104
+ backgroundColor: '#5ce600',
105
+ borderRadius: 30,
106
+ alignSelf: 'center'
107
+ },
108
+
109
+ monthLabel: {
110
+ fontSize: widthScreen > 320 ? 20 : 17,
111
+ fontWeight: '300',
112
+ color: '#000',
113
+ width: 180,
114
+ textAlign: 'center'
115
+ },
116
+
117
+ headerWrapper: {
118
+ width: widthScreen,
119
+ alignItems: 'center',
120
+ justifyContent: 'space-between',
121
+ flexDirection: 'row',
122
+ marginVertical: 10,
123
+ backgroundColor: 'rgba(0,0,0,0.0)'
124
+ },
125
+
126
+ monthSelector: {
127
+ width: 80,
128
+ },
129
+
130
+ prev: {
131
+ textAlign: 'left',
132
+ fontSize: 16,
133
+ color: '#dadada',
134
+ },
135
+
136
+ next: {
137
+ textAlign: 'right',
138
+ fontSize: 16,
139
+ color: '#dadada',
140
+ },
141
+
142
+ yearLabel: {
143
+ fontSize: 14,
144
+ fontWeight: 'bold',
145
+ color: '#000',
146
+ textAlign: 'center'
147
+ },
148
+
149
+ weeks: {
150
+ flexDirection: 'column'
151
+ },
152
+
153
+ weekRow: {
154
+ flexDirection: 'row'
155
+ },
156
+ btnCellHeader: {
157
+ flex: 1,
158
+ justifyContent: 'center',
159
+ alignItems: 'center',
160
+ borderWidth: 1,
161
+ borderColor: '#DADADA',
162
+ backgroundColor: 'white'
163
+ },
164
+ center: {
165
+ justifyContent: 'center',
166
+ alignItems: 'center'
167
+ },
168
+ txtDate: {
169
+ color: '#4D4D4D',
170
+ fontSize: 18,
171
+ fontWeight: 'bold',
172
+ paddingVertical: 10
173
+ },
174
+ lineActiveTab: {
175
+ height: 3,
176
+ width: '100%',
177
+ position: 'absolute',
178
+ bottom: 0,
179
+ left: 0,
180
+ backgroundColor: '#49A3BC'
181
+ }
182
+ });
183
+
184
+ export default styles;
@@ -0,0 +1,50 @@
1
+ import { SwitchLanguage } from '@momo-kits/core';
2
+
3
+ module.exports = {
4
+ WEEKDAYS: SwitchLanguage.getLocalize({
5
+ vi: [
6
+ 'T2', 'T3', 'T4', 'T5', 'T6', 'T7', 'CN',
7
+ ],
8
+ en: ['Mon', 'Tues', 'Wed', 'Thur', 'Fri', 'Sat', 'Sun'],
9
+ }),
10
+
11
+ WEEKDAYSNAME: [
12
+ 'Thứ 2', 'Thứ 3', 'Thứ 4', 'Thứ 5', 'Thứ 6', 'Thứ 7', 'Chủ nhật',
13
+ ],
14
+
15
+ MONTHS: SwitchLanguage.getLocalize({
16
+ vi: [
17
+ 'Tháng 1', 'Tháng 2', 'Tháng 3', 'Tháng 4', 'Tháng 5', 'Tháng 6', 'Tháng 7',
18
+ 'Tháng 8', 'Tháng 9', 'Tháng 10', 'Tháng 11', 'Tháng 12'
19
+ ],
20
+ en: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
21
+ }),
22
+
23
+ MAX_ROWS: 7,
24
+
25
+ MAX_COLUMNS: 7,
26
+
27
+ getDaysInMonth(month, year) {
28
+ const lastDayOfMonth = new Date(year, month + 1, 0);
29
+ return lastDayOfMonth.getDate();
30
+ },
31
+
32
+ getDayofDate(date) {
33
+ const WEEKDAYSNAME = ['Thứ hai', 'Thứ ba', 'Thứ tư', 'Thứ năm', 'Thứ sáu', 'Thứ bảy', 'Chủ nhật'];
34
+ let day = date.getDay();
35
+ if (date.getDay() === 0) {
36
+ day = 7;
37
+ }
38
+ return WEEKDAYSNAME[day - 1];
39
+ },
40
+ formatDate(date) {
41
+ const padding = (input) => `${input > 9 ? input : `0${input}`}`;
42
+ if (date && typeof date.getDate === 'function') {
43
+ return `${padding(date.getDate())}/${
44
+ padding(date.getMonth() + 1)}/${
45
+ (date.getFullYear()).toString()}`;
46
+ }
47
+ return null;
48
+ },
49
+
50
+ };