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)
}
componentDidUpdate(prevProps) {
if (prevProps.match.params.activityId !==
this.props.match.params.activityId) {
this.props.loadActivity(this.props.match.params.activityId)
}
}
render() {
const { activities, message, onDeleteActivity, sports } = this.props
const { displayModal } = this.state
@ -41,7 +48,7 @@ class ActivityDisplay extends React.Component {
<code>{message}</code>
) : (
<div className="container">
{ displayModal &&
{displayModal &&
<CustomModal
title="Confirmation"
text="Are you sure you want to delete this activity?"
@ -51,134 +58,176 @@ class ActivityDisplay extends React.Component {
}}
close={() => this.setState({ displayModal: false })}
/>}
{activity && sport && activities.length === 1 && (
<div className="row">
<div className="col">
<div className="card">
<div className="card-header">
<div className="row">
<div className="col-auto col-activity-logo">
<img
className="sport-img-medium"
src={sport.img}
alt="sport logo"
/>
</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">
{activity && sport && activities.length === 1 && (
<div className="row">
<div className="col">
<div className="card">
<div className="card-header">
<div className="row">
<div className="col-auto">
{activity.previous_activity ? (
<Link
className="unlink"
to={`/activities/${activity.previous_activity}`}
>
<i
className="fa fa-chevron-left"
aria-hidden="true"
/>
</Link>
) : (
<i
className="fa fa-chevron-left inactive-link"
aria-hidden="true"
/>
)}
</div>
<div className="col-auto col-activity-logo">
<img
className="sport-img-medium"
src={sport.img}
alt="sport logo"
/>
</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_time}`}
</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 className="card-body">
<div className="row">
{activity.with_gpx && (
<div className="col-8">
<ActivityMap activity={activity} />
<div className="card-body">
<div className="row">
{activity.with_gpx && (
<div className="col-8">
<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 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>

View File

@ -1,3 +1,4 @@
import hash from 'object-hash'
import React from 'react'
import { GeoJSON, Map, TileLayer } from 'react-leaflet'
import { connect } from 'react-redux'
@ -18,6 +19,13 @@ class ActivityMap extends React.Component {
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() {
this.props.loadActivityGpx(null)
}
@ -44,7 +52,11 @@ class ActivityMap extends React.Component {
// eslint-disable-next-line max-len
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>
)}
</div>

View File

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

View File

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

View File

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