import * as React from 'react' ; import { View , Text , StyleSheet } from 'react-native' ; import { OutlineBadge as Badge } from '@frogpond/badge' ; import isEqual from 'lodash/isEqual' ; import type { Moment } from 'moment' ; import type { BuildingType } from './types' ; import * as c from '@frogpond/colors' ; import { Row } from '@frogpond/layout' ; import { ListRow , Detail , Title } from '@frogpond/lists' ; import { getDetailedBuildingStatus , getShortBuildingStatus } from './lib' ; const styles = StyleSheet . create ( { title : { justifyContent : 'space-between' , alignItems : 'center' , } , titleText : { flex : 1 , } , detailWrapper : { paddingTop : 3 , } , detailRow : { paddingTop : 0 , } , subtitleText : { fontWeight : '400' , color : c . iosDisabledText , } , accessoryBadge : { marginLeft : 4 , } , bold : { fontWeight : 'bold' , } , } ) ; const BG_COLORS = { Open : c . moneyGreen , Closed : c . salmon , } ; const FG_COLORS = { Open : c . hollyGreen , Closed : c . brickRed , } ; type Props = { info : BuildingType ; name : string ; now : Moment ; onPress : ( info : BuildingType ) => any ; } ; type State = { now : Moment ; openStatus : string ; hours : Array < any > ; accentBg : string ; accentText : string ; } ; function deriveStateFromProps ( props ) { let openStatus = getShortBuildingStatus ( props . info , props . now ) ; let hours = getDetailedBuildingStatus ( props . info , props . now ) ; let accentBg = BG_COLORS [ openStatus ] || c . goldenrod ; let accentText = FG_COLORS [ openStatus ] || 'rgb(130, 82, 45)' ; return { now : props . now , openStatus , hours , accentBg , accentText , } ; } export class BuildingRow extends React . Component < Props , State > { state = deriveStateFromProps ( this . props ) ; static getDerivedStateFromProps ( nextProps , prevState ) { if ( prevState . now . isSame ( nextProps . now , 'minute' ) ) { return null ; } return deriveStateFromProps ( nextProps ) ; } shouldComponentUpdate ( nextProps , nextState ) { return ( this . props . name !== nextProps . name || this . props . info !== nextProps . info || this . props . onPress !== nextProps . onPress || this . state . openStatus !== nextState . openStatus || ! isEqual ( this . state . hours , nextState . hours ) ) ; } onPress = ( ) => { this . props . onPress ( this . props . info ) ; } ; render ( ) { let { info , name } = this . props ; let { openStatus , hours , accentBg , accentText } = this . state ; return ( < ListRow arrowPosition = "center" onPress = { this . onPress } > < Row style = { styles . title } > < Title lines = { 1 } style = { styles . titleText } > < Text > { name } < /Text> { info . abbreviation ? < Text > ( { info . abbreviation } ) < /Text> : null} { info . subtitle ? ( < Text style = { styles . subtitleText } > { info . subtitle } < /Text>) : null} < /Title> { ! info . isNotice ? ( < Badge accentColor = { accentBg } style = { styles . accessoryBadge } text = { openStatus } textColor = { accentText } / > ) : null } < /Row> < View style = { styles . detailWrapper } > { info . noticeMessage ? ( < Detail style = { styles . detailRow } > { info . noticeMessage } < /Detail>) : null} { ! ( info . noticeMessage && info . isNotice ) ? hours . map ( ( { isActive , label , status } , i ) => ( < Detail key = { i } style = { styles . detailRow } > < BuildingTimeSlot highlight = { hours . length > 1 && isActive } label = { label } status = { status } / > < /Detail>)) : null } < /View> < /ListRow>); } } const BuildingTimeSlot = ( { label , status , highlight , } ) => { let showLabel = label && label !== 'Hours' ; return ( < Text > { showLabel ? ( < Text style = { highlight && styles . bold } > { label } : < /Text>) : null} < Text style = { highlight && styles . bold } > { status } < /Text> < /Text>); } ;