Client - rename existing front
This commit is contained in:
@ -1,189 +0,0 @@
|
||||
import React from 'react'
|
||||
|
||||
import { translateSports } from '../../utils/workouts'
|
||||
|
||||
export default class WorkoutsFilter extends React.PureComponent {
|
||||
render() {
|
||||
const { loadWorkouts, sports, t, updateParams } = this.props
|
||||
const translatedSports = translateSports(sports, t)
|
||||
return (
|
||||
<div className="card">
|
||||
<div className="card-body workout-filter">
|
||||
<form onSubmit={event => event.preventDefault()}>
|
||||
<div className="form-group">
|
||||
<label>
|
||||
{t('workouts:From')}:
|
||||
<input
|
||||
className="form-control col-md"
|
||||
name="from"
|
||||
onChange={e => updateParams(e)}
|
||||
type="date"
|
||||
/>
|
||||
</label>
|
||||
<label>
|
||||
{t('workouts:To')}:
|
||||
<input
|
||||
className="form-control col-md"
|
||||
name="to"
|
||||
onChange={e => updateParams(e)}
|
||||
type="date"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<label>
|
||||
{t('common:Sport')}:
|
||||
<select
|
||||
className="form-control input-lg"
|
||||
name="sport_id"
|
||||
onChange={e => updateParams(e)}
|
||||
>
|
||||
<option value="" />
|
||||
{translatedSports.map(sport => (
|
||||
<option key={sport.id} value={sport.id}>
|
||||
{sport.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<label>
|
||||
{t('workouts:Distance')} (km):
|
||||
<div className="container">
|
||||
<div className="row">
|
||||
<div className="col-5">
|
||||
<input
|
||||
className="form-control"
|
||||
min={0}
|
||||
name="distance_from"
|
||||
onChange={e => updateParams(e)}
|
||||
step="1"
|
||||
type="number"
|
||||
/>
|
||||
</div>
|
||||
<div className="col-2 align-middle text-center">
|
||||
{t('common:to')}
|
||||
</div>
|
||||
<div className="col-5">
|
||||
<input
|
||||
className="form-control"
|
||||
min={0}
|
||||
name="distance_to"
|
||||
onChange={e => updateParams(e)}
|
||||
step="1"
|
||||
type="number"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<label>
|
||||
{t('workouts:Duration')}:
|
||||
<div className="container">
|
||||
<div className="row">
|
||||
<div className="col-5">
|
||||
<input
|
||||
className="form-control"
|
||||
name="duration_from"
|
||||
onChange={e => updateParams(e)}
|
||||
pattern="^([0-9]*[0-9]):([0-5][0-9])$"
|
||||
placeholder="hh:mm"
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
<div className="col-2 align-middle text-center">
|
||||
{t('common:to')}
|
||||
</div>
|
||||
<div className="col-5">
|
||||
<input
|
||||
className="form-control"
|
||||
name="duration_to"
|
||||
onChange={e => updateParams(e)}
|
||||
pattern="^([0-9]*[0-9]):([0-5][0-9])$"
|
||||
placeholder="hh:mm"
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<label>
|
||||
{t('workouts:Average speed')} (km/h):
|
||||
<div className="container">
|
||||
<div className="row">
|
||||
<div className="col-5">
|
||||
<input
|
||||
className="form-control"
|
||||
min={0}
|
||||
name="ave_speed_from"
|
||||
onChange={e => updateParams(e)}
|
||||
step="1"
|
||||
type="number"
|
||||
/>
|
||||
</div>
|
||||
<div className="col-2 align-middle text-center">
|
||||
{t('common:to')}
|
||||
</div>
|
||||
<div className="col-5">
|
||||
<input
|
||||
className="form-control"
|
||||
min={0}
|
||||
name="ave_speed_to"
|
||||
onChange={e => updateParams(e)}
|
||||
step="1"
|
||||
type="number"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<label>
|
||||
{t('workouts:Max. speed')} (km/h):
|
||||
<div className="container">
|
||||
<div className="row">
|
||||
<div className="col-5">
|
||||
<input
|
||||
className="form-control"
|
||||
min={0}
|
||||
name="max_speed_from"
|
||||
onChange={e => updateParams(e)}
|
||||
step="1"
|
||||
type="number"
|
||||
/>
|
||||
</div>
|
||||
<div className="col-2 align-middle text-center">
|
||||
{t('common:to')}
|
||||
</div>
|
||||
<div className="col-5">
|
||||
<input
|
||||
className="form-control"
|
||||
min={0}
|
||||
name="max_speed_to"
|
||||
onChange={e => updateParams(e)}
|
||||
step="1"
|
||||
type="number"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
<input
|
||||
className="btn btn-primary btn-lg btn-block"
|
||||
onClick={() => loadWorkouts()}
|
||||
type="submit"
|
||||
value={t('workouts:Filter')}
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
@ -1,111 +0,0 @@
|
||||
import { format } from 'date-fns'
|
||||
import React from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
import StaticMap from '../Common/StaticMap'
|
||||
import { getDateWithTZ } from '../../utils'
|
||||
|
||||
export default class WorkoutsList extends React.PureComponent {
|
||||
render() {
|
||||
const { loading, sports, t, user, workouts } = this.props
|
||||
return (
|
||||
<div className="card workout-card">
|
||||
<div className="card-body">
|
||||
<table className="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" />
|
||||
<th scope="col">{t('common:Workout')}</th>
|
||||
<th scope="col">{t('workouts:Date')}</th>
|
||||
<th scope="col">{t('workouts:Distance')}</th>
|
||||
<th scope="col">{t('workouts:Duration')}</th>
|
||||
<th scope="col">{t('workouts:Ave. speed')}</th>
|
||||
<th scope="col">{t('workouts:Max. speed')}</th>
|
||||
<th scope="col">{t('workouts:Ascent')}</th>
|
||||
<th scope="col">{t('workouts:Descent')}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{!loading &&
|
||||
sports &&
|
||||
workouts.map((workout, idx) => (
|
||||
// eslint-disable-next-line react/no-array-index-key
|
||||
<tr key={idx}>
|
||||
<td>
|
||||
<span className="heading-span-absolute">
|
||||
{t('common:Sport')}
|
||||
</span>
|
||||
<img
|
||||
className="workout-sport"
|
||||
src={sports
|
||||
.filter(s => s.id === workout.sport_id)
|
||||
.map(s => s.img)}
|
||||
alt="workout sport logo"
|
||||
/>
|
||||
</td>
|
||||
<td className="workout-title">
|
||||
<span className="heading-span-absolute">
|
||||
{t('common:Workout')}
|
||||
</span>
|
||||
<Link to={`/workouts/${workout.id}`}>
|
||||
{workout.title}
|
||||
</Link>
|
||||
{workout.map && (
|
||||
<StaticMap workout={workout} display="list" />
|
||||
)}
|
||||
</td>
|
||||
<td>
|
||||
<span className="heading-span-absolute">
|
||||
{t('workouts:Date')}
|
||||
</span>
|
||||
{format(
|
||||
getDateWithTZ(workout.workout_date, user.timezone),
|
||||
'dd/MM/yyyy HH:mm'
|
||||
)}
|
||||
</td>
|
||||
<td className="text-right">
|
||||
<span className="heading-span-absolute">
|
||||
{t('workouts:Distance')}
|
||||
</span>
|
||||
{Number(workout.distance).toFixed(2)} km
|
||||
</td>
|
||||
<td className="text-right">
|
||||
<span className="heading-span-absolute">
|
||||
{t('workouts:Duration')}
|
||||
</span>
|
||||
{workout.moving}
|
||||
</td>
|
||||
<td className="text-right">
|
||||
<span className="heading-span-absolute">
|
||||
{t('workouts:Ave. speed')}
|
||||
</span>
|
||||
{workout.ave_speed} km/h
|
||||
</td>
|
||||
<td className="text-right">
|
||||
<span className="heading-span-absolute">
|
||||
{t('workouts:Max. speed')}
|
||||
</span>
|
||||
{workout.max_speed} km/h
|
||||
</td>
|
||||
<td className="text-right">
|
||||
<span className="heading-span-absolute">
|
||||
{t('workouts:Ascent')}
|
||||
</span>
|
||||
{workout.ascent === null ? '' : `${workout.ascent} m`}
|
||||
</td>
|
||||
<td className="text-right">
|
||||
<span className="heading-span-absolute">
|
||||
{t('workouts:Descent')}
|
||||
</span>
|
||||
{workout.descent === null ? '' : `${workout.descent} m`}
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
{loading && <div className="loader" />}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
@ -1,120 +0,0 @@
|
||||
import React from 'react'
|
||||
import { Helmet } from 'react-helmet'
|
||||
import { withTranslation } from 'react-i18next'
|
||||
import { connect } from 'react-redux'
|
||||
|
||||
import Message from '../Common/Message'
|
||||
import NoWorkouts from '../Common/NoWorkouts'
|
||||
import WorkoutsFilter from './WorkoutsFilter'
|
||||
import WorkoutsList from './WorkoutsList'
|
||||
import { getOrUpdateData } from '../../actions'
|
||||
import { getMoreWorkouts } from '../../actions/workouts'
|
||||
|
||||
class Workouts extends React.Component {
|
||||
constructor(props, context) {
|
||||
super(props, context)
|
||||
this.state = {
|
||||
params: {
|
||||
page: 1,
|
||||
per_page: 10,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.props.loadWorkouts(this.state.params)
|
||||
}
|
||||
|
||||
setParams(e) {
|
||||
const { params } = this.state
|
||||
if (e.target.value === '') {
|
||||
delete params[e.target.name]
|
||||
} else {
|
||||
params[e.target.name] = e.target.value
|
||||
}
|
||||
params.page = 1
|
||||
this.setState(params)
|
||||
}
|
||||
render() {
|
||||
const {
|
||||
loading,
|
||||
loadWorkouts,
|
||||
loadMoreWorkouts,
|
||||
message,
|
||||
sports,
|
||||
t,
|
||||
user,
|
||||
workouts,
|
||||
} = this.props
|
||||
const { params } = this.state
|
||||
const paginationEnd =
|
||||
workouts.length > 0
|
||||
? workouts[workouts.length - 1].previous_workout === null
|
||||
: true
|
||||
return (
|
||||
<div>
|
||||
<Helmet>
|
||||
<title>FitTrackee - {t('common:Workouts')}</title>
|
||||
</Helmet>
|
||||
{message ? (
|
||||
<Message message={message} t={t} />
|
||||
) : (
|
||||
<div className="container history">
|
||||
<div className="row">
|
||||
<div className="col-md-3">
|
||||
<WorkoutsFilter
|
||||
sports={sports}
|
||||
loadWorkouts={() => loadWorkouts(params)}
|
||||
t={t}
|
||||
updateParams={e => this.setParams(e)}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-md-9 workouts-result">
|
||||
<WorkoutsList
|
||||
workouts={workouts}
|
||||
loading={loading}
|
||||
sports={sports}
|
||||
t={t}
|
||||
user={user}
|
||||
/>
|
||||
{!paginationEnd && (
|
||||
<input
|
||||
type="submit"
|
||||
className="btn btn-default btn-md btn-block"
|
||||
value="Load more workouts"
|
||||
onClick={() => {
|
||||
params.page += 1
|
||||
loadMoreWorkouts(params)
|
||||
this.setState(params)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{workouts.length === 0 && <NoWorkouts t={t} />}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default withTranslation()(
|
||||
connect(
|
||||
state => ({
|
||||
workouts: state.workouts.data,
|
||||
loading: state.loading,
|
||||
message: state.message,
|
||||
sports: state.sports.data,
|
||||
user: state.user,
|
||||
}),
|
||||
dispatch => ({
|
||||
loadWorkouts: params => {
|
||||
dispatch(getOrUpdateData('getData', 'workouts', params))
|
||||
},
|
||||
loadMoreWorkouts: params => {
|
||||
dispatch(getMoreWorkouts(params))
|
||||
},
|
||||
})
|
||||
)(Workouts)
|
||||
)
|
Reference in New Issue
Block a user