import React from 'react'; import { motion } from 'framer-motion'; import { ToggleLeft, ToggleRight, Zap, Check } from 'lucide-react'; import { Card, Button, Select } from '@/components/common'; import Modal from '@/components/common/Modal'; import { useJobStore } from '@/store/appStore'; import { jobsAPI } from '@/utils/api'; import type { TailoringMode, LLMProvider } from '@/types'; interface SettingsModalProps { isOpen: boolean; onClose: () => void; } const SettingsModal: React.FC = ({ isOpen, onClose }) => { const { tailoringMode, llmProvider, setEnableProfessionalSummary: setStoreProfessionalSummary, setIncludeCoverLetters: setStoreCoverLetters, setTailoringMode, setLLMProvider, setNotification, } = useJobStore(); const [draftMode, setDraftMode] = React.useState(tailoringMode); const [draftProvider, setDraftProvider] = React.useState(llmProvider || 'groq'); const [enableProfessionalSummary, setEnableProfessionalSummary] = React.useState(false); const [includeCoverLetters, setIncludeCoverLetters] = React.useState(false); const [isSaving, setIsSaving] = React.useState(false); const [isLoading, setIsLoading] = React.useState(false); const llmProviders: Array<{ value: LLMProvider; label: string; description: string }> = [ { value: 'ollama', label: 'Ollama (Local)', description: 'Runs locally, slowest' }, { value: 'groq', label: 'Groq API', description: 'Fast and cost-effective' }, { value: 'grok', label: 'Grok API', description: 'Fast and affordable' }, { value: 'openai', label: 'OpenAI', description: 'Premium quality' }, ]; React.useEffect(() => { if (!isOpen) { return; } setDraftMode(tailoringMode); setDraftProvider(llmProvider || 'groq'); const loadConfig = async () => { setIsLoading(true); try { const config = await jobsAPI.getConfig(); setDraftMode(config.tailoring_mode); setDraftProvider(config.llm_provider); setEnableProfessionalSummary(!!config.enable_professional_summary); setIncludeCoverLetters(!!config.include_cover_letters); setTailoringMode(config.tailoring_mode); setLLMProvider(config.llm_provider); setStoreProfessionalSummary(!!config.enable_professional_summary); setStoreCoverLetters(!!config.include_cover_letters); } catch (error) { setNotification({ type: 'error', message: 'Could not load settings. Using current values.', }); } finally { setIsLoading(false); } }; void loadConfig(); }, [ isOpen, llmProvider, setLLMProvider, setNotification, setStoreCoverLetters, setStoreProfessionalSummary, setTailoringMode, tailoringMode, ]); const handleSave = async () => { setIsSaving(true); try { await jobsAPI.saveSettings({ tailoring_mode: draftMode, llm_provider: draftProvider, enable_professional_summary: enableProfessionalSummary, include_cover_letters: includeCoverLetters, }); setTailoringMode(draftMode); setLLMProvider(draftProvider); setStoreProfessionalSummary(enableProfessionalSummary); setStoreCoverLetters(includeCoverLetters); setNotification({ type: 'success', message: 'Settings saved successfully', }); onClose(); } catch (error) { setNotification({ type: 'error', message: 'Failed to save settings', }); } finally { setIsSaving(false); } }; return ( {/* Tailoring Mode Section */}

CV Tailoring Mode

Choose how your CVs are tailored to job descriptions

{[ { mode: 'local' as TailoringMode, label: 'Smart Mode (Local)', description: 'Uses NLP-based skill matching', icon: ToggleLeft, }, { mode: 'api' as TailoringMode, label: 'AI Mode (API)', description: 'Uses advanced AI models for better tailoring', icon: ToggleRight, }, ].map((option) => ( setDraftMode(option.mode)} className={`w-full p-3 rounded-lg border transition-all ${ draftMode === option.mode ? 'border-emerald-500 bg-emerald-500/10' : 'border-slate-700 bg-slate-800/30 hover:border-emerald-400/30' }`} disabled={isLoading || isSaving} >

{option.label}

{option.description}

{draftMode === option.mode && (
)}
))}
{/* LLM Provider Section (if API mode) */} {draftMode === 'api' && (

AI Model Provider