diff options
| author | Solstice <solstice@local> | 2026-06-09 00:22:18 -0700 |
|---|---|---|
| committer | Solstice <solstice@local> | 2026-06-09 00:22:18 -0700 |
| commit | 6cb006cc136f1fc5c83537cc30c64d223d1755e4 (patch) | |
| tree | b12dfb4a8345c980dc8747657ce381016cdf3b34 /src/store | |
| parent | 25e1dcf205cd14feafdd9b4cf6b7a66f253ba6d2 (diff) | |
feat: frontend view, state management, and user interface
Diffstat (limited to 'src/store')
| -rw-r--r-- | src/store/settingsStore.ts | 33 | ||||
| -rw-r--r-- | src/store/taskStore.ts | 80 | ||||
| -rw-r--r-- | src/store/timerStore.ts | 42 |
3 files changed, 155 insertions, 0 deletions
diff --git a/src/store/settingsStore.ts b/src/store/settingsStore.ts new file mode 100644 index 0000000..ea7be34 --- /dev/null +++ b/src/store/settingsStore.ts @@ -0,0 +1,33 @@ +import { create } from 'zustand'; +import { invoke } from '@tauri-apps/api/core'; + +export interface Settings { + work_duration_secs: number; + short_break_secs: number; + long_break_secs: number; + sessions_before_long_break: number; +} + +interface SettingsStore { + settings: Settings | null; + fetchSettings: () => Promise<void>; + updateSettings: (s: Settings) => Promise<void>; +} + +export const useSettingsStore = create<SettingsStore>((set) => ({ + settings: null, + + fetchSettings: async () => { + try { + const settings = await invoke<Settings>('get_settings'); + set({ settings }); + } catch (e) { + console.error('fetchSettings error:', e); + } + }, + + updateSettings: async (s) => { + await invoke('update_settings', { settings: s }); + set({ settings: s }); + }, +})); diff --git a/src/store/taskStore.ts b/src/store/taskStore.ts new file mode 100644 index 0000000..dccd17d --- /dev/null +++ b/src/store/taskStore.ts @@ -0,0 +1,80 @@ +import { create } from 'zustand'; +import { invoke } from '@tauri-apps/api/core'; + +export interface Task { + id: string; + name: string; + total_sessions: number; + remaining_sessions: number; + completed: boolean; + created_at: string; +} + +interface TaskStore { + tasks: Task[]; + loading: boolean; + fetchTasks: () => Promise<void>; + addTask: (name: string, totalSessions: number) => Promise<void>; + updateTask: (id: string, remainingSessions?: number, completed?: boolean) => Promise<void>; + deleteTask: (id: string) => Promise<void>; + setCurrentTask: (id: string | null) => Promise<void>; + refreshTask: (task: Task) => void; +} + +export const useTaskStore = create<TaskStore>((set) => ({ + tasks: [], + loading: false, + + fetchTasks: async () => { + set({ loading: true }); + try { + const tasks = await invoke<Task[]>('get_tasks'); + set({ tasks, loading: false }); + } catch (e) { + console.error('fetchTasks error:', e); + set({ loading: false }); + } + }, + + addTask: async (name, totalSessions) => { + const task = await invoke<Task>('add_task', { + name, + totalSessions, + }); + set((state) => ({ tasks: [...state.tasks, task] })); + }, + + updateTask: async (id, remainingSessions, completed) => { + await invoke('update_task', { + id, + remainingSessions: remainingSessions ?? null, + completed: completed ?? null, + }); + set((state) => ({ + tasks: state.tasks.map((t) => + t.id === id + ? { + ...t, + remaining_sessions: remainingSessions ?? t.remaining_sessions, + completed: completed ?? t.completed, + } + : t, + ), + })); + }, + + deleteTask: async (id) => { + await invoke('delete_task', { id }); + set((state) => ({ tasks: state.tasks.filter((t) => t.id !== id) })); + }, + + setCurrentTask: async (id) => { + await invoke('set_current_task', { taskId: id }); + }, + + refreshTask: (updatedTask) => { + set((state) => ({ + tasks: state.tasks.map((t) => (t.id === updatedTask.id ? updatedTask : t)), + })); + }, +})); diff --git a/src/store/timerStore.ts b/src/store/timerStore.ts new file mode 100644 index 0000000..6a81e20 --- /dev/null +++ b/src/store/timerStore.ts @@ -0,0 +1,42 @@ +import { create } from 'zustand'; + +export type TimerPhase = 'work' | 'short_break' | 'long_break'; + +export interface TimerTickPayload { + phase: TimerPhase; + remaining_secs: number; + total_secs: number; + session_count: number; + current_task_id: string | null; +} + +interface TimerState { + phase: TimerPhase; + remainingSecs: number; + totalSecs: number; + running: boolean; + sessionCount: number; + currentTaskId: string | null; + setTimerTick: (payload: TimerTickPayload) => void; + setRunning: (running: boolean) => void; +} + +export const useTimerStore = create<TimerState>((set) => ({ + phase: 'work', + remainingSecs: 25 * 60, + totalSecs: 25 * 60, + running: false, + sessionCount: 0, + currentTaskId: null, + + setTimerTick: (payload) => + set({ + phase: payload.phase, + remainingSecs: payload.remaining_secs, + totalSecs: payload.total_secs, + sessionCount: payload.session_count, + currentTaskId: payload.current_task_id, + }), + + setRunning: (running) => set({ running }), +})); |
