From 1e04f2e070773e0a67e4deb1379ae3728d8c297f Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Fri, 27 Jun 2025 11:00:10 -0700 Subject: [PATCH] Added question editing --- frontend/src/pages/JobAnalysisPage.tsx | 2 +- frontend/src/pages/candidate/Profile.tsx | 228 ++++++++++++++++------- 2 files changed, 166 insertions(+), 64 deletions(-) diff --git a/frontend/src/pages/JobAnalysisPage.tsx b/frontend/src/pages/JobAnalysisPage.tsx index 4f46116..3c65702 100644 --- a/frontend/src/pages/JobAnalysisPage.tsx +++ b/frontend/src/pages/JobAnalysisPage.tsx @@ -104,7 +104,7 @@ const capitalize = (str: string): string => { }; // Main component -const JobAnalysisPage: React.FC = (_props: BackstoryPageProps) => { +const JobAnalysisPage: React.FC = () => { const theme = useTheme(); const { user, guest } = useAuth(); const { selectedCandidate, setSelectedCandidate } = useSelectedCandidate(); diff --git a/frontend/src/pages/candidate/Profile.tsx b/frontend/src/pages/candidate/Profile.tsx index aee95e6..9eb5f4e 100644 --- a/frontend/src/pages/candidate/Profile.tsx +++ b/frontend/src/pages/candidate/Profile.tsx @@ -13,7 +13,6 @@ import { Tab, useMediaQuery, CircularProgress, - Snackbar, Alert, Card, CardContent, @@ -49,7 +48,6 @@ import { import { useTheme } from '@mui/material/styles'; import { useAuth } from 'hooks/AuthContext'; import * as Types from 'types/types'; -import { ComingSoon } from 'components/ui/ComingSoon'; import { BackstoryPageProps } from 'components/BackstoryTab'; import { useAppState } from 'hooks/GlobalContext'; @@ -98,9 +96,9 @@ function TabPanel(props: TabPanelProps): JSX.Element { ); } -const CandidateProfile: React.FC = (_props: BackstoryPageProps) => { - const { setSnack } = useAppState(); +const CandidateProfile: React.FC = () => { const theme = useTheme(); + const { setSnack } = useAppState(); const isMobile = useMediaQuery(theme.breakpoints.down('sm')); const { user, updateUserData, apiClient } = useAuth(); @@ -111,15 +109,6 @@ const CandidateProfile: React.FC = (_props: BackstoryPagePro const [tabValue, setTabValue] = useState('info'); const [editMode, setEditMode] = useState<{ [key: string]: boolean }>({}); const [loading, setLoading] = useState(false); - const [snackbar, setSnackbar] = useState<{ - open: boolean; - message: string; - severity: 'success' | 'error' | 'info' | 'warning'; - }>({ - open: false, - message: '', - severity: 'success', - }); // Form data state const [formData, setFormData] = useState>({}); @@ -137,6 +126,11 @@ const CandidateProfile: React.FC = (_props: BackstoryPagePro level: 'beginner', yearsOfExperience: 0, }); + + const [newQuestion, setNewQuestion] = useState>({ + question: '', + }); + const [newExperience, setNewExperience] = useState>({ companyName: '', position: '', @@ -155,7 +149,6 @@ const CandidateProfile: React.FC = (_props: BackstoryPagePro } else { setProfileImage(''); } - console.log({ isPublic: candidate.isPublic }); } }, [candidate]); @@ -195,19 +188,11 @@ const CandidateProfile: React.FC = (_props: BackstoryPagePro console.log(`Set profile image to: ${candidate.profileImage}`); updateUserData(candidate); } else { - setSnackbar({ - open: true, - message: 'Failed to upload profile image. Please try again.', - severity: 'error', - }); + setSnack('Failed to upload profile image. Please try again.', 'error'); } } catch (error) { console.error('Error uploading profile image:', error); - setSnackbar({ - open: true, - message: 'Failed to upload profile image. Please try again.', - severity: 'error', - }); + setSnack('Failed to upload profile image. Please try again.', 'error'); } }; @@ -230,11 +215,7 @@ const CandidateProfile: React.FC = (_props: BackstoryPagePro toggleEditMode(section); } } catch (error) { - setSnackbar({ - open: true, - message: 'Failed to update profile. Please try again.', - severity: 'error', - }); + setSnack('Failed to update profile. Please try again.', 'error'); } finally { setLoading(false); } @@ -258,6 +239,7 @@ const CandidateProfile: React.FC = (_props: BackstoryPagePro yearsOfExperience: 0, }); setSkillDialog(false); + setSnack('Skill added successfully!'); } }; @@ -265,6 +247,30 @@ const CandidateProfile: React.FC = (_props: BackstoryPagePro const handleRemoveSkill = (index: number): void => { const updatedSkills = (formData.skills || []).filter((_, i) => i !== index); setFormData({ ...formData, skills: updatedSkills }); + setSnack('Skill removed successfully!'); + }; + + // Add new question + const handleAddQuestion = (): void => { + if (newQuestion.question?.trim()) { + const questionToAdd: Types.CandidateQuestion = { + question: newQuestion.question.trim(), + }; + const updatedQuestions = [...(formData.questions || []), questionToAdd]; + setFormData({ ...formData, questions: updatedQuestions }); + setNewQuestion({ + question: '', + }); + setQuestionDialog(false); + setSnack('Question added successfully!'); + } + }; + + // Remove question + const handleRemoveQuestion = (index: number): void => { + const updatedQuestions = (formData.questions || []).filter((_, i) => i !== index); + setFormData({ ...formData, questions: updatedQuestions }); + setSnack('Question removed successfully!'); }; // Add new work experience @@ -285,6 +291,7 @@ const CandidateProfile: React.FC = (_props: BackstoryPagePro location: { city: '', country: '' }, }); setExperienceDialog(false); + setSnack('Experience added successfully!'); } }; @@ -292,6 +299,7 @@ const CandidateProfile: React.FC = (_props: BackstoryPagePro const handleRemoveExperience = (index: number): void => { const updatedExperience = (formData.experience || []).filter((_, i) => i !== index); setFormData({ ...formData, experience: updatedExperience }); + setSnack('Experience removed successfully!'); }; // Basic Information Tab @@ -676,14 +684,27 @@ const CandidateProfile: React.FC = (_props: BackstoryPagePro sx={{ fontSize: { xs: '0.9rem', sm: '1.25rem' }, wordBreak: 'break-word', + mb: 1, }} > {question.question} + {/* {question.category && ( + + )} */} handleRemoveSkill(index)} + onClick={(): void => handleRemoveQuestion(index)} color="error" sx={{ ml: 1 }} > @@ -696,7 +717,7 @@ const CandidateProfile: React.FC = (_props: BackstoryPagePro ))} - {(!formData.skills || formData.skills.length === 0) && ( + {(!formData.questions || formData.questions.length === 0) && ( No questions added yet. Click "Add Question" to get started. @@ -855,19 +876,17 @@ const CandidateProfile: React.FC = (_props: BackstoryPagePro - {(!formData.experience || formData.experience.length === 0) && ( - - No work experience added yet. Click "Add Experience" to get started. - - )} + + No education added yet. Click "Add Education" to get started. + ); @@ -947,15 +966,15 @@ const CandidateProfile: React.FC = (_props: BackstoryPagePro - {renderSkills()} + {renderSkills()} - {renderExperience()} + {renderExperience()} - {renderEducation()} + {renderEducation()} @@ -1012,7 +1031,7 @@ const CandidateProfile: React.FC = (_props: BackstoryPagePro onChange={(e): void => setNewSkill({ ...newSkill, - level: e.target.value as Types.SkillLevel, + level: e.target.value as 'beginner' | 'intermediate' | 'advanced' | 'expert', }) } label="Proficiency Level" @@ -1066,6 +1085,104 @@ const CandidateProfile: React.FC = (_props: BackstoryPagePro + {/* Add Question Dialog */} + setQuestionDialog(false)} + maxWidth="sm" + fullWidth + fullScreen={isMobile} + PaperProps={{ + sx: { + ...(isMobile && { + margin: 0, + width: '100%', + height: '100%', + maxHeight: '100%', + }), + }, + }} + > + Add New Question + + + + setNewQuestion({ ...newQuestion, question: e.target.value })} + placeholder="What would you potential employers to ask about you?" + size={isMobile ? 'small' : 'medium'} + /> + + {/* + setNewQuestion({ ...newQuestion, category: e.target.value })} + placeholder="e.g., General, Technical, Behavioral" + size={isMobile ? 'small' : 'medium'} + /> + */} + {/* + + setNewQuestion({ + ...newQuestion, + isActive: e.target.checked, + }) + } + size={isMobile ? 'small' : 'medium'} + /> + } + label="Active" + sx={{ + '& .MuiFormControlLabel-label': { + fontSize: { xs: '0.875rem', sm: '1rem' }, + }, + }} + /> + */} + + + + + + + + {/* Add Experience Dialog */} = (_props: BackstoryPagePro - - {/* Snackbar for notifications */} - setSnackbar({ ...snackbar, open: false })} - > - setSnackbar({ ...snackbar, open: false })} - severity={snackbar.severity} - sx={{ width: '100%' }} - > - {snackbar.message} - - ); };