Client: display activity date with user timezone - #11
This commit is contained in:
parent
fe91040370
commit
31d23da473
@ -2,8 +2,10 @@ import { format } from 'date-fns'
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
|
|
||||||
|
import { getDateWithTZ } from '../../utils'
|
||||||
|
|
||||||
export default function ActivitiesList (props) {
|
export default function ActivitiesList (props) {
|
||||||
const { activities, sports } = props
|
const { activities, sports, user } = props
|
||||||
return (
|
return (
|
||||||
<div className="card">
|
<div className="card">
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
@ -36,7 +38,12 @@ export default function ActivitiesList (props) {
|
|||||||
{activity.title}
|
{activity.title}
|
||||||
</Link>
|
</Link>
|
||||||
</td>
|
</td>
|
||||||
<td>{format(activity.activity_date, 'DD/MM/YYYY HH:mm')}</td>
|
<td>
|
||||||
|
{format(
|
||||||
|
getDateWithTZ(activity.activity_date, user.timezone),
|
||||||
|
'DD/MM/YYYY HH:mm'
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
<td className="text-right">
|
<td className="text-right">
|
||||||
{Number(activity.distance).toFixed(2)} km
|
{Number(activity.distance).toFixed(2)} km
|
||||||
</td>
|
</td>
|
||||||
|
@ -36,7 +36,7 @@ class Activities extends React.Component {
|
|||||||
}
|
}
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
activities, loadActivities, loadMoreActivities, message, sports
|
activities, loadActivities, loadMoreActivities, message, sports, user
|
||||||
} = this.props
|
} = this.props
|
||||||
const { params } = this.state
|
const { params } = this.state
|
||||||
const paginationEnd = activities.length > 0
|
const paginationEnd = activities.length > 0
|
||||||
@ -63,6 +63,7 @@ class Activities extends React.Component {
|
|||||||
<ActivitiesList
|
<ActivitiesList
|
||||||
activities={activities}
|
activities={activities}
|
||||||
sports={sports}
|
sports={sports}
|
||||||
|
user={user}
|
||||||
/>
|
/>
|
||||||
{!paginationEnd &&
|
{!paginationEnd &&
|
||||||
<input
|
<input
|
||||||
@ -100,6 +101,7 @@ export default connect(
|
|||||||
activities: state.activities.data,
|
activities: state.activities.data,
|
||||||
message: state.message,
|
message: state.message,
|
||||||
sports: state.sports.data,
|
sports: state.sports.data,
|
||||||
|
user: state.user,
|
||||||
}),
|
}),
|
||||||
dispatch => ({
|
dispatch => ({
|
||||||
loadActivities: params => {
|
loadActivities: params => {
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
|
|
||||||
import { formatActivityDate } from '../../../utils'
|
import { formatActivityDate, getDateWithTZ } from '../../../utils'
|
||||||
|
|
||||||
|
|
||||||
export default function ActivityCardHeader(props) {
|
export default function ActivityCardHeader(props) {
|
||||||
const { activity, displayModal, sport, title } = props
|
const { activity, displayModal, sport, title, user } = props
|
||||||
const activityDate = activity
|
const activityDate = activity
|
||||||
? formatActivityDate(activity.activity_date)
|
? formatActivityDate(
|
||||||
|
getDateWithTZ(activity.activity_date, user.timezone)
|
||||||
|
)
|
||||||
: null
|
: null
|
||||||
return (
|
return (
|
||||||
<div className="container">
|
<div className="container">
|
||||||
|
@ -34,7 +34,7 @@ class ActivityDisplay extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { activities, message, onDeleteActivity, sports } = this.props
|
const { activities, message, onDeleteActivity, sports, user } = this.props
|
||||||
const { displayModal } = this.state
|
const { displayModal } = this.state
|
||||||
const [activity] = activities
|
const [activity] = activities
|
||||||
const title = activity ? activity.title : 'Activity'
|
const title = activity ? activity.title : 'Activity'
|
||||||
@ -71,6 +71,7 @@ class ActivityDisplay extends React.Component {
|
|||||||
activity={activity}
|
activity={activity}
|
||||||
sport={sport}
|
sport={sport}
|
||||||
title={title}
|
title={title}
|
||||||
|
user={user}
|
||||||
displayModal={() => this.displayModal(true)}
|
displayModal={() => this.displayModal(true)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,10 +2,10 @@ import { format } from 'date-fns'
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
|
|
||||||
import { apiUrl } from '../../utils'
|
import { apiUrl, getDateWithTZ } from '../../utils'
|
||||||
|
|
||||||
export default function ActivityCard (props) {
|
export default function ActivityCard (props) {
|
||||||
const { activity, sports } = props
|
const { activity, sports, user } = props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="card activity-card text-center">
|
<div className="card activity-card text-center">
|
||||||
@ -13,7 +13,10 @@ export default function ActivityCard (props) {
|
|||||||
<Link to={`/activities/${activity.id}`}>
|
<Link to={`/activities/${activity.id}`}>
|
||||||
{sports.filter(sport => sport.id === activity.sport_id)
|
{sports.filter(sport => sport.id === activity.sport_id)
|
||||||
.map(sport => sport.label)} -{' '}
|
.map(sport => sport.label)} -{' '}
|
||||||
{format(activity.activity_date, 'DD/MM/YYYY HH:mm')}
|
{format(
|
||||||
|
getDateWithTZ(activity.activity_date, user.timezone),
|
||||||
|
'DD/MM/YYYY HH:mm'
|
||||||
|
)}
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
|
@ -4,7 +4,7 @@ import { Link } from 'react-router-dom'
|
|||||||
import { formatRecord } from '../../utils'
|
import { formatRecord } from '../../utils'
|
||||||
|
|
||||||
export default function RecordsCard (props) {
|
export default function RecordsCard (props) {
|
||||||
const { records, sports } = props
|
const { records, sports, user } = props
|
||||||
const recordsBySport = records.reduce((sportList, record) => {
|
const recordsBySport = records.reduce((sportList, record) => {
|
||||||
const sport = sports.find(s => s.id === record.sport_id)
|
const sport = sports.find(s => s.id === record.sport_id)
|
||||||
if (sportList[sport.label] === void 0) {
|
if (sportList[sport.label] === void 0) {
|
||||||
@ -13,7 +13,7 @@ export default function RecordsCard (props) {
|
|||||||
records: [],
|
records: [],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sportList[sport.label].records.push(formatRecord(record))
|
sportList[sport.label].records.push(formatRecord(record, user.timezone))
|
||||||
return sportList
|
return sportList
|
||||||
}, {})
|
}, {})
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ class DashBoard extends React.Component {
|
|||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-md-4">
|
<div className="col-md-4">
|
||||||
<Statistics />
|
<Statistics />
|
||||||
<Records records={records} sports={sports} />
|
<Records records={records} sports={sports} user={user} />
|
||||||
</div>
|
</div>
|
||||||
<div className="col-md-8">
|
<div className="col-md-8">
|
||||||
<Calendar />
|
<Calendar />
|
||||||
@ -55,6 +55,7 @@ class DashBoard extends React.Component {
|
|||||||
activity={activity}
|
activity={activity}
|
||||||
key={activity.id}
|
key={activity.id}
|
||||||
sports={sports}
|
sports={sports}
|
||||||
|
user={user}
|
||||||
/>)
|
/>)
|
||||||
)) : (
|
)) : (
|
||||||
<div className="card text-center">
|
<div className="card text-center">
|
||||||
|
@ -6,6 +6,7 @@ import { connect } from 'react-redux'
|
|||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
|
|
||||||
import { getMonthActivities } from '../../actions/activities'
|
import { getMonthActivities } from '../../actions/activities'
|
||||||
|
import { getDateWithTZ } from '../../utils'
|
||||||
|
|
||||||
const getStartAndEndMonth = date => {
|
const getStartAndEndMonth = date => {
|
||||||
const monthStart = dateFns.startOfMonth(date)
|
const monthStart = dateFns.startOfMonth(date)
|
||||||
@ -73,10 +74,13 @@ class Calendar extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
filterActivities(day) {
|
filterActivities(day) {
|
||||||
const { activities } = this.props
|
const { activities, user } = this.props
|
||||||
if (activities) {
|
if (activities) {
|
||||||
return activities
|
return activities
|
||||||
.filter(act => dateFns.isSameDay(act.activity_date, day))
|
.filter(act => dateFns.isSameDay(
|
||||||
|
getDateWithTZ(act.activity_date, user.timezone),
|
||||||
|
day
|
||||||
|
))
|
||||||
}
|
}
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
@ -108,11 +112,12 @@ class Calendar extends React.Component {
|
|||||||
{dayActivities.map(act => (
|
{dayActivities.map(act => (
|
||||||
<Link key={act.id} to={`/activities/${act.id}`}>
|
<Link key={act.id} to={`/activities/${act.id}`}>
|
||||||
<img
|
<img
|
||||||
|
alt="activity sport logo"
|
||||||
className={`activity-sport ${isDisabled}`}
|
className={`activity-sport ${isDisabled}`}
|
||||||
src={sports
|
src={sports
|
||||||
.filter(s => s.id === act.sport_id)
|
.filter(s => s.id === act.sport_id)
|
||||||
.map(s => s.img)}
|
.map(s => s.img)}
|
||||||
alt="activity sport logo"
|
title={act.title}
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
))}
|
))}
|
||||||
@ -167,6 +172,7 @@ export default connect(
|
|||||||
state => ({
|
state => ({
|
||||||
activities: state.calendarActivities.data,
|
activities: state.calendarActivities.data,
|
||||||
sports: state.sports.data,
|
sports: state.sports.data,
|
||||||
|
user: state.user,
|
||||||
}),
|
}),
|
||||||
dispatch => ({
|
dispatch => ({
|
||||||
loadMonthActivities: (start, end) => {
|
loadMonthActivities: (start, end) => {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import togeojson from '@mapbox/togeojson'
|
import togeojson from '@mapbox/togeojson'
|
||||||
import { addDays, format, parse, startOfWeek, subHours } from 'date-fns'
|
import { addDays, format, parse, startOfWeek, subHours } from 'date-fns'
|
||||||
|
import { DateTime } from 'luxon'
|
||||||
|
|
||||||
export const apiUrl = `${process.env.REACT_APP_API_URL}/api/`
|
export const apiUrl = `${process.env.REACT_APP_API_URL}/api/`
|
||||||
export const thunderforestApiKey = `${
|
export const thunderforestApiKey = `${
|
||||||
@ -63,24 +64,33 @@ export const getGeoJson = gpxContent => {
|
|||||||
return { jsonData }
|
return { jsonData }
|
||||||
}
|
}
|
||||||
|
|
||||||
export const formatActivityDate = (activityDateTime, dateFormat = null) => {
|
|
||||||
if (activityDateTime) {
|
export const getDateWithTZ = (date, tz) => {
|
||||||
const dateTime = parse(activityDateTime)
|
if (!date) {
|
||||||
return {
|
return ''
|
||||||
activity_date: format(
|
}
|
||||||
|
const dt = DateTime.fromISO(format(date)).setZone(tz)
|
||||||
|
return parse(dt.toFormat('yyyy-MM-dd HH:mm:ss'))
|
||||||
|
}
|
||||||
|
|
||||||
|
export const formatActivityDate = (
|
||||||
dateTime,
|
dateTime,
|
||||||
dateFormat ? dateFormat : 'DD/MM/YYYY'
|
dateFormat = null,
|
||||||
),
|
timeFormat = null,
|
||||||
activity_time: activityDateTime.match(/[0-2][0-9]:[0-5][0-9]/)[0]
|
) => {
|
||||||
|
if (!dateFormat) {
|
||||||
|
dateFormat = 'DD/MM/YYYY'
|
||||||
}
|
}
|
||||||
|
if (!timeFormat) {
|
||||||
|
timeFormat = 'HH:mm'
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
activity_date: null,
|
activity_date: dateTime ? format(dateTime, dateFormat) : null,
|
||||||
activity_time: null,
|
activity_time: dateTime ? format(dateTime, timeFormat) : null,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const formatRecord = record => {
|
export const formatRecord = (record, tz) => {
|
||||||
let value, recordType = null
|
let value, recordType = null
|
||||||
switch (record.record_type) {
|
switch (record.record_type) {
|
||||||
case 'AS':
|
case 'AS':
|
||||||
@ -97,7 +107,9 @@ export const formatRecord = record => {
|
|||||||
recordType = 'Longest duration'
|
recordType = 'Longest duration'
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
activity_date: formatActivityDate(record.activity_date).activity_date,
|
activity_date: formatActivityDate(
|
||||||
|
getDateWithTZ(record.activity_date, tz)
|
||||||
|
).activity_date,
|
||||||
activity_id: record.activity_id,
|
activity_id: record.activity_id,
|
||||||
id: record.id,
|
id: record.id,
|
||||||
record_type: recordType,
|
record_type: recordType,
|
||||||
|
@ -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",
|
||||||
|
"luxon": "^1.2.1",
|
||||||
"object-hash": "^1.3.0",
|
"object-hash": "^1.3.0",
|
||||||
"react": "^16.4.0",
|
"react": "^16.4.0",
|
||||||
"react-dom": "^16.4.0",
|
"react-dom": "^16.4.0",
|
||||||
|
@ -5669,6 +5669,10 @@ lru-cache@^3.2.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
pseudomap "^1.0.1"
|
pseudomap "^1.0.1"
|
||||||
|
|
||||||
|
luxon@^1.2.1:
|
||||||
|
version "1.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/luxon/-/luxon-1.2.1.tgz#5c4948d141939c2b2820f0c3a99276932245efb1"
|
||||||
|
|
||||||
macaddress@^0.2.8:
|
macaddress@^0.2.8:
|
||||||
version "0.2.8"
|
version "0.2.8"
|
||||||
resolved "https://registry.yarnpkg.com/macaddress/-/macaddress-0.2.8.tgz#5904dc537c39ec6dbefeae902327135fa8511f12"
|
resolved "https://registry.yarnpkg.com/macaddress/-/macaddress-0.2.8.tgz#5904dc537c39ec6dbefeae902327135fa8511f12"
|
||||||
|
Loading…
Reference in New Issue
Block a user