Calendar refactoring

old
Javi Velasco 2015-09-03 09:21:55 +02:00
parent 5f62ce283a
commit 18a51d8d26
7 changed files with 119 additions and 110 deletions

View File

@ -0,0 +1,29 @@
css = require './style'
dateUtils = require '../date_utils'
module.exports = React.createClass
displayName: 'Day',
propTypes:
day : React.PropTypes.number
onClick : React.PropTypes.func
selectedDate : React.PropTypes.object
viewDate : React.PropTypes.object
_dayStyle: ->
marginLeft: "#{dateUtils.firstWeekDay(@props.viewDate) * 100/7}%"
_isSelected: () ->
isSameYear = @props.viewDate.getFullYear() == @props.selectedDate.getFullYear()
isSameMonth = @props.viewDate.getMonth() == @props.selectedDate.getMonth()
isSameDay = @props.day == @props.selectedDate.getDate()
isSameYear && isSameMonth && isSameDay
render: ->
className = " #{css.day}"
className += " active" if @_isSelected()
dayStyle = @_dayStyle() if @props.day == 1
<div className={className} style={dayStyle}>
<span onClick={@props.onClick}>{ @props.day }</span>
</div>

View File

@ -1,9 +1,12 @@
CTG = React.addons.CSSTransitionGroup
css = require './style'
FontIcon = require '../font_icon'
dateUtils = require '../date_utils'
CTG = React.addons.CSSTransitionGroup
FontIcon = require '../font_icon'
Month = require './month'
module.exports = React.createClass
displayName: 'Calendar',
# -- States & Properties
propTypes:
@ -21,8 +24,10 @@ module.exports = React.createClass
selectedDate: @props.selectedDate
viewDate: @props.viewDate
# -- Lifecycle
componentDidUpdate: (prevProps, prevState) ->
@props.onChange? @ if prevState.selectedDate.getTime() != @state.selectedDate.getTime()
if prevState.selectedDate.getTime() != @state.selectedDate.getTime() && @props.onChange
@props.onChange? @
# -- Events
onDayClick: (event) ->
@ -31,7 +36,7 @@ module.exports = React.createClass
newDate.setDate(day)
@setState selectedDate: newDate
# -- Handle month increment and decrement
# -- Public methods
incrementViewMonth: ->
@setState
viewDate: dateUtils.addMonths(@state.viewDate, 1)
@ -42,58 +47,19 @@ module.exports = React.createClass
viewDate: dateUtils.addMonths(@state.viewDate, -1)
direction: 'left'
# -- Render helpers
isDaySelected: (day) ->
isSameYear = @state.viewDate.getFullYear() == @state.selectedDate.getFullYear()
isSameMonth = @state.viewDate.getMonth() == @state.selectedDate.getMonth()
isSameDay = day == @state.selectedDate.getDate()
if isSameYear && isSameMonth && isSameDay then 'active' else ''
getValue: ->
@state.selectedDate
# -- Render
render: ->
<div className={"#{css.root} #{@state.direction}"}>
{# Controllers to move to prev and next month }
<FontIcon className={css.prevMonth} value='chevron_left' onClick={@decrementViewMonth} />
<FontIcon className={css.nextMonth} value='chevron_right' onClick={@incrementViewMonth} />
{# Calendar itself }
<FontIcon className={css.prev} value='chevron_left' onClick={@decrementViewMonth} />
<FontIcon className={css.next} value='chevron_right' onClick={@incrementViewMonth} />
<CTG transitionName='slide-horizontal'>
<div key={@state.viewDate.getMonth()}>
<div className={css.title}>
{"#{dateUtils.monthInWords(@state.viewDate)}, #{@state.viewDate.getFullYear()}"}
</div>
<div className={css.calendar}>
<div className={css.calendarWeekDays}>
{
for i in [0..6]
<span className={css.calendarWeekDay}
key={"dw#{i}"}>
{dateUtils.weekDayInWords(i).charAt(0)}
</span>
}
</div>
<div className={css.calendarBody}>
<span key={"d1"}
onClick={@onDayClick}
className={css.calendarBodyDay + ' ' + @isDaySelected(1)}
style={marginLeft: "#{dateUtils.firstWeekDay(@state.viewDate) * 100/7}%"}>
1
</span>
{
for i in [2..dateUtils.daysInMonth(@state.viewDate)]
<span key={"d#{i}"}
onClick={@onDayClick}
className={css.calendarBodyDay + ' ' + @isDaySelected(i)}>
{i}
</span>
}
</div>
</div>
</div>
<Month
key={@state.viewDate.getMonth()}
viewDate={@state.viewDate}
selectedDate={@state.selectedDate}
onDayClick={@onDayClick} />
</CTG>
</div>
getValue: ->
@state.selectedDate

View File

@ -0,0 +1,27 @@
css = require './style'
Day = require './day'
util = require '../date_utils'
module.exports = React.createClass
displayName: 'Month',
propTypes:
onDayClick : React.PropTypes.func
selectedDate : React.PropTypes.object
viewDate : React.PropTypes.object
render: ->
<div>
<span>{ util.monthInWords(@props.viewDate)}, {@props.viewDate.getFullYear() }</span>
<div className={css.week}>
{ <span key={"dw#{i}"}>{ util.weekDayInWords(i).charAt(0) }</span> for i in [0..6] }
</div>
<div className={css.days}>
{ for i in [1..util.daysInMonth(@props.viewDate)]
<Day key={"d#{i}"}
day={i}
onClick={@props.onDayClick}
selectedDate={@props.selectedDate}
viewDate={@props.viewDate} /> }
</div>
</div>

View File

@ -1,94 +1,78 @@
@import '../constants'
// -- Calendar sizes
monthHeight = 38px
dayWidth = 38px
innerPadding = 10px
dayHeight = dayWidth
calendarWidth = dayWidth * 7
calendarHeight = dayHeight * 7
totalHeight = monthHeight + calendarHeight + innerPadding * 2
totalWidth = calendarWidth + innerPadding * 2
ROW_HEIGHT = 40px
TOTAL_HEIGHT = ROW_HEIGHT * 8
:local(.root)
border-radius : 3px
height : totalHeight
background : WHITE
height : TOTAL_HEIGHT
font-size : 14px
overflow : hidden
position : relative
line-height : ROW_HEIGHT
text-align : center
width : totalWidth
// -- Prev and next controls
:local(.prevMonth), :local(.nextMonth)
:local(.prev), :local(.next)
cursor : pointer
height : monthHeight
line-height : monthHeight
height : ROW_HEIGHT
line-height : ROW_HEIGHT
opacity : .7
position : absolute
text-align : center
top : innerPadding
width : dayWidth
z-index : 2
top : 0
width : ROW_HEIGHT
z-index : Z_INDEX_HIGH
:local(.prevMonth)
left : innerPadding
:local(.prev)
left : 0
:local(.nextMonth)
right : innerPadding
:local(.next)
right : 0
// -- Calendar
:local(.title)
font-size : 14px
left : innerPadding
line-height : monthHeight
position : absolute
right : innerPadding
top : innerPadding
:local(.calendar)
bottom : innerPadding
font-size : 12px
left : innerPadding
position : absolute
right : innerPadding
top : monthHeight + innerPadding
:local(.calendarWeekDays)
:local(.week)
display : flex
flex-wrap : wrap
height : dayHeight
line-height : dayHeight
font-size : 13px
height : ROW_HEIGHT
line-height : ROW_HEIGHT
opacity : .5
:local(.calendarWeekDay)
flex : 0 0 (100/7)%
> span
flex : 0 0 (100/7)%
:local(.calendarBody)
:local(.days)
display : flex
flex-wrap : wrap
font-size : 13px
:local(.calendarBodyDay)
border-radius : 50%
cursor : pointer
:local(.day)
flex : 0 0 (100/7)%
height : dayHeight
line-height : dayHeight
padding : 2px
&:hover:not(.active)
> span
border-radius : 50%
cursor : pointer
display : inline-block
height : ROW_HEIGHT
line-height : ROW_HEIGHT
width : ROW_HEIGHT
&:hover:not(.active) > span
background : lighten(ACCENT, 65%)
color : white
color : WHITE
&.active
&.active > span
background : ACCENT
color : white
color : WHITE
// -- Slide transitions
// -- Transitions
:local(.root) .slide-horizontal-enter, :local(.root) .slide-horizontal-leave
transition : all .5s
// -- Slide horizontal transition left to right
:local(.root).right
.slide-horizontal-enter
position : absolute
transform : translateX(100%)
opacity : 0
@ -100,9 +84,9 @@ totalWidth = calendarWidth + innerPadding * 2
transform : translateX(-100%)
opacity : 0
// -- Slide horizontal transition right to left
:local(.root).left
.slide-horizontal-enter
position : absolute
transform : translateX(-100%)
opacity : 0

View File

@ -1,6 +1,6 @@
module.exports =
daysInMonth: (date) ->
(new Date(date.getFullYear(), date.getMonth(), 0)).getDate()
(new Date(date.getFullYear(), date.getMonth() + 1, 0)).getDate()
firstWeekDay: (date) ->
(new Date(date.getFullYear(), date.getMonth(), 1)).getDay()

View File

@ -1,6 +1,7 @@
localCSS = require './style'
module.exports = React.createClass
displayName: 'FontIcon',
# -- States & Properties
propTypes:

View File

@ -1,5 +1,7 @@
Calendar = require '../../components/calendar'
module.exports = React.createClass
displayName: 'TestCalendar',
render: ->
<Calendar />