Skip to content

Commit

Permalink
refact: web: charts (#227)
Browse files Browse the repository at this point in the history
  • Loading branch information
crlssn authored Dec 15, 2024
1 parent 153d4cc commit 818c4ef
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 22 deletions.
9 changes: 9 additions & 0 deletions web/src/ui/components/AppCard.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<script setup lang="ts"></script>

<template>
<div class="bg-white border border-gray-200 mb-4 rounded-md">
<slot />
</div>
</template>

<style scoped></style>
17 changes: 10 additions & 7 deletions web/src/ui/components/AppList.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<script setup lang="ts">
import { vInfiniteScroll } from '@vueuse/components'
import { ArrowPathIcon } from '@heroicons/vue/24/outline'
import AppCard from '@/ui/components/AppCard.vue'
defineProps<{
canFetch?: boolean
Expand All @@ -14,17 +15,19 @@ const onFetch = async () => {
</script>

<template>
<ul role="list">
<slot />
<li v-if="canFetch" v-infinite-scroll="onFetch" class="fetching">
<ArrowPathIcon class="size-7 animate-spin" />
</li>
</ul>
<AppCard>
<ul role="list">
<slot />
<li v-if="canFetch" v-infinite-scroll="onFetch" class="fetching">
<ArrowPathIcon class="size-7 animate-spin" />
</li>
</ul>
</AppCard>
</template>

<style scoped>
ul {
@apply divide-y divide-gray-100 bg-white border border-gray-200 mb-4 rounded-md;
@apply divide-y divide-gray-100;
li.fetching {
@apply h-16 flex justify-center items-center text-gray-800;
Expand Down
8 changes: 3 additions & 5 deletions web/src/ui/components/CardWorkout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { deleteWorkout, postWorkoutComment } from '@/http/requests.ts'
import CardWorkoutComment from '@/ui/components/CardWorkoutComment.vue'
import CardWorkoutExercise from '@/ui/components/CardWorkoutExercise.vue'
import { type Workout, type WorkoutComment } from '@/proto/api/v1/workout_service_pb'
import AppCard from '@/ui/components/AppCard.vue'
const { input, textarea } = useTextareaAutosize()
const authStore = useAuthStore()
Expand Down Expand Up @@ -58,10 +59,7 @@ const formatComment = computed(() => {
</script>

<template>
<div
v-if="!workoutDeleted"
class="divide-y divide-gray-100 bg-white rounded-md border border-gray-200 mb-4"
>
<AppCard v-if="!workoutDeleted" class="divide-y divide-gray-100">
<div class="px-4 py-4">
<div class="flex items-center justify-between">
<div class="flex items-center">
Expand Down Expand Up @@ -112,5 +110,5 @@ const formatComment = computed(() => {
<AppButton type="submit" colour="primary"> Comment </AppButton>
</form>
</div>
</div>
</AppCard>
</template>
54 changes: 47 additions & 7 deletions web/src/ui/components/LineChart.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { formatToShortDateTime } from '@/utils/datetime.ts'
import {
CategoryScale,
Chart as ChartJS,
Filler,
Legend,
LinearScale,
LineElement,
Expand All @@ -15,20 +16,29 @@ import {
Tooltip,
} from 'chart.js'
ChartJS.register(Title, Tooltip, Legend, LineElement, CategoryScale, LinearScale, PointElement)
ChartJS.register(
Title,
Tooltip,
Legend,
LineElement,
CategoryScale,
LinearScale,
Filler,
PointElement,
)
const props = defineProps<{
sets: Set[]
}>()
const options = {
maintainAspectRatio: false,
maintainAspectRatio: true,
responsive: true,
scales: {
x: {
grid: {
display: false,
drawBorder: false,
drawBorder: true,
},
ticks: {
display: false,
Expand All @@ -43,7 +53,7 @@ const options = {
drawBorder: false,
},
ticks: {
display: false,
display: true,
},
title: {
display: false,
Expand All @@ -52,30 +62,60 @@ const options = {
},
}
const calc1RM = (weight: number, reps: number): number => {
if (reps === 1) {
return weight
}
return weight * (1 + reps / 30)
}
const sets = computed(() => [...props.sets].reverse())
const data = computed(() => {
const labels: string[] = []
const weights: number[] = []
const reps: number[] = []
const oneRM: number[] = []
sets.value.map((set) => {
labels.push(formatToShortDateTime(set.metadata?.createdAt))
weights.push(set.weight)
reps.push(set.reps)
oneRM.push(calc1RM(set.weight, set.reps))
})
return {
datasets: [
{
backgroundColor: '#000000',
borderColor: '#818cf8',
borderWidth: 1,
backgroundColor: '#818cf8',
data: reps,
label: 'Reps',
tension: 0.4,
pointRadius: 0,
fill: true,
},
{
borderColor: '#6366f1',
borderWidth: 1,
backgroundColor: '#6366f1',
data: weights,
label: 'Weight',
tension: 0.4,
pointRadius: 0,
fill: true,
},
{
borderColor: '#4f46e5',
borderWidth: 1,
backgroundColor: '#4f46e5',
data: reps,
label: 'Reps',
data: oneRM,
label: '1RM',
tension: 0.4,
pointRadius: 0,
fill: true,
},
],
labels: labels,
Expand Down
18 changes: 15 additions & 3 deletions web/src/ui/exercises/ViewExercise.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import AppListItemLink from '@/ui/components/AppListItemLink.vue'
import { deleteExercise, getExercise, listSets } from '@/http/requests'
import { ChevronRightIcon, TrashIcon } from '@heroicons/vue/24/outline'
import usePagination from '@/utils/usePagination'
import AppCard from '@/ui/components/AppCard.vue'
const sets = ref([] as Set[])
const exercise = ref<Exercise>()
Expand Down Expand Up @@ -49,6 +50,17 @@ const onDeleteExercise = async () => {
await router.push('/exercises')
}
}
const downSample = (data: Set[], sampleSize: number): Set[] => {
const sampled: Set[] = []
const step = Math.ceil(data.length / sampleSize)
for (let i = 0; i < data.length; i += step) {
sampled.push(data[i])
}
return sampled
}
</script>

<template>
Expand All @@ -62,9 +74,9 @@ const onDeleteExercise = async () => {
</div>

<h6>Chart</h6>
<div class="bg-white border border-gray-200 px-4 py-4 lg:rounded-md">
<LineChart :sets="sets" />
</div>
<AppCard class="p-2">
<LineChart :sets="downSample(sets, 50)" />
</AppCard>

<h6 class="mt-8">Sets</h6>
<AppList :can-fetch="hasMorePages" @fetch="fetchSets">
Expand Down

0 comments on commit 818c4ef

Please sign in to comment.