Client - add user sports preferences
+ minor refactor
This commit is contained in:
parent
7afdd04d7d
commit
7c49fd31ad
2
fittrackee/dist/index.html
vendored
2
fittrackee/dist/index.html
vendored
@ -1 +1 @@
|
||||
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><!--[if IE]><link rel="icon" href="/favicon.ico"><![endif]--><link rel="stylesheet" href="/static/css/fork-awesome.min.css"><link rel="stylesheet" href="/static/css/leaflet.css"><title>FitTrackee</title><link href="/static/css/admin.04e24276.css" rel="prefetch"><link href="/static/css/main.c790adb1.css" rel="prefetch"><link href="/static/css/main~workouts.66c5ef05.css" rel="prefetch"><link href="/static/css/profile.b52bc193.css" rel="prefetch"><link href="/static/css/reset.bd9657a8.css" rel="prefetch"><link href="/static/css/workouts.d0767062.css" rel="prefetch"><link href="/static/js/admin.2f1d393d.js" rel="prefetch"><link href="/static/js/chunk-2d0c9189.c81458cc.js" rel="prefetch"><link href="/static/js/chunk-2d0cf391.020c75ea.js" rel="prefetch"><link href="/static/js/chunk-2d0da8f3.c8c3e7e8.js" rel="prefetch"><link href="/static/js/chunk-2d2248b6.d84473c1.js" rel="prefetch"><link href="/static/js/chunk-2d22523a.4b710d99.js" rel="prefetch"><link href="/static/js/main.e5da50b8.js" rel="prefetch"><link href="/static/js/main~workouts.a74990d7.js" rel="prefetch"><link href="/static/js/profile.6a786c1d.js" rel="prefetch"><link href="/static/js/reset.518e646f.js" rel="prefetch"><link href="/static/js/workouts.1c22fd12.js" rel="prefetch"><link href="/static/css/app.534b9c5c.css" rel="preload" as="style"><link href="/static/js/app.9ada5ac5.js" rel="preload" as="script"><link href="/static/js/chunk-vendors.71654064.js" rel="preload" as="script"><link href="/static/css/app.534b9c5c.css" rel="stylesheet"><link rel="icon" type="image/png" sizes="32x32" href="/img/icons/favicon-32x32.png"><link rel="icon" type="image/png" sizes="16x16" href="/img/icons/favicon-16x16.png"><link rel="manifest" href="/manifest.json"><meta name="theme-color" content="#4DBA87"><meta name="apple-mobile-web-app-capable" content="no"><meta name="apple-mobile-web-app-status-bar-style" content="default"><meta name="apple-mobile-web-app-title" content="fittrackee_client"><link rel="apple-touch-icon" href="/img/icons/apple-touch-icon-152x152.png"><link rel="mask-icon" href="/img/icons/safari-pinned-tab.svg" color="#4DBA87"><meta name="msapplication-TileImage" content="/img/icons/msapplication-icon-144x144.png"><meta name="msapplication-TileColor" content="#000000"></head><body><noscript><strong>We're sorry but FitTrackee doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="/static/js/chunk-vendors.71654064.js"></script><script src="/static/js/app.9ada5ac5.js"></script></body></html>
|
||||
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><!--[if IE]><link rel="icon" href="/favicon.ico"><![endif]--><link rel="stylesheet" href="/static/css/fork-awesome.min.css"><link rel="stylesheet" href="/static/css/leaflet.css"><title>FitTrackee</title><link href="/static/css/admin.dc8b6d66.css" rel="prefetch"><link href="/static/css/main.411e7bd3.css" rel="prefetch"><link href="/static/css/main~workouts.c8c5694b.css" rel="prefetch"><link href="/static/css/profile.314b1d45.css" rel="prefetch"><link href="/static/css/reset.a71577d5.css" rel="prefetch"><link href="/static/css/workouts.773dfff0.css" rel="prefetch"><link href="/static/js/admin.2f1d393d.js" rel="prefetch"><link href="/static/js/chunk-2d0c9189.c81458cc.js" rel="prefetch"><link href="/static/js/chunk-2d0cf391.020c75ea.js" rel="prefetch"><link href="/static/js/chunk-2d0da8f3.c8c3e7e8.js" rel="prefetch"><link href="/static/js/chunk-2d2248b6.d84473c1.js" rel="prefetch"><link href="/static/js/chunk-2d22523a.4b710d99.js" rel="prefetch"><link href="/static/js/main.88fa3c28.js" rel="prefetch"><link href="/static/js/main~workouts.a74990d7.js" rel="prefetch"><link href="/static/js/profile.62578012.js" rel="prefetch"><link href="/static/js/reset.518e646f.js" rel="prefetch"><link href="/static/js/workouts.46dd8fa5.js" rel="prefetch"><link href="/static/css/app.97115085.css" rel="preload" as="style"><link href="/static/js/app.38e0c4d5.js" rel="preload" as="script"><link href="/static/js/chunk-vendors.71654064.js" rel="preload" as="script"><link href="/static/css/app.97115085.css" rel="stylesheet"><link rel="icon" type="image/png" sizes="32x32" href="/img/icons/favicon-32x32.png"><link rel="icon" type="image/png" sizes="16x16" href="/img/icons/favicon-16x16.png"><link rel="manifest" href="/manifest.json"><meta name="theme-color" content="#4DBA87"><meta name="apple-mobile-web-app-capable" content="no"><meta name="apple-mobile-web-app-status-bar-style" content="default"><meta name="apple-mobile-web-app-title" content="fittrackee_client"><link rel="apple-touch-icon" href="/img/icons/apple-touch-icon-152x152.png"><link rel="mask-icon" href="/img/icons/safari-pinned-tab.svg" color="#4DBA87"><meta name="msapplication-TileImage" content="/img/icons/msapplication-icon-144x144.png"><meta name="msapplication-TileColor" content="#000000"></head><body><noscript><strong>We're sorry but FitTrackee doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="/static/js/chunk-vendors.71654064.js"></script><script src="/static/js/app.38e0c4d5.js"></script></body></html>
|
@ -64,7 +64,7 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([
|
||||
"url": "/img/workouts/mountains.svg"
|
||||
},
|
||||
{
|
||||
"revision": "04e22b3a72bc3a810319eb7a512e4b23",
|
||||
"revision": "59c5cdf1d1708e7f936a0a30db0bbffb",
|
||||
"url": "/index.html"
|
||||
},
|
||||
{
|
||||
@ -76,12 +76,12 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([
|
||||
"url": "/robots.txt"
|
||||
},
|
||||
{
|
||||
"revision": "ca5244fc3bcfc65816b9",
|
||||
"url": "/static/css/admin.04e24276.css"
|
||||
"revision": "55e1f50bd31cac2908e3",
|
||||
"url": "/static/css/admin.dc8b6d66.css"
|
||||
},
|
||||
{
|
||||
"revision": "fe2e967e1efad7b13e67",
|
||||
"url": "/static/css/app.534b9c5c.css"
|
||||
"revision": "9ae7710525db019efc86",
|
||||
"url": "/static/css/app.97115085.css"
|
||||
},
|
||||
{
|
||||
"revision": "82c1118c918377daaa71a320ab8eea42",
|
||||
@ -92,24 +92,24 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([
|
||||
"url": "/static/css/leaflet.css"
|
||||
},
|
||||
{
|
||||
"revision": "d3cf46cfc6340753d540",
|
||||
"url": "/static/css/main.c790adb1.css"
|
||||
"revision": "12cfbc42bf674769c6f0",
|
||||
"url": "/static/css/main.411e7bd3.css"
|
||||
},
|
||||
{
|
||||
"revision": "68364924c988a1f11b42",
|
||||
"url": "/static/css/main~workouts.66c5ef05.css"
|
||||
"revision": "ce60ed388b792b0e9a0e",
|
||||
"url": "/static/css/main~workouts.c8c5694b.css"
|
||||
},
|
||||
{
|
||||
"revision": "3438ac3f32223591afd9",
|
||||
"url": "/static/css/profile.b52bc193.css"
|
||||
"revision": "74137feddeb35e2de067",
|
||||
"url": "/static/css/profile.314b1d45.css"
|
||||
},
|
||||
{
|
||||
"revision": "688d813785d3c55a7d33",
|
||||
"url": "/static/css/reset.bd9657a8.css"
|
||||
"revision": "6066a5f13daad652feea",
|
||||
"url": "/static/css/reset.a71577d5.css"
|
||||
},
|
||||
{
|
||||
"revision": "5e13fc66c78986a630a0",
|
||||
"url": "/static/css/workouts.d0767062.css"
|
||||
"revision": "9a0901331d45e214aa27",
|
||||
"url": "/static/css/workouts.773dfff0.css"
|
||||
},
|
||||
{
|
||||
"revision": "e719f9244c69e28e7d00e725ca1e280e",
|
||||
@ -192,12 +192,12 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([
|
||||
"url": "/static/img/pt-sans-v9-latin-regular.f1f73e45.svg"
|
||||
},
|
||||
{
|
||||
"revision": "ca5244fc3bcfc65816b9",
|
||||
"revision": "55e1f50bd31cac2908e3",
|
||||
"url": "/static/js/admin.2f1d393d.js"
|
||||
},
|
||||
{
|
||||
"revision": "fe2e967e1efad7b13e67",
|
||||
"url": "/static/js/app.9ada5ac5.js"
|
||||
"revision": "9ae7710525db019efc86",
|
||||
"url": "/static/js/app.38e0c4d5.js"
|
||||
},
|
||||
{
|
||||
"revision": "bd7d183c9f68e5f4027d",
|
||||
@ -224,23 +224,23 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([
|
||||
"url": "/static/js/chunk-vendors.71654064.js"
|
||||
},
|
||||
{
|
||||
"revision": "d3cf46cfc6340753d540",
|
||||
"url": "/static/js/main.e5da50b8.js"
|
||||
"revision": "12cfbc42bf674769c6f0",
|
||||
"url": "/static/js/main.88fa3c28.js"
|
||||
},
|
||||
{
|
||||
"revision": "68364924c988a1f11b42",
|
||||
"revision": "ce60ed388b792b0e9a0e",
|
||||
"url": "/static/js/main~workouts.a74990d7.js"
|
||||
},
|
||||
{
|
||||
"revision": "3438ac3f32223591afd9",
|
||||
"url": "/static/js/profile.6a786c1d.js"
|
||||
"revision": "74137feddeb35e2de067",
|
||||
"url": "/static/js/profile.62578012.js"
|
||||
},
|
||||
{
|
||||
"revision": "688d813785d3c55a7d33",
|
||||
"revision": "6066a5f13daad652feea",
|
||||
"url": "/static/js/reset.518e646f.js"
|
||||
},
|
||||
{
|
||||
"revision": "5e13fc66c78986a630a0",
|
||||
"url": "/static/js/workouts.1c22fd12.js"
|
||||
"revision": "9a0901331d45e214aa27",
|
||||
"url": "/static/js/workouts.46dd8fa5.js"
|
||||
}
|
||||
]);
|
2
fittrackee/dist/service-worker.js
vendored
2
fittrackee/dist/service-worker.js
vendored
@ -14,7 +14,7 @@
|
||||
importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js");
|
||||
|
||||
importScripts(
|
||||
"/precache-manifest.200309f56fa439f700e940d169066203.js"
|
||||
"/precache-manifest.94b00578e2690280739258ebb12c465f.js"
|
||||
);
|
||||
|
||||
workbox.core.setCacheNameDetails({prefix: "fittrackee_client"});
|
||||
|
File diff suppressed because one or more lines are too long
1
fittrackee/dist/static/css/admin.dc8b6d66.css
vendored
Normal file
1
fittrackee/dist/static/css/admin.dc8b6d66.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
fittrackee/dist/static/css/app.534b9c5c.css
vendored
1
fittrackee/dist/static/css/app.534b9c5c.css
vendored
File diff suppressed because one or more lines are too long
1
fittrackee/dist/static/css/app.97115085.css
vendored
Normal file
1
fittrackee/dist/static/css/app.97115085.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
fittrackee/dist/static/css/main.411e7bd3.css
vendored
Normal file
1
fittrackee/dist/static/css/main.411e7bd3.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
fittrackee/dist/static/css/main.c790adb1.css
vendored
1
fittrackee/dist/static/css/main.c790adb1.css
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
fittrackee/dist/static/css/main~workouts.c8c5694b.css
vendored
Normal file
1
fittrackee/dist/static/css/main~workouts.c8c5694b.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
fittrackee/dist/static/css/profile.314b1d45.css
vendored
Normal file
1
fittrackee/dist/static/css/profile.314b1d45.css
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
fittrackee/dist/static/css/reset.a71577d5.css
vendored
Normal file
1
fittrackee/dist/static/css/reset.a71577d5.css
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
fittrackee/dist/static/css/workouts.773dfff0.css
vendored
Normal file
1
fittrackee/dist/static/css/workouts.773dfff0.css
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
fittrackee/dist/static/js/app.38e0c4d5.js
vendored
Normal file
2
fittrackee/dist/static/js/app.38e0c4d5.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
fittrackee/dist/static/js/app.38e0c4d5.js.map
vendored
Normal file
1
fittrackee/dist/static/js/app.38e0c4d5.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
2
fittrackee/dist/static/js/app.9ada5ac5.js
vendored
2
fittrackee/dist/static/js/app.9ada5ac5.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
fittrackee/dist/static/js/main.88fa3c28.js
vendored
Normal file
2
fittrackee/dist/static/js/main.88fa3c28.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
fittrackee/dist/static/js/main.88fa3c28.js.map
vendored
Normal file
1
fittrackee/dist/static/js/main.88fa3c28.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
2
fittrackee/dist/static/js/main.e5da50b8.js
vendored
2
fittrackee/dist/static/js/main.e5da50b8.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
fittrackee/dist/static/js/profile.62578012.js
vendored
Normal file
2
fittrackee/dist/static/js/profile.62578012.js
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["profile"],{"0bb3":function(e,t,n){},"36e8":function(e,t,n){"use strict";n.r(t);var c=n("7a23"),r=n("dad5"),o=n("2906"),u=function(e){return Object(c["pushScopeId"])("data-v-d342b648"),e=e(),Object(c["popScopeId"])(),e},a={key:0,id:"profile",class:"container view"},s=u((function(){return Object(c["createElementVNode"])("div",{id:"bottom"},null,-1)})),d=Object(c["defineComponent"])({setup:function(e){var t=Object(o["a"])(),n=Object(c["computed"])((function(){return t.getters[r["a"].GETTERS.AUTH_USER_PROFILE]}));return function(e,t){var r=Object(c["resolveComponent"])("router-view");return Object(c["unref"])(n).username?(Object(c["openBlock"])(),Object(c["createElementBlock"])("div",a,[Object(c["createVNode"])(r,{user:Object(c["unref"])(n)},null,8,["user"]),s])):Object(c["createCommentVNode"])("",!0)}}}),b=(n("6171"),n("6b0d")),i=n.n(b);const f=i()(d,[["__scopeId","data-v-d342b648"]]);t["default"]=f},6171:function(e,t,n){"use strict";n("0bb3")},"9b98":function(e,t,n){"use strict";n("d332")},ad3d:function(e,t,n){"use strict";n.r(t);var c=n("7a23"),r=n("6c02"),o=n("3c44"),u=n("71a7"),a=n("dad5"),s=n("2906"),d={key:0,id:"user",class:"view"},b={class:"box"},i=Object(c["defineComponent"])({setup:function(e){var t=Object(r["c"])(),n=Object(s["a"])(),i=Object(c["computed"])((function(){return n.getters[a["e"].GETTERS.USER]}));return Object(c["onBeforeMount"])((function(){t.params.username&&"string"===typeof t.params.username&&n.dispatch(a["e"].ACTIONS.GET_USER,t.params.username)})),Object(c["onBeforeUnmount"])((function(){n.dispatch(a["e"].ACTIONS.EMPTY_USER)})),function(e,t){return Object(c["unref"])(i).username?(Object(c["openBlock"])(),Object(c["createElementBlock"])("div",d,[Object(c["createVNode"])(o["a"],{user:Object(c["unref"])(i)},null,8,["user"]),Object(c["createElementVNode"])("div",b,[Object(c["createVNode"])(u["a"],{user:Object(c["unref"])(i),"from-admin":!0},null,8,["user"])])])):Object(c["createCommentVNode"])("",!0)}}}),f=(n("9b98"),n("6b0d")),O=n.n(f);const p=O()(i,[["__scopeId","data-v-218f8f1e"]]);t["default"]=p},d332:function(e,t,n){}}]);
|
||||
//# sourceMappingURL=profile.62578012.js.map
|
1
fittrackee/dist/static/js/profile.62578012.js.map
vendored
Normal file
1
fittrackee/dist/static/js/profile.62578012.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -1,2 +0,0 @@
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["profile"],{"36e8":function(e,t,n){"use strict";n.r(t);var c=n("7a23"),r=n("dad5"),o=n("2906"),u={key:0,id:"profile",class:"container view"},a=Object(c["defineComponent"])({setup:function(e){var t=Object(o["a"])(),n=Object(c["computed"])((function(){return t.getters[r["a"].GETTERS.AUTH_USER_PROFILE]}));return function(e,t){var r=Object(c["resolveComponent"])("router-view");return Object(c["unref"])(n).username?(Object(c["openBlock"])(),Object(c["createElementBlock"])("div",u,[Object(c["createVNode"])(r,{user:Object(c["unref"])(n)},null,8,["user"])])):Object(c["createCommentVNode"])("",!0)}}}),s=(n("44ab"),n("6b0d")),b=n.n(s);const i=b()(a,[["__scopeId","data-v-bb090bfa"]]);t["default"]=i},"44ab":function(e,t,n){"use strict";n("4fe6")},"4fe6":function(e,t,n){},"9b98":function(e,t,n){"use strict";n("d332")},ad3d:function(e,t,n){"use strict";n.r(t);var c=n("7a23"),r=n("6c02"),o=n("3c44"),u=n("71a7"),a=n("dad5"),s=n("2906"),b={key:0,id:"user",class:"view"},i={class:"box"},d=Object(c["defineComponent"])({setup:function(e){var t=Object(r["c"])(),n=Object(s["a"])(),d=Object(c["computed"])((function(){return n.getters[a["e"].GETTERS.USER]}));return Object(c["onBeforeMount"])((function(){t.params.username&&"string"===typeof t.params.username&&n.dispatch(a["e"].ACTIONS.GET_USER,t.params.username)})),Object(c["onBeforeUnmount"])((function(){n.dispatch(a["e"].ACTIONS.EMPTY_USER)})),function(e,t){return Object(c["unref"])(d).username?(Object(c["openBlock"])(),Object(c["createElementBlock"])("div",b,[Object(c["createVNode"])(o["a"],{user:Object(c["unref"])(d)},null,8,["user"]),Object(c["createElementVNode"])("div",i,[Object(c["createVNode"])(u["a"],{user:Object(c["unref"])(d),"from-admin":!0},null,8,["user"])])])):Object(c["createCommentVNode"])("",!0)}}}),f=(n("9b98"),n("6b0d")),O=n.n(f);const j=O()(d,[["__scopeId","data-v-218f8f1e"]]);t["default"]=j},d332:function(e,t,n){}}]);
|
||||
//# sourceMappingURL=profile.6a786c1d.js.map
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
fittrackee/dist/static/js/workouts.46dd8fa5.js
vendored
Normal file
2
fittrackee/dist/static/js/workouts.46dd8fa5.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
fittrackee/dist/static/js/workouts.46dd8fa5.js.map
vendored
Normal file
1
fittrackee/dist/static/js/workouts.46dd8fa5.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -35,6 +35,7 @@
|
||||
<SportImage
|
||||
:title="sport.translatedLabel"
|
||||
:sport-label="sport.label"
|
||||
:color="sport.color"
|
||||
/>
|
||||
</td>
|
||||
<td class="sport-label">
|
||||
@ -127,9 +128,6 @@
|
||||
font-style: italic;
|
||||
padding: 0 $default-padding;
|
||||
}
|
||||
.text-left {
|
||||
text-align: left;
|
||||
}
|
||||
.sport-action {
|
||||
padding-left: $default-padding * 4;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div
|
||||
class="sport-img"
|
||||
:style="{ fill: sportColors[sportLabel] }"
|
||||
:style="{ fill: color ? color : sportColors[sportLabel] }"
|
||||
:title="title ? title : $t(`sports.${sportLabel}.LABEL`)"
|
||||
>
|
||||
<CyclingSport v-if="sportLabel === 'Cycling (Sport)'" />
|
||||
@ -37,12 +37,13 @@
|
||||
|
||||
interface Props {
|
||||
sportLabel: string
|
||||
color: string | null
|
||||
title?: string
|
||||
}
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
title: '',
|
||||
})
|
||||
|
||||
const { sportLabel, title } = toRefs(props)
|
||||
const { color, sportLabel, title } = toRefs(props)
|
||||
const sportColors = inject('sportColors')
|
||||
</script>
|
||||
|
@ -5,7 +5,11 @@
|
||||
$router.push({ name: 'Workout', params: { workoutId: workout.id } })
|
||||
"
|
||||
>
|
||||
<SportImage :sport-label="sportLabel" :title="workout.title" />
|
||||
<SportImage
|
||||
:sport-label="sportLabel"
|
||||
:title="workout.title"
|
||||
:color="sportColor"
|
||||
/>
|
||||
<sup>
|
||||
<i
|
||||
v-if="workout.records.length > 0"
|
||||
@ -28,6 +32,7 @@
|
||||
interface Props {
|
||||
workout: IWorkout
|
||||
sportLabel: string
|
||||
sportColor: string | null
|
||||
}
|
||||
const props = defineProps<Props>()
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
:key="index"
|
||||
:workout="workout"
|
||||
:sportLabel="getSportLabel(workout, sports)"
|
||||
:sportColor="getSportColor(workout, sports)"
|
||||
/>
|
||||
</div>
|
||||
<div v-else class="donut-display">
|
||||
@ -41,7 +42,7 @@
|
||||
import CalendarWorkoutsChart from '@/components/Dashboard/UserCalendar/CalendarWorkoutsChart.vue'
|
||||
import { ISport } from '@/types/sports'
|
||||
import { IWorkout } from '@/types/workouts'
|
||||
import { getSportLabel, sportIdColors } from '@/utils/sports'
|
||||
import { getSportColor, getSportLabel, sportIdColors } from '@/utils/sports'
|
||||
import { getDonutDatasets } from '@/utils/workouts'
|
||||
|
||||
interface Props {
|
||||
|
@ -2,7 +2,7 @@
|
||||
<div class="records-card">
|
||||
<Card>
|
||||
<template #title>
|
||||
<SportImage :sport-label="records.label" />
|
||||
<SportImage :sport-label="records.label" :color="records.color" />
|
||||
{{ sportTranslatedLabel }}
|
||||
</template>
|
||||
<template #content>
|
||||
|
@ -13,7 +13,7 @@
|
||||
:checked="selectedSportIds.includes(sport.id)"
|
||||
@input="updateSelectedSportIds(sport.id)"
|
||||
/>
|
||||
<SportImage :sport-label="sport.label" />
|
||||
<SportImage :sport-label="sport.label" :color="sport.color" />
|
||||
<span class="sport-label">{{ sport.translatedLabel }}</span>
|
||||
</label>
|
||||
</div>
|
||||
|
@ -91,9 +91,5 @@
|
||||
.user-bio {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
.profile-buttons {
|
||||
display: flex;
|
||||
gap: $default-padding;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -38,13 +38,3 @@
|
||||
props.user.timezone ? props.user.timezone : 'Europe/Paris'
|
||||
)
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '~@/scss/base.scss';
|
||||
#user-preferences {
|
||||
.profile-buttons {
|
||||
display: flex;
|
||||
gap: $default-padding;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -22,7 +22,7 @@
|
||||
const props = defineProps<Props>()
|
||||
|
||||
const { user, tab } = toRefs(props)
|
||||
const tabs = ['PROFILE', 'PREFERENCES']
|
||||
const tabs = ['PROFILE', 'PREFERENCES', 'SPORTS']
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
@ -34,7 +34,7 @@
|
||||
const store = useStore()
|
||||
|
||||
const { user, tab } = toRefs(props)
|
||||
const tabs = ['PROFILE', 'PICTURE', 'PREFERENCES']
|
||||
const tabs = ['PROFILE', 'PICTURE', 'PREFERENCES', 'SPORTS']
|
||||
const loading = computed(
|
||||
() => store.getters[AUTH_USER_STORE.GETTERS.USER_LOADING]
|
||||
)
|
||||
|
@ -38,7 +38,10 @@
|
||||
case 'PICTURE':
|
||||
return '/profile/edit/picture'
|
||||
case 'PREFERENCES':
|
||||
return `/profile${props.edition ? '/edit' : ''}/preferences`
|
||||
case 'SPORTS':
|
||||
return `/profile${
|
||||
props.edition ? '/edit' : ''
|
||||
}/${tab.toLocaleLowerCase()}`
|
||||
default:
|
||||
case 'PROFILE':
|
||||
return `/profile${props.edition ? '/edit' : ''}`
|
||||
|
280
fittrackee_client/src/components/User/UserSportPreferences.vue
Normal file
280
fittrackee_client/src/components/User/UserSportPreferences.vue
Normal file
@ -0,0 +1,280 @@
|
||||
<template>
|
||||
<div id="user-sport-preferences">
|
||||
<div class="responsive-table" v-if="sports.length > 0">
|
||||
<div class="mobile-display">
|
||||
<div v-if="isEdition" class="profile-buttons mobile-display">
|
||||
<button
|
||||
class="cancel"
|
||||
@click.prevent="$router.push('/profile/sports')"
|
||||
>
|
||||
{{ $t('buttons.BACK') }}
|
||||
</button>
|
||||
</div>
|
||||
<div v-else class="profile-buttons">
|
||||
<button @click="$router.push('/profile/edit/sports')">
|
||||
{{ $t('user.PROFILE.EDIT_SPORTS_PREFERENCES') }}
|
||||
</button>
|
||||
<button @click="$router.push('/')">{{ $t('common.HOME') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ $t('user.PROFILE.SPORT.COLOR') }}</th>
|
||||
<th class="text-left">{{ $t('workouts.SPORT', 0) }}</th>
|
||||
<th>{{ $t('user.PROFILE.SPORT.IS_ACTIVE') }}</th>
|
||||
<th>{{ $t('user.PROFILE.SPORT.STOPPED_SPEED_THRESHOLD') }}</th>
|
||||
<th v-if="isEdition">{{ $t('user.PROFILE.SPORT.ACTION') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="sport in translatedSports" :key="sport.id">
|
||||
<td>
|
||||
<span class="cell-heading">
|
||||
{{ $t('user.PROFILE.SPORT.COLOR') }}
|
||||
</span>
|
||||
<input
|
||||
v-if="isSportInEdition(sport.id)"
|
||||
class="sport-color"
|
||||
type="color"
|
||||
:value="sportPayload.color"
|
||||
@input="updateColor"
|
||||
/>
|
||||
<SportImage
|
||||
v-else
|
||||
:title="sport.translatedLabel"
|
||||
:sport-label="sport.label"
|
||||
:color="sport.color ? sport.color : sportColors[sport.label]"
|
||||
/>
|
||||
</td>
|
||||
<td class="sport-label">
|
||||
<span class="cell-heading">
|
||||
{{ $t('user.PROFILE.SPORT.LABEL') }}
|
||||
</span>
|
||||
{{ sport.translatedLabel }}
|
||||
<i
|
||||
v-if="loading && isSportInEdition(sport.id)"
|
||||
class="fa fa-refresh fa-spin fa-fw"
|
||||
/>
|
||||
<ErrorMessage
|
||||
:message="errorMessages"
|
||||
v-if="errorMessages && sportPayload.sport_id === sport.id"
|
||||
/>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<span class="cell-heading">
|
||||
{{ $t('user.PROFILE.SPORT.IS_ACTIVE') }}
|
||||
</span>
|
||||
<input
|
||||
v-if="isSportInEdition(sport.id)"
|
||||
type="checkbox"
|
||||
:checked="sport.is_active_for_user"
|
||||
@change="updateIsActive"
|
||||
/>
|
||||
<i
|
||||
v-else
|
||||
:class="`fa fa${
|
||||
sport.is_active_for_user ? '-check' : ''
|
||||
}-square-o`"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<span class="cell-heading">
|
||||
{{ $t('user.PROFILE.SPORT.STOPPED_SPEED_THRESHOLD') }}
|
||||
</span>
|
||||
<input
|
||||
class="threshold-input"
|
||||
v-if="isSportInEdition(sport.id)"
|
||||
type="number"
|
||||
min="0"
|
||||
step="0.1"
|
||||
:value="sportPayload.stopped_speed_threshold"
|
||||
@input="updateThreshold"
|
||||
/>
|
||||
<span v-else>
|
||||
{{ sport.stopped_speed_threshold }}
|
||||
</span>
|
||||
</td>
|
||||
<td v-if="isEdition" class="action-buttons">
|
||||
<span class="cell-heading">
|
||||
{{ $t('user.PROFILE.SPORT.ACTION') }}
|
||||
</span>
|
||||
<button
|
||||
v-if="sportPayload.sport_id === 0"
|
||||
@click="updateSportInEdition(sport)"
|
||||
>
|
||||
{{ $t('buttons.EDIT') }}
|
||||
</button>
|
||||
<div v-if="isSportInEdition(sport.id)" class="edition-buttons">
|
||||
<button :disabled="loading" @click="updateSport">
|
||||
{{ $t('buttons.SUBMIT') }}
|
||||
</button>
|
||||
<button :disabled="loading" @click="updateSportInEdition(null)">
|
||||
{{ $t('buttons.CANCEL') }}
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div v-if="isEdition" class="profile-buttons">
|
||||
<button class="cancel" @click.prevent="$router.push('/profile/sports')">
|
||||
{{ $t('buttons.BACK') }}
|
||||
</button>
|
||||
</div>
|
||||
<div v-else class="profile-buttons">
|
||||
<button @click="$router.push('/profile/edit/sports')">
|
||||
{{ $t('user.PROFILE.EDIT_SPORTS_PREFERENCES') }}
|
||||
</button>
|
||||
<button @click="$router.push('/')">{{ $t('common.HOME') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ComputedRef, computed, inject, reactive, toRefs, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import { AUTH_USER_STORE, ROOT_STORE, SPORTS_STORE } from '@/store/constants'
|
||||
import { ISport, ITranslatedSport } from '@/types/sports'
|
||||
import { IUserSportPreferencesPayload } from '@/types/user'
|
||||
import { useStore } from '@/use/useStore'
|
||||
import { translateSports } from '@/utils/sports'
|
||||
|
||||
interface Props {
|
||||
isEdition: boolean
|
||||
}
|
||||
const props = defineProps<Props>()
|
||||
|
||||
const store = useStore()
|
||||
const { t } = useI18n()
|
||||
|
||||
const { isEdition } = toRefs(props)
|
||||
const sportColors = inject('sportColors')
|
||||
const sports: ComputedRef<ISport[]> = computed(
|
||||
() => store.getters[SPORTS_STORE.GETTERS.SPORTS]
|
||||
)
|
||||
const translatedSports: ComputedRef<ITranslatedSport[]> = computed(() =>
|
||||
translateSports(sports.value, t)
|
||||
)
|
||||
const loading = computed(
|
||||
() => store.getters[AUTH_USER_STORE.GETTERS.USER_LOADING]
|
||||
)
|
||||
const errorMessages: ComputedRef<string | string[] | null> = computed(
|
||||
() => store.getters[ROOT_STORE.GETTERS.ERROR_MESSAGES]
|
||||
)
|
||||
const sportPayload: IUserSportPreferencesPayload = reactive({
|
||||
sport_id: 0,
|
||||
color: null,
|
||||
is_active: true,
|
||||
stopped_speed_threshold: 1,
|
||||
})
|
||||
|
||||
function updateSportInEdition(sport: ISport | null) {
|
||||
if (sport !== null) {
|
||||
sportPayload.sport_id = sport.id
|
||||
sportPayload.color = sport.color ? sport.color : sportColors[sport.label]
|
||||
sportPayload.is_active = sport.is_active_for_user
|
||||
sportPayload.stopped_speed_threshold = sport.stopped_speed_threshold
|
||||
} else {
|
||||
resetSportPayload()
|
||||
}
|
||||
}
|
||||
function isSportInEdition(sportId: number) {
|
||||
return sportPayload.sport_id === sportId
|
||||
}
|
||||
function updateColor(event: Event & { target: HTMLInputElement }) {
|
||||
sportPayload.color = event.target.value
|
||||
}
|
||||
function updateThreshold(event: Event & { target: HTMLInputElement }) {
|
||||
sportPayload.stopped_speed_threshold = parseFloat(event.target.value)
|
||||
}
|
||||
function updateIsActive(event: Event & { target: HTMLInputElement }) {
|
||||
sportPayload.is_active = event.target.checked
|
||||
}
|
||||
function resetSportPayload() {
|
||||
sportPayload.sport_id = 0
|
||||
sportPayload.color = null
|
||||
sportPayload.is_active = true
|
||||
sportPayload.stopped_speed_threshold = 1
|
||||
store.commit(ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGES)
|
||||
}
|
||||
function updateSport(event: Event) {
|
||||
event.preventDefault()
|
||||
store.dispatch(
|
||||
AUTH_USER_STORE.ACTIONS.UPDATE_USER_SPORT_PREFERENCES,
|
||||
sportPayload
|
||||
)
|
||||
}
|
||||
|
||||
watch(
|
||||
() => loading.value,
|
||||
(newIsLoading) => {
|
||||
if (!newIsLoading && !errorMessages.value) {
|
||||
resetSportPayload()
|
||||
}
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '~@/scss/base.scss';
|
||||
#user-sport-preferences {
|
||||
.sport-img {
|
||||
height: 35px;
|
||||
width: 35px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.sport-color {
|
||||
border: none;
|
||||
margin: 6px 1px 6px 0;
|
||||
padding: 0;
|
||||
width: 40px;
|
||||
}
|
||||
.sport-label {
|
||||
width: 170px;
|
||||
}
|
||||
.action-buttons {
|
||||
width: 70px;
|
||||
}
|
||||
.edition-buttons {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: $default-padding * 0.5;
|
||||
line-height: 1.3em;
|
||||
|
||||
button {
|
||||
text-align: center;
|
||||
min-width: 80px;
|
||||
}
|
||||
}
|
||||
.threshold-input {
|
||||
padding: $default-padding * 0.5;
|
||||
width: 50px;
|
||||
}
|
||||
.mobile-display {
|
||||
display: none;
|
||||
}
|
||||
div.error-message {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@media screen and (max-width: $small-limit) {
|
||||
.sport-label {
|
||||
width: 100%;
|
||||
}
|
||||
.action-buttons {
|
||||
width: 100%;
|
||||
}
|
||||
.edition-buttons {
|
||||
justify-content: center;
|
||||
}
|
||||
.mobile-display {
|
||||
display: flex;
|
||||
margin: $default-margin * 2 0 $default-margin;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -75,7 +75,11 @@
|
||||
"
|
||||
>
|
||||
<div class="img">
|
||||
<SportImage v-if="sport.label" :sport-label="sport.label" />
|
||||
<SportImage
|
||||
v-if="sport.label"
|
||||
:sport-label="sport.label"
|
||||
:color="sport.color"
|
||||
/>
|
||||
</div>
|
||||
<div class="data">
|
||||
<i class="fa fa-clock-o" aria-hidden="true" />
|
||||
|
@ -17,7 +17,7 @@
|
||||
<i class="fa fa-chevron-left" aria-hidden="true" />
|
||||
</div>
|
||||
<div class="workout-card-title">
|
||||
<SportImage :sport-label="sport.label" />
|
||||
<SportImage :sport-label="sport.label" :color="sport.color" />
|
||||
<div class="workout-title-date">
|
||||
<div class="workout-title" v-if="workoutObject.type === 'WORKOUT'">
|
||||
{{ workoutObject.title }}
|
||||
|
@ -46,7 +46,7 @@
|
||||
v-model="workoutForm.sport_id"
|
||||
>
|
||||
<option
|
||||
v-for="sport in translatedSports.filter((s) => s.is_active)"
|
||||
v-for="sport in translatedSports"
|
||||
:value="sport.id"
|
||||
:key="sport.id"
|
||||
>
|
||||
@ -259,7 +259,7 @@
|
||||
|
||||
const { workout, isCreation, loading } = toRefs(props)
|
||||
const translatedSports: ComputedRef<ISport[]> = computed(() =>
|
||||
translateSports(props.sports, t)
|
||||
translateSports(props.sports, t, true)
|
||||
)
|
||||
const appConfig: ComputedRef<TAppConfig> = computed(
|
||||
() => store.getters[ROOT_STORE.GETTERS.APP_CONFIG]
|
||||
|
@ -52,6 +52,9 @@
|
||||
:sport-label="
|
||||
sports.filter((s) => s.id === workout.sport_id)[0].label
|
||||
"
|
||||
:color="
|
||||
sports.filter((s) => s.id === workout.sport_id)[0].color
|
||||
"
|
||||
/>
|
||||
</td>
|
||||
<td
|
||||
|
@ -23,6 +23,7 @@
|
||||
"BIRTH_DATE": "Birth date",
|
||||
"EDIT": "Edit profile",
|
||||
"EDIT_PREFERENCES": "Edit preferences",
|
||||
"EDIT_SPORTS_PREFERENCES": "Edit sports preferences",
|
||||
"FIRST_NAME": "First name",
|
||||
"FIRST_DAY_OF_WEEK": "First day of week",
|
||||
"LANGUAGE": "Language",
|
||||
@ -36,11 +37,20 @@
|
||||
"PREFERENCES_EDITION": "Preferences edition",
|
||||
"PROFILE_EDITION": "Profile edition",
|
||||
"REGISTRATION_DATE": "Registration date",
|
||||
"SPORTS_EDITION": "Sports preferences edition",
|
||||
"SUNDAY": "Sunday",
|
||||
"TABS": {
|
||||
"PICTURE": "picture",
|
||||
"PREFERENCES": "preferences",
|
||||
"PROFILE": "profile"
|
||||
"PROFILE": "profile",
|
||||
"SPORTS": "sports"
|
||||
},
|
||||
"SPORT": {
|
||||
"ACTION": "action",
|
||||
"COLOR": "color",
|
||||
"IS_ACTIVE": "active",
|
||||
"LABEL": "label",
|
||||
"STOPPED_SPEED_THRESHOLD": "stopped speed threshold"
|
||||
},
|
||||
"TIMEZONE": "Timezone"
|
||||
},
|
||||
|
@ -23,6 +23,7 @@
|
||||
"BIRTH_DATE": "Date de naissance",
|
||||
"EDIT": "Modifier le profil",
|
||||
"EDIT_PREFERENCES": "Modifier les préférences",
|
||||
"EDIT_SPORTS_PREFERENCES": "Modifier les préférences des sports",
|
||||
"FIRST_DAY_OF_WEEK": "Premier jour de la semaine",
|
||||
"FIRST_NAME": "Prénom",
|
||||
"LANGUAGE": "Langue",
|
||||
@ -36,11 +37,20 @@
|
||||
"PREFERENCES_EDITION": "Mise à jour des préférences",
|
||||
"PROFILE_EDITION": "Mise à jour du profil",
|
||||
"REGISTRATION_DATE": "Date d'inscription",
|
||||
"SPORTS_EDITION": "Mise à jour des préférences des sports",
|
||||
"SUNDAY": "Dimanche",
|
||||
"TABS": {
|
||||
"PICTURE": "image",
|
||||
"PREFERENCES": "préférences",
|
||||
"PROFILE": "profil"
|
||||
"PROFILE": "profil",
|
||||
"SPORTS": "sports"
|
||||
},
|
||||
"SPORT": {
|
||||
"ACTION": "action",
|
||||
"COLOR": "couleur",
|
||||
"IS_ACTIVE": "actif",
|
||||
"LABEL": "label",
|
||||
"STOPPED_SPEED_THRESHOLD": "seuil de vitesse arrêtée"
|
||||
},
|
||||
"TIMEZONE": "Fuseau horaire"
|
||||
},
|
||||
@ -49,4 +59,4 @@
|
||||
"RESET_PASSWORD": "Réinitialiser votre mot de passe",
|
||||
"USER_PICTURE": "photo de l'utilisateur",
|
||||
"USERNAME": "Nom d'utilisateur"
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import ProfileEdition from '@/components/User/ProfileEdition/index.vue'
|
||||
import UserInfosEdition from '@/components/User/ProfileEdition/UserInfosEdition.vue'
|
||||
import UserPictureEdition from '@/components/User/ProfileEdition/UserPictureEdition.vue'
|
||||
import UserPreferencesEdition from '@/components/User/ProfileEdition/UserPreferencesEdition.vue'
|
||||
import UserSportPreferences from '@/components/User/UserSportPreferences.vue'
|
||||
import store from '@/store'
|
||||
import { AUTH_USER_STORE } from '@/store/constants'
|
||||
|
||||
@ -101,6 +102,12 @@ const routes: Array<RouteRecordRaw> = [
|
||||
name: 'UserPreferences',
|
||||
component: UserPreferences,
|
||||
},
|
||||
{
|
||||
path: 'sports',
|
||||
name: 'UserSportPreferences',
|
||||
component: UserSportPreferences,
|
||||
props: { isEdition: false },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
@ -126,6 +133,12 @@ const routes: Array<RouteRecordRaw> = [
|
||||
name: 'UserPreferencesEdition',
|
||||
component: UserPreferencesEdition,
|
||||
},
|
||||
{
|
||||
path: 'sports',
|
||||
name: 'UserSportPreferencesEdition',
|
||||
component: UserSportPreferences,
|
||||
props: { isEdition: true },
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
@ -254,9 +254,12 @@ button {
|
||||
}
|
||||
}
|
||||
|
||||
.center-text {
|
||||
.text-center {
|
||||
text-align: center;
|
||||
}
|
||||
.text-left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.responsive-table {
|
||||
margin-bottom: 15px;
|
||||
@ -337,3 +340,14 @@ button {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.profile-buttons {
|
||||
display: flex;
|
||||
gap: $default-padding;
|
||||
}
|
||||
|
||||
.medium-sport-img {
|
||||
height: 35px;
|
||||
width: 35px;
|
||||
margin: 0 auto;
|
||||
}
|
@ -25,6 +25,7 @@ import {
|
||||
IUserPayload,
|
||||
IUserPicturePayload,
|
||||
IUserPreferencesPayload,
|
||||
IUserSportPreferencesPayload,
|
||||
} from '@/types/user'
|
||||
import { handleError } from '@/utils'
|
||||
|
||||
@ -172,6 +173,26 @@ export const actions: ActionTree<IAuthUserState, IRootState> &
|
||||
context.commit(AUTH_USER_STORE.MUTATIONS.UPDATE_USER_LOADING, false)
|
||||
)
|
||||
},
|
||||
[AUTH_USER_STORE.ACTIONS.UPDATE_USER_SPORT_PREFERENCES](
|
||||
context: ActionContext<IAuthUserState, IRootState>,
|
||||
payload: IUserSportPreferencesPayload
|
||||
): void {
|
||||
context.commit(ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGES)
|
||||
context.commit(AUTH_USER_STORE.MUTATIONS.UPDATE_USER_LOADING, true)
|
||||
authApi
|
||||
.post('auth/profile/edit/sports', payload)
|
||||
.then((res) => {
|
||||
if (res.data.status === 'success') {
|
||||
context.dispatch(SPORTS_STORE.ACTIONS.GET_SPORTS)
|
||||
} else {
|
||||
handleError(context, null)
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
handleError(context, error)
|
||||
context.commit(AUTH_USER_STORE.MUTATIONS.UPDATE_USER_LOADING, false)
|
||||
})
|
||||
},
|
||||
[AUTH_USER_STORE.ACTIONS.UPDATE_USER_PICTURE](
|
||||
context: ActionContext<IAuthUserState, IRootState>,
|
||||
payload: IUserPicturePayload
|
||||
|
@ -10,6 +10,7 @@ export enum AuthUserActions {
|
||||
UPDATE_USER_PICTURE = 'UPDATE_USER_PICTURE',
|
||||
UPDATE_USER_PROFILE = 'UPDATE_USER_PROFILE',
|
||||
UPDATE_USER_PREFERENCES = 'UPDATE_USER_PREFERENCES',
|
||||
UPDATE_USER_SPORT_PREFERENCES = 'UPDATE_USER_SPORT_PREFERENCES',
|
||||
}
|
||||
|
||||
export enum AuthUserGetters {
|
||||
|
@ -16,6 +16,7 @@ import {
|
||||
IUserPayload,
|
||||
IUserPicturePayload,
|
||||
IUserPreferencesPayload,
|
||||
IUserSportPreferencesPayload,
|
||||
} from '@/types/user'
|
||||
|
||||
export interface IAuthUserState {
|
||||
@ -52,6 +53,11 @@ export interface IAuthUserActions {
|
||||
payload: IUserPreferencesPayload
|
||||
): void
|
||||
|
||||
[AUTH_USER_STORE.ACTIONS.UPDATE_USER_SPORT_PREFERENCES](
|
||||
context: ActionContext<IAuthUserState, IRootState>,
|
||||
payload: IUserSportPreferencesPayload
|
||||
): void
|
||||
|
||||
[AUTH_USER_STORE.ACTIONS.UPDATE_USER_PICTURE](
|
||||
context: ActionContext<IAuthUserState, IRootState>,
|
||||
payload: IUserPicturePayload
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { ActionContext, ActionTree } from 'vuex'
|
||||
|
||||
import authApi from '@/api/authApi'
|
||||
import { ROOT_STORE, SPORTS_STORE } from '@/store/constants'
|
||||
import { AUTH_USER_STORE, ROOT_STORE, SPORTS_STORE } from '@/store/constants'
|
||||
import { IRootState } from '@/store/modules/root/types'
|
||||
import { ISportsActions, ISportsState } from '@/store/modules/sports/types'
|
||||
import { ISportPayload } from '@/types/sports'
|
||||
@ -20,6 +20,7 @@ export const actions: ActionTree<ISportsState, IRootState> & ISportsActions = {
|
||||
SPORTS_STORE.MUTATIONS.SET_SPORTS,
|
||||
res.data.data.sports
|
||||
)
|
||||
context.commit(AUTH_USER_STORE.MUTATIONS.UPDATE_USER_LOADING, false)
|
||||
} else {
|
||||
handleError(context, null)
|
||||
}
|
||||
|
@ -1,9 +1,12 @@
|
||||
export interface ISport {
|
||||
color: string | null
|
||||
has_workouts: boolean
|
||||
id: number
|
||||
img: string
|
||||
is_active: boolean
|
||||
is_active_for_user: boolean
|
||||
label: string
|
||||
stopped_speed_threshold: number
|
||||
}
|
||||
|
||||
export interface ITranslatedSport extends ISport {
|
||||
|
@ -45,6 +45,13 @@ export interface IUserPreferencesPayload {
|
||||
weekm: boolean
|
||||
}
|
||||
|
||||
export interface IUserSportPreferencesPayload {
|
||||
sport_id: number
|
||||
color: string | null
|
||||
is_active: boolean
|
||||
stopped_speed_threshold: number
|
||||
}
|
||||
|
||||
export interface IUserPicturePayload {
|
||||
picture: File
|
||||
}
|
||||
|
@ -27,8 +27,9 @@ export interface IRecord {
|
||||
}
|
||||
|
||||
export interface IRecordsBySport {
|
||||
[key: string]: string | Record<string, string | number>[]
|
||||
[key: string]: string | Record<string, string | number>[] | null
|
||||
label: string
|
||||
color: string | null
|
||||
records: Record<string, string | number>[]
|
||||
}
|
||||
|
||||
|
@ -44,6 +44,7 @@ export const getRecordsBySports = (
|
||||
if (sportList[sport.translatedLabel] === void 0) {
|
||||
sportList[sport.translatedLabel] = {
|
||||
label: sport.label,
|
||||
color: sport.color,
|
||||
records: [],
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ export const translateSports = (
|
||||
onlyActive = false
|
||||
): ITranslatedSport[] =>
|
||||
sports
|
||||
.filter((sport) => (onlyActive ? sport.is_active : true))
|
||||
.filter((sport) => (onlyActive ? sport.is_active_for_user : true))
|
||||
.map((sport) => ({
|
||||
...sport,
|
||||
translatedLabel: t(`sports.${sport.label}.LABEL`),
|
||||
@ -50,3 +50,12 @@ export const getSportLabel = (workout: IWorkout, sports: ISport[]): string => {
|
||||
.filter((sport) => sport.id === workout.sport_id)
|
||||
.map((sport) => sport.label)[0]
|
||||
}
|
||||
|
||||
export const getSportColor = (
|
||||
workout: IWorkout,
|
||||
sports: ISport[]
|
||||
): string | null => {
|
||||
return sports
|
||||
.filter((sport) => sport.id === workout.sport_id)
|
||||
.map((sport) => sport.color)[0]
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<div id="profile" class="container view" v-if="authUser.username">
|
||||
<router-view :user="authUser"></router-view>
|
||||
<div id="bottom" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -5,25 +5,34 @@ import { translateSports } from '@/utils/sports'
|
||||
const { t } = createI18n.global
|
||||
export const sports: ISport[] = [
|
||||
{
|
||||
color: null,
|
||||
has_workouts: false,
|
||||
id: 1,
|
||||
img: '/img/sports/cycling-sport.png',
|
||||
is_active: true,
|
||||
is_active_for_user: true,
|
||||
label: 'Cycling (Sport)',
|
||||
stopped_speed_threshold: 1,
|
||||
},
|
||||
{
|
||||
color: '#000000',
|
||||
has_workouts: false,
|
||||
id: 2,
|
||||
img: '/img/sports/cycling-transport.png',
|
||||
is_active: false,
|
||||
is_active_for_user: false,
|
||||
label: 'Cycling (Transport)',
|
||||
stopped_speed_threshold: 1,
|
||||
},
|
||||
{
|
||||
color: null,
|
||||
has_workouts: true,
|
||||
id: 3,
|
||||
img: '/img/sports/hiking.png',
|
||||
is_active: true,
|
||||
is_active_for_user: false,
|
||||
label: 'Hiking',
|
||||
stopped_speed_threshold: 0.1,
|
||||
},
|
||||
]
|
||||
|
||||
|
@ -157,6 +157,7 @@ describe('getRecordsBySports', () => {
|
||||
},
|
||||
expected: {
|
||||
'Cycling (Sport)': {
|
||||
color: null,
|
||||
label: 'Cycling (Sport)',
|
||||
records: [
|
||||
{
|
||||
@ -206,6 +207,7 @@ describe('getRecordsBySports', () => {
|
||||
},
|
||||
expected: {
|
||||
'Cycling (Sport)': {
|
||||
color: null,
|
||||
label: 'Cycling (Sport)',
|
||||
records: [
|
||||
{
|
||||
@ -225,6 +227,7 @@ describe('getRecordsBySports', () => {
|
||||
],
|
||||
},
|
||||
'Cycling (Transport)': {
|
||||
color: '#000000',
|
||||
label: 'Cycling (Transport)',
|
||||
records: [
|
||||
{
|
||||
|
@ -18,27 +18,36 @@ describe('sortSports', () => {
|
||||
},
|
||||
expected: [
|
||||
{
|
||||
color: null,
|
||||
has_workouts: false,
|
||||
id: 1,
|
||||
img: '/img/sports/cycling-sport.png',
|
||||
is_active: true,
|
||||
is_active_for_user: true,
|
||||
label: 'Cycling (Sport)',
|
||||
stopped_speed_threshold: 1,
|
||||
translatedLabel: 'Cycling (Sport)',
|
||||
},
|
||||
{
|
||||
color: '#000000',
|
||||
has_workouts: false,
|
||||
id: 2,
|
||||
img: '/img/sports/cycling-transport.png',
|
||||
is_active: false,
|
||||
is_active_for_user: false,
|
||||
label: 'Cycling (Transport)',
|
||||
stopped_speed_threshold: 1,
|
||||
translatedLabel: 'Cycling (Transport)',
|
||||
},
|
||||
{
|
||||
color: null,
|
||||
has_workouts: true,
|
||||
id: 3,
|
||||
img: '/img/sports/hiking.png',
|
||||
is_active: true,
|
||||
is_active_for_user: false,
|
||||
label: 'Hiking',
|
||||
stopped_speed_threshold: 0.1,
|
||||
translatedLabel: 'Hiking',
|
||||
},
|
||||
],
|
||||
@ -53,21 +62,16 @@ describe('sortSports', () => {
|
||||
},
|
||||
expected: [
|
||||
{
|
||||
color: null,
|
||||
has_workouts: false,
|
||||
id: 1,
|
||||
img: '/img/sports/cycling-sport.png',
|
||||
is_active: true,
|
||||
is_active_for_user: true,
|
||||
label: 'Cycling (Sport)',
|
||||
stopped_speed_threshold: 1,
|
||||
translatedLabel: 'Cycling (Sport)',
|
||||
},
|
||||
{
|
||||
has_workouts: true,
|
||||
id: 3,
|
||||
img: '/img/sports/hiking.png',
|
||||
is_active: true,
|
||||
label: 'Hiking',
|
||||
translatedLabel: 'Hiking',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
@ -88,27 +92,36 @@ describe('sortSports', () => {
|
||||
},
|
||||
expected: [
|
||||
{
|
||||
color: null,
|
||||
has_workouts: true,
|
||||
id: 3,
|
||||
img: '/img/sports/hiking.png',
|
||||
is_active: true,
|
||||
is_active_for_user: false,
|
||||
label: 'Hiking',
|
||||
stopped_speed_threshold: 0.1,
|
||||
translatedLabel: 'Randonnée',
|
||||
},
|
||||
{
|
||||
color: null,
|
||||
has_workouts: false,
|
||||
id: 1,
|
||||
img: '/img/sports/cycling-sport.png',
|
||||
is_active: true,
|
||||
is_active_for_user: true,
|
||||
label: 'Cycling (Sport)',
|
||||
stopped_speed_threshold: 1,
|
||||
translatedLabel: 'Vélo (Sport)',
|
||||
},
|
||||
{
|
||||
color: '#000000',
|
||||
has_workouts: false,
|
||||
id: 2,
|
||||
img: '/img/sports/cycling-transport.png',
|
||||
is_active: false,
|
||||
is_active_for_user: false,
|
||||
label: 'Cycling (Transport)',
|
||||
stopped_speed_threshold: 1,
|
||||
translatedLabel: 'Vélo (Transport)',
|
||||
},
|
||||
],
|
||||
@ -123,19 +136,14 @@ describe('sortSports', () => {
|
||||
},
|
||||
expected: [
|
||||
{
|
||||
has_workouts: true,
|
||||
id: 3,
|
||||
img: '/img/sports/hiking.png',
|
||||
is_active: true,
|
||||
label: 'Hiking',
|
||||
translatedLabel: 'Randonnée',
|
||||
},
|
||||
{
|
||||
color: null,
|
||||
has_workouts: false,
|
||||
id: 1,
|
||||
img: '/img/sports/cycling-sport.png',
|
||||
is_active: true,
|
||||
is_active_for_user: true,
|
||||
label: 'Cycling (Sport)',
|
||||
stopped_speed_threshold: 1,
|
||||
translatedLabel: 'Vélo (Sport)',
|
||||
},
|
||||
],
|
||||
|
Loading…
Reference in New Issue
Block a user