gym-nuxt3/components/ExerciseChart.vue

130 lines
3.3 KiB
Vue

<script setup>
import Chart from 'chart.js/auto'
const props = defineProps({
muscle: {
type: String,
required: true,
},
exercise: {
type: String,
required: true,
},
fromDate: {
type: String,
required: true,
},
toDate: {
type: String,
required: true,
},
})
const weightInput = useWeightInputStore()
// Convert fromDate and toDate to Date objects
const fromDate = computed(() => new Date(props.fromDate))
const toDate = computed(() => new Date(props.toDate))
// Retrieve exercise data based on the date range
const exerciseData = weightInput.exercises
// Filter the exercise data within the specified date range
const filteredData = computed(() =>
Object.entries(exerciseData)
.filter(([date]) => {
const currentDate = new Date(date)
return currentDate >= fromDate.value && currentDate <= toDate.value
})
.map(([, muscleData]) => muscleData[props.muscle]?.[props.exercise])
.filter(Boolean),
)
// Prepare the chart data
const chartData = computed(() =>
filteredData.value.map((exercise, index) => {
const date = new Date(Object.keys(exerciseData)[index])
const formattedDate = `${date.getMonth() + 1}/${date.getDate()}`
const maxWarmUpSetWeight = Math.max(
...exercise.warmUpSet.map(set => set.warmSetWeight),
)
const maxWorkingSetWeight = Math.max(
...exercise.workingSet.map(set => set.workingSetWeight),
)
return {
date: formattedDate,
warmUpSet: isNaN(maxWarmUpSetWeight) ? 0 : maxWarmUpSetWeight,
workingSet: isNaN(maxWorkingSetWeight) ? 0 : maxWorkingSetWeight,
}
}),
)
const labels = computed(() => chartData.value.map(data => data.date))
const warmUpSetWeights = computed(() => chartData.value.map(data => data.warmUpSet))
const workingSetWeights = computed(() => chartData.value.map(data => data.workingSet))
const chartOptions = computed(() => ({
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: true,
suggestedMax: Math.max(
Math.max(...warmUpSetWeights.value),
Math.max(...workingSetWeights.value),
),
},
},
}))
const chartConfig = computed(() => ({
type: 'line',
data: {
labels: labels.value,
datasets: [
{
label: 'Warm-Up Sets',
data: warmUpSetWeights.value,
fill: false,
borderColor: 'rgba(75, 192, 192, 1)',
},
{
label: 'Working Sets',
data: workingSetWeights.value,
fill: false,
borderColor: 'rgba(192, 75, 192, 1)',
},
],
},
options: chartOptions.value,
}))
const exerciseChart = ref(null)
let chartInstance = null
onMounted(() => {
const ctx = exerciseChart.value.getContext('2d')
chartInstance = new Chart(ctx, chartConfig.value)
})
watch([filteredData, chartOptions], () => {
if (chartInstance) {
chartInstance.data.labels = labels.value
chartInstance.data.datasets[0].data = warmUpSetWeights.value
chartInstance.data.datasets[1].data = workingSetWeights.value
chartInstance.options.scales.y.suggestedMax = Math.max(
Math.max(...warmUpSetWeights.value),
Math.max(...workingSetWeights.value),
)
chartInstance.update()
}
})
</script>
<template>
<div>
<canvas ref="exerciseChart" :style="{ height: '400px', width: '600px' }" />
</div>
</template>