feat: add Zustand stores for focus, navigation, capture, and batch
Implements the frontend state management layer using Zustand. Each store is single-purpose and testable in isolation. Focus Store (focus-store.ts): - Tracks current focused item (THE ONE THING) - Manages the queue of remaining items - Actions: setItems, act (start/defer/skip), setFocus, reorderQueue - Advancing through items removes from queue, promotes next to current Navigation Store (nav-store.ts): - Simple view routing: focus | queue | inbox - No URL-based routing needed for native app - Default view is "focus" Capture Store (capture-store.ts): - Manages quick capture overlay state - Tracks submission status and errors - Opens via global shortcut event listener Batch Store (batch-store.ts): - Manages batch processing mode for rapid item completion - Tracks items, their statuses (pending/done/skipped), and current index - Derives counts: completedCount, skippedCount, isFinished - Used for "knock out all code reviews" workflow State design principles: - No derived state stored; computed on access - Actions are pure mutations with logging - Loading/error states colocated with data Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
55
src/stores/capture-store.ts
Normal file
55
src/stores/capture-store.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Quick Capture store.
|
||||
*
|
||||
* Manages the overlay state for the global Cmd+Shift+C capture flow.
|
||||
*/
|
||||
|
||||
import { create } from "zustand";
|
||||
|
||||
interface CaptureState {
|
||||
isOpen: boolean;
|
||||
isSubmitting: boolean;
|
||||
lastCapturedId: string | null;
|
||||
error: string | null;
|
||||
}
|
||||
|
||||
interface CaptureActions {
|
||||
open: () => void;
|
||||
close: () => void;
|
||||
setSubmitting: (submitting: boolean) => void;
|
||||
captureSuccess: (beadId: string) => void;
|
||||
captureError: (message: string) => void;
|
||||
}
|
||||
|
||||
export const useCaptureStore = create<CaptureState & CaptureActions>((set) => ({
|
||||
isOpen: false,
|
||||
isSubmitting: false,
|
||||
lastCapturedId: null,
|
||||
error: null,
|
||||
|
||||
open: () => set({ isOpen: true, error: null }),
|
||||
|
||||
close: () =>
|
||||
set({
|
||||
isOpen: false,
|
||||
isSubmitting: false,
|
||||
error: null,
|
||||
}),
|
||||
|
||||
setSubmitting: (submitting) => set({ isSubmitting: submitting }),
|
||||
|
||||
captureSuccess: (beadId) =>
|
||||
set({
|
||||
lastCapturedId: beadId,
|
||||
isSubmitting: false,
|
||||
isOpen: false,
|
||||
error: null,
|
||||
}),
|
||||
|
||||
captureError: (message) =>
|
||||
set({
|
||||
error: message,
|
||||
isSubmitting: false,
|
||||
isOpen: true,
|
||||
}),
|
||||
}));
|
||||
Reference in New Issue
Block a user