- RecipesView: level selector (1-4), constraints/allergies tag inputs, hard day mode toggle, max missing input, expiry-first pantry extraction, recipe cards with collapsible swaps/directions, grocery links, rate limit banner - SettingsView: cooking equipment tag input with quick-add chips, save with confirmation feedback - stores/recipes.ts: Pinia store for recipe state + suggest() action - stores/settings.ts: Pinia store for cooking_equipment persistence - api.ts: RecipeRequest/Result/Suggestion types + recipesAPI + settingsAPI - App.vue: two new tabs (Recipes, Settings), lazy inventory load on tab switch
57 lines
1.2 KiB
TypeScript
57 lines
1.2 KiB
TypeScript
/**
|
|
* Settings Store
|
|
*
|
|
* Manages user settings (cooking equipment, preferences) using Pinia.
|
|
*/
|
|
|
|
import { defineStore } from 'pinia'
|
|
import { ref } from 'vue'
|
|
import { settingsAPI } from '../services/api'
|
|
|
|
export const useSettingsStore = defineStore('settings', () => {
|
|
// State
|
|
const cookingEquipment = ref<string[]>([])
|
|
const loading = ref(false)
|
|
const saved = ref(false)
|
|
|
|
// Actions
|
|
async function load() {
|
|
loading.value = true
|
|
try {
|
|
const raw = await settingsAPI.getSetting('cooking_equipment')
|
|
if (raw) {
|
|
cookingEquipment.value = JSON.parse(raw)
|
|
}
|
|
} catch (err: unknown) {
|
|
console.error('Failed to load settings:', err)
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
async function save() {
|
|
loading.value = true
|
|
try {
|
|
await settingsAPI.setSetting('cooking_equipment', JSON.stringify(cookingEquipment.value))
|
|
saved.value = true
|
|
setTimeout(() => {
|
|
saved.value = false
|
|
}, 2000)
|
|
} catch (err: unknown) {
|
|
console.error('Failed to save settings:', err)
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
return {
|
|
// State
|
|
cookingEquipment,
|
|
loading,
|
|
saved,
|
|
|
|
// Actions
|
|
load,
|
|
save,
|
|
}
|
|
})
|