Spaces:
Paused
Paused
| 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<string>(), | |
| batchProgress: { | |
| total: 0, | |
| completed: 0, | |
| failed: 0, | |
| isProcessing: false, | |
| } as BatchProgress, | |
| generatedCVs: [] as GeneratedCV[], | |
| notification: null as AppState['notification'], | |
| }; | |
| export const useJobStore = create<AppState>()( | |
| 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, | |
| }), | |
| } | |
| ) | |
| ); | |