mirror of
https://github.com/joaovitoriasilva/endurain.git
synced 2026-01-09 07:47:58 -05:00
feat: change hr zone to bar chart
- return transform_activity_streams to get_public_activity_stream_by_type -
This commit is contained in:
@@ -313,7 +313,7 @@ def get_public_activity_stream_by_type(activity_id: int, stream_type: int, db: S
|
||||
return None
|
||||
|
||||
# Return the activity stream
|
||||
return activity_stream
|
||||
return transform_activity_streams(activity_stream, activity, db)
|
||||
except Exception as err:
|
||||
# Log the exception
|
||||
core_logger.print_to_log(
|
||||
|
||||
10
frontend/app/package-lock.json
generated
10
frontend/app/package-lock.json
generated
@@ -15,6 +15,7 @@
|
||||
"@fortawesome/vue-fontawesome": "^3.0.8",
|
||||
"bootstrap": "^5.3.3",
|
||||
"chart.js": "^4.4.6",
|
||||
"chartjs-plugin-datalabels": "^2.2.0",
|
||||
"flag-icons": "^7.2.3",
|
||||
"leaflet": "^1.9.4",
|
||||
"luxon": "^3.5.0",
|
||||
@@ -3864,6 +3865,15 @@
|
||||
"pnpm": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/chartjs-plugin-datalabels": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/chartjs-plugin-datalabels/-/chartjs-plugin-datalabels-2.2.0.tgz",
|
||||
"integrity": "sha512-14ZU30lH7n89oq+A4bWaJPnAG8a7ZTk7dKf48YAzMvJjQtjrgg5Dpk9f+LbjCF6bpx3RAGTeL13IXpKQYyRvlw==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"chart.js": ">=3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/check-error": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz",
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
"@fortawesome/vue-fontawesome": "^3.0.8",
|
||||
"bootstrap": "^5.3.3",
|
||||
"chart.js": "^4.4.6",
|
||||
"chartjs-plugin-datalabels": "^2.2.0",
|
||||
"flag-icons": "^7.2.3",
|
||||
"leaflet": "^1.9.4",
|
||||
"luxon": "^3.5.0",
|
||||
|
||||
@@ -200,10 +200,14 @@
|
||||
<br>
|
||||
<span>{{ $t("activitySummaryComponent.activityAvgHR") }}: {{ formatHr(activity.average_hr) }}</span> <br>
|
||||
<span>{{ $t("activitySummaryComponent.activityMaxHR") }}: {{ formatHr(activity.max_hr) }}</span> <br><br>
|
||||
<span v-for="(value, zone, index) in hrZones" :key="zone"
|
||||
:style="{ color: getZoneColor(index) }">
|
||||
{{ $t("activitySummaryComponent.activityHRZone") }} {{ index + 1 }} ({{ value.hr }}) : {{ value.percent }}%<br>
|
||||
</span>
|
||||
<BarChartComponent
|
||||
v-if="Object.values(hrZones).length > 0"
|
||||
:labels="getHrBarChartData().labels"
|
||||
:values="getHrBarChartData().values"
|
||||
:barColors="getHrBarChartData().barColors"
|
||||
:datalabelsFormatter="(value) => `${Math.round(value)}%`"
|
||||
:title="$t('activitySummaryComponent.activityHRZone')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -224,6 +228,7 @@ import LoadingComponent from "@/components/GeneralComponents/LoadingComponent.vu
|
||||
import UserAvatarComponent from "@/components/Users/UserAvatarComponent.vue";
|
||||
import EditActivityModalComponent from "@/components/Activities/Modals/EditActivityModalComponent.vue";
|
||||
import ModalComponent from "@/components/Modals/ModalComponent.vue";
|
||||
import BarChartComponent from '@/components/GeneralComponents/BarChartComponent.vue';
|
||||
// Importing the services
|
||||
import { users } from "@/services/usersService";
|
||||
import { activities } from "@/services/activitiesService";
|
||||
@@ -336,4 +341,14 @@ function getZoneColor(index) {
|
||||
];
|
||||
return colors[index] || '#000';
|
||||
}
|
||||
|
||||
function getHrBarChartData() {
|
||||
const zones = Object.values(hrZones.value);
|
||||
return {
|
||||
labels: zones.map((z, i) => `${t('activitySummaryComponent.activityHRZone')} ${i + 1} (${z.hr || ''})`),
|
||||
// values: zones.map(z => `${z.percent ?? 0}%`),
|
||||
values: zones.map(z => z.percent ?? 0),
|
||||
barColors: zones.map((_, i) => getZoneColor(i)),
|
||||
};
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,97 @@
|
||||
<template>
|
||||
<div>
|
||||
<canvas ref="barChartCanvas"></canvas>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, watch } from 'vue';
|
||||
import { Chart, registerables } from 'chart.js';
|
||||
import ChartDataLabels from 'chartjs-plugin-datalabels';
|
||||
|
||||
Chart.register(...registerables);
|
||||
|
||||
const props = defineProps({
|
||||
labels: {
|
||||
type: Array,
|
||||
required: true
|
||||
},
|
||||
values: {
|
||||
type: Array,
|
||||
required: true
|
||||
},
|
||||
barColors: {
|
||||
type: Array,
|
||||
default: () => ['#1e90ff', '#28a745', '#ffc107', '#fd7e14', '#dc3545']
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
datalabelsFormatter: {
|
||||
type: Function,
|
||||
default: null
|
||||
}
|
||||
});
|
||||
|
||||
const barChartCanvas = ref(null);
|
||||
let chartInstance = null;
|
||||
|
||||
function renderChart() {
|
||||
if (chartInstance) {
|
||||
chartInstance.destroy();
|
||||
}
|
||||
chartInstance = new Chart(barChartCanvas.value, {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: props.labels,
|
||||
datasets: [
|
||||
{
|
||||
label: props.title,
|
||||
data: props.values,
|
||||
backgroundColor: props.barColors,
|
||||
}
|
||||
]
|
||||
},
|
||||
options: {
|
||||
indexAxis: 'y',
|
||||
responsive: true,
|
||||
plugins: {
|
||||
legend: { display: false },
|
||||
title: {
|
||||
display: !!props.title,
|
||||
text: props.title
|
||||
},
|
||||
tooltip: { enabled: false },
|
||||
datalabels: {
|
||||
backgroundColor: function(context) {
|
||||
return "black";
|
||||
},
|
||||
borderRadius: 4,
|
||||
color: 'white',
|
||||
font: {
|
||||
weight: 'bold'
|
||||
},
|
||||
align: 'start', // Align datalabels to the start of the bar
|
||||
anchor: 'start', // Anchor datalabels to the start of the bar
|
||||
formatter: props.datalabelsFormatter || undefined,
|
||||
padding: 6
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
ticks: { stepSize: 10 }
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: [ChartDataLabels]
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
renderChart();
|
||||
});
|
||||
|
||||
watch(() => [props.labels, props.values, props.barColors, props.title], renderChart, { deep: true });
|
||||
</script>
|
||||
Reference in New Issue
Block a user