trainUs/src/composables/useStats.js
David 352a3d5e88
Some checks are pending
CI / Lint & Format (push) Waiting to run
CI / Build (push) Waiting to run
CI / Tests (${{ matrix.browser }}) (chromium) (push) Waiting to run
CI / Tests (${{ matrix.browser }}) (firefox) (push) Waiting to run
Initial commit
2026-06-18 13:06:57 +02:00

112 lines
3 KiB
JavaScript

import { ref, watch } from 'vue'
import { executionLogRepository } from '../db/repositories/executionLogRepository.js'
export function useStats() {
const dateRange = ref('30d')
const frequencyGroupBy = ref('week')
const selectedExerciseId = ref('')
const totalSessions = ref(0)
const totalExercises = ref(0)
const streak = ref(0)
const loggedExercises = ref([])
const frequencyRaw = ref([])
const volumeRaw = ref([])
const progressionRaw = ref([])
const loading = ref(false)
function getSinceDate(range) {
if (range === 'all') return null
const d = new Date()
d.setHours(0, 0, 0, 0)
if (range === '7d') d.setDate(d.getDate() - 7)
else if (range === '30d') d.setDate(d.getDate() - 30)
else if (range === '3m') d.setMonth(d.getMonth() - 3)
return d.toISOString()
}
function computeStreak(days) {
if (!days.length) return 0
// Use UTC midnight to match SQLite DATE() which extracts UTC dates
const daySet = new Set(days.map((r) => r.day))
const cur = new Date()
cur.setUTCHours(0, 0, 0, 0)
let count = 0
while (true) {
const dateStr = cur.toISOString().slice(0, 10)
if (daySet.has(dateStr)) {
count++
cur.setUTCDate(cur.getUTCDate() - 1)
} else {
break
}
}
return count
}
async function loadFrequency() {
const since = getSinceDate(dateRange.value)
frequencyRaw.value = await executionLogRepository.getFrequencyData(
since,
frequencyGroupBy.value,
)
}
async function loadProgression() {
if (!selectedExerciseId.value) {
progressionRaw.value = []
return
}
const since = getSinceDate(dateRange.value)
progressionRaw.value = await executionLogRepository.getProgressionData(
selectedExerciseId.value,
since,
)
}
async function loadAll() {
loading.value = true
try {
const since = getSinceDate(dateRange.value)
const [sessions, exercises, days, frequency, volume, logged] = await Promise.all([
executionLogRepository.getTotalSessionsSince(since),
executionLogRepository.getTotalExercisesDone(since),
executionLogRepository.getDistinctSessionDays(),
executionLogRepository.getFrequencyData(since, frequencyGroupBy.value),
executionLogRepository.getVolumeData(since),
executionLogRepository.getLoggedExercises(),
])
totalSessions.value = sessions
totalExercises.value = exercises
streak.value = computeStreak(days)
frequencyRaw.value = frequency
volumeRaw.value = volume
loggedExercises.value = logged
await loadProgression()
} finally {
loading.value = false
}
}
watch(dateRange, loadAll)
watch(frequencyGroupBy, loadFrequency)
watch(selectedExerciseId, loadProgression)
return {
dateRange,
frequencyGroupBy,
selectedExerciseId,
totalSessions,
totalExercises,
streak,
loggedExercises,
frequencyRaw,
volumeRaw,
progressionRaw,
loading,
loadAll,
loadProgression,
getSinceDate,
}
}