Files
igny8/docs/30-FRONTEND/STORES.md
IGNY8 VPS (Salman) 4bffede052 docs & ux improvmeents
2025-12-25 20:31:58 +00:00

376 lines
8.6 KiB
Markdown

# Zustand State Management
**Last Verified:** December 25, 2025
**Framework:** Zustand 4 with persist middleware
---
## Store Architecture
All stores in `/frontend/src/store/` use Zustand with TypeScript.
**Key Patterns:**
- `persist` middleware for localStorage persistence
- Async actions for API calls
- Selectors for derived state
---
## Auth Store (`authStore.ts`)
**Purpose:** User authentication and session management
```typescript
interface AuthState {
user: User | null;
account: Account | null;
isAuthenticated: boolean;
accessToken: string | null;
refreshToken: string | null;
isLoading: boolean;
error: string | null;
}
interface AuthActions {
login(email: string, password: string): Promise<void>;
logout(): void;
register(data: RegisterData): Promise<void>;
refreshAccessToken(): Promise<void>;
fetchUser(): Promise<void>;
updateUser(data: UserUpdate): Promise<void>;
}
```
**Persistence:** `accessToken`, `refreshToken` in localStorage
**Usage:**
```typescript
const { user, login, logout, isAuthenticated } = useAuthStore();
```
---
## Site Store (`siteStore.ts`)
**Purpose:** Site selection and management
```typescript
interface SiteState {
sites: Site[];
currentSite: Site | null;
isLoading: boolean;
error: string | null;
}
interface SiteActions {
fetchSites(): Promise<void>;
createSite(data: SiteCreate): Promise<Site>;
updateSite(id: string, data: SiteUpdate): Promise<Site>;
deleteSite(id: string): Promise<void>;
setCurrentSite(site: Site): void;
}
```
**Persistence:** `currentSite.id` in localStorage
**Auto-selection:** If no site selected and sites exist, auto-selects first site
---
## Sector Store (`sectorStore.ts`)
**Purpose:** Sector selection and management within sites
```typescript
interface SectorState {
sectors: Sector[];
currentSector: Sector | null;
isLoading: boolean;
error: string | null;
}
interface SectorActions {
fetchSectors(siteId: string): Promise<void>;
createSector(data: SectorCreate): Promise<Sector>;
updateSector(id: string, data: SectorUpdate): Promise<Sector>;
deleteSector(id: string): Promise<void>;
setCurrentSector(sector: Sector): void;
}
```
**Persistence:** `currentSector.id` in localStorage
**Dependency:** Reloads when `currentSite` changes
---
## Module Store (`moduleStore.ts`)
**Purpose:** Track which modules are enabled/disabled
```typescript
interface ModuleState {
modules: ModuleSettings;
isLoading: boolean;
error: string | null;
}
interface ModuleSettings {
planner_enabled: boolean;
writer_enabled: boolean;
linker_enabled: boolean;
optimizer_enabled: boolean;
automation_enabled: boolean;
integration_enabled: boolean;
publisher_enabled: boolean;
}
interface ModuleActions {
fetchModules(): Promise<void>;
updateModules(settings: Partial<ModuleSettings>): Promise<void>;
isModuleEnabled(module: ModuleName): boolean;
}
```
**Usage:**
```typescript
const { isModuleEnabled } = useModuleStore();
if (isModuleEnabled('planner')) { /* show planner */ }
```
**Currently used for:** Sidebar visibility only
---
## Billing Store (`billingStore.ts`)
**Purpose:** Credit balance and usage tracking
```typescript
interface BillingState {
balance: CreditBalance | null;
usage: CreditUsage[];
limits: PlanLimits | null;
isLoading: boolean;
error: string | null;
}
interface CreditBalance {
ideaCredits: number;
contentCredits: number;
imageCredits: number;
optimizationCredits: number;
}
interface BillingActions {
fetchBalance(): Promise<void>;
fetchUsage(period?: string): Promise<void>;
fetchLimits(): Promise<void>;
}
```
**Refresh triggers:**
- After content generation
- After image generation
- After optimization (when implemented)
---
## Planner Store (`plannerStore.ts`)
**Purpose:** Keywords, clusters, and content ideas state
```typescript
interface PlannerState {
keywords: Keyword[];
clusters: Cluster[];
ideas: ContentIdea[];
selectedKeywords: string[];
filters: KeywordFilters;
isLoading: boolean;
error: string | null;
}
interface PlannerActions {
fetchKeywords(siteId: string, sectorId?: string): Promise<void>;
createKeyword(data: KeywordCreate): Promise<Keyword>;
bulkDeleteKeywords(ids: string[]): Promise<void>;
autoCluster(keywordIds: string[]): Promise<void>;
generateIdeas(clusterId: string): Promise<void>;
setFilters(filters: Partial<KeywordFilters>): void;
selectKeywords(ids: string[]): void;
}
```
---
## Writer Store (`writerStore.ts`)
**Purpose:** Tasks and content management
```typescript
interface WriterState {
tasks: Task[];
content: Content[];
currentContent: Content | null;
filters: TaskFilters;
isLoading: boolean;
isGenerating: boolean;
error: string | null;
}
interface WriterActions {
fetchTasks(siteId: string, sectorId?: string): Promise<void>;
createTask(data: TaskCreate): Promise<Task>;
generateContent(taskId: string): Promise<Content>;
fetchContent(contentId: string): Promise<Content>;
updateContent(id: string, data: ContentUpdate): Promise<Content>;
generateImages(contentId: string): Promise<void>;
publishToWordPress(contentId: string): Promise<void>;
}
```
**Generation state:** `isGenerating` tracks active AI operations
---
## Automation Store (`automationStore.ts`)
**Purpose:** Automation pipeline state and control
```typescript
interface AutomationState {
config: AutomationConfig | null;
currentRun: AutomationRun | null;
pipeline: PipelineOverview | null;
history: AutomationRun[];
logs: AutomationLog[];
isLoading: boolean;
error: string | null;
}
interface AutomationActions {
fetchConfig(siteId: string): Promise<void>;
updateConfig(data: ConfigUpdate): Promise<void>;
startRun(siteId: string): Promise<void>;
pauseRun(runId: string): Promise<void>;
resumeRun(runId: string): Promise<void>;
cancelRun(runId: string): Promise<void>;
fetchPipeline(siteId: string): Promise<void>;
fetchLogs(runId: string): Promise<void>;
}
```
**Polling:** Active runs trigger status polling every 5 seconds
---
## Integration Store (`integrationStore.ts`)
**Purpose:** WordPress integration management
```typescript
interface IntegrationState {
integrations: SiteIntegration[];
currentIntegration: SiteIntegration | null;
syncStatus: SyncStatus | null;
isLoading: boolean;
isSyncing: boolean;
error: string | null;
}
interface IntegrationActions {
fetchIntegrations(siteId: string): Promise<void>;
createIntegration(data: IntegrationCreate): Promise<SiteIntegration>;
testConnection(id: string): Promise<TestResult>;
triggerSync(id: string): Promise<void>;
fetchSyncStatus(id: string): Promise<SyncStatus>;
}
```
---
## UI Store (`uiStore.ts`)
**Purpose:** UI state (sidebar, modals, notifications)
```typescript
interface UIState {
sidebarOpen: boolean;
sidebarCollapsed: boolean;
theme: 'light' | 'dark' | 'system';
notifications: Notification[];
}
interface UIActions {
toggleSidebar(): void;
collapseSidebar(): void;
setTheme(theme: Theme): void;
addNotification(notification: Notification): void;
removeNotification(id: string): void;
}
```
**Persistence:** `theme`, `sidebarCollapsed` in localStorage
---
## Store Dependencies
```
authStore
└── siteStore (loads after auth)
└── sectorStore (loads when site changes)
├── plannerStore (scoped to site/sector)
├── writerStore (scoped to site/sector)
├── automationStore (scoped to site)
└── integrationStore (scoped to site)
moduleStore (global, loads once per account)
billingStore (global, loads once per account)
uiStore (local only, no API)
```
---
## Store Files Location
```
frontend/src/store/
├── authStore.ts
├── siteStore.ts
├── sectorStore.ts
├── moduleStore.ts
├── billingStore.ts
├── plannerStore.ts
├── writerStore.ts
├── automationStore.ts
├── integrationStore.ts
├── uiStore.ts
└── index.ts (re-exports)
```
---
## Best Practices
1. **Always scope to site/sector** when fetching module data
2. **Check module enabled** before showing features
3. **Handle loading states** in UI components
4. **Clear store on logout** to prevent data leaks
5. **Use selectors** for derived/filtered data
---
## Planned Changes
| Item | Description | Priority |
|------|-------------|----------|
| Add `linkerStore` | State for internal linking results | Medium |
| Add `optimizerStore` | State for optimization results | Medium |
| Better error typing | Typed error codes per store | Low |
| DevTools integration | Zustand devtools middleware | Low |