summaryrefslogtreecommitdiff
path: root/src/store
diff options
context:
space:
mode:
authorSolstice <solstice@local>2026-06-09 00:22:18 -0700
committerSolstice <solstice@local>2026-06-09 00:22:18 -0700
commit6cb006cc136f1fc5c83537cc30c64d223d1755e4 (patch)
treeb12dfb4a8345c980dc8747657ce381016cdf3b34 /src/store
parent25e1dcf205cd14feafdd9b4cf6b7a66f253ba6d2 (diff)
feat: frontend view, state management, and user interface
Diffstat (limited to 'src/store')
-rw-r--r--src/store/settingsStore.ts33
-rw-r--r--src/store/taskStore.ts80
-rw-r--r--src/store/timerStore.ts42
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 }),
+}));