import { useState, useEffect, useRef } from 'react'; import { Authentication } from '../../../scripts/pocketbase/Authentication'; import { FileManager } from '../../../scripts/pocketbase/FileManager'; import { Update } from '../../../scripts/pocketbase/Update'; import { Get } from '../../../scripts/pocketbase/Get'; import { Collections, type User } from '../../../schemas/pocketbase/schema'; import { toast } from 'react-hot-toast'; import FilePreview from '../universal/FilePreview'; export default function ResumeSettings() { const auth = Authentication.getInstance(); const fileManager = FileManager.getInstance(); const update = Update.getInstance(); const get = Get.getInstance(); const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); const [uploading, setUploading] = useState(false); const [resumeUrl, setResumeUrl] = useState(null); const [resumeFilename, setResumeFilename] = useState(null); const [resumeFile, setResumeFile] = useState(null); const fileInputRef = useRef(null); // Fetch user data on component mount useEffect(() => { const fetchUserData = async () => { try { setLoading(true); const currentUser = auth.getCurrentUser(); if (!currentUser) { throw new Error('User not authenticated'); } const userData = await get.getOne('users', currentUser.id); setUser(userData); // Check if user has a resume if (userData.resume) { const resumeFile = userData.resume; const fileUrl = fileManager.getFileUrl('users', userData.id, resumeFile); setResumeUrl(fileUrl); setResumeFilename(resumeFile); } } catch (error) { console.error('Error fetching user data:', error); toast.error('Failed to load user data'); } finally { setLoading(false); } }; fetchUserData(); }, []); const handleFileChange = (e: React.ChangeEvent) => { const files = e.target.files; if (files && files.length > 0) { const file = files[0]; // Validate file type (PDF or DOCX) const allowedTypes = ['application/pdf', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document']; const fileExtension = file.name.split('.').pop()?.toLowerCase(); // Check both MIME type and file extension if (!allowedTypes.includes(file.type) && !(fileExtension === 'pdf' || fileExtension === 'docx')) { toast.error('Please upload a PDF or DOCX file'); if (fileInputRef.current) { fileInputRef.current.value = ''; } return; } // Validate file size (max 50MB) const maxSize = 50 * 1024 * 1024; // 50MB in bytes if (file.size > maxSize) { const sizeMB = (file.size / (1024 * 1024)).toFixed(2); toast.error(`File too large (${sizeMB}MB). Maximum size is 50MB.`); if (fileInputRef.current) { fileInputRef.current.value = ''; } return; } setResumeFile(file); setResumeFilename(file.name); toast.success(`File "${file.name}" selected. Click Upload to confirm.`); } }; const handleUpload = async () => { if (!resumeFile || !user) { toast.error('No file selected or user not authenticated'); return; } try { setUploading(true); // Create a FormData object for the file upload const formData = new FormData(); formData.append('resume', resumeFile); // Show progress toast const loadingToast = toast.loading('Uploading resume...'); // Log the file being uploaded for debugging // console.log('Uploading file:', { // name: resumeFile.name, // size: resumeFile.size, // type: resumeFile.type // }); let updatedUserData: User; try { // Use the FileManager to upload the file directly // console.log('Using FileManager to upload resume file'); // Upload the file using the FileManager's uploadFile method const result = await fileManager.uploadFile( Collections.USERS, user.id, 'resume', resumeFile, false // Don't append, replace existing file ); // Verify the file was uploaded by checking the response if (!result || !result.resume) { throw new Error('Resume was not properly saved to the user record'); } // console.log('Resume upload successful:', result.resume); // Store the updated user data updatedUserData = result; // Fetch the updated user record to ensure we have the latest data const refreshedUser = await get.getOne(Collections.USERS, user.id); // console.log('Refreshed user data:', refreshedUser); // Double check that the resume field is populated if (!refreshedUser.resume) { // console.warn('Resume field is missing in the refreshed user data'); } } catch (uploadError) { console.error('Error in file upload process:', uploadError); toast.dismiss(loadingToast); toast.error('Failed to upload resume: ' + (uploadError instanceof Error ? uploadError.message : 'Unknown error')); setUploading(false); return; } // Get the URL of the uploaded file if (!updatedUserData.resume) { throw new Error('Resume filename is missing in the updated user data'); } const fileUrl = fileManager.getFileUrl('users', user.id, updatedUserData.resume); // Update state with the new resume information setResumeUrl(fileUrl); setResumeFilename(updatedUserData.resume); setResumeFile(null); // Reset file input if (fileInputRef.current) { fileInputRef.current.value = ''; } // Dismiss loading toast and show success message toast.dismiss(loadingToast); toast.success('Resume uploaded successfully'); // Log the successful upload // console.log('Resume uploaded successfully:', updatedUserData.resume); // Dispatch a custom event to notify the dashboard about the resume upload const event = new CustomEvent('resumeUploaded', { detail: { hasResume: true } }); window.dispatchEvent(event); } catch (error) { console.error('Error uploading resume:', error); // Provide more specific error messages based on the error type if (error instanceof Error) { if (error.message.includes('size')) { toast.error('File size exceeds the maximum allowed limit (50MB)'); } else if (error.message.includes('type')) { toast.error('Invalid file type. Please upload a PDF or DOCX file'); } else if (error.message.includes('network')) { toast.error('Network error. Please check your connection and try again'); } else if (error.message.includes('permission')) { toast.error('Permission denied. You may not have the right permissions'); } else { toast.error(`Upload failed: ${error.message}`); } } else { toast.error('Failed to upload resume. Please try again later'); } } finally { setUploading(false); } }; const handleDelete = async () => { if (!user) { toast.error('User not authenticated'); return; } // Ask for confirmation before deleting if (!confirm('Are you sure you want to delete your resume? This action cannot be undone.')) { return; } try { setUploading(true); // Show progress toast const loadingToast = toast.loading('Deleting resume...'); // Log the deletion attempt // console.log('Attempting to delete resume for user:', user.id); // Create a FormData with empty resume field to remove the file const formData = new FormData(); formData.append('resume', ''); try { // console.log('Using FileManager to delete resume file'); // Use the FileManager's deleteFile method to remove the file const result = await fileManager.deleteFile( Collections.USERS, user.id, 'resume' ); // Verify the file was deleted if (result.resume) { // console.warn('Resume field still exists after deletion attempt:', result.resume); toast.dismiss(loadingToast); toast.error('Failed to completely remove the resume. Please try again.'); setUploading(false); return; } // console.log('Resume deletion successful for user:', user.id); // Fetch the updated user record to ensure we have the latest data const refreshedUser = await get.getOne(Collections.USERS, user.id); // console.log('Refreshed user data after deletion:', refreshedUser); // Double check that the resume field is empty if (refreshedUser.resume) { // console.warn('Resume field is still present in the refreshed user data:', refreshedUser.resume); } } catch (deleteError) { console.error('Error in file deletion process:', deleteError); toast.dismiss(loadingToast); toast.error('Failed to delete resume: ' + (deleteError instanceof Error ? deleteError.message : 'Unknown error')); setUploading(false); return; } // Update state to reflect the deletion setResumeUrl(null); setResumeFilename(null); // Dismiss loading toast and show success message toast.dismiss(loadingToast); toast.success('Resume deleted successfully'); // Log the successful deletion // console.log('Resume deleted successfully for user:', user.id); // Dispatch a custom event to notify the dashboard about the resume deletion const event = new CustomEvent('resumeUploaded', { detail: { hasResume: false } }); window.dispatchEvent(event); } catch (error) { console.error('Error deleting resume:', error); // Provide more specific error messages based on the error type if (error instanceof Error) { if (error.message.includes('permission')) { toast.error('Permission denied. You may not have the right permissions'); } else if (error.message.includes('network')) { toast.error('Network error. Please check your connection and try again'); } else { toast.error(`Deletion failed: ${error.message}`); } } else { toast.error('Failed to delete resume. Please try again later'); } } finally { setUploading(false); } }; const handleReplace = async () => { if (!user) { toast.error('User not authenticated'); return; } // Create a file input element const fileInput = document.createElement('input'); fileInput.type = 'file'; fileInput.accept = '.pdf,.docx'; fileInput.style.display = 'none'; document.body.appendChild(fileInput); // Trigger click to open file dialog fileInput.click(); // Handle file selection fileInput.onchange = async (e) => { const input = e.target as HTMLInputElement; if (!input.files || input.files.length === 0) { document.body.removeChild(fileInput); return; } const file = input.files[0]; // Validate file type (PDF or DOCX) const allowedTypes = ['application/pdf', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document']; const fileExtension = file.name.split('.').pop()?.toLowerCase(); if (!allowedTypes.includes(file.type) && !(fileExtension === 'pdf' || fileExtension === 'docx')) { toast.error('Please upload a PDF or DOCX file'); document.body.removeChild(fileInput); return; } // Validate file size (max 50MB) const maxSize = 50 * 1024 * 1024; // 50MB in bytes if (file.size > maxSize) { const sizeMB = (file.size / (1024 * 1024)).toFixed(2); toast.error(`File too large (${sizeMB}MB). Maximum size is 50MB.`); document.body.removeChild(fileInput); return; } try { setUploading(true); // Show progress toast const loadingToast = toast.loading('Replacing resume...'); // Log the file being uploaded for debugging // console.log('Replacing resume with file:', { // name: file.name, // size: file.size, // type: file.type // }); // Create a FormData object for the file upload const formData = new FormData(); formData.append('resume', file); // Use the update service to directly update the user record const result = await update.updateFields( Collections.USERS, user.id, formData ); // Verify the file was uploaded if (!result || !result.resume) { throw new Error('Resume was not properly saved to the user record'); } // Get the URL of the uploaded file const fileUrl = fileManager.getFileUrl('users', user.id, result.resume); // Update state with the new resume information setResumeUrl(fileUrl); setResumeFilename(result.resume); setResumeFile(null); // Dismiss loading toast and show success message toast.dismiss(loadingToast); toast.success('Resume replaced successfully'); // Dispatch a custom event to notify the dashboard about the resume upload const event = new CustomEvent('resumeUploaded', { detail: { hasResume: true } }); window.dispatchEvent(event); } catch (error) { console.error('Error replacing resume:', error); toast.error('Failed to replace resume: ' + (error instanceof Error ? error.message : 'Unknown error')); } finally { setUploading(false); document.body.removeChild(fileInput); } }; }; return (
{loading ? (
) : ( <> {/* Resume Upload Section */}

Resume

Upload your resume for recruiters and career opportunities

{!resumeUrl && (
)}
{/* File selected but not uploaded yet */} {resumeFile && !uploading && (

{resumeFile.name}

{(resumeFile.size / 1024 / 1024).toFixed(2)} MB

)} {/* Uploading state */} {uploading && (
Processing your resume...
)} {/* Resume preview */} {resumeUrl && resumeFilename && !resumeFile && !uploading && (

Current Resume

)} {/* Resume upload guidelines */}

Resume Guidelines

  • Accepted formats: PDF, DOCX
  • Maximum file size: 50MB
  • Keep your resume up-to-date for better opportunities
  • Highlight your skills, experience, and education
{/* Resume Benefits */}

Why Upload Your Resume?

  • Increase visibility to recruiters and industry partners
  • Get matched with relevant job opportunities
  • Simplify application process for IEEE UCSD events
  • Access personalized career resources and recommendations
)}
); }