import { create } from 'zustand'; import { persist } from 'zustand/middleware'; import type { AppState, Job, CVTemplate, TailoringMode, LLMProvider, GeneratedCV, BatchProgress } from '@/types'; export type AppPage = 'home' | 'workflow' | 'joblist'; const initialState = { tailoringMode: 'local' as TailoringMode, llmProvider: 'groq' as LLMProvider, enableProfessionalSummary: false, includeCoverLetters: false, currentPage: 'home' as AppPage, cvTemplate: null as CVTemplate | null, jobs: [] as Job[], isSearching: false, isGenerating: false, selectedJobIds: new Set(), batchProgress: { total: 0, completed: 0, failed: 0, isProcessing: false, } as BatchProgress, generatedCVs: [] as GeneratedCV[], notification: null as AppState['notification'], }; export const useJobStore = create()( persist( (set) => ({ ...initialState, // Navigation Methods setCurrentPage: (page: AppPage) => set({ currentPage: page }), navigateToWorkflow: () => set({ currentPage: 'workflow' }), navigateToJobList: () => set({ currentPage: 'joblist' }), navigateToHome: () => set({ currentPage: 'home' }), // CV Methods setCVTemplate: (template) => set({ cvTemplate: template }), // Jobs Methods setJobs: (jobs) => set({ jobs }), addJob: (job) => set((state) => ({ jobs: [...state.jobs, job] })), removeJob: (jobId) => set((state) => ({ jobs: state.jobs.filter((j) => j.id !== jobId), })), // UI Methods setIsSearching: (value) => set({ isSearching: value }), setIsGenerating: (value) => set({ isGenerating: value }), // Selection Methods toggleJobSelection: (jobId) => set((state) => { const newSelection = new Set(state.selectedJobIds); if (newSelection.has(jobId)) { newSelection.delete(jobId); } else { newSelection.add(jobId); } return { selectedJobIds: newSelection }; }), selectAllJobs: () => set((state) => ({ selectedJobIds: new Set(state.jobs.map((j) => j.id)), })), deselectAllJobs: () => set({ selectedJobIds: new Set(), }), // Progress Methods setBatchProgress: (progress) => set({ batchProgress: progress }), // Generated CVs Methods addGeneratedCV: (cv) => set((state) => ({ generatedCVs: [...state.generatedCVs, cv], })), setGeneratedCVs: (cvs) => set({ generatedCVs: cvs }), // Notification Methods setNotification: (notification) => set({ notification }), // Settings Methods setTailoringMode: (mode) => set({ tailoringMode: mode }), setLLMProvider: (provider) => set({ llmProvider: provider }), setEnableProfessionalSummary: (enabled) => set({ enableProfessionalSummary: enabled }), setIncludeCoverLetters: (enabled) => set({ includeCoverLetters: enabled }), // Reset Method reset: () => set(initialState), }), { name: 'job-apply-store', partialize: (state) => ({ tailoringMode: state.tailoringMode, llmProvider: state.llmProvider, enableProfessionalSummary: state.enableProfessionalSummary, includeCoverLetters: state.includeCoverLetters, // Don't persist large data cvTemplate: null, jobs: [], generatedCVs: [], notification: null, }), } ) );