Client - replace sports PNG images with SVG

This commit is contained in:
Sam 2021-10-01 16:48:48 +02:00
parent ba0b94de45
commit 5856599377
28 changed files with 461 additions and 118 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -0,0 +1,51 @@
<template>
<svg
version="1.1"
id="Capa_1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px"
y="0px"
viewBox="0 0 491.737 491.737"
style="enable-background: new 0 0 491.737 491.737"
xml:space="preserve"
>
<desc id="cyclingSportDescription">
silhouette of a person riding a bicycle
</desc>
<g>
<path
d="M321.097,112.359c20.973,12.338,47.985,5.315,60.293-15.652c12.34-20.973,5.35-47.974-15.623-60.304
c-21.009-12.332-47.99-5.317-60.314,15.65C293.129,73.036,300.103,100.027,321.097,112.359z"
/>
<path
d="M393.081,264.102c-2.414,0-4.8,0.194-7.169,0.362l-14.431-71.605l4.702-1.757c10.666-3.987,16.093-15.868,12.098-26.54
c-3.994-10.681-15.946-16.084-26.531-12.09l-51.823,19.38l-2.321-18.864c6.3-13.193,5.541-29.78-4.767-41.482
c-21.224-24.092-47.12-12.508-55.191-5.976l-106.884,86.555l0.016,0.024c-3.319,2.893-6.089,6.485-7.86,10.842
c-2.191,5.396-2.596,11.067-1.564,16.384c-8.503,0.669-15.255,7.571-15.255,16.246c0,9.085,7.346,16.44,16.432,16.48l-6.797,15.906
c-8.62-2.465-17.674-3.866-27.066-3.866C44.27,264.102,0,308.354,0,362.754c0,54.403,44.27,98.663,98.668,98.663
c54.403,0,98.652-44.26,98.652-98.663c0-36.228-19.683-67.867-48.858-85.024l10.957-25.652h17.767l60.281,24.462l-32.201,52.773
c-8.297,13.612-3.994,31.382,9.615,39.685c4.691,2.86,9.878,4.229,15,4.229c9.729,0,19.234-4.929,24.677-13.838l29.339-48.095
l19.072,11.511c-5.447,12.227-8.54,25.726-8.54,39.95c0,54.403,44.254,98.663,98.652,98.663c54.402,0,98.656-44.26,98.656-98.663
C491.737,308.354,447.483,264.102,393.081,264.102z M98.668,436.671c-40.756,0-73.923-33.161-73.923-73.917
c0-40.756,33.167-73.909,73.923-73.909c5.944,0,11.649,0.896,17.188,2.224l-20.476,47.893
c-11.758,1.619-20.843,11.598-20.843,23.792c0,13.323,10.808,24.132,24.13,24.132c8.767,0,16.367-4.745,20.589-11.76h52.065
C165.395,409.988,135.188,436.671,98.668,436.671z M171.322,350.383h-52.065c-0.355-0.588-0.708-1.176-1.112-1.732l20.476-47.901
C155.679,311.776,167.793,329.595,171.322,350.383z M296.781,290.175l7.666-12.564c4.416-7.233,5.431-16.038,2.774-24.084
c-2.661-8.046-8.718-14.515-16.562-17.704l-52.725-21.395l32.443-26.281l1.804,14.691c0.756,6.267,4.366,11.841,9.761,15.12
c3.271,1.981,6.979,2.988,10.698,2.988c2.435,0,4.88-0.435,7.218-1.306l48.15-18.001l13.627,67.691
c-18.268,6.162-34.117,17.51-45.848,32.314L296.781,290.175z M375.396,337.633l-38.003-22.94
c7.877-9.118,17.787-16.319,29.205-20.734L375.396,337.633z M393.081,436.671c-40.757,0-73.907-33.161-73.907-73.917
c0-9.544,1.965-18.597,5.268-26.983l44.541,26.888c0,0.032-0.016,0.064-0.016,0.095c0,13.323,10.808,24.132,24.114,24.132
c13.322,0,24.118-10.81,24.118-24.132c0-10.478-6.721-19.307-16.06-22.64l-10.277-51.043c0.756-0.024,1.463-0.226,2.22-0.226
c40.757,0,73.911,33.153,73.911,73.909C466.992,403.51,433.838,436.671,393.081,436.671z"
/>
</g>
</svg>
</template>
<script>
export default {
name: 'CyclingSport',
}
</script>

View File

@ -0,0 +1,33 @@
<template>
<svg
version="1.1"
id="Capa_1"
x="0px"
y="0px"
viewBox="0 0 491.737 491.737"
style="enable-background: new 0 0 491.737 491.737"
xml:space="preserve"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
>
<desc id="cyclingTransportDescription">
silhouette of a person riding a bicycle (for transportation)
</desc>
<g id="g147">
<path
d="m 189.097,82.359 c 20.97701,12.331184 47.97442,5.308784 60.293,-15.652 12.32942,-20.979222 5.35418,-47.981117 -15.623,-60.304 -21.00482,-12.3391184 -47.99,-5.317 -60.314,15.65 -12.324,20.983 -5.34599,47.967183 15.644,60.306 z"
id="path143"
/>
<path
d="m 393.081,264.102 c -2.414,0 -4.8,0.194 -7.169,0.362 l -14.431,-71.605 4.702,-1.757 c 10.666,-3.987 16.093,-15.868 12.098,-26.54 -3.994,-10.681 -15.946,-16.084 -26.531,-12.09 l -63.05508,-1.53717 C 284.04753,137.09803 248.90259,106.55858 243.33317,101.62481 217.77732,75.090916 186.1698,85.012419 178.0988,91.544419 L 140.764,192.085 l 0.016,0.024 c -3.319,2.893 -6.089,6.485 -7.86,10.842 -2.191,5.396 -2.596,11.067 -1.564,16.384 -8.503,0.669 -15.255,7.571 -15.255,16.246 0,9.085 7.346,16.44 16.432,16.48 l -6.797,15.906 c -8.62,-2.465 -17.674,-3.866 -27.066,-3.866 C 44.27,264.102 0,308.354 0,362.754 c 0,54.403 44.27,98.663 98.668,98.663 54.403,0 98.652,-44.26 98.652,-98.663 0,-36.228 -19.683,-67.867 -48.858,-85.024 l 10.957,-25.652 h 17.767 l 60.281,24.462 -32.201,52.773 c -8.297,13.612 -3.994,31.382 9.615,39.685 4.691,2.86 9.878,4.229 15,4.229 9.729,0 19.234,-4.929 24.677,-13.838 l 29.339,-48.095 19.072,11.511 c -5.447,12.227 -8.54,25.726 -8.54,39.95 0,54.403 44.254,98.663 98.652,98.663 54.402,0 98.656,-44.26 98.656,-98.663 0,-54.401 -44.254,-98.653 -98.656,-98.653 z M 98.668,436.671 c -40.756,0 -73.923,-33.161 -73.923,-73.917 0,-40.756 33.167,-73.909 73.923,-73.909 5.944,0 11.649,0.896 17.188,2.224 L 95.38,338.962 c -11.758,1.619 -20.843,11.598 -20.843,23.792 0,13.323 10.808,24.132 24.13,24.132 8.767,0 16.367,-4.745 20.589,-11.76 h 52.065 c -5.926,34.862 -36.133,61.545 -72.653,61.545 z m 72.654,-86.288 h -52.065 c -0.355,-0.588 -0.708,-1.176 -1.112,-1.732 l 20.476,-47.901 c 17.058,11.026 29.172,28.845 32.701,49.633 z m 125.459,-60.208 7.666,-12.564 c 4.416,-7.233 5.431,-16.038 2.774,-24.084 -2.661,-8.046 -8.718,-14.515 -16.562,-17.704 l -73.83357,-31.7176 16.7558,-45.21274 c 10.36934,4.13303 41.82171,27.90767 45.77423,28.08592 3.271,1.981 8.57725,1.46711 12.29625,1.46711 2.435,0 18.50584,0.70472 20.84384,-0.16628 L 343.32113,188.03378 361.635,269.33 c -18.268,6.162 -34.117,17.51 -45.848,32.314 z m 78.615,47.458 -38.003,-22.94 c 7.877,-9.118 17.787,-16.319 29.205,-20.734 z m 17.685,99.038 c -40.757,0 -73.907,-33.161 -73.907,-73.917 0,-9.544 1.965,-18.597 5.268,-26.983 l 44.541,26.888 c 0,0.032 -0.016,0.064 -0.016,0.095 0,13.323 10.808,24.132 24.114,24.132 13.322,0 24.118,-10.81 24.118,-24.132 0,-10.478 -6.721,-19.307 -16.06,-22.64 l -10.277,-51.043 c 0.756,-0.024 1.463,-0.226 2.22,-0.226 40.757,0 73.911,33.153 73.911,73.909 -10e-4,40.756 -33.155,73.917 -73.912,73.917 z"
id="path145"
/>
</g>
</svg>
</template>
<script>
export default {
name: 'CyclingTransport',
}
</script>

View File

@ -0,0 +1,38 @@
<template>
<svg
version="1.1"
id="Capa_1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px"
y="0px"
viewBox="0 0 463.507 463.507"
style="enable-background: new 0 0 463.507 463.507"
xml:space="preserve"
>
<desc id="hikingDescription">silhouette of a person hiking</desc>
<g>
<path
d="M246.413,78.492c21.688,0,39.255-17.573,39.255-39.251c0-21.67-17.567-39.24-39.255-39.24
c-21.652,0-39.242,17.57-39.242,39.24C207.171,60.919,224.761,78.492,246.413,78.492z"
/>
<path
d="M386.604,202.858c0-11.185-9.066-20.251-20.253-20.251h-68.479l-38.62-54.832l0.127-0.933
c1.378-10.474-1.474-21.067-7.911-29.444c-6.441-8.378-15.932-13.852-26.408-15.23c-11.596-1.511-22.592,2.224-30.852,9.225V45.779
c0-7.847-6.362-14.217-14.225-14.217H140.59c-7.867,0-14.225,6.37-14.225,14.217v168.953c0,20.68,15.821,37.476,35.979,39.446
l-3.043,7.073l-23.859,90.136l-53.73,72.188c-8.006,10.768-5.794,25.987,4.984,34.001c4.348,3.245,9.443,4.811,14.491,4.811
c7.422,0,14.729-3.385,19.511-9.795l56.529-75.945c1.851-2.484,3.213-5.299,4.003-8.289l16.266-61.414l44.521,40.877l-6.076,88.603
c-0.917,13.393,9.177,24.99,22.58,25.908c0.552,0.04,1.124,0.056,1.691,0.056c12.66,0,23.339-9.819,24.208-22.642l6.882-100.264
c0.508-7.364-2.371-14.572-7.815-19.564l-45.994-42.219l13.992-90.613l19.331,27.435c3.801,5.387,9.972,8.592,16.552,8.592h70.882
l1.339,232.294c0,4.478,3.626,8.101,8.101,8.101c4.479,0,8.101-3.624,8.101-8.101l-1.339-234.036
C381.588,218.245,386.604,211.15,386.604,202.858z"
/>
</g>
</svg>
</template>
<script>
export default {
name: 'Hiking',
}
</script>

View File

@ -0,0 +1,51 @@
<template>
<svg
version="1.1"
id="Capa_1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px"
y="0px"
viewBox="0 0 503.162 503.162"
style="enable-background: new 0 0 503.162 503.162"
xml:space="preserve"
>
<desc id="mountainBikingDescription">
silhouette of a person riding a mountain bike
</desc>
<g>
<g>
<path
d="M149.951,67.997c15.711-7.143,22.739-25.675,15.596-41.416c-7.124-15.701-25.723-22.682-41.453-15.539
c-15.721,7.134-22.702,25.752-15.578,41.444C115.679,68.216,134.23,75.14,149.951,67.997z"
/>
<path
d="M87.517,89.072l-32.828,87.755c-1.979,5.967-1.683,12.594,1.1,18.733c4.055,8.922,12.604,14.525,21.755,15.271
l76.873,6.244l29.137,64.184c4.122,9.046,14.832,13.148,23.906,9.017c9.075-4.131,13.072-14.859,8.951-23.944l-36.424-80.201
c0,0-3.605-13.76-21.343-14.133l-43.873-2.572l21.009-55.166l31.671,20.588c5.584,3.663,10.997,3.682,15.1,1.722l55.051-24.997
c17.069-7.755,6.952-30.036-10.108-22.29l-47.506,21.707l-53.55-34.846c0,0-11.638-8.013-24.241-2.285
C102.205,73.858,91.112,77.243,87.517,89.072z"
/>
<path
d="M423.687,182.488l-2.61,15.042c-2.123,12.154-13.35,25.092-25.092,28.888l-3.711,1.195
c3.041-16.543,1.282-34.148-6.215-50.633c-19.498-42.974-70.094-61.87-112.943-42.419
c-42.878,19.479-61.936,70.017-42.438,112.981c17.069,37.562,57.881,56.744,96.534,47.966l-0.784,1.415
c-5.968,10.796-20.817,19.221-33.144,18.8l-17.892-0.622c-12.336-0.411-30.514,5.002-40.603,12.116l-22.376,15.759
c-10.107,7.104-28.276,12.632-40.612,12.354l-12.001-0.277c12.718-22.845,14.889-51.159,3.242-76.806
c-19.517-42.955-70.074-61.879-113.019-42.381c-42.792,19.44-61.87,70.007-42.372,112.933
c16.667,36.711,56.084,55.788,93.914,48.444l-1.32,2.056c-6.675,10.385-22.08,18.398-34.406,17.92l-32.79-1.291
c-12.326-0.497-24.021,8.97-26.096,21.143l-2.62,15.339c-0.564,3.271-0.354,6.11,0.401,8.501c-0.43,1.778-0.736,3.548-0.736,5.326
v9.562c0,10.557,8.568,19.125,19.125,19.125h460.932c10.557,0,19.115-8.568,19.106-19.125l-0.125-167.507
c0-2.782-0.593-5.221-1.616-7.286c1.396-3.806,2.057-7.841,1.598-11.839l-4.677-40.497c-1.415-12.249-9.763-29.146-18.637-37.724
l-36.127-34.951C434.712,167.418,425.79,170.325,423.687,182.488z"
/>
</g>
</g>
</svg>
</template>
<script>
export default {
name: 'MountainBiking',
}
</script>

View File

@ -0,0 +1,38 @@
<template>
<svg
version="1.1"
id="Capa_1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px"
y="0px"
viewBox="0 0 494.49 494.49"
style="enable-background: new 0 0 494.49 494.49"
xml:space="preserve"
>
<desc id="runningDescription">silhouette of a running person</desc>
<g>
<path
d="M282.74,80.771c22.318,0,40.401-18.08,40.401-40.389C323.141,18.084,305.058,0,282.74,0
c-22.281,0-40.378,18.084-40.378,40.383C242.362,62.691,260.458,80.771,282.74,80.771z"
/>
<path
d="M400.207,188.547H331.47l-38.766-55.03l0.123-0.944c1.384-10.514-1.475-21.146-7.94-29.556
c-6.461-8.409-16.007-13.903-26.52-15.287c-10.926-1.429-22.619,3.12-31.206,8.646c-1.441,0.928-84.97,54.921-84.97,54.921
c-5.175,3.358-8.542,8.877-9.165,15.016c-0.634,6.13,1.574,12.222,5.976,16.541l58.982,58l-6.417,48.954l-18.707,65.584l-67.8-19.4
c-12.911-3.676-26.44,3.796-30.159,16.747c-3.699,12.951,3.799,26.459,16.758,30.168l91.271,26.109
c2.192,0.627,4.444,0.936,6.7,0.936c4.113,0,8.195-1.04,11.848-3.073c5.655-3.146,9.833-8.409,11.611-14.635l21.963-77.057
l26.365,36.639l6.684,119.628c0.73,12.991,11.501,23.036,24.349,23.036c0.441,0,0.92-0.016,1.379-0.039
c13.453-0.748,23.745-12.262,23-25.713l-7.083-126.736c-0.271-4.643-1.846-9.116-4.56-12.887l-32.24-44.811l11.959-91.279
l19.409,27.555c3.794,5.407,10.005,8.624,16.613,8.624h79.28c11.226,0,20.326-9.101,20.326-20.329
C420.533,197.647,411.432,188.547,400.207,188.547z M204.606,190.357l-19.026-18.717l23.476-15.206L204.606,190.357z"
/>
</g>
</svg>
</template>
<script>
export default {
name: 'Running',
}
</script>

View File

@ -0,0 +1,53 @@
<template>
<div
class="sport-img"
:style="{ fill: sportColors[sportLabel] }"
:title="title ? title : t(`sports.${sportLabel}.LABEL`)"
>
<CyclingSport v-if="sportLabel === 'Cycling (Sport)'" />
<CyclingTransport v-if="sportLabel === 'Cycling (Transport)'" />
<Hiking v-if="sportLabel === 'Hiking'" />
<MountainBiking v-if="sportLabel === 'Mountain Biking'" />
<Running v-if="sportLabel === 'Running'" />
<Walking v-if="sportLabel === 'Walking'" />
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import { useI18n } from 'vue-i18n'
import CyclingSport from '@/components/Common/Sports/CyclingSport.vue'
import CyclingTransport from '@/components/Common/Sports/CyclingTransport.vue'
import Hiking from '@/components/Common/Sports/Hiking.vue'
import MountainBiking from '@/components/Common/Sports/MountainBiking.vue'
import Running from '@/components/Common/Sports/Running.vue'
import Walking from '@/components/Common/Sports/Walking.vue'
import { sportColors } from '@/utils/sports'
export default defineComponent({
name: 'SportImg',
components: {
CyclingSport,
CyclingTransport,
Hiking,
MountainBiking,
Running,
Walking,
},
props: {
sportLabel: {
type: String,
required: true,
},
title: {
type: String,
required: false,
},
},
setup() {
const { t } = useI18n()
return { sportColors, t }
},
})
</script>

View File

@ -0,0 +1,32 @@
<template>
<svg
version="1.1"
id="Capa_1"
x="0px"
y="0px"
viewBox="0 0 494.49 494.49"
style="enable-background: new 0 0 494.49 494.49"
xml:space="preserve"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
>
<desc id="walkingDescription">silhouette of a walking person</desc>
<defs id="defs797" />
<g id="g792">
<path
d="m 272.74,80.771 c 22.318,0 40.401,-18.08 40.401,-40.389 C 313.141,18.084 295.058,0 272.74,0 c -22.281,0 -40.378,18.084 -40.378,40.383 0,22.308 18.096,40.388 40.378,40.388 z"
id="path788"
/>
<path
d="m 328.5854,174.48445 -40.64148,10.93729 4.76008,-51.90474 0.123,-0.944 c 1.384,-10.514 -1.475,-21.146 -7.94,-29.556 -6.461,-8.409 -16.007,-13.903 -26.52,-15.287 -10.926,-1.429 -22.619,3.12 -31.206,8.646 -1.441,0.928 -84.97,54.921 -84.97,54.921 -5.175,3.358 -8.542,8.877 -9.165,15.016 -0.634,6.13 1.574,12.222 5.976,16.541 l 58.982,58 -6.417,48.954 -25.88143,79.08977 -54.08338,43.67932 c -14.762199,11.1022 -24.410111,22.37008 -15.912276,36.07186 8.515526,13.68031 27.439076,15.75973 42.273746,4.63076 l 48.9456,-38.84296 c 12.09075,-7.84858 23.84126,-20.18502 28.3003,-35.27702 L 235.052,315.187 l 26.365,36.639 6.684,119.628 c 0.73,12.991 11.501,23.036 24.349,23.036 0.441,0 0.92,-0.016 1.379,-0.039 13.453,-0.748 23.745,-12.262 23,-25.713 l -7.083,-126.736 c -0.271,-4.643 -1.846,-9.116 -4.56,-12.887 l -32.24,-44.811 7.981,-57.1 c -15.00943,6.0905 -25.84439,5.48716 0,0 l 59.50354,-17.8263 c 10.75379,-3.22166 16.4326,-12.34116 13.52152,-25.36894 -2.44853,-10.95778 -14.74571,-13.15695 -25.36666,-9.52431 z M 204.606,190.357 185.58,171.64 209.056,156.434 Z"
id="path790"
/>
</g>
</svg>
</template>
<script>
export default {
name: 'Walking',
}
</script>

View File

@ -61,12 +61,7 @@
"
>
<div>
<img
v-if="sport"
class="sport-img"
alt="workout sport logo"
:src="sport.img"
/>
<SportImage v-if="sport" :sport-label="sport.label" />
</div>
<div>
<i class="fa fa-clock-o" aria-hidden="true" />
@ -88,6 +83,7 @@
import { useI18n } from 'vue-i18n'
import Card from '@/components/Common/Card.vue'
import SportImage from '@/components/Common/Sports/SportImage.vue'
import StaticMap from '@/components/Common/StaticMap.vue'
import { ROOT_STORE } from '@/store/constants'
import { ISport } from '@/types/sports'
@ -102,6 +98,7 @@
components: {
Card,
StaticMap,
SportImage,
},
props: {
workout: {
@ -196,8 +193,10 @@
width: 28px;
}
div {
display: flex;
justify-content: center;
align-items: center;
width: 33%;
text-align: center;
}
}
.workout-map,

View File

@ -5,7 +5,7 @@
$router.push({ name: 'Workout', params: { workoutId: workout.id } })
"
>
<img alt="workout sport logo" :src="sportImg" :title="workout.title" />
<SportImage :sport-label="sportLabel" :title="workout.title" />
<sup>
<i
v-if="workout.records.length > 0"
@ -25,16 +25,20 @@
import { defineComponent, PropType } from 'vue'
import { useI18n } from 'vue-i18n'
import SportImage from '@/components/Common/Sports/SportImage.vue'
import { IWorkout } from '@/types/workouts'
export default defineComponent({
name: 'CalendarWorkouts',
components: {
SportImage,
},
props: {
workout: {
type: Object as PropType<IWorkout>,
required: true,
},
sportImg: {
sportLabel: {
type: String,
required: true,
},
@ -53,9 +57,9 @@
display: flex;
padding: 1px;
cursor: pointer;
img {
max-width: 18px;
max-height: 18px;
.sport-img {
width: 18px;
height: 18px;
}
sup {
position: relative;
@ -68,9 +72,9 @@
}
@media screen and (max-width: $small-limit) {
img {
max-width: 14px;
max-height: 14px;
.sport-img {
width: 14px;
height: 14px;
}
sup {
.custom-fa-small {

View File

@ -9,7 +9,7 @@
v-for="(workout, index) in workouts.slice(0, displayedWorkoutCount)"
:key="index"
:workout="workout"
:sportImg="getSportImg(workout, sports)"
:sportLabel="getSportLabel(workout, sports)"
/>
</div>
<div v-else class="donut-display">
@ -41,7 +41,7 @@
import CalendarWorkoutsChart from '@/components/Dashboard/UserCalendar/CalendarWorkoutsChart.vue'
import { ISport } from '@/types/sports'
import { IWorkout } from '@/types/workouts'
import { getSportImg, sportIdColors } from '@/utils/sports'
import { getSportLabel, sportIdColors } from '@/utils/sports'
import { getDonutDatasets } from '@/utils/workouts'
export default defineComponent({
@ -65,7 +65,7 @@
chartDatasets: computed(() => getDonutDatasets(props.workouts)),
colors: computed(() => sportIdColors(props.sports)),
displayedWorkoutCount: 6,
getSportImg,
getSportLabel,
}
},
})

View File

@ -11,12 +11,12 @@
aria-hidden="true"
@click="togglePane"
/>
<div v-for="(workout, index) in workouts" :key="index">
<CalendarWorkout
:workout="workout"
:sportImg="getSportImg(workout, sports)"
/>
</div>
<CalendarWorkout
v-for="(workout, index) in workouts"
:key="index"
:workout="workout"
:sportLabel="getSportLabel(workout, sports)"
/>
</div>
</div>
</div>
@ -29,7 +29,7 @@
import DonutChart from '@/components/Dashboard/UserCalendar/DonutChart.vue'
import { ISport } from '@/types/sports'
import { IWorkout } from '@/types/workouts'
import { getSportImg } from '@/utils/sports'
import { getSportLabel } from '@/utils/sports'
export default defineComponent({
name: 'CalendarWorkoutsChart',
@ -61,7 +61,7 @@
event.stopPropagation()
isHidden.value = !isHidden.value
}
return { isHidden, getSportImg, togglePane }
return { isHidden, getSportLabel, togglePane }
},
})
</script>

View File

@ -2,14 +2,8 @@
<div class="records-card">
<Card :without-title="false">
<template #title>
<div>
<img
class="sport-img"
:alt="`${sportLabel} logo`"
:src="records.img"
/>
</div>
{{ sportLabel }}
<SportImage :sport-label="records.label" />
{{ sportTranslatedLabel }}
</template>
<template #content>
<div class="record" v-for="record in records.records" :key="record.id">
@ -37,19 +31,21 @@
import { useI18n } from 'vue-i18n'
import Card from '@/components/Common/Card.vue'
import SportImage from '@/components/Common/Sports/SportImage.vue'
import { IRecord } from '@/types/workouts'
export default defineComponent({
name: 'RecordsCard',
components: {
Card,
SportImage,
},
props: {
records: {
type: Object as PropType<IRecord[]>,
required: true,
},
sportLabel: {
sportTranslatedLabel: {
type: String,
required: true,
},

View File

@ -9,10 +9,10 @@
{{ t('workouts.NO_RECORDS') }}
</div>
<RecordsCard
v-for="sportLabel in Object.keys(recordsBySport).sort()"
:sportLabel="sportLabel"
:records="recordsBySport[sportLabel]"
:key="sportLabel"
v-for="sportTranslatedLabel in Object.keys(recordsBySport).sort()"
:sportTranslatedLabel="sportTranslatedLabel"
:records="recordsBySport[sportTranslatedLabel]"
:key="sportTranslatedLabel"
/>
</div>
</div>
@ -52,7 +52,10 @@
props.user.timezone
)
)
return { recordsBySport, t }
return {
recordsBySport,
t,
}
},
})
</script>

View File

@ -17,9 +17,7 @@
<i class="fa fa-chevron-left" aria-hidden="true" />
</div>
<div class="workout-card-title">
<div class="sport-img">
<img alt="workout sport logo" :src="sport.img" />
</div>
<SportImage :sport-label="sport.label" />
<div class="workout-title-date">
<div class="workout-title" v-if="workoutObject.type === 'WORKOUT'">
{{ workoutObject.title }}
@ -86,11 +84,15 @@
import { PropType, defineComponent } from 'vue'
import { useI18n } from 'vue-i18n'
import SportImage from '@/components/Common/Sports/SportImage.vue'
import { ISport } from '@/types/sports'
import { IWorkoutObject } from '@/types/workouts'
export default defineComponent({
name: 'WorkoutCardTitle',
components: {
SportImage,
},
props: {
sport: {
type: Object as PropType<ISport>,
@ -129,11 +131,9 @@
display: flex;
flex-grow: 1;
.sport-img {
img {
height: 35px;
width: 35px;
padding: 0 $default-padding;
}
height: 35px;
width: 35px;
padding: 0 $default-padding;
}
.workout-date {
font-size: 0.8em;

View File

@ -5,3 +5,6 @@ export interface ISport {
is_active: boolean
label: string
}
export interface ITranslatedSport extends ISport {
translatedLabel: string
}

View File

@ -27,7 +27,7 @@ export interface IRecord {
export interface IRecordsBySport {
[key: string]: string | Record<string, string | number>[]
img: string
label: string
records: Record<string, string | number>[]
}

View File

@ -1,4 +1,4 @@
import { ISport } from '@/types/sports'
import { ITranslatedSport } from '@/types/sports'
import { IRecord, IRecordsBySports } from '@/types/workouts'
import { formatWorkoutDate, getDateWithTZ } from '@/utils/dates'
@ -35,19 +35,19 @@ export const formatRecord = (
export const getRecordsBySports = (
records: IRecord[],
sports: ISport[],
translatedSports: ITranslatedSport[],
tz: string
): IRecordsBySports =>
records.reduce((sportList: IRecordsBySports, record) => {
const sport = sports.find((s) => s.id === record.sport_id)
const sport = translatedSports.find((s) => s.id === record.sport_id)
if (sport && sport.label) {
if (sportList[sport.label] === void 0) {
sportList[sport.label] = {
img: sport.img,
if (sportList[sport.translatedLabel] === void 0) {
sportList[sport.translatedLabel] = {
label: sport.label,
records: [],
}
}
sportList[sport.label].records.push(formatRecord(record, tz))
sportList[sport.translatedLabel].records.push(formatRecord(record, tz))
}
return sportList
}, {})

View File

@ -1,13 +1,14 @@
import { ISport } from '@/types/sports'
import { ISport, ITranslatedSport } from '@/types/sports'
import { IWorkout } from '@/types/workouts'
// TODO: allow user to change colors
export const sportColors: Record<string, string> = {
'Cycling (Sport)': '#55A8A3',
'Cycling (Transport)': '#98C3A9',
Hiking: '#D0838A',
'Mountain Biking': '#ECC77E',
Running: '#926692',
Walking: '#929292',
'Cycling (Sport)': '#4c9792',
'Cycling (Transport)': '#88af98',
Hiking: '#bb757c',
'Mountain Biking': '#d4b371',
Running: '#835b83',
Walking: '#838383',
}
export const sportIdColors = (sports: ISport[]): Record<number, string> => {
@ -16,27 +17,31 @@ export const sportIdColors = (sports: ISport[]): Record<number, string> => {
return colors
}
const sortSports = (a: ISport, b: ISport): number => {
const sportALabel = a.label.toLowerCase()
const sportBLabel = b.label.toLowerCase()
return sportALabel > sportBLabel ? 1 : sportALabel < sportBLabel ? -1 : 0
const sortSports = (a: ITranslatedSport, b: ITranslatedSport): number => {
const sportATranslatedLabel = a.translatedLabel.toLowerCase()
const sportBTranslatedLabel = b.translatedLabel.toLowerCase()
return sportATranslatedLabel > sportBTranslatedLabel
? 1
: sportATranslatedLabel < sportBTranslatedLabel
? -1
: 0
}
export const translateSports = (
sports: ISport[],
t: CallableFunction,
onlyActive = false
): ISport[] =>
): ITranslatedSport[] =>
sports
.filter((sport) => (onlyActive ? sport.is_active : true))
.map((sport) => ({
...sport,
label: t(`sports.${sport.label}.LABEL`),
translatedLabel: t(`sports.${sport.label}.LABEL`),
}))
.sort(sortSports)
export const getSportImg = (workout: IWorkout, sports: ISport[]): string => {
export const getSportLabel = (workout: IWorkout, sports: ISport[]): string => {
return sports
.filter((sport) => sport.id === workout.sport_id)
.map((sport) => sport.img)[0]
.map((sport) => sport.label)[0]
}

View File

@ -1,5 +1,8 @@
import createI18n from '@/i18n'
import { ISport } from '@/types/sports'
import { translateSports } from '@/utils/sports'
const { t } = createI18n.global
export const sports: ISport[] = [
{
has_workouts: false,
@ -23,3 +26,5 @@ export const sports: ISport[] = [
label: 'Hiking',
},
]
export const translatedSports = translateSports(sports, t)

View File

@ -1,6 +1,6 @@
import { assert, expect } from 'chai'
import { sports } from './fixtures'
import { translatedSports } from './fixtures'
import { formatRecord, getRecordsBySports } from '@/utils/records'
@ -157,7 +157,7 @@ describe('getRecordsBySports', () => {
},
expected: {
'Cycling (Sport)': {
img: '/img/sports/cycling-sport.png',
label: 'Cycling (Sport)',
records: [
{
id: 9,
@ -206,7 +206,7 @@ describe('getRecordsBySports', () => {
},
expected: {
'Cycling (Sport)': {
img: '/img/sports/cycling-sport.png',
label: 'Cycling (Sport)',
records: [
{
id: 9,
@ -225,7 +225,7 @@ describe('getRecordsBySports', () => {
],
},
'Cycling (Transport)': {
img: '/img/sports/cycling-transport.png',
label: 'Cycling (Transport)',
records: [
{
id: 10,
@ -244,7 +244,7 @@ describe('getRecordsBySports', () => {
assert.deepEqual(
getRecordsBySports(
testParams.input.records,
sports,
translatedSports,
testParams.input.tz
),
// eslint-disable-next-line @typescript-eslint/ban-ts-comment

View File

@ -16,7 +16,32 @@ describe('sortSports', () => {
locale: 'en',
onlyActive: false,
},
expected: sports,
expected: [
{
has_workouts: false,
id: 1,
img: '/img/sports/cycling-sport.png',
is_active: true,
label: 'Cycling (Sport)',
translatedLabel: 'Cycling (Sport)',
},
{
has_workouts: false,
id: 2,
img: '/img/sports/cycling-transport.png',
is_active: false,
label: 'Cycling (Transport)',
translatedLabel: 'Cycling (Transport)',
},
{
has_workouts: true,
id: 3,
img: '/img/sports/hiking.png',
is_active: true,
label: 'Hiking',
translatedLabel: 'Hiking',
},
],
},
{
description:
@ -33,6 +58,7 @@ describe('sortSports', () => {
img: '/img/sports/cycling-sport.png',
is_active: true,
label: 'Cycling (Sport)',
translatedLabel: 'Cycling (Sport)',
},
{
has_workouts: true,
@ -40,6 +66,7 @@ describe('sortSports', () => {
img: '/img/sports/hiking.png',
is_active: true,
label: 'Hiking',
translatedLabel: 'Hiking',
},
],
},
@ -65,21 +92,24 @@ describe('sortSports', () => {
id: 3,
img: '/img/sports/hiking.png',
is_active: true,
label: 'Randonnée',
label: 'Hiking',
translatedLabel: 'Randonnée',
},
{
has_workouts: false,
id: 1,
img: '/img/sports/cycling-sport.png',
is_active: true,
label: 'Vélo (Sport)',
label: 'Cycling (Sport)',
translatedLabel: 'Vélo (Sport)',
},
{
has_workouts: false,
id: 2,
img: '/img/sports/cycling-transport.png',
is_active: false,
label: 'Vélo (Transport)',
label: 'Cycling (Transport)',
translatedLabel: 'Vélo (Transport)',
},
],
},
@ -97,14 +127,16 @@ describe('sortSports', () => {
id: 3,
img: '/img/sports/hiking.png',
is_active: true,
label: 'Randonnée',
label: 'Hiking',
translatedLabel: 'Randonnée',
},
{
has_workouts: false,
id: 1,
img: '/img/sports/cycling-sport.png',
is_active: true,
label: 'Vélo (Sport)',
label: 'Cycling (Sport)',
translatedLabel: 'Vélo (Sport)',
},
],
},

View File

@ -164,51 +164,51 @@ describe('getDatasets', () => {
nb_workouts: [
{
label: 'Cycling (Sport)',
backgroundColor: ['#55A8A3'],
backgroundColor: ['#4c9792'],
data: [],
},
{
label: 'Cycling (Transport)',
backgroundColor: ['#98C3A9'],
backgroundColor: ['#88af98'],
data: [],
},
{
label: 'Hiking',
backgroundColor: ['#D0838A'],
backgroundColor: ['#bb757c'],
data: [],
},
],
total_distance: [
{
label: 'Cycling (Sport)',
backgroundColor: ['#55A8A3'],
backgroundColor: ['#4c9792'],
data: [],
},
{
label: 'Cycling (Transport)',
backgroundColor: ['#98C3A9'],
backgroundColor: ['#88af98'],
data: [],
},
{
label: 'Hiking',
backgroundColor: ['#D0838A'],
backgroundColor: ['#bb757c'],
data: [],
},
],
total_duration: [
{
label: 'Cycling (Sport)',
backgroundColor: ['#55A8A3'],
backgroundColor: ['#4c9792'],
data: [],
},
{
label: 'Cycling (Transport)',
backgroundColor: ['#98C3A9'],
backgroundColor: ['#88af98'],
data: [],
},
{
label: 'Hiking',
backgroundColor: ['#D0838A'],
backgroundColor: ['#bb757c'],
data: [],
},
],
@ -220,21 +220,21 @@ describe('getDatasets', () => {
nb_workouts: [
{
label: 'Cycling (Transport)',
backgroundColor: ['#98C3A9'],
backgroundColor: ['#88af98'],
data: [],
},
],
total_distance: [
{
label: 'Cycling (Transport)',
backgroundColor: ['#98C3A9'],
backgroundColor: ['#88af98'],
data: [],
},
],
total_duration: [
{
label: 'Cycling (Transport)',
backgroundColor: ['#98C3A9'],
backgroundColor: ['#88af98'],
data: [],
},
],
@ -257,51 +257,51 @@ describe('formatStats', () => {
nb_workouts: [
{
label: 'Cycling (Sport)',
backgroundColor: ['#55A8A3'],
backgroundColor: ['#4c9792'],
data: [0, 0, 0],
},
{
label: 'Cycling (Transport)',
backgroundColor: ['#98C3A9'],
backgroundColor: ['#88af98'],
data: [0, 0, 0],
},
{
label: 'Hiking',
backgroundColor: ['#D0838A'],
backgroundColor: ['#bb757c'],
data: [0, 0, 0],
},
],
total_distance: [
{
label: 'Cycling (Sport)',
backgroundColor: ['#55A8A3'],
backgroundColor: ['#4c9792'],
data: [0, 0, 0],
},
{
label: 'Cycling (Transport)',
backgroundColor: ['#98C3A9'],
backgroundColor: ['#88af98'],
data: [0, 0, 0],
},
{
label: 'Hiking',
backgroundColor: ['#D0838A'],
backgroundColor: ['#bb757c'],
data: [0, 0, 0],
},
],
total_duration: [
{
label: 'Cycling (Sport)',
backgroundColor: ['#55A8A3'],
backgroundColor: ['#4c9792'],
data: [0, 0, 0],
},
{
label: 'Cycling (Transport)',
backgroundColor: ['#98C3A9'],
backgroundColor: ['#88af98'],
data: [0, 0, 0],
},
{
label: 'Hiking',
backgroundColor: ['#D0838A'],
backgroundColor: ['#bb757c'],
data: [0, 0, 0],
},
],
@ -326,21 +326,21 @@ describe('formatStats', () => {
nb_workouts: [
{
label: 'Cycling (Transport)',
backgroundColor: ['#98C3A9'],
backgroundColor: ['#88af98'],
data: [0, 0, 0],
},
],
total_distance: [
{
label: 'Cycling (Transport)',
backgroundColor: ['#98C3A9'],
backgroundColor: ['#88af98'],
data: [0, 0, 0],
},
],
total_duration: [
{
label: 'Cycling (Transport)',
backgroundColor: ['#98C3A9'],
backgroundColor: ['#88af98'],
data: [0, 0, 0],
},
],
@ -392,51 +392,51 @@ describe('formatStats', () => {
nb_workouts: [
{
label: 'Cycling (Sport)',
backgroundColor: ['#55A8A3'],
backgroundColor: ['#4c9792'],
data: [1, 1, 0],
},
{
label: 'Cycling (Transport)',
backgroundColor: ['#98C3A9'],
backgroundColor: ['#88af98'],
data: [0, 2, 0],
},
{
label: 'Hiking',
backgroundColor: ['#D0838A'],
backgroundColor: ['#bb757c'],
data: [0, 0, 2],
},
],
total_distance: [
{
label: 'Cycling (Sport)',
backgroundColor: ['#55A8A3'],
backgroundColor: ['#4c9792'],
data: [10, 15, 0],
},
{
label: 'Cycling (Transport)',
backgroundColor: ['#98C3A9'],
backgroundColor: ['#88af98'],
data: [0, 20, 0],
},
{
label: 'Hiking',
backgroundColor: ['#D0838A'],
backgroundColor: ['#bb757c'],
data: [0, 0, 12],
},
],
total_duration: [
{
label: 'Cycling (Sport)',
backgroundColor: ['#55A8A3'],
backgroundColor: ['#4c9792'],
data: [3000, 3500, 0],
},
{
label: 'Cycling (Transport)',
backgroundColor: ['#98C3A9'],
backgroundColor: ['#88af98'],
data: [0, 3000, 0],
},
{
label: 'Hiking',
backgroundColor: ['#D0838A'],
backgroundColor: ['#bb757c'],
data: [0, 0, 5000],
},
],
@ -488,21 +488,21 @@ describe('formatStats', () => {
nb_workouts: [
{
label: 'Cycling (Sport)',
backgroundColor: ['#55A8A3'],
backgroundColor: ['#4c9792'],
data: [1, 1, 0],
},
],
total_distance: [
{
label: 'Cycling (Sport)',
backgroundColor: ['#55A8A3'],
backgroundColor: ['#4c9792'],
data: [10, 15, 0],
},
],
total_duration: [
{
label: 'Cycling (Sport)',
backgroundColor: ['#55A8A3'],
backgroundColor: ['#4c9792'],
data: [3000, 3500, 0],
},
],