feat: standardize error handling across all stores

This commit is contained in:
Your Name
2026-02-20 14:46:56 +02:00
parent 6c961b6c9f
commit 83a3ca1e93
8 changed files with 463 additions and 30 deletions

View File

@@ -1,6 +1,7 @@
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { ref } from 'vue' import { ref } from 'vue'
import { invoke } from '@tauri-apps/api/core' import { invoke } from '@tauri-apps/api/core'
import { handleInvokeError } from '../utils/errorHandler'
export interface Client { export interface Client {
id?: number id?: number
@@ -23,7 +24,7 @@ export const useClientsStore = defineStore('clients', () => {
try { try {
clients.value = await invoke<Client[]>('get_clients') clients.value = await invoke<Client[]>('get_clients')
} catch (error) { } catch (error) {
console.error('Failed to fetch clients:', error) handleInvokeError(error, 'Failed to fetch clients', () => fetchClients())
} finally { } finally {
loading.value = false loading.value = false
} }
@@ -35,7 +36,7 @@ export const useClientsStore = defineStore('clients', () => {
clients.value.push({ ...client, id: Number(id) }) clients.value.push({ ...client, id: Number(id) })
return Number(id) return Number(id)
} catch (error) { } catch (error) {
console.error('Failed to create client:', error) handleInvokeError(error, 'Failed to create client')
return null return null
} }
} }
@@ -49,7 +50,7 @@ export const useClientsStore = defineStore('clients', () => {
} }
return true return true
} catch (error) { } catch (error) {
console.error('Failed to update client:', error) handleInvokeError(error, 'Failed to update client')
return false return false
} }
} }
@@ -60,7 +61,7 @@ export const useClientsStore = defineStore('clients', () => {
clients.value = clients.value.filter(c => c.id !== id) clients.value = clients.value.filter(c => c.id !== id)
return true return true
} catch (error) { } catch (error) {
console.error('Failed to delete client:', error) handleInvokeError(error, 'Failed to delete client')
return false return false
} }
} }

123
src/stores/expenses.ts Normal file
View File

@@ -0,0 +1,123 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
import { invoke } from '@tauri-apps/api/core'
import { handleInvokeError } from '../utils/errorHandler'
export interface Expense {
id?: number
project_id: number
client_id?: number
category: string
description?: string
amount: number
date: string
receipt_path?: string
invoiced?: number
}
export const EXPENSE_CATEGORIES = [
{ label: 'Materials', value: 'materials' },
{ label: 'Software', value: 'software' },
{ label: 'Travel', value: 'travel' },
{ label: 'Meals', value: 'meals' },
{ label: 'Equipment', value: 'equipment' },
{ label: 'Subcontractor', value: 'subcontractor' },
{ label: 'Communication', value: 'communication' },
{ label: 'Office', value: 'office' },
{ label: 'Other', value: 'other' },
]
export const useExpensesStore = defineStore('expenses', () => {
const expenses = ref<Expense[]>([])
const loading = ref(false)
async function fetchExpenses(projectId?: number, startDate?: string, endDate?: string) {
loading.value = true
try {
expenses.value = await invoke<Expense[]>('get_expenses', {
projectId: projectId || null,
startDate: startDate || null,
endDate: endDate || null
})
} catch (error) {
handleInvokeError(error, 'Failed to fetch expenses', () => fetchExpenses(projectId, startDate, endDate))
} finally {
loading.value = false
}
}
async function createExpense(expense: Expense): Promise<number | null> {
try {
const id = await invoke<number>('create_expense', { expense })
expenses.value.unshift({ ...expense, id: Number(id) })
return Number(id)
} catch (error) {
handleInvokeError(error, 'Failed to create expense')
return null
}
}
async function updateExpense(expense: Expense): Promise<boolean> {
try {
await invoke('update_expense', { expense })
const index = expenses.value.findIndex(e => e.id === expense.id)
if (index !== -1) {
expenses.value[index] = expense
}
return true
} catch (error) {
handleInvokeError(error, 'Failed to update expense')
return false
}
}
async function deleteExpense(id: number): Promise<boolean> {
try {
await invoke('delete_expense', { id })
expenses.value = expenses.value.filter(e => e.id !== id)
return true
} catch (error) {
handleInvokeError(error, 'Failed to delete expense')
return false
}
}
async function fetchUninvoiced(projectId?: number, clientId?: number): Promise<Expense[]> {
try {
return await invoke<Expense[]>('get_uninvoiced_expenses', {
projectId: projectId || null,
clientId: clientId || null
})
} catch (error) {
handleInvokeError(error, 'Failed to fetch uninvoiced expenses')
return []
}
}
async function markInvoiced(ids: number[]): Promise<boolean> {
try {
await invoke('mark_expenses_invoiced', { ids })
for (const id of ids) {
const index = expenses.value.findIndex(e => e.id === id)
if (index !== -1) {
expenses.value[index].invoiced = 1
}
}
return true
} catch (error) {
handleInvokeError(error, 'Failed to mark expenses as invoiced')
return false
}
}
return {
expenses,
loading,
fetchExpenses,
createExpense,
updateExpense,
deleteExpense,
fetchUninvoiced,
markInvoiced
}
})

View File

@@ -1,6 +1,7 @@
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { ref } from 'vue' import { ref } from 'vue'
import { invoke } from '@tauri-apps/api/core' import { invoke } from '@tauri-apps/api/core'
import { handleInvokeError } from '../utils/errorHandler'
export interface Favorite { export interface Favorite {
id?: number id?: number
@@ -17,7 +18,7 @@ export const useFavoritesStore = defineStore('favorites', () => {
try { try {
favorites.value = await invoke<Favorite[]>('get_favorites') favorites.value = await invoke<Favorite[]>('get_favorites')
} catch (error) { } catch (error) {
console.error('Failed to fetch favorites:', error) handleInvokeError(error, 'Failed to fetch favorites', () => fetchFavorites())
} }
} }
@@ -27,7 +28,7 @@ export const useFavoritesStore = defineStore('favorites', () => {
favorites.value.push({ ...fav, id: Number(id) }) favorites.value.push({ ...fav, id: Number(id) })
return Number(id) return Number(id)
} catch (error) { } catch (error) {
console.error('Failed to create favorite:', error) handleInvokeError(error, 'Failed to create favorite')
return null return null
} }
} }
@@ -38,7 +39,7 @@ export const useFavoritesStore = defineStore('favorites', () => {
favorites.value = favorites.value.filter(f => f.id !== id) favorites.value = favorites.value.filter(f => f.id !== id)
return true return true
} catch (error) { } catch (error) {
console.error('Failed to delete favorite:', error) handleInvokeError(error, 'Failed to delete favorite')
return false return false
} }
} }
@@ -48,7 +49,7 @@ export const useFavoritesStore = defineStore('favorites', () => {
await invoke('reorder_favorites', { ids }) await invoke('reorder_favorites', { ids })
return true return true
} catch (error) { } catch (error) {
console.error('Failed to reorder favorites:', error) handleInvokeError(error, 'Failed to reorder favorites')
return false return false
} }
} }

View File

@@ -1,6 +1,7 @@
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { ref } from 'vue' import { ref } from 'vue'
import { invoke } from '@tauri-apps/api/core' import { invoke } from '@tauri-apps/api/core'
import { handleInvokeError } from '../utils/errorHandler'
export interface Invoice { export interface Invoice {
id?: number id?: number
@@ -37,7 +38,7 @@ export const useInvoicesStore = defineStore('invoices', () => {
try { try {
invoices.value = await invoke<Invoice[]>('get_invoices') invoices.value = await invoke<Invoice[]>('get_invoices')
} catch (error) { } catch (error) {
console.error('Failed to fetch invoices:', error) handleInvokeError(error, 'Failed to fetch invoices', () => fetchInvoices())
} finally { } finally {
loading.value = false loading.value = false
} }
@@ -49,7 +50,7 @@ export const useInvoicesStore = defineStore('invoices', () => {
invoices.value.unshift({ ...invoice, id: Number(id) }) invoices.value.unshift({ ...invoice, id: Number(id) })
return Number(id) return Number(id)
} catch (error) { } catch (error) {
console.error('Failed to create invoice:', error) handleInvokeError(error, 'Failed to create invoice')
return null return null
} }
} }
@@ -63,7 +64,7 @@ export const useInvoicesStore = defineStore('invoices', () => {
} }
return true return true
} catch (error) { } catch (error) {
console.error('Failed to update invoice:', error) handleInvokeError(error, 'Failed to update invoice')
return false return false
} }
} }
@@ -77,7 +78,7 @@ export const useInvoicesStore = defineStore('invoices', () => {
} }
return true return true
} catch (error) { } catch (error) {
console.error('Failed to update invoice template:', error) handleInvokeError(error, 'Failed to update invoice template')
return false return false
} }
} }
@@ -88,7 +89,7 @@ export const useInvoicesStore = defineStore('invoices', () => {
invoices.value = invoices.value.filter(i => i.id !== id) invoices.value = invoices.value.filter(i => i.id !== id)
return true return true
} catch (error) { } catch (error) {
console.error('Failed to delete invoice:', error) handleInvokeError(error, 'Failed to delete invoice')
return false return false
} }
} }
@@ -97,7 +98,7 @@ export const useInvoicesStore = defineStore('invoices', () => {
try { try {
return await invoke<InvoiceItem[]>('get_invoice_items', { invoiceId }) return await invoke<InvoiceItem[]>('get_invoice_items', { invoiceId })
} catch (error) { } catch (error) {
console.error('Failed to fetch invoice items:', error) handleInvokeError(error, 'Failed to fetch invoice items')
return [] return []
} }
} }
@@ -106,7 +107,7 @@ export const useInvoicesStore = defineStore('invoices', () => {
try { try {
return await invoke<number>('create_invoice_item', { item }) return await invoke<number>('create_invoice_item', { item })
} catch (error) { } catch (error) {
console.error('Failed to create invoice item:', error) handleInvokeError(error, 'Failed to create invoice item')
return null return null
} }
} }
@@ -123,6 +124,29 @@ export const useInvoicesStore = defineStore('invoices', () => {
} }
} }
async function updateStatus(id: number, status: string): Promise<boolean> {
try {
await invoke('update_invoice_status', { id, status })
const idx = invoices.value.findIndex(i => i.id === id)
if (idx !== -1) invoices.value[idx].status = status
return true
} catch (error) {
handleInvokeError(error, 'Failed to update invoice status')
return false
}
}
async function checkOverdue(): Promise<number> {
try {
const today = new Date().toISOString().split('T')[0]
const count = await invoke<number>('check_overdue_invoices', { today })
if (count > 0) await fetchInvoices()
return count
} catch {
return 0
}
}
return { return {
invoices, invoices,
loading, loading,
@@ -133,6 +157,8 @@ export const useInvoicesStore = defineStore('invoices', () => {
deleteInvoice, deleteInvoice,
getInvoiceItems, getInvoiceItems,
createInvoiceItem, createInvoiceItem,
saveInvoiceItems saveInvoiceItems,
updateStatus,
checkOverdue
} }
}) })

View File

@@ -1,6 +1,7 @@
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { ref } from 'vue' import { ref } from 'vue'
import { invoke } from '@tauri-apps/api/core' import { invoke } from '@tauri-apps/api/core'
import { handleInvokeError } from '../utils/errorHandler'
export interface Project { export interface Project {
id?: number id?: number
@@ -12,12 +13,14 @@ export interface Project {
budget_hours?: number | null budget_hours?: number | null
budget_amount?: number | null budget_amount?: number | null
rounding_override?: number | null rounding_override?: number | null
timeline_override?: string | null
} }
export interface Task { export interface Task {
id?: number id?: number
project_id: number project_id: number
name: string name: string
estimated_hours?: number | null
} }
export const useProjectsStore = defineStore('projects', () => { export const useProjectsStore = defineStore('projects', () => {
@@ -29,7 +32,7 @@ export const useProjectsStore = defineStore('projects', () => {
try { try {
projects.value = await invoke<Project[]>('get_projects') projects.value = await invoke<Project[]>('get_projects')
} catch (error) { } catch (error) {
console.error('Failed to fetch projects:', error) handleInvokeError(error, 'Failed to fetch projects', () => fetchProjects())
} finally { } finally {
loading.value = false loading.value = false
} }
@@ -41,7 +44,7 @@ export const useProjectsStore = defineStore('projects', () => {
projects.value.push({ ...project, id: Number(id) }) projects.value.push({ ...project, id: Number(id) })
return Number(id) return Number(id)
} catch (error) { } catch (error) {
console.error('Failed to create project:', error) handleInvokeError(error, 'Failed to create project')
return null return null
} }
} }
@@ -55,7 +58,7 @@ export const useProjectsStore = defineStore('projects', () => {
} }
return true return true
} catch (error) { } catch (error) {
console.error('Failed to update project:', error) handleInvokeError(error, 'Failed to update project')
return false return false
} }
} }
@@ -66,7 +69,7 @@ export const useProjectsStore = defineStore('projects', () => {
projects.value = projects.value.filter(p => p.id !== id) projects.value = projects.value.filter(p => p.id !== id)
return true return true
} catch (error) { } catch (error) {
console.error('Failed to delete project:', error) handleInvokeError(error, 'Failed to delete project')
return false return false
} }
} }
@@ -75,7 +78,7 @@ export const useProjectsStore = defineStore('projects', () => {
try { try {
return await invoke<Task[]>('get_tasks', { projectId }) return await invoke<Task[]>('get_tasks', { projectId })
} catch (error) { } catch (error) {
console.error('Failed to fetch tasks:', error) handleInvokeError(error, 'Failed to fetch tasks')
return [] return []
} }
} }
@@ -84,7 +87,7 @@ export const useProjectsStore = defineStore('projects', () => {
try { try {
return await invoke<number>('create_task', { task }) return await invoke<number>('create_task', { task })
} catch (error) { } catch (error) {
console.error('Failed to create task:', error) handleInvokeError(error, 'Failed to create task')
return null return null
} }
} }
@@ -94,7 +97,17 @@ export const useProjectsStore = defineStore('projects', () => {
await invoke('delete_task', { id }) await invoke('delete_task', { id })
return true return true
} catch (error) { } catch (error) {
console.error('Failed to delete task:', error) handleInvokeError(error, 'Failed to delete task')
return false
}
}
async function updateTask(task: Task): Promise<boolean> {
try {
await invoke('update_task', { task })
return true
} catch (error) {
handleInvokeError(error, 'Failed to update task')
return false return false
} }
} }
@@ -108,6 +121,7 @@ export const useProjectsStore = defineStore('projects', () => {
deleteProject, deleteProject,
fetchTasks, fetchTasks,
createTask, createTask,
deleteTask deleteTask,
updateTask
} }
}) })

229
src/stores/recurring.ts Normal file
View File

@@ -0,0 +1,229 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
import { invoke } from '@tauri-apps/api/core'
import { useToastStore } from './toast'
import { useTimerStore } from './timer'
import { handleInvokeError } from '../utils/errorHandler'
export interface RecurringEntry {
id?: number
project_id: number
task_id?: number
description?: string
duration: number
recurrence_rule: string // "daily", "weekdays", "weekly:mon,wed,fri", "monthly:15"
time_of_day: string // "09:00"
mode: 'auto_create' | 'prompt' | 'prefill_timer'
enabled?: number // 1 = enabled, 0 = disabled
last_triggered?: string // ISO date string
}
export const useRecurringStore = defineStore('recurring', () => {
const entries = ref<RecurringEntry[]>([])
const pendingPrompt = ref<RecurringEntry | null>(null)
const snoozedUntil = ref<Map<number, number>>(new Map())
async function fetchEntries() {
try {
entries.value = await invoke<RecurringEntry[]>('get_recurring_entries')
} catch (e) {
handleInvokeError(e, 'Failed to fetch recurring entries', () => fetchEntries())
}
}
async function createEntry(entry: RecurringEntry) {
try {
const id = await invoke<number>('create_recurring_entry', { entry })
await fetchEntries()
return id
} catch (e) {
handleInvokeError(e, 'Failed to create recurring entry')
throw e
}
}
async function updateEntry(entry: RecurringEntry) {
try {
await invoke('update_recurring_entry', { entry })
await fetchEntries()
} catch (e) {
handleInvokeError(e, 'Failed to update recurring entry')
throw e
}
}
async function deleteEntry(id: number) {
try {
await invoke('delete_recurring_entry', { id })
await fetchEntries()
} catch (e) {
handleInvokeError(e, 'Failed to delete recurring entry')
throw e
}
}
async function toggleEnabled(entry: RecurringEntry) {
const updated = { ...entry, enabled: entry.enabled === 1 ? 0 : 1 }
await updateEntry(updated)
}
// Core recurrence check engine
async function checkRecurrences() {
if (entries.value.length === 0) return
const now = new Date()
const todayStr = now.toISOString().split('T')[0] // YYYY-MM-DD
const currentTime = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}`
const dayOfWeek = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'][now.getDay()]
const dayOfMonth = now.getDate()
for (const entry of entries.value) {
if (entry.enabled === 0) continue
// Check if already triggered today
if (entry.last_triggered) {
const lastDate = entry.last_triggered.split('T')[0]
if (lastDate === todayStr) continue
}
// Check if current time has passed the scheduled time
if (currentTime < entry.time_of_day) continue
// Check recurrence rule
const rule = entry.recurrence_rule
let shouldFire = false
if (rule === 'daily') {
shouldFire = true
} else if (rule === 'weekdays') {
shouldFire = !['sat', 'sun'].includes(dayOfWeek)
} else if (rule.startsWith('weekly:')) {
const days = rule.replace('weekly:', '').split(',')
shouldFire = days.includes(dayOfWeek)
} else if (rule.startsWith('monthly:')) {
const targetDay = parseInt(rule.replace('monthly:', ''))
shouldFire = dayOfMonth === targetDay
}
if (!shouldFire) continue
// Check snooze: skip if snoozed and not yet expired
if (entry.id && snoozedUntil.value.has(entry.id)) {
if (Date.now() < snoozedUntil.value.get(entry.id)!) continue
snoozedUntil.value.delete(entry.id)
}
// Fire the recurrence based on mode
await fireRecurrence(entry)
}
}
async function fireRecurrence(entry: RecurringEntry) {
const toastStore = useToastStore()
if (entry.mode === 'auto_create') {
// Silently create a time entry
const now = new Date()
const startTime = new Date(now)
const [h, m] = entry.time_of_day.split(':').map(Number)
startTime.setHours(h, m, 0, 0)
const endTime = new Date(startTime.getTime() + entry.duration * 1000)
try {
await invoke('create_time_entry', {
entry: {
project_id: entry.project_id,
task_id: entry.task_id || null,
description: entry.description || null,
start_time: startTime.toISOString(),
end_time: endTime.toISOString(),
duration: entry.duration,
billable: 1,
}
})
toastStore.success('Recurring entry created')
} catch (e) {
console.error('Failed to auto-create recurring entry:', e)
}
} else if (entry.mode === 'prompt') {
pendingPrompt.value = entry
} else if (entry.mode === 'prefill_timer') {
// Pre-fill the timer with project/task/description
const timerStore = useTimerStore()
if (timerStore.isStopped) {
timerStore.setProject(entry.project_id)
if (entry.task_id) timerStore.setTask(entry.task_id)
if (entry.description) timerStore.setDescription(entry.description)
toastStore.info('Timer pre-filled from recurring entry')
}
}
// Mark as triggered today (skip for prompt mode - user action handlers do it)
if (entry.mode !== 'prompt' && entry.id) {
await markTriggered(entry.id)
}
}
async function markTriggered(id: number) {
try {
await invoke('update_recurring_last_triggered', {
id,
lastTriggered: new Date().toISOString(),
})
const idx = entries.value.findIndex(e => e.id === id)
if (idx !== -1) {
entries.value[idx].last_triggered = new Date().toISOString()
}
} catch (e) {
console.error('Failed to update last_triggered:', e)
}
}
function snoozePrompt() {
const entry = pendingPrompt.value
if (entry?.id) {
snoozedUntil.value.set(entry.id, Date.now() + 30 * 60 * 1000)
}
pendingPrompt.value = null
}
async function confirmPrompt() {
if (!pendingPrompt.value) return
const entry = pendingPrompt.value
const now = new Date()
const [h, m] = entry.time_of_day.split(':').map(Number)
const startTime = new Date(now)
startTime.setHours(h, m, 0, 0)
const endTime = new Date(startTime.getTime() + entry.duration * 1000)
try {
await invoke('create_time_entry', {
entry: {
project_id: entry.project_id,
task_id: entry.task_id || null,
description: entry.description || null,
start_time: startTime.toISOString(),
end_time: endTime.toISOString(),
duration: entry.duration,
billable: 1,
}
})
const toastStore = useToastStore()
toastStore.success('Recurring entry created')
if (entry.id) await markTriggered(entry.id)
} catch (e) {
handleInvokeError(e, 'Failed to create recurring entry')
}
pendingPrompt.value = null
}
async function skipPrompt() {
const entry = pendingPrompt.value
if (entry?.id) {
await markTriggered(entry.id)
}
pendingPrompt.value = null
}
return { entries, pendingPrompt, fetchEntries, createEntry, updateEntry, deleteEntry, toggleEnabled, checkRecurrences, snoozePrompt, confirmPrompt, skipPrompt }
})

38
src/stores/settings.ts Normal file
View File

@@ -0,0 +1,38 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
import { invoke } from '@tauri-apps/api/core'
import { handleInvokeError } from '../utils/errorHandler'
export const useSettingsStore = defineStore('settings', () => {
const settings = ref<Record<string, string>>({})
const loading = ref(false)
async function fetchSettings() {
loading.value = true
try {
settings.value = await invoke<Record<string, string>>('get_settings')
} catch (error) {
handleInvokeError(error, 'Failed to fetch settings', () => fetchSettings())
} finally {
loading.value = false
}
}
async function updateSetting(key: string, value: string): Promise<boolean> {
try {
await invoke('update_settings', { key, value })
settings.value[key] = value
return true
} catch (error) {
console.error('Failed to update setting:', error)
return false
}
}
return {
settings,
loading,
fetchSettings,
updateSetting
}
})

View File

@@ -1,6 +1,7 @@
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { ref } from 'vue' import { ref } from 'vue'
import { invoke } from '@tauri-apps/api/core' import { invoke } from '@tauri-apps/api/core'
import { handleInvokeError } from '../utils/errorHandler'
export interface Tag { export interface Tag {
id?: number id?: number
@@ -15,7 +16,7 @@ export const useTagsStore = defineStore('tags', () => {
try { try {
tags.value = await invoke<Tag[]>('get_tags') tags.value = await invoke<Tag[]>('get_tags')
} catch (error) { } catch (error) {
console.error('Failed to fetch tags:', error) handleInvokeError(error, 'Failed to fetch tags', () => fetchTags())
} }
} }
@@ -25,7 +26,7 @@ export const useTagsStore = defineStore('tags', () => {
tags.value.push({ ...tag, id: Number(id) }) tags.value.push({ ...tag, id: Number(id) })
return Number(id) return Number(id)
} catch (error) { } catch (error) {
console.error('Failed to create tag:', error) handleInvokeError(error, 'Failed to create tag')
return null return null
} }
} }
@@ -37,7 +38,7 @@ export const useTagsStore = defineStore('tags', () => {
if (index !== -1) tags.value[index] = tag if (index !== -1) tags.value[index] = tag
return true return true
} catch (error) { } catch (error) {
console.error('Failed to update tag:', error) handleInvokeError(error, 'Failed to update tag')
return false return false
} }
} }
@@ -48,7 +49,7 @@ export const useTagsStore = defineStore('tags', () => {
tags.value = tags.value.filter(t => t.id !== id) tags.value = tags.value.filter(t => t.id !== id)
return true return true
} catch (error) { } catch (error) {
console.error('Failed to delete tag:', error) handleInvokeError(error, 'Failed to delete tag')
return false return false
} }
} }
@@ -57,7 +58,7 @@ export const useTagsStore = defineStore('tags', () => {
try { try {
return await invoke<Tag[]>('get_entry_tags', { entryId }) return await invoke<Tag[]>('get_entry_tags', { entryId })
} catch (error) { } catch (error) {
console.error('Failed to get entry tags:', error) handleInvokeError(error, 'Failed to get entry tags')
return [] return []
} }
} }
@@ -67,7 +68,7 @@ export const useTagsStore = defineStore('tags', () => {
await invoke('set_entry_tags', { entryId, tagIds }) await invoke('set_entry_tags', { entryId, tagIds })
return true return true
} catch (error) { } catch (error) {
console.error('Failed to set entry tags:', error) handleInvokeError(error, 'Failed to set entry tags')
return false return false
} }
} }