@momo-kits/calendar 0.0.33-beta → 0.0.35

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.
@@ -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;