From 6c961b6c9f6204f2cea30e035a3a0e09f9078deb Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 20 Feb 2026 14:43:10 +0200 Subject: [PATCH] feat: use unified error handler in entries store --- src/stores/entries.ts | 120 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 src/stores/entries.ts diff --git a/src/stores/entries.ts b/src/stores/entries.ts new file mode 100644 index 0000000..f897e87 --- /dev/null +++ b/src/stores/entries.ts @@ -0,0 +1,120 @@ +import { defineStore } from 'pinia' +import { ref } from 'vue' +import { invoke } from '@tauri-apps/api/core' +import { handleInvokeError } from '../utils/errorHandler' + +export interface TimeEntry { + id?: number + project_id: number + task_id?: number + description?: string + start_time: string + end_time?: string + duration: number + billable?: number +} + +export const useEntriesStore = defineStore('entries', () => { + const entries = ref([]) + const loading = ref(false) + const total = ref(0) + const hasMore = ref(false) + + async function fetchEntriesPaginated(startDate?: string, endDate?: string) { + loading.value = true + try { + const result = await invoke<{ entries: TimeEntry[]; total: number; has_more: boolean }>('get_time_entries_paginated', { + startDate: startDate || null, + endDate: endDate || null, + limit: 50, + offset: 0, + }) + entries.value = result.entries + total.value = result.total + hasMore.value = result.has_more + } catch (error) { + handleInvokeError(error, 'Failed to fetch time entries', () => fetchEntriesPaginated(startDate, endDate)) + } finally { + loading.value = false + } + } + + async function fetchMore(startDate?: string, endDate?: string) { + try { + const result = await invoke<{ entries: TimeEntry[]; total: number; has_more: boolean }>('get_time_entries_paginated', { + startDate: startDate || null, + endDate: endDate || null, + limit: 50, + offset: entries.value.length, + }) + entries.value.push(...result.entries) + total.value = result.total + hasMore.value = result.has_more + } catch (error) { + handleInvokeError(error, 'Failed to load more entries', () => fetchMore(startDate, endDate)) + } + } + + async function fetchEntries(startDate?: string, endDate?: string) { + loading.value = true + try { + entries.value = await invoke('get_time_entries', { + startDate: startDate || null, + endDate: endDate || null + }) + } catch (error) { + handleInvokeError(error, 'Failed to fetch time entries', () => fetchEntries(startDate, endDate)) + } finally { + loading.value = false + } + } + + async function createEntry(entry: TimeEntry): Promise { + try { + const id = await invoke('create_time_entry', { entry }) + entries.value.unshift({ ...entry, id: Number(id) }) + return Number(id) + } catch (error) { + handleInvokeError(error, 'Failed to create time entry') + throw error + } + } + + async function updateEntry(entry: TimeEntry): Promise { + try { + await invoke('update_time_entry', { entry }) + const index = entries.value.findIndex(e => e.id === entry.id) + if (index !== -1) { + entries.value[index] = entry + } + return true + } catch (error) { + handleInvokeError(error, 'Failed to update time entry') + throw error + } + } + + async function deleteEntry(id: number): Promise { + try { + await invoke('delete_time_entry', { id }) + entries.value = entries.value.filter(e => e.id !== id) + return true + } catch (error) { + handleInvokeError(error, 'Failed to delete time entry') + throw error + } + } + + return { + entries, + loading, + total, + hasMore, + fetchEntries, + fetchEntriesPaginated, + fetchMore, + createEntry, + updateEntry, + deleteEntry + } +})