Files
chrono-snap/src/store/dashboardStore.ts
Julian Freeman 06fb78edab fix bugs
2026-03-26 14:46:18 -04:00

94 lines
3.4 KiB
TypeScript

import { ref, computed, watch } from "vue";
import { invoke } from "@tauri-apps/api/core";
import { DBEvent } from "../types";
import { currentDate, getTagColor, getTagName, formatMinutes, parseISODate, toISODate, viewMode, refreshSignal } from "./index";
// Re-export for easier access in Dashboard component
export { getTagColor, getTagName, formatMinutes };
export const dashboardRange = ref<'today' | '7days' | '30days'>('today');
export const dashboardStartDate = ref(currentDate.value);
export const dashboardEndDate = ref(currentDate.value);
export const dashboardEvents = ref<DBEvent[]>([]);
export const dailyAverageMode = ref<'natural' | 'recorded'>('natural');
export const loadDashboardEvents = async () => {
dashboardEvents.value = await invoke("get_events_range", { startDate: dashboardStartDate.value, endDate: dashboardEndDate.value });
};
watch([dashboardRange, currentDate], () => {
const end = parseISODate(currentDate.value);
let start = parseISODate(currentDate.value);
if (dashboardRange.value === '7days') {
start.setDate(end.getDate() - 6);
} else if (dashboardRange.value === '30days') {
start.setDate(end.getDate() - 29);
}
dashboardStartDate.value = toISODate(start);
dashboardEndDate.value = toISODate(end);
loadDashboardEvents();
}, { immediate: true });
// Auto-refresh dashboard when a refresh signal is received (event added/deleted)
watch(refreshSignal, () => {
if (viewMode.value === 'dashboard') {
loadDashboardEvents();
}
});
// Refresh when switching to dashboard mode to catch updates that happened in preview mode
watch(viewMode, (mode) => {
if (mode === 'dashboard') {
loadDashboardEvents();
}
});
export const dashboardStats = computed(() => {
let totalMinutes = 0;
const mainTagMap = new Map<number, { total: number, subTags: Map<number, number> }>();
const uniqueDays = new Set<string>();
dashboardEvents.value.forEach(ev => {
const diff = Math.max(0, ev.end_minute - ev.start_minute);
totalMinutes += diff;
uniqueDays.add(ev.date);
if (!mainTagMap.has(ev.main_tag_id)) {
mainTagMap.set(ev.main_tag_id, { total: 0, subTags: new Map() });
}
const mainStat = mainTagMap.get(ev.main_tag_id)!;
mainStat.total += diff;
if (ev.sub_tag_id) {
const subTotal = mainStat.subTags.get(ev.sub_tag_id) || 0;
mainStat.subTags.set(ev.sub_tag_id, subTotal + diff);
}
});
const start = new Date(dashboardStartDate.value);
const end = new Date(dashboardEndDate.value);
const naturalDays = Math.max(1, Math.floor((end.getTime() - start.getTime()) / 86400000) + 1);
const recordedDays = Math.max(1, uniqueDays.size);
const daysCount = dailyAverageMode.value === 'natural' ? naturalDays : recordedDays;
const mainTagsList = Array.from(mainTagMap.entries()).map(([id, stat]) => {
const subTagsList = Array.from(stat.subTags.entries()).map(([subId, subTotal]) => ({
id: subId,
total: subTotal,
percentage: stat.total > 0 ? (subTotal / stat.total) * 100 : 0
})).sort((a, b) => b.total - a.total);
return {
id,
total: stat.total,
dailyAverage: stat.total / daysCount,
percentage: totalMinutes > 0 ? (stat.total / totalMinutes) * 100 : 0,
subTags: subTagsList
};
}).sort((a, b) => b.total - a.total);
return { totalMinutes, dailyAverage: totalMinutes / daysCount, mainTags: mainTagsList, naturalDays, recordedDays, daysCount };
});