API & Client - add wind direction to workout detail - fix #134
This commit is contained in:
@ -0,0 +1,58 @@
|
||||
<template>
|
||||
<div class="wind">
|
||||
<Distance
|
||||
:distance="weather.wind"
|
||||
unitFrom="m"
|
||||
:digits="1"
|
||||
:displayUnit="false"
|
||||
:useImperialUnits="useImperialUnits"
|
||||
/>
|
||||
{{ useImperialUnits ? 'ft' : 'm' }}/s
|
||||
<div class="wind-bearing">
|
||||
<i
|
||||
v-if="weather.windBearing"
|
||||
class="fa fa-long-arrow-up"
|
||||
:style="{
|
||||
transform: `rotate(${weather.windBearing}deg)`,
|
||||
}"
|
||||
aria-hidden="true"
|
||||
:title="getWindDirectionTitle(weather.windBearing)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { toRefs } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import { IWeather } from '@/types/workouts'
|
||||
import { convertDegreeToDirection } from '@/utils/weather'
|
||||
|
||||
interface Props {
|
||||
weather: IWeather
|
||||
useImperialUnits: boolean
|
||||
}
|
||||
const props = defineProps<Props>()
|
||||
|
||||
const { useImperialUnits, weather } = toRefs(props)
|
||||
const { t } = useI18n()
|
||||
|
||||
function getWindDirectionTitle(windBearing: number): string {
|
||||
return t(
|
||||
`workouts.WEATHER.WIND_DIRECTIONS.${convertDegreeToDirection(
|
||||
windBearing
|
||||
)}`
|
||||
)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.wind {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
.wind-bearing {
|
||||
padding-left: 5px;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -90,24 +90,16 @@
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<Distance
|
||||
:distance="workoutObject.weatherStart.wind"
|
||||
unitFrom="m"
|
||||
:digits="1"
|
||||
:displayUnit="false"
|
||||
<WeatherWind
|
||||
:weather="workoutObject.weatherStart"
|
||||
:useImperialUnits="useImperialUnits"
|
||||
/>
|
||||
{{ useImperialUnits ? 'ft' : 'm' }}/s
|
||||
</td>
|
||||
<td>
|
||||
<Distance
|
||||
:distance="workoutObject.weatherEnd.wind"
|
||||
unitFrom="m"
|
||||
:digits="1"
|
||||
:displayUnit="false"
|
||||
<WeatherWind
|
||||
:weather="workoutObject.weatherEnd"
|
||||
:useImperialUnits="useImperialUnits"
|
||||
/>
|
||||
{{ useImperialUnits ? 'ft' : 'm' }}/s
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
@ -118,6 +110,7 @@
|
||||
<script setup lang="ts">
|
||||
import { toRefs } from 'vue'
|
||||
|
||||
import WeatherWind from '@/components/Workout/WorkoutDetail/WeatherWind.vue'
|
||||
import { IWorkoutObject } from '@/types/workouts'
|
||||
|
||||
interface Props {
|
||||
|
@ -60,6 +60,24 @@
|
||||
"HUMIDITY": "humidity",
|
||||
"TEMPERATURE": "temperature",
|
||||
"WIND": "wind",
|
||||
"WIND_DIRECTIONS": {
|
||||
"N": "N",
|
||||
"NNE": "NNE",
|
||||
"NE": "NE",
|
||||
"ENE": "ENE",
|
||||
"E": "E",
|
||||
"ESE": "ESE",
|
||||
"SE": "SE",
|
||||
"SSE": "SSE",
|
||||
"S": "S",
|
||||
"SSW": "SSW",
|
||||
"SW": "SW",
|
||||
"WSW": "WSW",
|
||||
"W": "W",
|
||||
"WNW": "WNW",
|
||||
"NW": "NW",
|
||||
"NNW": "NNW"
|
||||
},
|
||||
"DARK_SKY": {
|
||||
"clear-day": "clear day",
|
||||
"clear-night": "clear night",
|
||||
@ -70,7 +88,7 @@
|
||||
"rain": "rain",
|
||||
"sleet": "sleet",
|
||||
"snow": "snow",
|
||||
"wind": "wind"
|
||||
"wind": "wind"
|
||||
}
|
||||
},
|
||||
"WITH_GPX": "with .gpx file",
|
||||
|
@ -60,6 +60,24 @@
|
||||
"HUMIDITY": "humidité",
|
||||
"TEMPERATURE": "température",
|
||||
"WIND": "vent",
|
||||
"WIND_DIRECTIONS": {
|
||||
"N": "N",
|
||||
"NNE": "NNE",
|
||||
"NE": "NE",
|
||||
"ENE": "ENE",
|
||||
"E": "E",
|
||||
"ESE": "ESE",
|
||||
"SE": "SE",
|
||||
"SSE": "SSE",
|
||||
"S": "S",
|
||||
"SSW": "SSO",
|
||||
"SW": "SO",
|
||||
"WSW": "OSO",
|
||||
"W": "O",
|
||||
"WNW": "ONO",
|
||||
"NW": "NO",
|
||||
"NNW": "NNO"
|
||||
},
|
||||
"DARK_SKY": {
|
||||
"clear-day": "ensoleillé",
|
||||
"clear-night": "nuit claire",
|
||||
|
@ -43,6 +43,7 @@ export interface IWeather {
|
||||
summary: string
|
||||
temperature: number
|
||||
wind: number
|
||||
windBearing?: number
|
||||
}
|
||||
|
||||
export interface IWorkout {
|
||||
|
23
fittrackee_client/src/utils/weather.ts
Normal file
23
fittrackee_client/src/utils/weather.ts
Normal file
@ -0,0 +1,23 @@
|
||||
const directions = [
|
||||
'N',
|
||||
'NNE',
|
||||
'NE',
|
||||
'ENE',
|
||||
'E',
|
||||
'ESE',
|
||||
'SE',
|
||||
'SSE',
|
||||
'S',
|
||||
'SSW',
|
||||
'SW',
|
||||
'WSW',
|
||||
'W',
|
||||
'WNW',
|
||||
'NW',
|
||||
'NNW',
|
||||
]
|
||||
|
||||
export const convertDegreeToDirection = (angle: number): string => {
|
||||
const value = Math.floor(angle / 22.5 + 0.5)
|
||||
return directions[value % 16]
|
||||
}
|
23
fittrackee_client/tests/unit/utils/weather.spec.ts
Normal file
23
fittrackee_client/tests/unit/utils/weather.spec.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import { assert } from 'chai'
|
||||
|
||||
import { convertDegreeToDirection } from '@/utils/weather'
|
||||
|
||||
describe('convertDegreeToDirection', () => {
|
||||
const testsParams: [number, string][] = [
|
||||
[0, 'N'],
|
||||
[45, 'NE'],
|
||||
[90, 'E'],
|
||||
[135, 'SE'],
|
||||
[180, 'S'],
|
||||
[225, 'SW'],
|
||||
[270, 'W'],
|
||||
[315, 'NW'],
|
||||
[22, 'NNE'],
|
||||
[359, 'N'],
|
||||
]
|
||||
testsParams.map((testParams) => {
|
||||
it(`convert ${testParams[0]}° to ${testParams[1]}`, () => {
|
||||
assert.equal(convertDegreeToDirection(testParams[0]), testParams[1])
|
||||
})
|
||||
})
|
||||
})
|
Reference in New Issue
Block a user