Skip to content

Instantly share code, notes, and snippets.

@samcorcos
Last active December 1, 2016 05:03
Show Gist options
  • Save samcorcos/69c57728cae1b7b0a1b3a2f548d98935 to your computer and use it in GitHub Desktop.
Save samcorcos/69c57728cae1b7b0a1b3a2f548d98935 to your computer and use it in GitHub Desktop.
import React from 'react'
import { View, Text, TouchableOpacity, } from 'react-native'
import style from './style'
const pipe = (fns, init) => fns.reduce((acc, fn) => fn(acc), init)
const monthLabels = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
const getDaysInMonth = (month, year) => {
if (month === 1) {
if ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0) {
return 29
}
}
const daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
return daysInMonth[month]
}
const dateValues = (c) => {
const month = c.getMonth()
const year = c.getFullYear()
const daysInMonth = getDaysInMonth(month, year)
return {
month,
firstDay: new Date(year, month, 1).getDay(),
daysInMonth,
}
}
const renderDayLabels = () => {
const dayLabels = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
return dayLabels.map((day) => {
return (
<View
key={day}
style={style.dayLabel}>
<Text>
{day}
</Text>
</View>
)
})
}
/**
creates array based on number of days in current month
*/
const createArray = d => Array(d).fill(1).map((v, i) => v + i)
/**
takes in the day of the week of the first day (as an index) and returns a new
array with null values for each day that comes before the first day
*/
const addEmptyValues = (firstDay) => (a) => {
const l = (firstDay + a.length) % 7
// TODO need to add values to the end (should be 3 for November)
return [...Array((firstDay)).fill(null), ...a, ...Array((l)).fill(null)]
}
const splitRows = (arr) => {
return arr.map((d, i) => {
if (i % 7 === 0) return arr.slice(i, (i + 7))
return undefined
}).filter(e => e !== undefined)
}
/**
takes in an array
=> [null, null, 1, 2...30]
*/
const renderWeek = (arr) => {
const daysArray = arr.map((day) => {
if (day === null) return (<View style={style.emptyCalendarItem} />)
return (<Text style={style.calendarItem}>{day}</Text>)
})
return (
<View style={style.calendarRow}>
{daysArray}
</View>
)
}
/**
takes in an array of arrays
=> [ [null, null, 1...4], [5...11], ... ]
*/
const renderAllWeeks = (arr) => {
return arr.map((week) => {
return renderWeek(week)
})
}
const renderCalendarRows = (firstDay, daysInMonth) => {
return pipe([
createArray, // => [1, 2...30]
addEmptyValues(firstDay), // => [null, null, 1, 2...30, null, null, null]
splitRows, // => [ [null, null, 1...4], [5...11], ... ]
renderAllWeeks, // => JSX
], daysInMonth)
}
const Calendar = (props) => {
const { month, firstDay, daysInMonth, } = dateValues(props.date)
return (
<View>
<Text style={{ textAlign: 'center', }}>{monthLabels[month]}</Text>
<View
style={style.dayLabelRow}>
{renderDayLabels()}
</View>
<View
style={style.calendar}>
{renderCalendarRows(firstDay, daysInMonth)}
</View>
</View>
)
}
Calendar.propTypes = {
date: React.PropTypes.shape({
// TODO how to represent this as proptypes? date type?
}),
}
export default Calendar
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment