Client - display converted speed/elevation in workout chart
This commit is contained in:
parent
c0acff9e3d
commit
9b7f685992
@ -55,12 +55,14 @@
|
|||||||
import { LineChart, useLineChart } from 'vue-chart-3'
|
import { LineChart, useLineChart } from 'vue-chart-3'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
|
import { TUnit } from '@/types/units'
|
||||||
import { IUserProfile } from '@/types/user'
|
import { IUserProfile } from '@/types/user'
|
||||||
import {
|
import {
|
||||||
IWorkoutChartData,
|
IWorkoutChartData,
|
||||||
IWorkoutData,
|
IWorkoutData,
|
||||||
TCoordinates,
|
TCoordinates,
|
||||||
} from '@/types/workouts'
|
} from '@/types/workouts'
|
||||||
|
import { units } from '@/utils/units'
|
||||||
import { getDatasets } from '@/utils/workouts'
|
import { getDatasets } from '@/utils/workouts'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@ -76,8 +78,10 @@
|
|||||||
let displayDistance = ref(true)
|
let displayDistance = ref(true)
|
||||||
let beginElevationAtZero = ref(true)
|
let beginElevationAtZero = ref(true)
|
||||||
const datasets: ComputedRef<IWorkoutChartData> = computed(() =>
|
const datasets: ComputedRef<IWorkoutChartData> = computed(() =>
|
||||||
getDatasets(props.workoutData.chartData, t)
|
getDatasets(props.workoutData.chartData, t, props.authUser.imperial_units)
|
||||||
)
|
)
|
||||||
|
const fromKmUnit = getUnitTo('km')
|
||||||
|
const fromMUnit = getUnitTo('m')
|
||||||
let chartData: ComputedRef<ChartData<'line'>> = computed(() => ({
|
let chartData: ComputedRef<ChartData<'line'>> = computed(() => ({
|
||||||
labels: displayDistance.value
|
labels: displayDistance.value
|
||||||
? datasets.value.distance_labels
|
? datasets.value.distance_labels
|
||||||
@ -119,7 +123,7 @@
|
|||||||
title: {
|
title: {
|
||||||
display: true,
|
display: true,
|
||||||
text: displayDistance.value
|
text: displayDistance.value
|
||||||
? t('workouts.DISTANCE') + ' (km)'
|
? t('workouts.DISTANCE') + ` (${fromKmUnit})`
|
||||||
: t('workouts.DURATION'),
|
: t('workouts.DURATION'),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -130,7 +134,7 @@
|
|||||||
position: 'left',
|
position: 'left',
|
||||||
title: {
|
title: {
|
||||||
display: true,
|
display: true,
|
||||||
text: t('workouts.SPEED') + ' (km/h)',
|
text: t('workouts.SPEED') + ` (${fromKmUnit}/h)`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
yElevation: {
|
yElevation: {
|
||||||
@ -141,7 +145,7 @@
|
|||||||
position: 'right',
|
position: 'right',
|
||||||
title: {
|
title: {
|
||||||
display: true,
|
display: true,
|
||||||
text: t('workouts.ELEVATION') + ' (m)',
|
text: t('workouts.ELEVATION') + ` (${fromMUnit})`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -164,8 +168,8 @@
|
|||||||
label: function (context) {
|
label: function (context) {
|
||||||
const label = ` ${context.dataset.label}: ${context.formattedValue}`
|
const label = ` ${context.dataset.label}: ${context.formattedValue}`
|
||||||
return context.dataset.yAxisID === 'yElevation'
|
return context.dataset.yAxisID === 'yElevation'
|
||||||
? label + ' m'
|
? label + ` ${fromMUnit}`
|
||||||
: label + ' km/h'
|
: label + ` ${fromKmUnit}/h`
|
||||||
},
|
},
|
||||||
title: function (tooltipItems) {
|
title: function (tooltipItems) {
|
||||||
if (tooltipItems.length > 0) {
|
if (tooltipItems.length > 0) {
|
||||||
@ -174,7 +178,9 @@
|
|||||||
return tooltipItems.length === 0
|
return tooltipItems.length === 0
|
||||||
? ''
|
? ''
|
||||||
: displayDistance.value
|
: displayDistance.value
|
||||||
? `${t('workouts.DISTANCE')}: ${tooltipItems[0].label} km`
|
? `${t('workouts.DISTANCE')}: ${
|
||||||
|
tooltipItems[0].label
|
||||||
|
} ${fromKmUnit}`
|
||||||
: `${t('workouts.DURATION')}: ${formatDuration(
|
: `${t('workouts.DURATION')}: ${formatDuration(
|
||||||
tooltipItems[0].label.replace(',', '')
|
tooltipItems[0].label.replace(',', '')
|
||||||
)}`
|
)}`
|
||||||
@ -200,6 +206,11 @@
|
|||||||
function emitEmptyCoordinates() {
|
function emitEmptyCoordinates() {
|
||||||
emitCoordinates({ latitude: null, longitude: null })
|
emitCoordinates({ latitude: null, longitude: null })
|
||||||
}
|
}
|
||||||
|
function getUnitTo(unitFrom: TUnit): TUnit {
|
||||||
|
return props.authUser.imperial_units
|
||||||
|
? units[unitFrom].defaultTarget
|
||||||
|
: unitFrom
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
<Distance
|
<Distance
|
||||||
:distance="segment.distance"
|
:distance="segment.distance"
|
||||||
unitFrom="km"
|
unitFrom="km"
|
||||||
:strong="true"
|
|
||||||
:useImperialUnits="useImperialUnits"
|
:useImperialUnits="useImperialUnits"
|
||||||
/>, {{ $t('workouts.DURATION') }}: {{ segment.duration }})
|
/>, {{ $t('workouts.DURATION') }}: {{ segment.duration }})
|
||||||
</li>
|
</li>
|
||||||
|
@ -25,7 +25,7 @@ import {
|
|||||||
} from '@/types/statistics'
|
} from '@/types/statistics'
|
||||||
import { incrementDate, getStartDate } from '@/utils/dates'
|
import { incrementDate, getStartDate } from '@/utils/dates'
|
||||||
import { sportColors } from '@/utils/sports'
|
import { sportColors } from '@/utils/sports'
|
||||||
import { convertDistance, units } from '@/utils/units'
|
import { convertStatsDistance } from '@/utils/units'
|
||||||
|
|
||||||
const dateFormats: Record<string, Record<string, string>> = {
|
const dateFormats: Record<string, Record<string, string>> = {
|
||||||
week: {
|
week: {
|
||||||
@ -103,13 +103,12 @@ export const convertStatsValue = (
|
|||||||
switch (datasetKey) {
|
switch (datasetKey) {
|
||||||
case 'total_distance':
|
case 'total_distance':
|
||||||
case 'total_ascent':
|
case 'total_ascent':
|
||||||
case 'total_descent': {
|
case 'total_descent':
|
||||||
const unitFrom = datasetKey === 'total_distance' ? 'km' : 'm'
|
return convertStatsDistance(
|
||||||
const unitTo = useImperialUnits ? units[unitFrom].defaultTarget : unitFrom
|
datasetKey === 'total_distance' ? 'km' : 'm',
|
||||||
return useImperialUnits
|
value,
|
||||||
? convertDistance(value, unitFrom, unitTo, 2)
|
useImperialUnits
|
||||||
: value
|
)
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
case 'nb_workouts':
|
case 'nb_workouts':
|
||||||
case 'total_duration':
|
case 'total_duration':
|
||||||
|
@ -54,3 +54,12 @@ export const convertDistance = (
|
|||||||
}
|
}
|
||||||
return convertedDistance
|
return convertedDistance
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const convertStatsDistance = (
|
||||||
|
unitFrom: TUnit,
|
||||||
|
value: number,
|
||||||
|
useImperialUnits: boolean
|
||||||
|
): number => {
|
||||||
|
const unitTo = useImperialUnits ? units[unitFrom].defaultTarget : unitFrom
|
||||||
|
return useImperialUnits ? convertDistance(value, unitFrom, unitTo, 2) : value
|
||||||
|
}
|
||||||
|
@ -5,10 +5,12 @@ import {
|
|||||||
TCoordinates,
|
TCoordinates,
|
||||||
TWorkoutDatasets,
|
TWorkoutDatasets,
|
||||||
} from '@/types/workouts'
|
} from '@/types/workouts'
|
||||||
|
import { convertStatsDistance } from '@/utils/units'
|
||||||
|
|
||||||
export const getDatasets = (
|
export const getDatasets = (
|
||||||
chartData: IWorkoutApiChartData[],
|
chartData: IWorkoutApiChartData[],
|
||||||
t: CallableFunction
|
t: CallableFunction,
|
||||||
|
useImperialUnits: boolean
|
||||||
): IWorkoutChartData => {
|
): IWorkoutChartData => {
|
||||||
const datasets: TWorkoutDatasets = {
|
const datasets: TWorkoutDatasets = {
|
||||||
speed: {
|
speed: {
|
||||||
@ -36,8 +38,12 @@ export const getDatasets = (
|
|||||||
chartData.map((data) => {
|
chartData.map((data) => {
|
||||||
distance_labels.push(data.distance)
|
distance_labels.push(data.distance)
|
||||||
duration_labels.push(data.duration)
|
duration_labels.push(data.duration)
|
||||||
datasets.speed.data.push(data.speed)
|
datasets.speed.data.push(
|
||||||
datasets.elevation.data.push(data.elevation)
|
convertStatsDistance('km', data.speed, useImperialUnits)
|
||||||
|
)
|
||||||
|
datasets.elevation.data.push(
|
||||||
|
convertStatsDistance('m', data.elevation, useImperialUnits)
|
||||||
|
)
|
||||||
coordinates.push({ latitude: data.latitude, longitude: data.longitude })
|
coordinates.push({ latitude: data.latitude, longitude: data.longitude })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ describe('getDatasets', () => {
|
|||||||
inputParams: {
|
inputParams: {
|
||||||
charData: [],
|
charData: [],
|
||||||
locale: 'fr',
|
locale: 'fr',
|
||||||
|
useImperialUnits: false,
|
||||||
},
|
},
|
||||||
expected: {
|
expected: {
|
||||||
distance_labels: [],
|
distance_labels: [],
|
||||||
@ -72,6 +73,7 @@ describe('getDatasets', () => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
locale: 'en',
|
locale: 'en',
|
||||||
|
useImperialUnits: false,
|
||||||
},
|
},
|
||||||
expected: {
|
expected: {
|
||||||
distance_labels: [0, 0, 0.01],
|
distance_labels: [0, 0, 0.01],
|
||||||
@ -102,12 +104,80 @@ describe('getDatasets', () => {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
description: 'returns datasets w/ units conversion',
|
||||||
|
inputParams: {
|
||||||
|
charData: [
|
||||||
|
{
|
||||||
|
distance: 0,
|
||||||
|
duration: 0,
|
||||||
|
elevation: 83.6,
|
||||||
|
latitude: 48.845574,
|
||||||
|
longitude: 2.373723,
|
||||||
|
speed: 2.89,
|
||||||
|
time: 'Sun, 12 Sep 2021 13:29:24 GMT',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
distance: 0,
|
||||||
|
duration: 1,
|
||||||
|
elevation: 83.7,
|
||||||
|
latitude: 48.845578,
|
||||||
|
longitude: 2.373732,
|
||||||
|
speed: 1.56,
|
||||||
|
time: 'Sun, 12 Sep 2021 13:29:25 GMT',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
distance: 0.01,
|
||||||
|
duration: 96,
|
||||||
|
elevation: 84.3,
|
||||||
|
latitude: 48.845591,
|
||||||
|
longitude: 2.373811,
|
||||||
|
speed: 14.73,
|
||||||
|
time: 'Sun, 12 Sep 2021 13:31:00 GMT',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
locale: 'en',
|
||||||
|
useImperialUnits: true,
|
||||||
|
},
|
||||||
|
expected: {
|
||||||
|
distance_labels: [0, 0, 0.01],
|
||||||
|
duration_labels: [0, 1, 96],
|
||||||
|
datasets: {
|
||||||
|
speed: {
|
||||||
|
label: 'speed',
|
||||||
|
backgroundColor: ['#FFFFFF'],
|
||||||
|
borderColor: ['#8884d8'],
|
||||||
|
borderWidth: 2,
|
||||||
|
data: [1.8, 0.97, 9.15],
|
||||||
|
yAxisID: 'ySpeed',
|
||||||
|
},
|
||||||
|
elevation: {
|
||||||
|
label: 'elevation',
|
||||||
|
backgroundColor: ['#e5e5e5'],
|
||||||
|
borderColor: ['#cccccc'],
|
||||||
|
borderWidth: 1,
|
||||||
|
fill: true,
|
||||||
|
data: [274.28, 274.61, 276.57],
|
||||||
|
yAxisID: 'yElevation',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
coordinates: [
|
||||||
|
{ latitude: 48.845574, longitude: 2.373723 },
|
||||||
|
{ latitude: 48.845578, longitude: 2.373732 },
|
||||||
|
{ latitude: 48.845591, longitude: 2.373811 },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
]
|
]
|
||||||
testparams.map((testParams) => {
|
testparams.map((testParams) => {
|
||||||
it(testParams.description, () => {
|
it(testParams.description, () => {
|
||||||
locale.value = testParams.inputParams.locale
|
locale.value = testParams.inputParams.locale
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
getDatasets(testParams.inputParams.charData, t),
|
getDatasets(
|
||||||
|
testParams.inputParams.charData,
|
||||||
|
t,
|
||||||
|
testParams.inputParams.useImperialUnits
|
||||||
|
),
|
||||||
testParams.expected
|
testParams.expected
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user