import React, { useState, useCallback, useEffect } from 'react'; import { Tabs, Tab, Box, Button, Paper, Typography, LinearProgress } from '@mui/material'; import { Job, Candidate, SkillAssessment } from 'types/types'; import { Scrollable } from './Scrollable'; import { useAuth } from 'hooks/AuthContext'; import * as Types from 'types/types'; import { StyledMarkdown } from './StyledMarkdown'; import InputIcon from '@mui/icons-material/Input'; import TuneIcon from '@mui/icons-material/Tune'; import ArticleIcon from '@mui/icons-material/Article'; import { StatusBox, StatusIcon } from './ui/StatusIcon'; import { CopyBubble } from './CopyBubble'; import { useAppState } from 'hooks/GlobalContext'; import { StreamingOptions } from 'services/api-client'; import { useNavigate } from 'react-router-dom'; interface ResumeGeneratorProps { job: Job; candidate: Candidate; skills: SkillAssessment[]; onComplete?: (resume: string) => void; } const ResumeGenerator: React.FC = (props: ResumeGeneratorProps) => { const { job, candidate, skills, onComplete } = props; const { setSnack } = useAppState(); const navigate = useNavigate(); const { apiClient, user } = useAuth(); const [resume, setResume] = useState(''); const [prompt, setPrompt] = useState(''); const [systemPrompt, setSystemPrompt] = useState(''); const [generated, setGenerated] = useState(false); const [tabValue, setTabValue] = useState('resume'); const [status, setStatus] = useState(''); const [statusType, setStatusType] = useState(null); const [error, setError] = useState(null); const handleTabChange = (event: React.SyntheticEvent, newValue: string): void => { setTabValue(newValue); }; useEffect(() => { if (!job || !candidate || !skills || generated) { return; } setGenerated(true); setStatusType('thinking'); setStatus('Starting resume generation...'); const generateResumeHandlers: StreamingOptions = { onMessage: (message: Types.ChatMessageResume) => { const resume: Types.Resume = message.resume; setSystemPrompt(resume.systemPrompt || ''); setPrompt(resume.prompt || ''); setResume(resume.resume || ''); setStatus(''); }, onStreaming: (chunk: Types.ChatMessageStreaming) => { if (status === '') { setStatus('Generating resume...'); setStatusType('generating'); } setResume(chunk.content); }, onStatus: (status: Types.ChatMessageStatus) => { console.log('status:', status.content); setStatusType(status.activity); setStatus(status.content); }, onComplete: () => { onComplete && onComplete(resume); }, onError: (error: Types.ChatMessageError) => { console.log('error:', error); setStatusType(null); setStatus(error.content); setError(error); }, }; const generateResume = async (): Promise => { const request = await apiClient.generateResume( candidate.id || '', job.id || '', generateResumeHandlers ); await request.promise; }; generateResume(); }, [ job, candidate, apiClient, resume, skills, generated, status, setSystemPrompt, setPrompt, setResume, onComplete, setStatus, setStatusType, setError, ]); const handleSave = useCallback(async () => { if (!resume) { setSnack('No resume to save!'); return; } try { if (!candidate.id || !job.id) { setSnack('Candidate or job ID is missing.'); return; } const submission: Types.Resume = { jobId: job.id, candidateId: candidate.id, resume, systemPrompt, prompt, }; const controller = apiClient.saveResume(submission); const result = await controller.promise; if (result.resume.id) { setSnack('Resume saved successfully!'); navigate(`/candidate/resumes/${result.resume.id}`); } } catch (error) { console.error('Error saving resume:', error); setSnack('Error saving resume.'); } }, [apiClient, candidate.id, job.id, resume, setSnack, navigate, prompt, systemPrompt]); return ( } label="System" /> } label="Prompt" /> } label="Resume" /> {status && ( {statusType && } {status || 'Processing...'} {status && !error && } )} {tabValue === 'system' &&
{systemPrompt}
} {tabValue === 'prompt' &&
{prompt}
} {tabValue === 'resume' && ( <> { setSnack('Resume copied to clipboard!'); }} sx={{ position: 'absolute', top: 0, right: 0 }} content={resume} /> )}
{resume && !status && !error && ( )}
); }; export { ResumeGenerator };