feat(analytics): add custom event tracking to NutriPhi and ManaDeck

Add NutriPhiEvents (mealAdded, mealDeleted, photoAnalyzed, textAnalyzed,
goalsUpdated, favoriteSaved, favoriteUsed) to shared analytics utils.
Add deckDeleted and cardDeleted to ManaDeckEvents. Wire up event calls
in NutriPhi meals store and ManaDeck deck/card stores.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Till JS 2026-03-25 12:12:01 +01:00
parent 59c8974af8
commit 1fe8f8902d
4 changed files with 25 additions and 0 deletions

View file

@ -1,6 +1,7 @@
import type { Card, CreateCardInput, UpdateCardInput } from '$lib/types/card';
import { PUBLIC_API_URL } from '$env/static/public';
import { authService } from '$lib/auth';
import { ManaDeckEvents } from '@manacore/shared-utils/analytics';
// Svelte 5 runes-based card store
let cards = $state<Card[]>([]);
@ -128,6 +129,7 @@ export const cardStore = {
if (response.card) {
const card = mapCardFromApi(response.card);
cards = [...cards, card];
ManaDeckEvents.cardCreated();
return card;
}
return null;
@ -191,6 +193,7 @@ export const cardStore = {
// Remove from list
cards = cards.filter((c) => c.id !== id);
ManaDeckEvents.cardDeleted();
// Clear current if it's the same
if (currentCard?.id === id) {

View file

@ -1,6 +1,7 @@
import type { Deck, CreateDeckInput, UpdateDeckInput } from '$lib/types/deck';
import { PUBLIC_API_URL } from '$env/static/public';
import { authService } from '$lib/auth';
import { ManaDeckEvents } from '@manacore/shared-utils/analytics';
// Svelte 5 runes-based deck store
let decks = $state<Deck[]>([]);
@ -109,6 +110,7 @@ export const deckStore = {
if (response.deck) {
const deck = { ...response.deck, card_count: 0 };
decks = [deck, ...decks];
ManaDeckEvents.deckCreated();
return deck;
}
return null;
@ -165,6 +167,7 @@ export const deckStore = {
// Remove from list
decks = decks.filter((d) => d.id !== id);
ManaDeckEvents.deckDeleted();
// Clear current if it's the same
if (currentDeck?.id === id) {

View file

@ -1,5 +1,6 @@
import { apiClient } from '$lib/api/client';
import type { Meal, MealNutrition, DailySummary } from '@nutriphi/shared';
import { NutriPhiEvents } from '@manacore/shared-utils/analytics';
interface MealWithNutrition extends Meal {
nutrition: MealNutrition | null;
@ -59,6 +60,7 @@ class MealsStore {
const meal = await apiClient.post<MealWithNutrition>('/meals', mealData);
this.meals = [...this.meals, meal];
await this.fetchDailySummary();
NutriPhiEvents.mealAdded(mealData.mealType, mealData.inputType);
return meal;
} catch (err) {
const message =
@ -74,6 +76,7 @@ class MealsStore {
await apiClient.delete(`/meals/${mealId}`);
this.meals = this.meals.filter((m) => m.id !== mealId);
await this.fetchDailySummary();
NutriPhiEvents.mealDeleted();
} catch (err) {
this.deleteError =
err instanceof Error ? err.message : 'Mahlzeit konnte nicht gelöscht werden';

View file

@ -249,8 +249,10 @@ export const ContactsEvents = {
*/
export const ManaDeckEvents = {
deckCreated: () => trackEvent('deck_created'),
deckDeleted: () => trackEvent('deck_deleted'),
deckStudied: (cardsCount: number) => trackEvent('deck_studied', { cards: cardsCount }),
cardCreated: () => trackEvent('card_created'),
cardDeleted: () => trackEvent('card_deleted'),
cardReviewed: (rating: 1 | 2 | 3 | 4 | 5) => trackEvent('card_reviewed', { rating }),
aiCardsGenerated: (count: number) => trackEvent('ai_cards_generated', { count }),
};
@ -297,6 +299,20 @@ export const SkillTreeEvents = {
trackEvent('xp_added', { xp, leveled_up: leveledUp }),
};
/**
* NutriPhi App Events
*/
export const NutriPhiEvents = {
mealAdded: (mealType: string, inputType: string) =>
trackEvent('meal_added', { meal_type: mealType, input_type: inputType }),
mealDeleted: () => trackEvent('meal_deleted'),
photoAnalyzed: () => trackEvent('photo_analyzed'),
textAnalyzed: () => trackEvent('text_analyzed'),
goalsUpdated: () => trackEvent('goals_updated'),
favoriteSaved: () => trackEvent('favorite_saved'),
favoriteUsed: () => trackEvent('favorite_used'),
};
/**
* Planta App Events
*/