Client - update workout card on timeline and workout detail

This commit is contained in:
Sam 2021-09-27 15:34:36 +02:00
parent f8c0f89852
commit a7c268ca67
8 changed files with 148 additions and 28 deletions

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<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 512.002 512.002" style="enable-background:new 0 0 512.002 512.002;" xml:space="preserve">
<g>
<g>
<path fill="#2c3e50" opacity="0.1" d="M511.89,475.873l-29.997-165.398c-0.74-4.084-4.651-6.795-8.735-6.054c-4.084,0.74-6.793,4.652-6.053,8.735l12.683,69.933
l-97.782-113.58l65.766-14.678l9.738,5.421l4.228,23.316c0.74,4.084,4.651,6.793,8.735,6.054c4.084-0.74,6.793-4.652,6.054-8.735
l-4.864-26.814c-0.401-2.214-1.773-4.131-3.738-5.225l-15.343-8.541c0,0,0,0-0.001,0l-48.488-26.991h-0.001L366.68,192.49
c-0.001,0-0.002-0.001-0.002-0.001c-0.003-0.001-0.005-0.003-0.008-0.005c-0.289-0.16-0.585-0.298-0.888-0.417
c-0.095-0.037-0.192-0.062-0.289-0.095c-0.211-0.074-0.423-0.145-0.638-0.2c-0.122-0.031-0.245-0.049-0.369-0.073
c-0.193-0.038-0.387-0.076-0.582-0.099c-0.132-0.016-0.263-0.021-0.396-0.029c-0.189-0.012-0.378-0.022-0.567-0.02
c-0.135,0.001-0.269,0.011-0.404,0.019c-0.186,0.012-0.372,0.029-0.558,0.055c-0.135,0.019-0.27,0.043-0.404,0.07
c-0.182,0.036-0.362,0.078-0.542,0.127c-0.135,0.037-0.269,0.077-0.402,0.121c-0.174,0.059-0.346,0.126-0.517,0.198
c-0.132,0.056-0.263,0.111-0.394,0.175c-0.057,0.028-0.116,0.047-0.172,0.076l-17.168,8.949
c12.772-23.815,19.224-46.88,19.224-68.946c0-57.965-47.158-105.123-105.123-105.123S151.364,74.43,151.364,132.395
c0,22.28,6.572,45.579,19.594,69.64l-18.499-9.643c-0.057-0.03-0.118-0.05-0.176-0.078c-0.126-0.062-0.256-0.116-0.384-0.17
c-0.173-0.073-0.348-0.141-0.525-0.201c-0.131-0.044-0.264-0.083-0.397-0.12c-0.18-0.049-0.361-0.092-0.543-0.128
c-0.135-0.027-0.271-0.051-0.407-0.07c-0.183-0.026-0.367-0.042-0.551-0.054c-0.138-0.009-0.276-0.018-0.413-0.02
c-0.184-0.002-0.367,0.008-0.551,0.019c-0.138,0.009-0.276,0.014-0.414,0.031c-0.187,0.022-0.372,0.059-0.557,0.095
c-0.131,0.026-0.263,0.045-0.393,0.078c-0.205,0.052-0.406,0.121-0.607,0.19c-0.105,0.036-0.212,0.064-0.317,0.105
c-0.302,0.119-0.597,0.257-0.885,0.416c-0.003,0.001-0.005,0.003-0.008,0.005c-0.001,0-0.001,0.001-0.002,0.001L44.086,248.848
c-1.966,1.094-3.338,3.011-3.738,5.225L11.831,411.308c-0.74,4.083,1.97,7.995,6.054,8.735c4.085,0.743,7.995-1.97,8.735-6.054
l8.555-47.171l97.261-51.414l-7.822,100.994L17.457,464.513l3.771-20.8c0.74-4.083-1.969-7.994-6.053-8.735
c-4.081-0.738-7.994,1.97-8.735,6.054l-6.319,34.842c-0.498,2.744,0.566,5.539,2.762,7.258c1.347,1.054,2.982,1.597,4.632,1.597
c1.043,0,2.092-0.217,3.077-0.659l121.168-54.405l121.117,54.382c0.003,0.001,0.006,0.003,0.009,0.004l0.041,0.018
c0.068,0.031,0.139,0.052,0.209,0.081c0.111,0.046,0.223,0.089,0.337,0.13c0.109,0.039,0.219,0.078,0.331,0.112
c0.072,0.022,0.144,0.041,0.216,0.061c0.094,0.026,0.187,0.051,0.283,0.073c0.156,0.036,0.314,0.064,0.471,0.09
c0.075,0.012,0.149,0.03,0.225,0.04c0.051,0.007,0.102,0.014,0.153,0.02c0.251,0.029,0.505,0.044,0.757,0.047
c0.032,0,0.064,0.006,0.096,0.006c0.016,0,0.032-0.003,0.048-0.003c0.304-0.002,0.606-0.027,0.909-0.066
c0.037-0.005,0.075-0.003,0.113-0.009c0.057-0.008,0.113-0.027,0.171-0.036c0.235-0.039,0.47-0.09,0.702-0.153
c0.064-0.017,0.129-0.027,0.193-0.045c0.007-0.002,0.013-0.002,0.02-0.004c0.021-0.006,0.04-0.017,0.061-0.024
c0.292-0.09,0.579-0.193,0.862-0.32l121.164-54.405l121.167,54.404c0.117,0.052,0.237,0.091,0.357,0.137
c0.118,0.046,0.234,0.097,0.355,0.137c0.157,0.052,0.318,0.091,0.478,0.132c0.099,0.026,0.195,0.058,0.296,0.079
c0.193,0.042,0.388,0.069,0.583,0.096c0.07,0.009,0.138,0.025,0.208,0.033c0.267,0.029,0.534,0.044,0.801,0.044h0.001
c0.001,0,0.002,0,0.002,0c0.365,0,0.73-0.037,1.094-0.09c0.084-0.012,0.168-0.025,0.252-0.041
c0.359-0.065,0.715-0.149,1.067-0.269c0.022-0.008,0.044-0.019,0.066-0.026c0.232-0.081,0.463-0.17,0.689-0.277
c0.066-0.031,0.123-0.075,0.188-0.108c0.189-0.095,0.371-0.204,0.553-0.317c0.182-0.111,0.363-0.223,0.534-0.35
c0.059-0.044,0.125-0.075,0.184-0.12c0.132-0.103,0.247-0.222,0.371-0.334c0.099-0.089,0.202-0.173,0.297-0.266
c0.228-0.225,0.436-0.465,0.629-0.714c0.036-0.047,0.079-0.088,0.115-0.136c0.224-0.304,0.422-0.623,0.597-0.955
c0.049-0.093,0.086-0.192,0.132-0.288c0.116-0.244,0.223-0.49,0.313-0.745c0.045-0.128,0.081-0.258,0.119-0.39
c0.068-0.234,0.125-0.471,0.17-0.712c0.026-0.138,0.05-0.277,0.068-0.417c0.033-0.255,0.048-0.514,0.055-0.773
c0.003-0.123,0.013-0.245,0.01-0.37C511.993,476.646,511.961,476.259,511.89,475.873z M379.797,216.992l-7.704,1.802l-0.493-6.365
L379.797,216.992z M363.403,301.218l-31.384-24.505c-2.172-1.695-5.096-2.067-7.624-0.968l-60.844,26.482v-8.235
c4.546-3.703,14.875-12.433,27.255-24.962l67.797-29.784L363.403,301.218z M356.413,210.978l0.96,12.392l-42.353,18.607
c4.205-5.213,8.126-10.398,11.765-15.555L356.413,210.978z M155.598,210.978l31.15,16.238c4.613,6.487,9.666,13.021,15.173,19.598
c4.815,5.75,9.614,11.093,14.231,15.984l-63.86-9.138L155.598,210.978z M133.808,297.678l-95.224,50.336l4.638-25.574l0.119-0.659
l92.37-48.681L133.808,297.678z M137.084,255.388l-90.335,47.609l7.752-42.744l85.91-47.823l-2.159,27.881L137.084,255.388z
M139.662,416.737l7.115-91.869l88.77,134.922L139.662,416.737z M248.49,387.773l-46.293-72.958l46.293,5.543V387.773z
M248.49,305.22l-60.229-7.211c-2.879-0.339-5.704,1-7.251,3.456c-1.547,2.455-1.542,5.581,0.013,8.033l67.467,106.328v36.294
l-99.819-151.715l2.458-31.728l82.913,11.864c6.253,5.803,11.322,10.112,14.447,12.685V305.22z M256.487,280.303
c-18.977-16.005-90.093-80.494-90.093-147.907c-0.001-49.678,40.415-90.094,90.093-90.094s90.094,40.416,90.094,90.094
C346.581,199.809,275.464,264.299,256.487,280.303z M263.52,465.602v-33.357l22.466,23.269L263.52,465.602z M300.56,448.97
l-37.04-38.364v-91.976l62.772-27.32l38.681,30.203l7.375,95.224L300.56,448.97z M373.266,233.953l26.055-6.093l18.478,10.286
l10.224,5.692l-53.075,11.845L373.266,233.953z M387.397,416.398l-5.867-75.75l96.54,116.464L387.397,416.398z M379.519,314.671
l-2.042-26.37l-0.086-1.117l107.69,125.09l6.905,38.073L379.519,314.671z"/>
</g>
</g>
<g>
<g>
<path fill="#2c3e50" opacity="0.1" d="M256.487,85.95c-4.15,0-7.515,3.364-7.515,7.515s3.365,7.515,7.515,7.515c17.323,0,31.416,14.093,31.416,31.416
c0,17.322-14.093,31.416-31.416,31.416s-31.416-14.093-31.416-31.416c0-8.287,3.198-16.106,9.006-22.018
c2.909-2.96,2.867-7.718-0.094-10.626c-2.961-2.909-7.719-2.868-10.627,0.094c-8.586,8.739-13.314,20.299-13.314,32.55
c0,25.61,20.835,46.446,46.446,46.446s46.446-20.836,46.446-46.446C302.933,106.785,282.098,85.95,256.487,85.95z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

Before

Width:  |  Height:  |  Size: 888 B

After

Width:  |  Height:  |  Size: 888 B

View File

@ -3,9 +3,7 @@
<div <div
class="bg-map-image" class="bg-map-image"
:style="{ :style="{
backgroundImage: `url(${getApiUrl()}workouts/map/${ backgroundImage: `url(${getApiUrl()}workouts/map/${workout.map})`,
workout.map
}?${Date.now()})`,
}" }"
/> />
<div class="map-attribution"> <div class="map-attribution">

View File

@ -13,10 +13,13 @@
<div v-else class="no-picture"> <div v-else class="no-picture">
<i class="fa fa-user-circle-o" aria-hidden="true" /> <i class="fa fa-user-circle-o" aria-hidden="true" />
</div> </div>
<span class="workout-user-name">{{ user.username }}</span> <span v-if="user.username" class="workout-user-name">
{{ user.username }}
</span>
</div> </div>
<div <div
class="workout-date" class="workout-date"
v-if="workout && user"
:title=" :title="
format( format(
getDateWithTZ(workout.workout_date, user.timezone), getDateWithTZ(workout.workout_date, user.timezone),
@ -34,12 +37,22 @@
</div> </div>
<div <div
class="workout-map" class="workout-map"
v-if="workout.with_gpx" :class="{ 'no-cursor': !workout }"
@click=" @click="
$router.push({ name: 'Workout', params: { workoutId: workout.id } }) workout
? $router.push({
name: 'Workout',
params: { workoutId: workout.id },
})
: null
" "
> >
<StaticMap :workout="workout"></StaticMap> <div v-if="workout">
<StaticMap v-if="workout.with_gpx" :workout="workout" />
<div v-else class="no-map">
{{ t('workouts.NO_MAP') }}
</div>
</div>
</div> </div>
<div <div
class="workout-data" class="workout-data"
@ -48,15 +61,20 @@
" "
> >
<div> <div>
<img class="sport-img" alt="workout sport logo" :src="sport.img" /> <img
v-if="sport"
class="sport-img"
alt="workout sport logo"
:src="sport.img"
/>
</div> </div>
<div> <div>
<i class="fa fa-clock-o" aria-hidden="true" /> <i class="fa fa-clock-o" aria-hidden="true" />
{{ workout.moving }} <span v-if="workout">{{ workout.moving }}</span>
</div> </div>
<div> <div>
<i class="fa fa-road" aria-hidden="true" /> <i class="fa fa-road" aria-hidden="true" />
{{ workout.distance }} km <span v-if="workout">{{ workout.distance }} km</span>
</div> </div>
</div> </div>
</template> </template>
@ -88,7 +106,7 @@
props: { props: {
workout: { workout: {
type: Object as PropType<IWorkout>, type: Object as PropType<IWorkout>,
required: true, required: false,
}, },
user: { user: {
type: Object as PropType<IAuthUserProfile>, type: Object as PropType<IAuthUserProfile>,
@ -96,12 +114,13 @@
}, },
sport: { sport: {
type: Object as PropType<ISport>, type: Object as PropType<ISport>,
required: true, required: false,
}, },
}, },
setup(props) { setup(props) {
const { t } = useI18n() const { t } = useI18n()
const store = useStore() const store = useStore()
const userPictureUrl: ComputedRef<string> = computed(() => const userPictureUrl: ComputedRef<string> = computed(() =>
props.user.picture props.user.picture
? `${getApiUrl()}/users/${props.user.username}/picture?${Date.now()}` ? `${getApiUrl()}/users/${props.user.username}/picture?${Date.now()}`
@ -157,6 +176,18 @@
font-style: italic; font-style: italic;
} }
} }
.workout-map {
background-color: var(--workout-no-map-bg-color);
height: 150px;
.no-map {
line-height: 150px;
}
.bg-map-image {
height: 150px;
}
}
.workout-data { .workout-data {
display: flex; display: flex;
padding-top: $default-padding * 0.5; padding-top: $default-padding * 0.5;
@ -173,6 +204,12 @@
.workout-data { .workout-data {
cursor: pointer; cursor: pointer;
} }
.no-cursor {
cursor: default;
}
.fa {
padding-right: $default-padding;
}
} }
} }
} }

View File

@ -2,12 +2,16 @@
<div class="timeline"> <div class="timeline">
<div class="section-title">{{ t('workouts.LATEST_WORKOUTS') }}</div> <div class="section-title">{{ t('workouts.LATEST_WORKOUTS') }}</div>
<WorkoutCard <WorkoutCard
v-for="workout in workouts" v-for="index in [...Array(displayedWorkoutsCount).keys()]"
:workout="workout" :workout="workouts.length > 0 ? workouts[index] : null"
:sport="sports.filter((s) => s.id === workout.sport_id)[0]" :sport="
workouts.length > 0
? sports.filter((s) => s.id === workouts[index].sport_id)[0]
: null
"
:user="user" :user="user"
:key="workout.id" :key="index"
></WorkoutCard> />
<div v-if="workouts.length === 0" class="no-workouts"> <div v-if="workouts.length === 0" class="no-workouts">
{{ t('workouts.NO_WORKOUTS') }} {{ t('workouts.NO_WORKOUTS') }}
</div> </div>
@ -16,11 +20,11 @@
<script lang="ts"> <script lang="ts">
import { import {
computed,
ComputedRef, ComputedRef,
PropType,
computed,
defineComponent, defineComponent,
onBeforeMount, onBeforeMount,
PropType,
} from 'vue' } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
@ -46,19 +50,25 @@
required: true, required: true,
}, },
}, },
setup() { setup(props) {
const store = useStore() const store = useStore()
const { t } = useI18n() const { t } = useI18n()
const per_page = 5
const displayedWorkoutsCount =
props.user.nb_workouts >= per_page ? per_page : props.user.nb_workouts
onBeforeMount(() => onBeforeMount(() =>
store.dispatch(WORKOUTS_STORE.ACTIONS.GET_USER_WORKOUTS, { page: 1 }) store.dispatch(WORKOUTS_STORE.ACTIONS.GET_USER_WORKOUTS, {
page: 1,
per_page,
})
) )
const workouts: ComputedRef<IWorkout[]> = computed( const workouts: ComputedRef<IWorkout[]> = computed(
() => store.getters[WORKOUTS_STORE.GETTERS.USER_WORKOUTS] () => store.getters[WORKOUTS_STORE.GETTERS.USER_WORKOUTS]
) )
return { workouts, t } return { displayedWorkoutsCount, per_page, workouts, t }
}, },
}) })
</script> </script>

View File

@ -28,7 +28,7 @@
class="workout-data" class="workout-data"
v-if="workoutObject.maxAlt !== null && workoutObject.minAlt !== null" v-if="workoutObject.maxAlt !== null && workoutObject.minAlt !== null"
> >
<img class="mountains" src="/img/misc/mountains.svg" /> <img class="mountains" src="/img/workouts/mountains.svg" />
{{ t('workouts.MIN_ALTITUDE') }}: <span>{{ workoutObject.minAlt }} m</span {{ t('workouts.MIN_ALTITUDE') }}: <span>{{ workoutObject.minAlt }} m</span
><br /> ><br />
{{ t('workouts.MAX_ALTITUDE') }}: {{ t('workouts.MAX_ALTITUDE') }}:

View File

@ -138,12 +138,7 @@
width: 600px; width: 600px;
} }
.no-map { .no-map {
text-align: center;
vertical-align: center;
font-style: italic;
line-height: 400px; line-height: 400px;
color: var(--workout-no-map-color);
background-color: var(--workout-no-map-bg-color);
} }
@media screen and (max-width: $small-limit) { @media screen and (max-width: $small-limit) {

View File

@ -101,3 +101,16 @@ button {
padding-left: $default-padding; padding-left: $default-padding;
text-transform: capitalize; text-transform: capitalize;
} }
.no-map {
background-color: var(--workout-no-map-bg-color);
background-image: url('/img/workouts/map.svg');
background-size: contain;
background-repeat: no-repeat;
background-position: center;
color: var(--workout-no-map-color);
font-style: italic;
font-weight: bold;
text-align: center;
vertical-align: center;
}