Client - minor refactoring
This commit is contained in:
68
fittrackee_client/src/views/workouts/EditWorkout.vue
Normal file
68
fittrackee_client/src/views/workouts/EditWorkout.vue
Normal file
@ -0,0 +1,68 @@
|
||||
<template>
|
||||
<div id="edit-workout">
|
||||
<div class="container">
|
||||
<WorkoutEdition
|
||||
:authUser="authUser"
|
||||
:sports="sports"
|
||||
:workout="workoutData.workout"
|
||||
:loading="workoutData.loading"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import {
|
||||
computed,
|
||||
defineComponent,
|
||||
watch,
|
||||
onBeforeMount,
|
||||
ComputedRef,
|
||||
} from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
import WorkoutEdition from '@/components/Workout/WorkoutEdition.vue'
|
||||
import { SPORTS_STORE, USER_STORE, WORKOUTS_STORE } from '@/store/constants'
|
||||
import { ISport } from '@/types/sports'
|
||||
import { IAuthUserProfile } from '@/types/user'
|
||||
import { IWorkoutData } from '@/types/workouts'
|
||||
import { useStore } from '@/use/useStore'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'EditWorkout',
|
||||
components: {
|
||||
WorkoutEdition,
|
||||
},
|
||||
setup() {
|
||||
const route = useRoute()
|
||||
const store = useStore()
|
||||
|
||||
onBeforeMount(() => {
|
||||
store.dispatch(WORKOUTS_STORE.ACTIONS.GET_WORKOUT_DATA, {
|
||||
workoutId: route.params.workoutId,
|
||||
})
|
||||
})
|
||||
|
||||
const authUser: ComputedRef<IAuthUserProfile> = computed(
|
||||
() => store.getters[USER_STORE.GETTERS.AUTH_USER_PROFILE]
|
||||
)
|
||||
const sports: ComputedRef<ISport[]> = computed(
|
||||
() => store.getters[SPORTS_STORE.GETTERS.SPORTS]
|
||||
)
|
||||
const workoutData: ComputedRef<IWorkoutData> = computed(
|
||||
() => store.getters[WORKOUTS_STORE.GETTERS.WORKOUT_DATA]
|
||||
)
|
||||
|
||||
watch(
|
||||
() => route.params.workoutId,
|
||||
async (newWorkoutId) => {
|
||||
if (!newWorkoutId) {
|
||||
store.commit(WORKOUTS_STORE.MUTATIONS.EMPTY_WORKOUT)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
return { authUser, sports, workoutData }
|
||||
},
|
||||
})
|
||||
</script>
|
174
fittrackee_client/src/views/workouts/Workout.vue
Normal file
174
fittrackee_client/src/views/workouts/Workout.vue
Normal file
@ -0,0 +1,174 @@
|
||||
<template>
|
||||
<div id="workout">
|
||||
<div class="container">
|
||||
<div class="workout-container" v-if="sports.length > 0">
|
||||
<div v-if="workoutData.workout.id">
|
||||
<WorkoutDetail
|
||||
:workoutData="workoutData"
|
||||
:sports="sports"
|
||||
:authUser="authUser"
|
||||
:markerCoordinates="markerCoordinates"
|
||||
:displaySegment="displaySegment"
|
||||
/>
|
||||
<WorkoutChart
|
||||
v-if="
|
||||
workoutData.workout.with_gpx && workoutData.chartData.length > 0
|
||||
"
|
||||
:workoutData="workoutData"
|
||||
:authUser="authUser"
|
||||
:displaySegment="displaySegment"
|
||||
@getCoordinates="updateCoordinates"
|
||||
/>
|
||||
<WorkoutSegments
|
||||
v-if="!displaySegment && workoutData.workout.segments.length > 1"
|
||||
:segments="workoutData.workout.segments"
|
||||
/>
|
||||
<WorkoutNotes
|
||||
v-if="!displaySegment"
|
||||
:notes="workoutData.workout.notes"
|
||||
/>
|
||||
<div id="bottom" />
|
||||
</div>
|
||||
<div v-else>
|
||||
<NotFound v-if="!workoutData.loading" target="WORKOUT" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import {
|
||||
ComputedRef,
|
||||
Ref,
|
||||
computed,
|
||||
defineComponent,
|
||||
ref,
|
||||
watch,
|
||||
onBeforeMount,
|
||||
onUnmounted,
|
||||
} from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
import NotFound from '@/components/Common/NotFound.vue'
|
||||
import WorkoutChart from '@/components/Workout/WorkoutChart.vue'
|
||||
import WorkoutDetail from '@/components/Workout/WorkoutDetail/index.vue'
|
||||
import WorkoutNotes from '@/components/Workout/WorkoutNotes.vue'
|
||||
import WorkoutSegments from '@/components/Workout/WorkoutSegments.vue'
|
||||
import { SPORTS_STORE, USER_STORE, WORKOUTS_STORE } from '@/store/constants'
|
||||
import { ISport } from '@/types/sports'
|
||||
import { IAuthUserProfile } from '@/types/user'
|
||||
import { IWorkoutData, IWorkoutPayload, TCoordinates } from '@/types/workouts'
|
||||
import { useStore } from '@/use/useStore'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Workout',
|
||||
components: {
|
||||
NotFound,
|
||||
WorkoutChart,
|
||||
WorkoutDetail,
|
||||
WorkoutNotes,
|
||||
WorkoutSegments,
|
||||
},
|
||||
props: {
|
||||
displaySegment: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const route = useRoute()
|
||||
const store = useStore()
|
||||
|
||||
onBeforeMount(() => {
|
||||
const payload: IWorkoutPayload = { workoutId: route.params.workoutId }
|
||||
if (props.displaySegment) {
|
||||
payload.segmentId = route.params.segmentId
|
||||
}
|
||||
store.dispatch(WORKOUTS_STORE.ACTIONS.GET_WORKOUT_DATA, payload)
|
||||
})
|
||||
|
||||
const workoutData: ComputedRef<IWorkoutData> = computed(
|
||||
() => store.getters[WORKOUTS_STORE.GETTERS.WORKOUT_DATA]
|
||||
)
|
||||
const authUser: ComputedRef<IAuthUserProfile> = computed(
|
||||
() => store.getters[USER_STORE.GETTERS.AUTH_USER_PROFILE]
|
||||
)
|
||||
const sports: ComputedRef<ISport[]> = computed(
|
||||
() => store.getters[SPORTS_STORE.GETTERS.SPORTS]
|
||||
)
|
||||
let markerCoordinates: Ref<TCoordinates> = ref({
|
||||
latitude: null,
|
||||
longitude: null,
|
||||
})
|
||||
|
||||
function updateCoordinates(coordinates: TCoordinates) {
|
||||
markerCoordinates.value = {
|
||||
latitude: coordinates.latitude,
|
||||
longitude: coordinates.longitude,
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => route.params.workoutId,
|
||||
async (newWorkoutId) => {
|
||||
if (newWorkoutId) {
|
||||
store.dispatch(WORKOUTS_STORE.ACTIONS.GET_WORKOUT_DATA, {
|
||||
workoutId: newWorkoutId,
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
watch(
|
||||
() => route.params.segmentId,
|
||||
async (newSegmentId) => {
|
||||
if (route.params.workoutId) {
|
||||
const payload: IWorkoutPayload = {
|
||||
workoutId: route.params.workoutId,
|
||||
}
|
||||
if (newSegmentId) {
|
||||
payload.segmentId = newSegmentId
|
||||
}
|
||||
store.dispatch(WORKOUTS_STORE.ACTIONS.GET_WORKOUT_DATA, payload)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
onUnmounted(() => {
|
||||
store.commit(WORKOUTS_STORE.MUTATIONS.EMPTY_WORKOUT)
|
||||
})
|
||||
|
||||
return {
|
||||
authUser,
|
||||
markerCoordinates,
|
||||
sports,
|
||||
workoutData,
|
||||
updateCoordinates,
|
||||
}
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '~@/scss/base';
|
||||
#workout {
|
||||
display: flex;
|
||||
margin-bottom: 45px;
|
||||
.container {
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
.workout-container {
|
||||
width: 100%;
|
||||
}
|
||||
.workout-loading {
|
||||
height: $app-height;
|
||||
width: 100%;
|
||||
.loading {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
91
fittrackee_client/src/views/workouts/WorkoutsView.vue
Normal file
91
fittrackee_client/src/views/workouts/WorkoutsView.vue
Normal file
@ -0,0 +1,91 @@
|
||||
<template>
|
||||
<div id="workouts" v-if="authUser.username">
|
||||
<div class="container workouts-container">
|
||||
<div class="filters-container">
|
||||
<WorkoutsFilters :sports="translatedSports" @filter="updateParams" />
|
||||
</div>
|
||||
<div class="list-container">
|
||||
<WorkoutsList
|
||||
:user="authUser"
|
||||
:params="params"
|
||||
:sports="translatedSports"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { ComputedRef, Ref, computed, defineComponent, ref } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import WorkoutsFilters from '@/components/Workouts/WorkoutsFilters.vue'
|
||||
import WorkoutsList from '@/components/Workouts/WorkoutsList.vue'
|
||||
import { USER_STORE, SPORTS_STORE } from '@/store/constants'
|
||||
import { ISport, ITranslatedSport } from '@/types/sports'
|
||||
import { IAuthUserProfile } from '@/types/user'
|
||||
import { useStore } from '@/use/useStore'
|
||||
import { translateSports } from '@/utils/sports'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'WorkoutsView',
|
||||
components: {
|
||||
WorkoutsFilters,
|
||||
WorkoutsList,
|
||||
},
|
||||
setup() {
|
||||
const { t } = useI18n()
|
||||
const store = useStore()
|
||||
const authUser: ComputedRef<IAuthUserProfile> = computed(
|
||||
() => store.getters[USER_STORE.GETTERS.AUTH_USER_PROFILE]
|
||||
)
|
||||
const sports: ComputedRef<ISport[]> = computed(
|
||||
() => store.getters[SPORTS_STORE.GETTERS.SPORTS]
|
||||
)
|
||||
const translatedSports: ComputedRef<ITranslatedSport[]> = computed(() =>
|
||||
translateSports(sports.value, t)
|
||||
)
|
||||
const params: Ref<Record<string, string>> = ref({})
|
||||
|
||||
function updateParams(filters: Record<string, string>) {
|
||||
params.value = filters
|
||||
}
|
||||
return { authUser, params, translatedSports, updateParams }
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '~@/scss/base';
|
||||
#workouts {
|
||||
height: 100%;
|
||||
|
||||
.workouts-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
@media screen and (max-width: $medium-limit) {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.filters-container,
|
||||
.list-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.filters-container {
|
||||
width: 25%;
|
||||
@media screen and (max-width: $medium-limit) {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.list-container {
|
||||
width: 75%;
|
||||
@media screen and (max-width: $medium-limit) {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
Reference in New Issue
Block a user