Skip to content

Commit

Permalink
Merge pull request #1 from dmtrKovalenko/feature/Shared
Browse files Browse the repository at this point in the history
DatePicker
  • Loading branch information
dmtrKovalenko authored Oct 12, 2017
2 parents 524691b + aff739a commit fa18937
Show file tree
Hide file tree
Showing 14 changed files with 636 additions and 20 deletions.
4 changes: 2 additions & 2 deletions docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"material-ui": "^1.0.0-beta.13",
"material-ui": "^1.0.0`-beta.13",
"react": "^16.0.0",
"react-dom": "^16.0.0",
"react-scripts": "1.0.14"
},
"scripts": {
"start": "react-scripts start",
"start": "PORT=3002 react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
Expand Down
16 changes: 15 additions & 1 deletion docs/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,16 @@ import './App.css';


class App extends Component {
state = {
selectedDate: new Date()
}

handleDateChange = date => {
this.setState({ selectedDate: date })
}

render() {
const { selectedDate } = this.state
return (
<div className="root">
<AppBar position="static">
Expand All @@ -25,7 +34,12 @@ class App extends Component {
</Typography>

<div className="main-picker">
<DateTimePicker />
<DateTimePicker
disableFuture
value={selectedDate}
onChange={this.handleDateChange}
animateYearScrolling={false}
/>
</div>
</main>
</div>
Expand Down
24 changes: 24 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,20 @@
"main": "dist/index.js",
"peerDependencies": {
"react": "^16.0.0",
"react-dom": "^16.0.0",
"prop-types": "^15.6.0",
"material-ui": "^1.0.0-beta.13"
"material-ui": "^1.0.0-beta.13",
"classnames": "^2.2.5"
},
"dependencies": {
"classnames": "^2.2.5",
"material-ui": "^1.0.0-beta.13",
"moment": "^2.18.1",
"moment-range": "^3.0.3",
"peer-deps-externals-webpack-plugin": "^1.0.2",
"prop-types": "^15.6.0",
"react": "^16.0.0",
"react-dom": "^16.0.0",
"webpack": "^3.5.1"
},
"scripts": {
Expand Down
15 changes: 0 additions & 15 deletions src/DatePicker.jsx

This file was deleted.

118 changes: 118 additions & 0 deletions src/DatePicker/Calendar.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import { withStyles, IconButton } from 'material-ui';

import Moment from 'moment';
import { extendMoment } from 'moment-range';
import classnames from 'classnames';
import CalendarHeader from './CalendarHeader';

const moment = extendMoment(Moment);

class Calendar extends PureComponent {
static propTypes = {
date: PropTypes.shape({}).isRequired,
classes: PropTypes.shape({}).isRequired,
onChange: PropTypes.func.isRequired,
disableFuture: PropTypes.bool.isRequired,
}

state = {
currentMonth: this.props.date.clone().startOf('month'),
}

onDateSelect = (day) => {
this.props.onChange(day);
}

handleChangeMonth = (newMonth) => {
this.setState({ currentMonth: newMonth });
}

renderWeeks = () => {
const { currentMonth } = this.state;
const start = currentMonth.clone().startOf('week');
const end = currentMonth.clone().endOf('month').endOf('week');

return Array.from(moment.range(start, end).by('week'))
.map(week => (
<div key={`week-${week.toString()}`} className={this.props.classes.week}>
{ this.renderDays(week) }
</div>
));
}

renderDays = (week) => {
const { disableFuture, classes, date } = this.props;
const end = week.clone().endOf('week');
const currentMonthNumber = this.state.currentMonth.get('month');

return Array.from(moment.range(week, end).by('day'))
.map((day) => {
const dayClass = classnames(classes.day, {
[classes.hidden]: day.get('month') !== currentMonthNumber,
[classes.selected]: day.toString() === date.toString(),
[classes.disabled]: disableFuture && day.isAfter(moment()),
});

return (
<IconButton
key={day.toString()}
className={dayClass}
onClick={() => this.onDateSelect(day)}
>
<span> { day.format('DD')} </span>
</IconButton>
);
});
}

render() {
const { currentMonth } = this.state;
const { classes } = this.props;

return (
<div className={classes.container}>
<CalendarHeader
currentMonth={currentMonth}
onMonthChange={this.handleChangeMonth}
/>

<div className={classes.calendar}>
{ this.renderWeeks() }
</div>
</div>
);
}
}

const styles = theme => ({
calendar: {
marginTop: 10,
},
hidden: {
opacity: 0,
pointerEvents: 'none',
},
day: {
width: 36,
height: 36,
fontSize: 14,
margin: '0 2px',
color: theme.palette.text.primary,
},
selected: {
color: theme.palette.primary[700],
backgroundColor: theme.palette.primary[200],
},
disabled: {
pointerEvents: 'none',
color: theme.palette.text.hint,
},
week: {
display: 'flex',
justifyContent: 'center',
},
});

export default withStyles(styles)(Calendar);
65 changes: 65 additions & 0 deletions src/DatePicker/CalendarHeader.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import React from 'react';
import PropTypes from 'prop-types';
import moment from 'moment';
import { withStyles, IconButton } from 'material-ui';

const CalendarHeader = (props) => {
const { classes, currentMonth, onMonthChange } = props;

const selectNextMonth = () => onMonthChange(currentMonth.clone().add(1, 'months'));
const selectPreviousMonth = () => onMonthChange(currentMonth.clone().subtract(1, 'months'));

return (
<div>
<div className={classes.switchHeader}>
<IconButton onClick={selectPreviousMonth}>
keyboard_arrow_left
</IconButton>

<div className={classes.monthName}>
{ currentMonth.format('MMMM YYYY')}
</div>

<IconButton onClick={selectNextMonth}>
keyboard_arrow_right
</IconButton>
</div>

<div className={classes.daysHeader}>
{ moment.weekdaysMin().map(day => (
<div className={classes.dayLabel}> { day } </div>
))}
</div>
</div>
);
};

CalendarHeader.propTypes = {
currentMonth: PropTypes.object.isRequired,
onMonthChange: PropTypes.func.isRequired,
classes: PropTypes.object,
};

const styles = theme => ({
switchHeader: {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
margin: '10px 0 20px',
},
daysHeader: {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
},
dayLabel: {
width: 36,
margin: '0 2px',
fontSize: 13,
textAlign: 'center',
color: theme.palette.text.hint,
},
});

export default withStyles(styles)(CalendarHeader);

Loading

0 comments on commit fa18937

Please sign in to comment.