Client - rename existing front

This commit is contained in:
Sam
2021-09-01 20:08:06 +02:00
parent 6ba3f6d54e
commit 6d1de3c3bb
134 changed files with 0 additions and 0 deletions

View File

@ -1,198 +0,0 @@
// eslint-disable-next-line max-len
// source: https://blog.flowandform.agency/create-a-custom-calendar-in-react-3df1bfd0b728
import {
addDays,
addMonths,
endOfMonth,
endOfWeek,
format,
isSameDay,
isSameMonth,
isToday,
startOfMonth,
startOfWeek,
subMonths,
} from 'date-fns'
import { enGB, fr } from 'date-fns/locale'
import React from 'react'
import { connect } from 'react-redux'
import CalendarWorkouts from './CalendarWorkouts'
import { getMonthWorkouts } from '../../actions/workouts'
import { getDateWithTZ } from '../../utils'
const getStartAndEndMonth = (date, weekStartOnMonday) => {
const monthStart = startOfMonth(date)
const monthEnd = endOfMonth(date)
const weekStartsOn = weekStartOnMonday ? 1 : 0
return {
start: startOfWeek(monthStart, { weekStartsOn }),
end: endOfWeek(monthEnd),
}
}
class Calendar extends React.Component {
constructor(props, context) {
super(props, context)
const calendarDate = new Date()
this.state = {
currentMonth: calendarDate,
startDate: getStartAndEndMonth(calendarDate, props.weekm).start,
endDate: getStartAndEndMonth(calendarDate, props.weekm).end,
weekStartOnMonday: props.weekm,
}
}
componentDidMount() {
this.props.loadMonthWorkouts(this.state.startDate, this.state.endDate)
}
renderHeader(localeOptions) {
const dateFormat = 'MMM yyyy'
return (
<div className="header row flex-middle">
<div className="col col-start" onClick={() => this.handlePrevMonth()}>
<i className="fa fa-chevron-left" aria-hidden="true" />
</div>
<div className="col col-center">
<span>
{format(this.state.currentMonth, dateFormat, localeOptions)}
</span>
</div>
<div className="col col-end" onClick={() => this.handleNextMonth()}>
<i className="fa fa-chevron-right" aria-hidden="true" />
</div>
</div>
)
}
renderDays(localeOptions) {
const dateFormat = 'EEE'
const days = []
const { startDate } = this.state
for (let i = 0; i < 7; i++) {
days.push(
<div className="col col-center" key={i}>
{format(addDays(startDate, i), dateFormat, localeOptions)}
</div>
)
}
return <div className="days row">{days}</div>
}
filterWorkouts(day) {
const { workouts, user } = this.props
if (workouts) {
return workouts
.filter(act =>
isSameDay(getDateWithTZ(act.workout_date, user.timezone), day)
)
.reverse()
}
return []
}
renderCells() {
const { currentMonth, startDate, endDate, weekStartOnMonday } = this.state
const { sports } = this.props
const dateFormat = 'd'
const rows = []
let days = []
let day = startDate
let formattedDate = ''
while (day <= endDate) {
for (let i = 0; i < 7; i++) {
formattedDate = format(day, dateFormat)
const dayWorkouts = this.filterWorkouts(day)
const isDisabled = isSameMonth(day, currentMonth) ? '' : '-disabled'
const isWeekEnd = weekStartOnMonday
? [5, 6].includes(i)
: [0, 6].includes(i)
days.push(
<div
className={`col cell ${isWeekEnd ? ' weekend' : ''}${
isToday(day) ? ' today' : ''
}`}
key={day}
>
<div className={`img${isDisabled}`}>
<span className="number">{formattedDate}</span>
<CalendarWorkouts
dayWorkouts={dayWorkouts}
isDisabled={isDisabled}
sports={sports}
/>
</div>
</div>
)
day = addDays(day, 1)
}
rows.push(
<div className="row" key={day}>
{days}
</div>
)
days = []
}
return <div className="body">{rows}</div>
}
updateStateDate(calendarDate) {
const { start, end } = getStartAndEndMonth(
calendarDate,
this.state.weekStartOnMonday
)
this.setState({
currentMonth: calendarDate,
startDate: start,
endDate: end,
})
this.props.loadMonthWorkouts(start, end)
}
handleNextMonth() {
const calendarDate = addMonths(this.state.currentMonth, 1)
this.updateStateDate(calendarDate)
}
handlePrevMonth() {
const calendarDate = subMonths(this.state.currentMonth, 1)
this.updateStateDate(calendarDate)
}
render() {
const localeOptions = {
locale: this.props.language === 'fr' ? fr : enGB,
}
return (
<div className="card workout-card">
<div className="calendar">
{this.renderHeader(localeOptions)}
{this.renderDays(localeOptions)}
{this.renderCells()}
</div>
</div>
)
}
}
export default connect(
state => ({
workouts: state.calendarWorkouts.data,
language: state.language,
sports: state.sports.data,
user: state.user,
}),
dispatch => ({
loadMonthWorkouts: (start, end) => {
const dateFormat = 'yyyy-MM-dd'
dispatch(
getMonthWorkouts(format(start, dateFormat), format(end, dateFormat))
)
},
})
)(Calendar)

View File

@ -1,39 +0,0 @@
import React from 'react'
import { Link } from 'react-router-dom'
import { recordsLabels } from '../../utils/workouts'
export default function CalendarWorkout(props) {
const { isDisabled, isMore, sportImg, workout } = props
return (
<Link
className={`calendar-workout${isMore}`}
to={`/workouts/${workout.id}`}
>
<>
<img
alt="workout sport logo"
className={`workout-sport ${isDisabled}`}
src={sportImg}
title={workout.title}
/>
{workout.records.length > 0 && (
<sup>
<i
className="fa fa-trophy custom-fa-small"
aria-hidden="true"
title={workout.records.map(
rec =>
` ${
recordsLabels.filter(
r => r.record_type === rec.record_type
)[0].label
}`
)}
/>
</sup>
)}
</>
</Link>
)
}

View File

@ -1,59 +0,0 @@
import React from 'react'
import CalendarWorkout from './CalendarWorkout'
export default class CalendarWorkouts extends React.Component {
constructor(props, context) {
super(props, context)
this.state = {
isHidden: true,
}
}
handleDisplayMore() {
this.setState({
isHidden: !this.state.isHidden,
})
}
render() {
const { dayWorkouts, isDisabled, sports } = this.props
const { isHidden } = this.state
return (
<div>
{dayWorkouts.map(act => (
<CalendarWorkout
key={act.id}
workout={act}
isDisabled={isDisabled}
isMore=""
sportImg={sports.filter(s => s.id === act.sport_id).map(s => s.img)}
/>
))}
{dayWorkouts.length > 2 && (
<i
className={`fa fa-${isHidden ? 'plus' : 'times'} calendar-more`}
aria-hidden="true"
onClick={() => this.handleDisplayMore()}
title="show more workouts"
/>
)}
{!isHidden && (
<div className="calendar-display-more">
{dayWorkouts.map(act => (
<CalendarWorkout
key={act.id}
workout={act}
isDisabled={isDisabled}
isMore="-more"
sportImg={sports
.filter(s => s.id === act.sport_id)
.map(s => s.img)}
/>
))}
</div>
)}
</div>
)
}
}

View File

@ -1,74 +0,0 @@
import React from 'react'
import { Link } from 'react-router-dom'
import { formatRecord, translateSports } from '../../utils/workouts'
export default function RecordsCard(props) {
const { records, sports, t, user } = props
const translatedSports = translateSports(sports, t)
const recordsBySport = records.reduce((sportList, record) => {
const sport = translatedSports.find(s => s.id === record.sport_id)
if (sportList[sport.label] === void 0) {
sportList[sport.label] = {
img: sport.img,
records: [],
}
}
sportList[sport.label].records.push(formatRecord(record, user.timezone))
return sportList
}, {})
return (
<div className="card workout-card">
<div className="card-header">{t('workouts:Personal records')}</div>
<div className="card-body">
{Object.keys(recordsBySport).length === 0
? t('common:No records.')
: Object.keys(recordsBySport)
.sort()
.map(sportLabel => (
<div key={sportLabel}>
<span className="heading-span">
<img
alt={`${sportLabel} logo`}
className="record-logo"
src={recordsBySport[sportLabel].img}
/>
{sportLabel}
</span>
{/* eslint-disable-next-line max-len */}
<table className="table table-borderless table-sm record-table">
<thead>
<tr>
<th colSpan="3">
<img
alt={`${sportLabel} logo`}
className="record-logo"
src={recordsBySport[sportLabel].img}
/>
{sportLabel}
</th>
</tr>
</thead>
<tbody>
{recordsBySport[sportLabel].records.map(rec => (
<tr className="record-tr" key={rec.id}>
<td className="record-td">
{t(`workouts:${rec.record_type}`)}
</td>
<td className="record-td text-right">{rec.value}</td>
<td className="record-td text-right">
<Link to={`/workouts/${rec.workout_id}`}>
{rec.workout_date}
</Link>
</td>
</tr>
))}
</tbody>
</table>
</div>
))}
</div>
</div>
)
}

View File

@ -1,34 +0,0 @@
import { endOfMonth, startOfMonth } from 'date-fns'
import React from 'react'
import Stats from '../Common/Stats'
export default class Statistics extends React.Component {
constructor(props, context) {
super(props, context)
const date = new Date()
this.state = {
start: startOfMonth(date),
end: endOfMonth(date),
duration: 'week',
type: 'by_time',
}
}
render() {
const { t } = this.props
return (
<div className="card workout-card">
<div className="card-header">{t('dashboard:This month')}</div>
<div className="card-body">
<Stats
displayEmpty={false}
statsParams={this.state}
t={t}
withElevation={false}
/>
</div>
</div>
)
}
}

View File

@ -1,78 +0,0 @@
import React from 'react'
export default function UserStatistics(props) {
const { t, user } = props
const days = user.total_duration.match(/day/g)
? `${user.total_duration.split(' ')[0]} ${
user.total_duration.match(/days/g) ? t('common:days') : t('common:day')
}`
: `0 ${t('common:days')},`
let duration = user.total_duration.match(/day/g)
? user.total_duration.split(', ')[1]
: user.total_duration
duration = `${duration.split(':')[0]}h ${duration.split(':')[1]}min`
return (
<div className="row">
<div className="col-lg-3 col-md-6 col-sm-6">
<div className="card workout-card">
<div className="card-body row">
<div className="col-3">
<i className="fa fa-calendar fa-3x fa-color" />
</div>
<div className="col-9 text-right">
<div className="huge">{user.nb_workouts}</div>
<div>{`${
user.nb_workouts === 1
? t('common:workout')
: t('common:workouts')
}`}</div>
</div>
</div>
</div>
</div>
<div className="col-lg-3 col-md-6 col-sm-6">
<div className="card workout-card">
<div className="card-body row">
<div className="col-3">
<i className="fa fa-road fa-3x fa-color" />
</div>
<div className="col-9 text-right">
<div className="huge">
{Number(user.total_distance).toFixed(2)}
</div>
<div>km</div>
</div>
</div>
</div>
</div>
<div className="col-lg-3 col-md-6 col-sm-6">
<div className="card workout-card">
<div className="card-body row">
<div className="col-3">
<i className="fa fa-clock-o fa-3x fa-color" />
</div>
<div className="col-9 text-right">
<div className="huge">{days}</div>
<div>{duration}</div>
</div>
</div>
</div>
</div>
<div className="col-lg-3 col-md-6 col-sm-6">
<div className="card workout-card">
<div className="card-body row">
<div className="col-3">
<i className="fa fa-tags fa-3x fa-color" />
</div>
<div className="col-9 text-right">
<div className="huge">{user.nb_sports}</div>
<div>{`${
user.nb_sports === 1 ? t('common:sport') : t('common:sports')
}`}</div>
</div>
</div>
</div>
</div>
</div>
)
}

View File

@ -1,70 +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 function WorkoutCard(props) {
const { sports, t, user, workout } = props
return (
<div className="card workout-card text-center">
<div className="card-header">
<Link to={`/workouts/${workout.id}`}>
{sports
.filter(sport => sport.id === workout.sport_id)
.map(sport => t(`sports:${sport.label}`))}{' '}
-{' '}
{format(
getDateWithTZ(workout.workout_date, user.timezone),
'dd/MM/yyyy HH:mm'
)}
</Link>
</div>
<div className="card-body">
<div className="row">
{workout.map && (
<div className="col">
<StaticMap workout={workout} />
</div>
)}
<div className={`col${workout.map ? ' col-with-map' : ''}`}>
<p>
<i className="fa fa-clock-o" aria-hidden="true" />{' '}
{t('workouts:Duration')}: {workout.moving}
{workout.map ? (
<span>
<br />
<br />
</span>
) : (
' - '
)}
<i className="fa fa-road" aria-hidden="true" />{' '}
{t('workouts:Distance')}: {workout.distance} km
<br />
</p>
{workout.min_alt && workout.max_alt && (
<p>
<i className="fi-mountains custom-fa" />
{t('workouts:Min. altitude')}: {workout.min_alt}m
<br />
{t('workouts:Max. altitude')}: {workout.max_alt}m
<br />
</p>
)}
{workout.ascent && workout.descent && (
<p>
<i className="fa fa-location-arrow custom-fa" />
{t('workouts:Ascent')}: {workout.ascent}m
<br />
{t('workouts:Descent')}: {workout.descent}m
</p>
)}
</div>
</div>
</div>
</div>
)
}

View File

@ -1,114 +0,0 @@
import React from 'react'
import { Helmet } from 'react-helmet'
import { withTranslation } from 'react-i18next'
import { connect } from 'react-redux'
import Calendar from './Calendar'
import Message from '../Common/Message'
import NoWorkouts from '../Common/NoWorkouts'
import Records from './Records'
import Statistics from './Statistics'
import UserStatistics from './UserStatistics'
import WorkoutCard from './WorkoutCard'
import { getOrUpdateData } from '../../actions'
import { getMoreWorkouts } from '../../actions/workouts'
class DashBoard extends React.Component {
constructor(props, context) {
super(props, context)
this.state = {
page: 1,
}
}
componentDidMount() {
this.props.loadWorkouts()
}
render() {
const { loadMoreWorkouts, message, records, sports, t, user, workouts } =
this.props
const paginationEnd =
workouts.length > 0
? workouts[workouts.length - 1].previous_workout === null
: true
const { page } = this.state
return (
<div>
<Helmet>
<title>FitTrackee - {t('common:Dashboard')}</title>
</Helmet>
{message ? (
<Message message={message} t={t} />
) : (
workouts &&
user.total_duration &&
sports.length > 0 && (
<div className="container dashboard">
<UserStatistics user={user} t={t} />
<div className="row">
<div className="col-md-4">
<Statistics t={t} />
<Records
t={t}
records={records}
sports={sports}
user={user}
/>
</div>
<div className="col-md-8">
<Calendar weekm={user.weekm} />
{workouts.length > 0 ? (
workouts.map(workout => (
<WorkoutCard
workout={workout}
key={workout.id}
sports={sports}
t={t}
user={user}
/>
))
) : (
<NoWorkouts t={t} />
)}
{!paginationEnd && (
<input
type="submit"
className="btn btn-default btn-md btn-block"
value="Load more workouts"
onClick={() => {
loadMoreWorkouts(page + 1)
this.setState({ page: page + 1 })
}}
/>
)}
</div>
</div>
</div>
)
)}
</div>
)
}
}
export default withTranslation()(
connect(
state => ({
workouts: state.workouts.data,
message: state.message,
records: state.records.data,
sports: state.sports.data,
user: state.user,
}),
dispatch => ({
loadWorkouts: () => {
dispatch(getOrUpdateData('getData', 'workouts', { page: 1 }))
dispatch(getOrUpdateData('getData', 'records'))
},
loadMoreWorkouts: page => {
dispatch(getMoreWorkouts({ page }))
},
})
)(DashBoard)
)