112 lines
3 KiB
JavaScript
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,
|
|
}
|
|
}
|