Client: activities navigation

This commit is contained in:
Sam 2018-05-17 15:13:53 +02:00
parent f744eb0769
commit 948e49beef
5 changed files with 187 additions and 121 deletions

View File

@ -21,6 +21,13 @@ class ActivityDisplay extends React.Component {
this.props.loadActivity(this.props.match.params.activityId) this.props.loadActivity(this.props.match.params.activityId)
} }
componentDidUpdate(prevProps) {
if (prevProps.match.params.activityId !==
this.props.match.params.activityId) {
this.props.loadActivity(this.props.match.params.activityId)
}
}
render() { render() {
const { activities, message, onDeleteActivity, sports } = this.props const { activities, message, onDeleteActivity, sports } = this.props
const { displayModal } = this.state const { displayModal } = this.state
@ -41,7 +48,7 @@ class ActivityDisplay extends React.Component {
<code>{message}</code> <code>{message}</code>
) : ( ) : (
<div className="container"> <div className="container">
{ displayModal && {displayModal &&
<CustomModal <CustomModal
title="Confirmation" title="Confirmation"
text="Are you sure you want to delete this activity?" text="Are you sure you want to delete this activity?"
@ -51,134 +58,176 @@ class ActivityDisplay extends React.Component {
}} }}
close={() => this.setState({ displayModal: false })} close={() => this.setState({ displayModal: false })}
/>} />}
{activity && sport && activities.length === 1 && ( {activity && sport && activities.length === 1 && (
<div className="row"> <div className="row">
<div className="col"> <div className="col">
<div className="card"> <div className="card">
<div className="card-header"> <div className="card-header">
<div className="row"> <div className="row">
<div className="col-auto col-activity-logo"> <div className="col-auto">
<img {activity.previous_activity ? (
className="sport-img-medium" <Link
src={sport.img} className="unlink"
alt="sport logo" to={`/activities/${activity.previous_activity}`}
/> >
</div> <i
<div className="col"> className="fa fa-chevron-left"
{title}{' '} aria-hidden="true"
<Link />
className="unlink" </Link>
to={`/activities/${activity.id}/edit`} ) : (
> <i
<i className="fa fa-chevron-left inactive-link"
className="fa fa-edit custom-fa" aria-hidden="true"
aria-hidden="true" />
/> )}
</Link> </div>
<i <div className="col-auto col-activity-logo">
className="fa fa-trash custom-fa" <img
aria-hidden="true" className="sport-img-medium"
onClick={() => this.setState({ displayModal: true })} src={sport.img}
/><br /> alt="sport logo"
{activityDate && ( />
<span className="activity-date"> </div>
<div className="col">
{title}{' '}
<Link
className="unlink"
to={`/activities/${activity.id}/edit`}
>
<i
className="fa fa-edit custom-fa"
aria-hidden="true"
/>
</Link>
<i
className="fa fa-trash custom-fa"
aria-hidden="true"
onClick={
() => this.setState({ displayModal: true })
}
/><br />
{activityDate && (
<span className="activity-date">
{`${activityDate.activity_date} - ${ {`${activityDate.activity_date} - ${
activityDate.activity_time}`} activityDate.activity_time}`}
</span> </span>
)} )}
</div>
<div className="col-auto">
{activity.next_activity ? (
<Link
className="unlink"
to={`/activities/${activity.next_activity}`}
>
<i
className="fa fa-chevron-right"
aria-hidden="true"
/>
</Link>
) : (
<i
className="fa fa-chevron-right inactive-link"
aria-hidden="true"
/>
)}
</div>
</div> </div>
</div> </div>
</div> <div className="card-body">
<div className="card-body"> <div className="row">
<div className="row"> {activity.with_gpx && (
{activity.with_gpx && ( <div className="col-8">
<div className="col-8"> <ActivityMap activity={activity} />
<ActivityMap activity={activity} /> </div>
)}
<div className="col">
<p>
<i
className="fa fa-clock-o custom-fa"
aria-hidden="true"
/>
Duration: {activity.duration}
{activity.records.find(r => r.record_type === 'LD'
) && (
<sup>
<i
className="fa fa-trophy custom-fa"
aria-hidden="true"
/>
</sup>
)} {' '}
{activity.pauses !== '0:00:00' &&
activity.pauses !== null && (
`(pauses: ${activity.pauses})`
)}
</p>
<p>
<i
className="fa fa-road custom-fa"
aria-hidden="true"
/>
Distance: {activity.distance} km
{activity.records.find(r => r.record_type === 'FD'
) && (
<sup>
<i
className="fa fa-trophy custom-fa"
aria-hidden="true"
/>
</sup>
)}
</p>
<p>
<i
className="fa fa-tachometer custom-fa"
aria-hidden="true"
/>
Average speed: {activity.ave_speed} km/h
{activity.records.find(r => r.record_type === 'AS'
) && (
<sup>
<i
className="fa fa-trophy custom-fa"
aria-hidden="true"
/>
</sup>
)}
<br />
Max speed : {activity.max_speed} km/h
{activity.records.find(r => r.record_type === 'MS'
) && (
<sup>
<i
className="fa fa-trophy custom-fa"
aria-hidden="true"
/>
</sup>
)}
</p>
{activity.min_alt && activity.max_alt && (
<p>
<i className="fi-mountains custom-fa" />
Min altitude: {activity.min_alt}m
<br />
Max altitude: {activity.max_alt}m
</p>
)}
{activity.ascent && activity.descent && (
<p>
<i className="fa fa-location-arrow custom-fa" />
Ascent: {activity.ascent}m
<br />
Descent: {activity.descent}m
</p>
)}
</div>
</div> </div>
)}
<div className="col">
<p>
<i
className="fa fa-clock-o custom-fa"
aria-hidden="true"
/>
Duration: {activity.duration}
{activity.records.find(r => r.record_type === 'LD') && (
<sup>
<i
className="fa fa-trophy custom-fa"
aria-hidden="true"
/>
</sup>
)} {' '}
{activity.pauses !== '0:00:00' &&
activity.pauses !== null && (
`(pauses: ${activity.pauses})`
)}
</p>
<p>
<i
className="fa fa-road custom-fa"
aria-hidden="true"
/>
Distance: {activity.distance} km
{activity.records.find(r => r.record_type === 'FD') && (
<sup>
<i
className="fa fa-trophy custom-fa"
aria-hidden="true"
/>
</sup>
)}
</p>
<p>
<i
className="fa fa-tachometer custom-fa"
aria-hidden="true"
/>
Average speed: {activity.ave_speed} km/h
{activity.records.find(r => r.record_type === 'AS') && (
<sup>
<i
className="fa fa-trophy custom-fa"
aria-hidden="true"
/>
</sup>
)}
<br />
Max speed : {activity.max_speed} km/h
{activity.records.find(r => r.record_type === 'MS') && (
<sup>
<i
className="fa fa-trophy custom-fa"
aria-hidden="true"
/>
</sup>
)}
</p>
{activity.min_alt && activity.max_alt && (
<p>
<i className="fi-mountains custom-fa" />
Min altitude: {activity.min_alt}m
<br />
Max altitude: {activity.max_alt}m
</p>
)}
{activity.ascent && activity.descent && (
<p>
<i className="fa fa-location-arrow custom-fa" />
Ascent: {activity.ascent}m
<br />
Descent: {activity.descent}m
</p>
)}
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> )}
</div>
)}
</div> </div>
)} )}
</div> </div>

View File

@ -1,3 +1,4 @@
import hash from 'object-hash'
import React from 'react' import React from 'react'
import { GeoJSON, Map, TileLayer } from 'react-leaflet' import { GeoJSON, Map, TileLayer } from 'react-leaflet'
import { connect } from 'react-redux' import { connect } from 'react-redux'
@ -18,6 +19,13 @@ class ActivityMap extends React.Component {
this.props.loadActivityGpx(this.props.activity.id) this.props.loadActivityGpx(this.props.activity.id)
} }
componentDidUpdate(prevProps) {
if (prevProps.activity.id !==
this.props.activity.id) {
this.props.loadActivityGpx(this.props.activity.id)
}
}
componentWillUnmount() { componentWillUnmount() {
this.props.loadActivityGpx(null) this.props.loadActivityGpx(null)
} }
@ -44,7 +52,11 @@ class ActivityMap extends React.Component {
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
url={`https://{s}.tile.thunderforest.com/outdoors/{z}/{x}/{y}.png?apikey=${thunderforestApiKey}`} url={`https://{s}.tile.thunderforest.com/outdoors/{z}/{x}/{y}.png?apikey=${thunderforestApiKey}`}
/> />
<GeoJSON data={jsonData} /> <GeoJSON
// hash as a key to force re-rendering
key={hash(jsonData)}
data={jsonData}
/>
</Map> </Map>
)} )}
</div> </div>

View File

@ -124,6 +124,10 @@ input, textarea {
max-height: 35px; max-height: 35px;
} }
.inactive-link {
color: lightgrey;
}
.sport-img-medium { .sport-img-medium {
max-width: 45px; max-width: 45px;
max-height: 45px; max-height: 45px;

View File

@ -8,6 +8,7 @@
"date-fns": "^1.29.0", "date-fns": "^1.29.0",
"history": "^4.7.2", "history": "^4.7.2",
"leaflet": "^1.3.1", "leaflet": "^1.3.1",
"object-hash": "^1.3.0",
"react": "^16.3.2", "react": "^16.3.2",
"react-dom": "^16.3.2", "react-dom": "^16.3.2",
"react-helmet": "^5.2.0", "react-helmet": "^5.2.0",

View File

@ -6146,7 +6146,7 @@ object-copy@^0.1.0:
define-property "^0.2.5" define-property "^0.2.5"
kind-of "^3.0.3" kind-of "^3.0.3"
object-hash@^1.1.4: object-hash@^1.1.4, object-hash@^1.3.0:
version "1.3.0" version "1.3.0"
resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-1.3.0.tgz#76d9ba6ff113cf8efc0d996102851fe6723963e2" resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-1.3.0.tgz#76d9ba6ff113cf8efc0d996102851fe6723963e2"