FacilityCard.tsx 6.89 KB
Newer Older
1
import * as React from 'react';
Andrew Hrdy's avatar
Andrew Hrdy committed
2
import * as classNames from 'classnames';
3 4
import { connect } from 'react-redux';
import { removeBrackets } from '../utils/nameUtils';
Andrew Hrdy's avatar
Andrew Hrdy committed
5
import FacilityUtils from '../utils/facilityUtils';
6
import { IFacility } from '../models/facility.model';
Andrew Hrdy's avatar
Andrew Hrdy committed
7 8 9 10
import { ApplicationState } from '../store';
import { Dispatch } from 'redux';
import { addFavoriteFacility, removeFavoriteFacility, setSelectedFacility, setSidebarExpansion } from '../store/ui/ui.actions';
import { trackPiwikEvent } from '../piwik/piwik';
11

12 13 14 15
import FacilityStatus from '../components/FacilityStatus';
import FavoriteButton from '../components/FavoriteButton';
import FacilityCategory from '../components/FacilityCategory';
import FacilityDialog from '../components/FacilityDialog';
16

17 18 19 20 21 22 23 24 25
import Card from '@material-ui/core/Card';
import CardContent from '@material-ui/core/CardContent';
import Typography from '@material-ui/core/Typography';
import Grid from '@material-ui/core/Grid';
import LocationOnIcon from '@material-ui/icons/LocationOn';

class FacilityCard extends React.Component<FacilityCardProps, FacilityCardState> {

    constructor(props: FacilityCardProps) {
26
        super(props);
27

28
        this.state = {
29
            modified: null
Andrew Hrdy's avatar
Andrew Hrdy committed
30
        };
31
    }
32

33
    shouldComponentUpdate = (nextProps: FacilityCardProps) => {
34
        if (this.isFacilitySelected() !== (nextProps.selectedFacility.slug === this.props.facility.slug)) {
35 36 37
            return true;
        }

38
        const dateModified = nextProps.facility.modified;
39

40 41 42 43
        if (dateModified !== this.state.modified) {
            this.setState({
                modified: dateModified
            });
44

45 46
            return true;
        }
47

48 49 50
        return false;
    }

51
    isFacilitySelected = (): boolean => this.props.selectedFacility.slug === this.props.facility.slug;
52

53 54
    handleCardClick = () => {
        const newState = !this.isFacilitySelected();
55

Andrew Hrdy's avatar
Andrew Hrdy committed
56
        trackPiwikEvent('card-action', 'click');
57

58 59
        setTimeout(() => {
            this.props.setSelectedFacility(newState ? this.props.facility : null);
60
            this.props.setSidebarExpansion(newState);
61
        }, 0);
62
    }
63

64
    render() {
65
        const {facility, facilities, favorites, addFavoriteFacility, removeFavoriteFacility} = this.props;
66

Andrew Hrdy's avatar
Andrew Hrdy committed
67
        const dayOfWeek = [6, 0, 1, 2, 3, 4, 5][new Date().getDay()];
68 69

        const getDisplayHours = () => {
70
            const currentHour = new Date().getHours();
71 72 73 74 75
            const todaysHours = FacilityUtils.getHoursByDay(facility, dayOfWeek);

            if (todaysHours.length > 1) {
                for (let i = 0; i < todaysHours.length; i++) {
                    const hour = todaysHours[i];
76
                    if (currentHour <= hour.end && currentHour >= hour.start) {
77 78
                        return hour.text;
                    }
79
                }
80 81
            }

82
            return todaysHours[0].text;
83
        };
Andrew Hrdy's avatar
Andrew Hrdy committed
84

85 86 87
        const buildingName = facility.facility_location.friendly_building ?
            facility.facility_location.friendly_building :
            facility.facility_location.building;
Andrew Hrdy's avatar
Andrew Hrdy committed
88

89
        return (
90
            <Card onClick={this.handleCardClick} className={classNames('fc-root', this.isFacilitySelected() && 'fc-selected')}
Mattias J Duffy's avatar
Mattias J Duffy committed
91
                   elevation={3}>
92
                <div className={'fc-logo-container'}>
93
                    <img className={'fc-logo'}
94
                    alt={facility.slug} src={facility.logo} />
95 96
                </div>

Mattias J Duffy's avatar
Mattias J Duffy committed
97
                <FavoriteButton slug={facility.slug} initialState={favorites.includes(facility.slug)}
98
                                addFavoriteFacility={addFavoriteFacility}
99
                                removeFavoriteFacility={removeFavoriteFacility} />
100 101

                <CardContent className={'fc-card-content'}>
102 103
                    <Grid container={true} alignItems={'center'} direction={'column'}>
                        <Grid item={true}
104
                              className={classNames('fc-small-grid-item-spacing', 'fc-ellipsis-container', 'fc-title-container')}>
105
                            <Typography variant={'subtitle1'} align={'center'}
106 107 108 109
                                        className={classNames('fc-title', 'fc-one-line-ellipsis')}>
                                {removeBrackets(facility.facility_name)}
                            </Typography>
                        </Grid>
110

111
                        <Grid item={true} className={'fc-small-grid-item-spacing'}>
112
                            <FacilityCategory category={facility.facility_category} />
113
                        </Grid>
114
                        
115
                        <Grid item={true} className={'fc-small-grid-item-spacing fc-display-hours'}>
116
                            <Typography variant={'body1'}>
117
                                {`Today: ${getDisplayHours()}`}
118 119
                            </Typography>
                        </Grid>
120
                    </Grid>
121

122 123
                    <Grid container={true} justify={'space-around'}>
                        <Grid item={true} className={'fc-extra-info'}>
124
                            <FacilityStatus facility={facility} />
125 126
                        </Grid>

127
                        <Grid item={true} className={'fc-extra-info'}>
128
                            <Typography variant={'caption'}>
129
                                <LocationOnIcon className={'fc-card-map-marker-icon'} />
130
                            </Typography>
Andrew Hrdy's avatar
Andrew Hrdy committed
131
                            
132
                            <Typography title={buildingName} variant={'caption'} align={'center'}
133
                                        className={'fc-two-line-ellipsis'}>
134
                                {buildingName}
135 136
                            </Typography>
                        </Grid>
137
                    </Grid>
138
                </CardContent>
139

140
                <FacilityDialog facility={facility} facilities={facilities} isOpen={this.isFacilitySelected()}
141
                                onClose={this.handleCardClick} />
142
            </Card>
143
        );
144
    }
145
}
Mattias J Duffy's avatar
Mattias J Duffy committed
146

147 148 149 150 151 152 153 154
export interface FacilityCardProps {
    facility: IFacility;
    facilities: IFacility[];
    favorites: string[];
    selectedFacility: IFacility;
    setSelectedFacility: (facility: IFacility) => void;
    addFavoriteFacility: (slug: string) => void;
    removeFavoriteFacility: (slug: string) => void;
155
    setSidebarExpansion: (isOpen: boolean) => void;
156 157 158
}

export interface FacilityCardState {
159
    modified: string;
160 161
}

162
const mapStateToProps = (state: ApplicationState) => ({
163 164
    favorites: state.ui.favorites,
    selectedFacility: state.ui.selectedFacility
165 166
});

167
const mapDispatchToProps = (dispatch: Dispatch) => ({
168 169 170 171
    setSelectedFacility: (facility: IFacility) => dispatch(setSelectedFacility(facility)),
    addFavoriteFacility: (slug: string) => dispatch(addFavoriteFacility(slug)),
    removeFavoriteFacility: (slug: string) => dispatch(removeFavoriteFacility(slug)),
    setSidebarExpansion: (isOpen: boolean) => dispatch(setSidebarExpansion(isOpen))
172
});
173 174

export default connect(mapStateToProps, mapDispatchToProps)(FacilityCard);