import XDate from 'xdate'; import isEqual from 'lodash/isEqual'; import PropTypes from 'prop-types'; import React, {Component} from 'react'; import {TouchableWithoutFeedback, Text, View, ViewStyle} from 'react-native'; import {xdateToData} from '../../../interface'; import {Theme, DayState, DateData} from '../../../types'; import {shouldUpdate} from '../../../componentUpdater'; import * as defaultStyle from '../../../style'; import styleConstructor from './style'; import Dot from '../dot'; import {MarkingProps} from '../marking'; interface PeriodDayProps { state?: DayState; marking?: MarkingProps; theme?: Theme; onPress?: (date?: DateData) => void; onLongPress?: (date?: DateData) => void; date?: string; accessibilityLabel?: string; testID?: string; } export default class PeriodDay extends Component { static displayName = 'PeriodDay'; static propTypes = { state: PropTypes.oneOf(['selected', 'disabled', 'inactive', 'today', '']), marking: PropTypes.any, theme: PropTypes.object, onPress: PropTypes.func, onLongPress: PropTypes.func, date: PropTypes.string }; theme: Theme; style: any; markingStyle: any; dateData: any; constructor(props: PeriodDayProps) { super(props); this.theme = {...defaultStyle, ...(props.theme || {})}; this.style = styleConstructor(props.theme); this.markingStyle = this.getDrawingStyle(props.marking); this.dateData = props.date ? xdateToData(new XDate(props.date)) : undefined; } onPress = () => { this.props.onPress?.(this.dateData); }; onLongPress = () => { this.props.onLongPress?.(this.dateData); }; shouldComponentUpdate(nextProps: PeriodDayProps) { const newMarkingStyle = this.getDrawingStyle(nextProps.marking); if (!isEqual(this.markingStyle, newMarkingStyle)) { this.markingStyle = newMarkingStyle; return true; } return shouldUpdate(this.props, nextProps, ['children', 'state', 'marking', 'onPress', 'onLongPress', 'date']); } // TODO: refactor to use MarkingProps as the type getDrawingStyle(marking?: any) { const defaultStyle = {textStyle: {color: undefined}, containerStyle: {}}; if (!marking) { return defaultStyle; } if (marking.disabled) { defaultStyle.textStyle.color = this.style.disabledText.color; } else if (marking.inactive) { defaultStyle.textStyle.color = this.style.inactiveText.color; } else if (marking.selected) { defaultStyle.textStyle.color = this.style.selectedText.color; } const resultStyle = [marking].reduce((prev, next) => { // if (next.quickAction) { //??? // if (next.first || next.last) { // prev.containerStyle = this.style.firstQuickAction; // prev.textStyle = this.style.firstQuickActionText; // if (next.endSelected && next.first && !next.last) { // prev.rightFillerStyle = '#c1e4fe'; // } else if (next.endSelected && next.last && !next.first) { // prev.leftFillerStyle = '#c1e4fe'; // } // } else if (!next.endSelected) { // prev.containerStyle = this.style.quickAction; // prev.textStyle = this.style.quickActionText; // } else if (next.endSelected) { // prev.leftFillerStyle = '#c1e4fe'; // prev.rightFillerStyle = '#c1e4fe'; // } // return prev; // } // if (next.status === 'NotAvailable') { //??? // prev.textStyle = this.style.naText; // } const color = next.color; if (next.startingDay) { prev.startingDay = {color}; } if (next.endingDay) { prev.endingDay = {color}; } if (!next.startingDay && !next.endingDay) { prev.day = {color}; } if (next.textColor) { prev.textStyle.color = next.textColor; } if (marking.customTextStyle) { defaultStyle.textStyle = marking.customTextStyle; } if (marking.customContainerStyle) { defaultStyle.containerStyle = marking.customContainerStyle; } return prev; }, defaultStyle); return resultStyle; } render() { const {state, marking} = this.props; const containerStyle = [this.style.base]; const textStyle = [this.style.text]; let leftFillerStyle: ViewStyle = {backgroundColor: undefined}; let rightFillerStyle: ViewStyle = {backgroundColor: undefined}; let fillerStyle = {}; let fillers; // TODO: refactor - move all styling logic out of render() if (state === 'disabled') { textStyle.push(this.style.disabledText); } else if (state === 'inactive') { textStyle.push(this.style.inactiveText); } else if (state === 'today') { containerStyle.push(this.style.today); textStyle.push(this.style.todayText); } if (marking) { containerStyle.push({ borderRadius: 17, overflow: 'hidden' }); const flags = this.markingStyle; if (flags.textStyle) { textStyle.push(flags.textStyle); } if (flags.containerStyle) { containerStyle.push(flags.containerStyle); } if (flags.leftFillerStyle) { leftFillerStyle.backgroundColor = flags.leftFillerStyle; } if (flags.rightFillerStyle) { rightFillerStyle.backgroundColor = flags.rightFillerStyle; } if (flags.startingDay && !flags.endingDay) { leftFillerStyle = { backgroundColor: this.theme.calendarBackground }; rightFillerStyle = { backgroundColor: flags.startingDay.color }; containerStyle.push({ backgroundColor: flags.startingDay.color }); } else if (flags.endingDay && !flags.startingDay) { rightFillerStyle = { backgroundColor: this.theme.calendarBackground }; leftFillerStyle = { backgroundColor: flags.endingDay.color }; containerStyle.push({ backgroundColor: flags.endingDay.color }); } else if (flags.day) { leftFillerStyle = {backgroundColor: flags.day.color}; rightFillerStyle = {backgroundColor: flags.day.color}; fillerStyle = {backgroundColor: flags.day.color}; } else if (flags.endingDay && flags.startingDay) { rightFillerStyle = { backgroundColor: this.theme.calendarBackground }; leftFillerStyle = { backgroundColor: this.theme.calendarBackground }; containerStyle.push({ backgroundColor: flags.endingDay.color }); } // TODO: refactor - move all fillers logic out of render() fillers = ( ); } const {theme, accessibilityLabel, testID} = this.props; // TODO: refactor - allow feedback for unmarked days return ( {fillers} {String(this.props.children)} ); } }