File size: 3,443 Bytes
88da18c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
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,
      }),
    }
  )
);