feat(analytics): add key action tracking to todo, calendar, chat, contacts

Add Umami event tracking for the most important user actions:

- Todo: task_created (with deadline flag), task_completed, task_deleted
- Calendar: event_created (with recurring flag), view_changed
- Chat: message_sent (with model ID)
- Contacts: contact_created

Uses pre-built event helpers from @manacore/shared-utils/analytics.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Till JS 2026-03-22 18:48:18 +01:00
parent 6c140c181e
commit 79544160b7
5 changed files with 12 additions and 0 deletions

View file

@ -8,6 +8,7 @@ import * as api from '$lib/api/events';
import { format, isWithinInterval, isSameDay, differenceInMilliseconds } from 'date-fns';
import { toDate } from '$lib/utils/eventDateHelpers';
import { toastStore } from '@manacore/shared-ui';
import { CalendarEvents } from '@manacore/shared-utils/analytics';
// State
let events = $state<CalendarEvent[]>([]);
@ -168,6 +169,7 @@ export const eventsStore = {
if (result.data) {
events = [...events, result.data];
CalendarEvents.eventCreated(!!data.recurrenceRule);
}
return result;

View file

@ -4,6 +4,7 @@
import { browser } from '$app/environment';
import type { CalendarViewType } from '@calendar/shared';
import { CalendarEvents } from '@manacore/shared-utils/analytics';
import {
startOfDay,
startOfWeek,
@ -109,6 +110,7 @@ export const viewStore = {
if (browser) {
localStorage.setItem('calendar-view-type', type);
}
CalendarEvents.viewChanged(type as 'day' | 'week' | 'month' | 'agenda');
},
/**

View file

@ -5,6 +5,7 @@
import { chatService } from '$lib/services/chat';
import type { ChatCompletionRequest } from '$lib/services/chat';
import type { Message, AIModel, ChatMessage } from '@chat/types';
import { ChatEvents } from '@manacore/shared-utils/analytics';
// State
let messages = $state<Message[]>([]);
@ -103,6 +104,7 @@ export const chatStore = {
createdAt: new Date().toISOString(),
};
messages = [...messages, assistantMessage];
ChatEvents.messageSent(selectedModelId);
} else {
error = 'Failed to get response';
}

View file

@ -8,6 +8,7 @@ import { contactsApi } from '$lib/api/contacts';
import type { Contact, ContactFilters } from '$lib/api/contacts';
import { authStore } from './auth.svelte';
import { generateDemoContacts, isDemoContact } from '$lib/data/demo-contacts';
import { ContactsEvents } from '@manacore/shared-utils/analytics';
// Default page size for pagination
const DEFAULT_PAGE_SIZE = 50;
@ -186,6 +187,7 @@ export const contactsStore = {
// Add to local state
contacts = [contact, ...contacts];
total += 1;
ContactsEvents.contactCreated();
return contact;
} catch (e) {
error = e instanceof Error ? e.message : 'Failed to create contact';

View file

@ -9,6 +9,7 @@ import * as tasksApi from '$lib/api/tasks';
import { isToday, isPast, isFuture, startOfDay, addDays } from 'date-fns';
import { authStore } from './auth.svelte';
import { generateDemoTasks, isDemoTask } from '$lib/data/demo-tasks';
import { TodoEvents } from '@manacore/shared-utils/analytics';
// State
let tasks = $state<Task[]>([]);
@ -224,6 +225,7 @@ export const tasksStore = {
try {
const newTask = await tasksApi.createTask(data);
tasks = [...tasks, newTask];
TodoEvents.taskCreated(!!data.dueDate);
return newTask;
} catch (e) {
error = e instanceof Error ? e.message : 'Failed to create task';
@ -339,6 +341,7 @@ export const tasksStore = {
try {
await tasksApi.deleteTask(id);
tasks = tasks.filter((t) => t.id !== id);
TodoEvents.taskDeleted();
} catch (e) {
error = e instanceof Error ? e.message : 'Failed to delete task';
console.error('Failed to delete task:', e);
@ -362,6 +365,7 @@ export const tasksStore = {
try {
const completedTask = await tasksApi.completeTask(id);
tasks = tasks.map((t) => (t.id === id ? completedTask : t));
TodoEvents.taskCompleted();
return completedTask;
} catch (e) {
error = e instanceof Error ? e.message : 'Failed to complete task';