import React, { useState, useEffect } from 'react'; import { Box, Stepper, Step, StepLabel, Button, Typography, Paper, TextField, Grid, Card, CardContent, CardActionArea, Avatar, Divider, CircularProgress, Container, useTheme, Snackbar, Alert, Dialog, DialogTitle, DialogContent, DialogContentText, DialogActions, InputAdornment, IconButton } from '@mui/material'; import SearchIcon from '@mui/icons-material/Search'; import PersonIcon from '@mui/icons-material/Person'; import WorkIcon from '@mui/icons-material/Work'; import AssessmentIcon from '@mui/icons-material/Assessment'; import DescriptionIcon from '@mui/icons-material/Description'; import FileUploadIcon from '@mui/icons-material/FileUpload'; import { JobMatchAnalysis } from 'components/JobMatchAnalysis'; import { Candidate } from "types/types"; import { useNavigate } from 'react-router-dom'; import { BackstoryPageProps } from 'components/BackstoryTab'; import { useAuth } from 'hooks/AuthContext'; import { useSelectedCandidate } from 'hooks/GlobalContext'; import { CandidateInfo } from 'components/CandidateInfo'; import { ComingSoon } from 'components/ui/ComingSoon'; // Main component const JobAnalysisPage: React.FC = (props: BackstoryPageProps) => { const theme = useTheme(); const { user } = useAuth(); const { selectedCandidate, setSelectedCandidate } = useSelectedCandidate() const { setSnack, submitQuery } = props; const backstoryProps = { setSnack, submitQuery }; // State management const [activeStep, setActiveStep] = useState(0); const [jobDescription, setJobDescription] = useState(''); const [jobTitle, setJobTitle] = useState(''); const [jobLocation, setJobLocation] = useState(''); const [analysisStarted, setAnalysisStarted] = useState(false); const [error, setError] = useState(null); const [openUploadDialog, setOpenUploadDialog] = useState(false); const { apiClient } = useAuth(); const [candidates, setCandidates] = useState(null); useEffect(() => { if (candidates !== null || selectedCandidate) { return; } const getCandidates = async () => { try { const results = await apiClient.getCandidates(); const candidates: Candidate[] = results.data; candidates.sort((a, b) => { let result = a.lastName.localeCompare(b.lastName); if (result === 0) { result = a.firstName.localeCompare(b.firstName); } if (result === 0) { result = a.username.localeCompare(b.username); } return result; }); console.log(candidates); setCandidates(candidates); } catch (err) { setSnack("" + err); } }; getCandidates(); }, [candidates, setSnack]); useEffect(() => { if (selectedCandidate && activeStep === 0) { setActiveStep(1); } }, [selectedCandidate, activeStep]); // Steps in our process const steps = [ { index: 1, label: 'Job Description', icon: }, { index: 2, label: 'AI Analysis', icon: }, { index: 3, label: 'Generated Resume', icon: } ]; if (!selectedCandidate) { steps.unshift({ index: 0, label: 'Select Candidate', icon: }) } const fetchMatchForRequirement = async (requirement: string): Promise => { // Create different mock responses based on the requirement const mockResponses: Record = { "5+ years of React development experience": { requirement: "5+ years of React development experience", status: "complete", matchScore: 85, assessment: "The candidate demonstrates extensive React experience spanning over 6 years, with a strong portfolio of complex applications and deep understanding of React's component lifecycle and hooks.", citations: [ { text: "Led frontend development team of 5 engineers to rebuild our customer portal using React and TypeScript, resulting in 40% improved performance and 30% reduction in bugs.", source: "Resume, Work Experience", relevance: 95 }, { text: "Developed and maintained reusable React component library used across 12 different products within the organization.", source: "Resume, Work Experience", relevance: 90 }, { text: "I've been working with React since 2017, building everything from small widgets to enterprise applications.", source: "Cover Letter", relevance: 85 } ] }, "Strong TypeScript skills": { requirement: "Strong TypeScript skills", status: "complete", matchScore: 90, assessment: "The candidate shows excellent TypeScript proficiency through their work history and personal projects. They have implemented complex type systems and demonstrate an understanding of advanced TypeScript features.", citations: [ { text: "Converted a legacy JavaScript codebase of 100,000+ lines to TypeScript, implementing strict type checking and reducing runtime errors by 70%.", source: "Resume, Projects", relevance: 98 }, { text: "Created comprehensive TypeScript interfaces for our GraphQL API, ensuring type safety across the entire application stack.", source: "Resume, Technical Skills", relevance: 95 } ] }, "Experience with RESTful APIs": { requirement: "Experience with RESTful APIs", status: "complete", matchScore: 75, assessment: "The candidate has good experience with RESTful APIs, having both consumed and designed them. They understand REST principles but have less documented experience with API versioning and caching strategies.", citations: [ { text: "Designed and implemented a RESTful API serving over 1M requests daily with a focus on performance and scalability.", source: "Resume, Technical Projects", relevance: 85 }, { text: "Worked extensively with third-party APIs including Stripe, Twilio, and Salesforce to integrate payment processing and communication features.", source: "Resume, Work Experience", relevance: 70 } ] }, "Knowledge of state management solutions (Redux, Context API)": { requirement: "Knowledge of state management solutions (Redux, Context API)", status: "complete", matchScore: 65, assessment: "The candidate has moderate experience with state management, primarily using Redux. There is less evidence of Context API usage, which could indicate a knowledge gap in more modern React state management approaches.", citations: [ { text: "Implemented Redux for global state management in an e-commerce application, handling complex state logic for cart, user preferences, and product filtering.", source: "Resume, Skills", relevance: 80 }, { text: "My experience includes working with state management libraries like Redux and MobX.", source: "Cover Letter", relevance: 60 } ] }, "Experience with CI/CD pipelines": { requirement: "Experience with CI/CD pipelines", status: "complete", matchScore: 40, assessment: "The candidate shows limited experience with CI/CD pipelines. While they mention some exposure to Jenkins and GitLab CI, there is insufficient evidence of setting up or maintaining comprehensive CI/CD workflows.", citations: [ { text: "Familiar with CI/CD tools including Jenkins and GitLab CI.", source: "Resume, Skills", relevance: 40 } ] }, "Cloud platform experience (AWS, Azure, GCP)": { requirement: "Cloud platform experience (AWS, Azure, GCP)", status: "complete", matchScore: 30, assessment: "The candidate demonstrates minimal experience with cloud platforms. There is a brief mention of AWS S3 and Lambda, but no substantial evidence of deeper cloud architecture knowledge or experience with Azure or GCP.", citations: [ { text: "Used AWS S3 for file storage and Lambda for image processing in a photo sharing application.", source: "Resume, Projects", relevance: 35 } ] } }; // Return a promise that resolves with the mock data after a delay return new Promise((resolve) => { // Different requirements resolve at different speeds to simulate real-world analysis const delay = Math.random() * 5000 + 2000; // 2-7 seconds setTimeout(() => { resolve(mockResponses[requirement]); }, delay); }); }; // Navigation handlers const handleNext = () => { if (activeStep === 0 && !selectedCandidate) { setError('Please select a candidate before continuing.'); return; } if (activeStep === 1) { if ((/*(extraInfo && !jobTitle) || */!jobDescription)) { setError('Please provide job description before continuing.'); return; } } if (activeStep === 2) { setAnalysisStarted(true); } setActiveStep((prevActiveStep) => prevActiveStep + 1); }; const handleBack = () => { setActiveStep((prevActiveStep) => prevActiveStep - 1); }; const handleReset = () => { // setActiveStep(0); setActiveStep(1); // setSelectedCandidate(null); setJobDescription(''); // setJobTitle(''); // setJobLocation(''); setAnalysisStarted(false); }; // Render function for the candidate selection step const renderCandidateSelection = () => ( Select a Candidate {/* setSearchQuery(e.target.value)} InputProps={{ endAdornment: ( ), }} sx={{ mr: 2 }} /> */} {candidates?.map((candidate) => ( setSelectedCandidate(candidate)} sx={{ height: '100%', display: 'flex', flexDirection: 'column', alignItems: 'stretch' }} > {candidate.fullName} {candidate.description} {candidate.location && Location: {candidate.location.country} } Email: {candidate.email} {candidate.phone && Phone: {candidate.phone} } ))} ); const extraInfo = false; // Render function for the job description step const renderJobDescription = () => ( {extraInfo && <> Enter Job Details setJobTitle(e.target.value)} required margin="normal" /> setJobLocation(e.target.value)} margin="normal" /> } Job Description {extraInfo && } setJobDescription(e.target.value)} required InputProps={{ startAdornment: ( ), }} /> The job description will be used to extract requirements for candidate matching. ); // Render function for the analysis step const renderAnalysis = () => ( {selectedCandidate && ( )} ); const renderResume = () => ( {selectedCandidate && Resume Builder} ); // If no user is logged in, show message if (!user) { return ( Please log in to access candidate analysis ); } return ( Candidate Analysis {selectedCandidate && } Match candidates to job requirements with AI-powered analysis {steps.map(step => ( ( = step.index ? theme.palette.primary.main : theme.palette.grey[300], color: 'white' }} > {step.icon} ) }} > {step.label} ))} {activeStep === 0 && renderCandidateSelection()} {activeStep === 1 && renderJobDescription()} {activeStep === 2 && renderAnalysis()} {activeStep === 3 && renderResume()} {activeStep === steps[steps.length - 1].index ? ( ) : ( )} {/* Error Snackbar */} setError(null)} anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }} > setError(null)} severity="error" sx={{ width: '100%' }}> {error} {/* Upload Dialog */} setOpenUploadDialog(false)}> Upload Job Description Upload a job description document (.pdf, .docx, .txt, or .md) ); }; export { JobAnalysisPage };