import { computed, ref } from 'vue' import { defineStore } from 'pinia' import BackendAPI from '@/BackendAPI.ts' import { useAuthStore } from '@/stores/auth' import { useMealsStore } from '@/stores/meals' import type { DayMealsByType, DiaryDay, MealType } from '@/types/domain' import { MEAL_TYPES } from '@/types/domain' import { computeDayTotals, emptyTotals } from '@/utils/nutrition' import { unwrapApiData } from '@/utils/api' const createEmptyDay = (date: string): DiaryDay => ({ user_id: 0, day_date: date, diary_day_id: null, entries: [], totals: emptyTotals(), }) export const useDiaryStore = defineStore('diary', () => { const auth = useAuthStore() const mealsStore = useMealsStore() const currentDay = ref(null) const loading = ref(false) const requireToken = (): string => { if (!auth.token) { throw new Error('User is not authenticated') } return auth.token } const mealsByType = computed(() => { const ret: DayMealsByType = { breakfast: null, lunch: null, dinner: null, } for (const entry of currentDay.value?.entries ?? []) { const cachedMeal = mealsStore.getMealFromCache(entry.meal_id) ret[entry.meal_type] = cachedMeal ?? entry.meal ?? null } return ret }) const computedTotals = computed(() => computeDayTotals(mealsByType.value)) const hydrateDayMeals = async (day: DiaryDay) => { const loadTasks: Promise[] = [] for (const entry of day.entries) { loadTasks.push(mealsStore.ensureMeal(entry.meal_id)) } if (loadTasks.length > 0) { await Promise.all(loadTasks) } } const setCurrentDay = async (day: DiaryDay) => { currentDay.value = day await hydrateDayMeals(day) } const loadDay = async (date: string) => { loading.value = true try { const token = requireToken() const payload = unwrapApiData(await BackendAPI.diaryDayGet(token, date, true)) await setCurrentDay(payload) } finally { loading.value = false } } const setMealForType = async (date: string, mealType: MealType, mealId: number) => { const token = requireToken() const payload = unwrapApiData(await BackendAPI.diaryDaySetMeal(token, date, mealType, mealId)) await setCurrentDay(payload) } const unsetMealForType = async (date: string, mealType: MealType) => { const token = requireToken() const payload = unwrapApiData(await BackendAPI.diaryDayUnsetMeal(token, date, mealType)) await setCurrentDay(payload) } const selectedMealId = (mealType: MealType): number | null => { const entry = currentDay.value?.entries.find((item) => item.meal_type === mealType) return entry?.meal_id ?? null } const ensureCurrentDay = (date: string) => { if (!currentDay.value || currentDay.value.day_date !== date) { currentDay.value = createEmptyDay(date) } } const selectedMealOptions = computed(() => { const map: Record = { breakfast: [], lunch: [], dinner: [], } for (const type of MEAL_TYPES) { map[type] = mealsStore.sortedMeals .filter((meal) => meal.meal_type === type) .map((meal) => ({ value: meal.meal_id, label: meal.name })) } return map }) return { currentDay, loading, mealsByType, computedTotals, selectedMealOptions, selectedMealId, ensureCurrentDay, loadDay, setMealForType, unsetMealForType, } })