USER
# app.py
from flask import Flask, request, jsonify, send_from_directory
from flask_cors import CORS
import pandas as pd
import os
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
from werkzeug.utils import secure_filename
import datetime
import logging
app = Flask(__name__)
CORS(app) # Enable CORS for all routes
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger
# app.py (continued)
# Configuration
UPLOAD_FOLDER = 'uploads'
DATA_FOLDER = 'data'
ALLOWED_EXTENSIONS = {'pdf', 'doc', 'docx'}
EXCEL_FILE = os.path.join(DATA_FOLDER, 'referrals.xlsx')
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 # 16MB max upload size
# Create necessary folders if they don't exist
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
os.makedirs(DATA_FOLDER, exist_ok=True)
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
def send_email_notification(referral_data):
"""Send email notification to HR about new referral."""
try:
# Email configuration (use environment variables in production)
SMTP_SERVER = os.environ.get('SMTP_SERVER', 'smtp.gmail.com')
SMTP_PORT = int(os.environ.get('SMTP_PORT', 587))
SENDER_EMAIL = os.environ.get('SENDER_EMAIL', 'your-email@company.com')
SENDER_PASSWORD = os.environ.get('SENDER_PASSWORD', 'your-email-password')
HR_EMAIL = os.environ.get('HR_EMAIL', 'hr@company.com')
# Create message
msg = MIMEMultipart()
msg['From'] = SENDER_EMAIL
msg['To'] = HR_EMAIL
msg['Subject'] = f"New Referral: {referral_data['candidateFirstName']} {referral_data['candidateLastName']}"
# Email body
body = f"""
New Candidate Referral Details:
Candidate: {referral_data['candidateFirstName']} {referral_data['candidateLastName']}
Email: {referral_data['email']}
Phone: {referral_data['countryCode']} {referral_data['mobileNumber']}
Experience: {referral_data['workExperience']}
Position: {referral_data['applyingFor']}
Job Code: {referral_data['jobCode']}
Department: {referral_data['department']}
College: {referral_data['collegeName']}, {referral_data['collegeCity']}
Referred By:
Name: {referral_data['employeeName']}
ID: {referral_data['employeeId']}
Email: {referral_data['employeeEmail']}
Date: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
"""
msg.attach(MIMEText(body, 'plain'))
# Attach resume if available
if 'resumePath' in referral_data and os.path.exists(referral_data['resumePath']):
with open(referral_data['resumePath'], 'rb') as f:
attachment = MIMEApplication(f.read(), _subtype=referral_data['resumePath'].split('.')[-1])
attachment.add_header('Content-Disposition', 'attachment',
filename=os.path.basename(referral_data['resumePath']))
msg.attach(attachment)
# Send email
with smtplib.SMTP(SMTP_SERVER, SMTP_PORT) as server:
server.starttls()
server.login(SENDER_EMAIL, SENDER_PASSWORD)
server.send_message(msg)
logger.info(f"Email notification sent for referral of {referral_data['candidateFirstName']} {referral_data['candidateLastName']}")
return True
except Exception as e:
logger.error(f"Failed to send email: {str(e)}")
return False
def save_to_excel(referral_data):
"""Save referral data to Excel file."""
try:
# Prepare data for Excel
excel_data = {
'Candidate Name': f"{referral_data['candidateFirstName']} {referral_data['candidateLastName']}",
'Email': referral_data['email'],
'Mobile': f"{referral_data['countryCode']} {referral_data['mobileNumber']}",
'Experience': referral_data['workExperience'],
'Position': referral_data['applyingFor'],
'Job Code': referral_data['jobCode'],
'Department': referral_data['department'],
'College': referral_data['collegeName'],
'College City': referral_data['collegeCity'],
'Resume': referral_data.get('resumeFileName', 'No file'),
'Referred By': referral_data['employeeName'],
'Employee ID': referral_data['employeeId'],
'Employee Email': referral_data['employeeEmail'],
'Submission Date': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
}
# Create DataFrame
df_new = pd.DataFrame([excel_data])
# Check if excel file exists and append, otherwise create new
if os.path.exists(EXCEL_FILE):
df_existing = pd.read_excel(EXCEL_FILE)
df_combined = pd.concat([df_existing, df_new], ignore_index=True)
df_combined.to_excel(EXCEL_FILE, index=False)
else:
df_new.to_excel(EXCEL_FILE, index=False)
logger.info(f"Referral data saved to Excel for {referral_data['candidateFirstName']} {referral_data['candidateLastName']}")
return True
except Exception as e:
logger.error(f"Failed to save to Excel: {str(e)}")
return False
@app.route('/api/submit-referral', methods=['POST'])
def submit_referral():
"""Handle referral submission from the frontend."""
try:
# Extract form data
form_data = request.form.to_dict()
# Handle resume file upload
resume_file = request.files.get('resume')
resume_path = None
if resume_file and allowed_file(resume_file.filename):
filename = secure_filename(f"{form_data['candidateFirstName']}_{form_data['candidateLastName']}_{datetime.datetime.now().strftime('%Y%m%d%H%M%S')}_resume{os.path.splitext(resume_file.filename)[1]}")
resume_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
resume_file.save(resume_path)
form_data['resumePath'] = resume_path
form_data['resumeFileName'] = filename
# Save data to Excel
save_to_excel(form_data)
# Send email notification
send_email_notification(form_data)
return jsonify({
'success': True,
'message': 'Referral submitted successfully'
}), 200
except Exception as e:
logger.error(f"Error in referral submission: {str(e)}")
return jsonify({
'success': False,
'message': f'Error: {str(e)}'
}), 500
@app.route('/api/get-referrals', methods=['GET'])
def get_referrals():
"""Get all referrals from Excel file."""
try:
if os.path.exists(EXCEL_FILE):
df = pd.read_excel(EXCEL_FILE)
return jsonify({
'success': True,
'data': df.to_dict('records')
}), 200
else:
return jsonify({
'success': True,
'data': []
}), 200
except Exception as e:
logger.error(f"Error fetching referrals: {str(e)}")
return jsonify({
'success': False,
'message': f'Error: {str(e)}'
}), 500
@app.route('/api/download-excel', methods=['GET'])
def download_excel():
"""Download the referrals Excel file."""
try:
if os.path.exists(EXCEL_FILE):
return send_from_directory(DATA_FOLDER, os.path.basename(EXCEL_FILE), as_attachment=True)
else:
return jsonify({
'success': False,
'message': 'No referrals found'
}), 404
except Exception as e:
logger.error(f"Error downloading Excel: {str(e)}")
return jsonify({
'success': False,
'message': f'Error: {str(e)}'
}), 500
if __name__ == '__main__':
# For development only - use gunicorn for production
app.run(debug=True, port=5000) in this app.py and this # app.py
from flask import Flask, request, jsonify, send_from_directory
from flask_cors import CORS
import pandas as pd
import os
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
from werkzeug.utils import secure_filename
import datetime
import logging
app = Flask(__name__)
CORS(app) # Enable CORS for all routes
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger
# app.py (continued)
# Configuration
UPLOAD_FOLDER = 'uploads'
DATA_FOLDER = 'data'
ALLOWED_EXTENSIONS = {'pdf', 'doc', 'docx'}
EXCEL_FILE = os.path.join(DATA_FOLDER, 'referrals.xlsx')
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 # 16MB max upload size
# Create necessary folders if they don't exist
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
os.makedirs(DATA_FOLDER, exist_ok=True)
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
def send_email_notification(referral_data):
"""Send email notification to HR about new referral."""
try:
# Email configuration (use environment variables in production)
SMTP_SERVER = os.environ.get('SMTP_SERVER', 'smtp.gmail.com')
SMTP_PORT = int(os.environ.get('SMTP_PORT', 587))
SENDER_EMAIL = os.environ.get('SENDER_EMAIL', 'your-email@company.com')
SENDER_PASSWORD = os.environ.get('SENDER_PASSWORD', 'your-email-password')
HR_EMAIL = os.environ.get('HR_EMAIL', 'hr@company.com')
# Create message
msg = MIMEMultipart()
msg['From'] = SENDER_EMAIL
msg['To'] = HR_EMAIL
msg['Subject'] = f"New Referral: {referral_data['candidateFirstName']} {referral_data['candidateLastName']}"
# Email body
body = f"""
New Candidate Referral Details:
Candidate: {referral_data['candidateFirstName']} {referral_data['candidateLastName']}
Email: {referral_data['email']}
Phone: {referral_data['countryCode']} {referral_data['mobileNumber']}
Experience: {referral_data['workExperience']}
Position: {referral_data['applyingFor']}
Job Code: {referral_data['jobCode']}
Department: {referral_data['department']}
College: {referral_data['collegeName']}, {referral_data['collegeCity']}
Referred By:
Name: {referral_data['employeeName']}
ID: {referral_data['employeeId']}
Email: {referral_data['employeeEmail']}
Date: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
"""
msg.attach(MIMEText(body, 'plain'))
# Attach resume if available
if 'resumePath' in referral_data and os.path.exists(referral_data['resumePath']):
with open(referral_data['resumePath'], 'rb') as f:
attachment = MIMEApplication(f.read(), _subtype=referral_data['resumePath'].split('.')[-1])
attachment.add_header('Content-Disposition', 'attachment',
filename=os.path.basename(referral_data['resumePath']))
msg.attach(attachment)
# Send email
with smtplib.SMTP(SMTP_SERVER, SMTP_PORT) as server:
server.starttls()
server.login(SENDER_EMAIL, SENDER_PASSWORD)
server.send_message(msg)
logger.info(f"Email notification sent for referral of {referral_data['candidateFirstName']} {referral_data['candidateLastName']}")
return True
except Exception as e:
logger.error(f"Failed to send email: {str(e)}")
return False
def save_to_excel(referral_data):
"""Save referral data to Excel file."""
try:
# Prepare data for Excel
excel_data = {
'Candidate Name': f"{referral_data['candidateFirstName']} {referral_data['candidateLastName']}",
'Email': referral_data['email'],
'Mobile': f"{referral_data['countryCode']} {referral_data['mobileNumber']}",
'Experience': referral_data['workExperience'],
'Position': referral_data['applyingFor'],
'Job Code': referral_data['jobCode'],
'Department': referral_data['department'],
'College': referral_data['collegeName'],
'College City': referral_data['collegeCity'],
'Resume': referral_data.get('resumeFileName', 'No file'),
'Referred By': referral_data['employeeName'],
'Employee ID': referral_data['employeeId'],
'Employee Email': referral_data['employeeEmail'],
'Submission Date': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
}
# Create DataFrame
df_new = pd.DataFrame([excel_data])
# Check if excel file exists and append, otherwise create new
if os.path.exists(EXCEL_FILE):
df_existing = pd.read_excel(EXCEL_FILE)
df_combined = pd.concat([df_existing, df_new], ignore_index=True)
df_combined.to_excel(EXCEL_FILE, index=False)
else:
df_new.to_excel(EXCEL_FILE, index=False)
logger.info(f"Referral data saved to Excel for {referral_data['candidateFirstName']} {referral_data['candidateLastName']}")
return True
except Exception as e:
logger.error(f"Failed to save to Excel: {str(e)}")
return False
@app.route('/api/submit-referral', methods=['POST'])
def submit_referral():
"""Handle referral submission from the frontend."""
try:
# Extract form data
form_data = request.form.to_dict()
# Handle resume file upload
resume_file = request.files.get('resume')
resume_path = None
if resume_file and allowed_file(resume_file.filename):
filename = secure_filename(f"{form_data['candidateFirstName']}_{form_data['candidateLastName']}_{datetime.datetime.now().strftime('%Y%m%d%H%M%S')}_resume{os.path.splitext(resume_file.filename)[1]}")
resume_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
resume_file.save(resume_path)
form_data['resumePath'] = resume_path
form_data['resumeFileName'] = filename
# Save data to Excel
save_to_excel(form_data)
# Send email notification
send_email_notification(form_data)
return jsonify({
'success': True,
'message': 'Referral submitted successfully'
}), 200
except Exception as e:
logger.error(f"Error in referral submission: {str(e)}")
return jsonify({
'success': False,
'message': f'Error: {str(e)}'
}), 500
@app.route('/api/get-referrals', methods=['GET'])
def get_referrals():
"""Get all referrals from Excel file."""
try:
if os.path.exists(EXCEL_FILE):
df = pd.read_excel(EXCEL_FILE)
return jsonify({
'success': True,
'data': df.to_dict('records')
}), 200
else:
return jsonify({
'success': True,
'data': []
}), 200
except Exception as e:
logger.error(f"Error fetching referrals: {str(e)}")
return jsonify({
'success': False,
'message': f'Error: {str(e)}'
}), 500
@app.route('/api/download-excel', methods=['GET'])
def download_excel():
"""Download the referrals Excel file."""
try:
if os.path.exists(EXCEL_FILE):
return send_from_directory(DATA_FOLDER, os.path.basename(EXCEL_FILE), as_attachment=True)
else:
return jsonify({
'success': False,
'message': 'No referrals found'
}), 404
except Exception as e:
logger.error(f"Error downloading Excel: {str(e)}")
return jsonify({
'success': False,
'message': f'Error: {str(e)}'
}), 500
if __name__ == '__main__':
# For development only - use gunicorn for production
app.run(debug=True, port=5000) in thia app.py and // EmployeeReferralPortal.jsx
import React, { useState, useEffect } from 'react';
import './EmployeeReferralPortal.css';
import { saveAs } from 'file-saver';
import * as XLSX from 'xlsx';
import apiService from '../services/api.js';
const EmployeeReferralPortal = () => {
// State for form data
const [formData, setFormData] = useState({
candidateFirstName: '',
candidateLastName: '',
email: '',
mobileNumber: '',
countryCode: '+91',
workExperience: '',
applyingFor: '',
jobCode: '',
source: 'Employee Referral',
department: '',
collegeName: '',
collegeCity: '',
resume: null,
rejectionReason: '',
employeeId: '',
employeeName: '',
employeeEmail: ''
});
// State for validation
const [errors, setErrors] = useState({});
const [submitted, setSubmitted] = useState(false);
const [showPopup, setShowPopup] = useState(false);
// State for storing all submissions
const [allSubmissions, setAllSubmissions] = useState([]);
// Options for dropdowns
const departments = ['IT', 'HR', 'Finance', 'Marketing', 'Operations', 'Sales', 'Other'];
const positions = ['Software Developer', 'Project Manager', 'Business Analyst', 'HR Executive', 'Marketing Specialist', 'Sales Representative', 'Other'];
const jobCodes = ['IT001', 'HR001', 'FIN001', 'MKT001', 'OPS001', 'SLS001', 'OTH001'];
const colleges = ['MIT', 'Harvard', 'Stanford', 'Oxford', 'Cambridge', 'IIT', 'Other'];
const cities = ['Mumbai', 'Delhi', 'Bangalore', 'Chennai', 'Hyderabad', 'Pune', 'Other'];
// Handle form input changes
const handleChange = (e) => {
const { name, value } = e.target;
setFormData({ ...formData, [name]: value });
// Clear error for this field when user types
if (errors[name]) {
setErrors({ ...errors, [name]: '' });
}
};
// Handle file upload for resume
const handleFileChange = (e) => {
const file = e.target.files[0];
if (file) {
setFormData({ ...formData, resume: file });
if (errors.resume) {
setErrors({ ...errors, resume: '' });
}
}
};
// Validate form before submission
const validateForm = () => {
const newErrors = {};
// Required fields validation
if (!formData.candidateFirstName) newErrors.candidateFirstName = 'First name is required';
if (!formData.candidateLastName) newErrors.candidateLastName = 'Last name is required';
if (!formData.email) {
newErrors.email = 'Email is required';
} else if (!/\S+@\S+\.\S+/.test(formData.email)) {
newErrors.email = 'Email is invalid';
}
if (!formData.mobileNumber) {
newErrors.mobileNumber = 'Mobile number is required';
} else if (!/^\d{10}$/.test(formData.mobileNumber)) {
newErrors.mobileNumber = 'Mobile number should be 10 digits';
}
if (!formData.workExperience) newErrors.workExperience = 'Work experience is required';
if (!formData.applyingFor) newErrors.applyingFor = 'Position is required';
if (!formData.jobCode) newErrors.jobCode = 'Job code is required';
if (!formData.collegeName) newErrors.collegeName = 'College name is required';
if (!formData.collegeCity) newErrors.collegeCity = 'College city is required';
if (!formData.resume) newErrors.resume = 'Resume is required';
if (!formData.employeeId) newErrors.employeeId = 'Employee ID is required';
if (!formData.employeeName) newErrors.employeeName = 'Employee name is required';
if (!formData.employeeEmail) newErrors.employeeEmail = 'Employee email is required';
setErrors(newErrors);
return Object.keys(newErrors).length === 0;
};
// Handle form submission
const handleSubmit = (e) => {
e.preventDefault();
if (validateForm()) {
// Add timestamp to submission
const submissionWithTimestamp = {
...formData,
submissionDate: new Date().toISOString(),
resumeFileName: formData.resume ? formData.resume.name : 'No file'
};
// Add to all submissions
setAllSubmissions([...allSubmissions, submissionWithTimestamp]);
// Save to localStorage
const storedSubmissions = JSON.parse(localStorage.getItem('referralSubmissions') || '[]');
localStorage.setItem('referralSubmissions', JSON.stringify([...storedSubmissions, submissionWithTimestamp]));
// Send email notification (simulated)
sendEmailNotification(submissionWithTimestamp);
// Show success popup
setShowPopup(true);
setSubmitted(true);
// Reset form
resetForm();
// Close popup after 3 seconds
setTimeout(() => {
setShowPopup(false);
}, 3000);
}
};
// Reset form after submission
const resetForm = () => {
setFormData({
candidateFirstName: '',
candidateLastName: '',
email: '',
mobileNumber: '',
countryCode: '+91',
workExperience: '',
applyingFor: '',
jobCode: '',
source: 'Employee Referral',
department: '',
collegeName: '',
collegeCity: '',
resume: null,
rejectionReason: '',
employeeId: '',
employeeName: '',
employeeEmail: ''
});
// Reset file input
const fileInput = document.getElementById('resume');
if (fileInput) fileInput.value = '';
};
// Simulate sending email notification
const sendEmailNotification = (submission) => {
console.log(`Email notification sent to HR about referral for ${submission.candidateFirstName} ${submission.candidateLastName}`);
// In production, you would use an API endpoint to send the email
// Example:
// fetch('/api/send-email', {
// method: 'POST',
// headers: { 'Content-Type': 'application/json' },
// body: JSON.stringify({
// to: 'hr@yourcompany.com',
// subject: `New Referral: ${submission.candidateFirstName} ${submission.candidateLastName}`,
// body: `A new candidate has been referred by ${submission.employeeName} (${submission.employeeId})`
// })
// });
};
// Export all submissions to Excel
const exportToExcel = () => {
apiService.downloadExcel();
const worksheet = XLSX.utils.json_to_sheet(allSubmissions.map(item => ({
'Candidate Name': `${item.candidateFirstName} ${item.candidateLastName}`,
'Email': item.email,
'Mobile': `${item.countryCode} ${item.mobileNumber}`,
'Experience': item.workExperience,
'Position': item.applyingFor,
'Job Code': item.jobCode,
'Department': item.department,
'College': item.collegeName,
'College City': item.collegeCity,
'Resume': item.resumeFileName,
'Referred By': item.employeeName,
'Employee ID': item.employeeId,
'Employee Email': item.employeeEmail,
'Submission Date': new Date(item.submissionDate).toLocaleString()
})));
const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, worksheet, 'Referrals');
// Generate Excel file and download
const excelBuffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
const data = new Blob([excelBuffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
saveAs(data, `Referrals_${new Date().toISOString().slice(0,10)}.xlsx`);
};
// Load saved submissions from localStorage on component mount
useEffect(() => {
const storedSubmissions = JSON.parse(localStorage.getItem('referralSubmissions') || '[]');
setAllSubmissions(storedSubmissions);
}, []);
return (
<div className="portal-container">
{/* Navbar */}
<nav className="navbar">
<div className="navbar-container">
<div className="logo-container">
<h1 className="navbar-title">Employee Referral Portal</h1>
</div>
{allSubmissions.length > 0 && (
<button type="button" className="export-button" onClick={exportToExcel}>
<i className="fa fa-download"></i> Export to Excel
</button>
)}
</div>
</nav>
{/* Main Content */}
<div className="main-content">
<div className="form-container">
<h2>Refer a Candidate</h2>
<form onSubmit={handleSubmit}>
<div className="form-section">
<h3>Candidate Details</h3>
<div className="form-row">
<div className="form-group">
<label htmlFor="candidateFirstName">First Name <span className="required">*</span></label>
<input
type="text"
id="candidateFirstName"
name="candidateFirstName"
value={formData.candidateFirstName}
onChange={handleChange}
className={errors.candidateFirstName ? 'error' : ''}
/>
{errors.candidateFirstName && <span className="error-text">{errors.candidateFirstName}</span>}
</div>
<div className="form-group">
<label htmlFor="candidateLastName">Last Name <span className="required">*</span></label>
<input
type="text"
id="candidateLastName"
name="candidateLastName"
value={formData.candidateLastName}
onChange={handleChange}
className={errors.candidateLastName ? 'error' : ''}
/>
{errors.candidateLastName && <span className="error-text">{errors.candidateLastName}</span>}
</div>
</div>
<div className="form-row">
<div className="form-group">
<label htmlFor="email">Email ID <span className="required">*</span></label>
<input
type="email"
id="email"
name="email"
value={formData.email}
onChange={handleChange}
className={errors.email ? 'error' : ''}
/>
{errors.email && <span className="error-text">{errors.email}</span>}
</div>
<div className="form-group">
<label htmlFor="mobileNumber">Mobile Number <span className="required">*</span></label>
<div className="phone-input-container">
<select
name="countryCode"
value={formData.countryCode}
onChange={handleChange}
className="country-code"
>
<option value="+91">+91 (India)</option>
<option value="+1">+1 (USA)</option>
<option value="+44">+44 (UK)</option>
<option value="+61">+61 (Australia)</option>
<option value="+65">+65 (Singapore)</option>
</select>
<input
type="text"
id="mobileNumber"
name="mobileNumber"
value={formData.mobileNumber}
onChange={handleChange}
className={errors.mobileNumber ? 'error phone-number' : 'phone-number'}
placeholder="10 digit number"
/>
</div>
{errors.mobileNumber && <span className="error-text">{errors.mobileNumber}</span>}
</div>
</div>
<div className="form-row">
<div className="form-group">
<label>Work Experience <span className="required">*</span></label>
<div className="radio-group">
<label className="radio-label">
<input
type="radio"
name="workExperience"
value="Fresher"
checked={formData.workExperience === 'Fresher'}
onChange={handleChange}
/>
Fresher
</label>
<label className="radio-label">
<input
type="radio"
name="workExperience"
value="Experienced"
checked={formData.workExperience === 'Experienced'}
onChange={handleChange}
/>
Experienced
</label>
</div>
{errors.workExperience && <span className="error-text">{errors.workExperience}</span>}
</div>
<div className="form-group">
<label htmlFor="department">Department</label>
<select
id="department"
name="department"
value={formData.department}
onChange={handleChange}
>
<option value="">--Select--</option>
{departments.map((dept, index) => (
<option key={index} value={dept}>{dept}</option>
))}
</select>
</div>
</div>
<div className="form-row">
<div className="form-group">
<label htmlFor="applyingFor">Applying for <span className="required">*</span></label>
<select
id="applyingFor"
name="applyingFor"
value={formData.applyingFor}
onChange={handleChange}
className={errors.applyingFor ? 'error' : ''}
>
<option value="">--Select--</option>
{positions.map((position, index) => (
<option key={index} value={position}>{position}</option>
))}
</select>
{errors.applyingFor && <span className="error-text">{errors.applyingFor}</span>}
</div>
<div className="form-group">
<label htmlFor="jobCode">Job Code <span className="required">*</span></label>
<select
id="jobCode"
name="jobCode"
value={formData.jobCode}
onChange={handleChange}
className={errors.jobCode ? 'error' : ''}
>
<option value="">--Select--</option>
{jobCodes.map((code, index) => (
<option key={index} value={code}>{code}</option>
))}
</select>
{errors.jobCode && <span className="error-text">{errors.jobCode}</span>}
</div>
</div>
<div className="form-row">
<div className="form-group">
<label htmlFor="collegeName">College Name <span className="required">*</span></label>
<select
id="collegeName"
name="collegeName"
value={formData.collegeName}
onChange={handleChange}
className={errors.collegeName ? 'error' : ''}
>
<option value="">--Select--</option>
{colleges.map((college, index) => (
<option key={index} value={college}>{college}</option>
))}
</select>
{errors.collegeName && <span className="error-text">{errors.collegeName}</span>}
</div>
<div className="form-group">
<label htmlFor="collegeCity">College City <span className="required">*</span></label>
<select
id="collegeCity"
name="collegeCity"
value={formData.collegeCity}
onChange={handleChange}
className={errors.collegeCity ? 'error' : ''}
>
<option value="">--Select--</option>
{cities.map((city, index) => (
<option key={index} value={city}>{city}</option>
))}
</select>
{errors.collegeCity && <span className="error-text">{errors.collegeCity}</span>}
</div>
</div>
<div className="form-row">
<div className="form-group">
<label htmlFor="resume">Resume <span className="required">*</span></label>
<div className="file-input-container">
<input
type="file"
id="resume"
name="resume"
accept=".pdf,.doc,.docx"
onChange={handleFileChange}
className={errors.resume ? 'error' : ''}
/>
<label htmlFor="resume" className="file-label">
<span>{formData.resume ? formData.resume.name : 'Select File'}</span>
<span className="browse-btn">Browse</span>
</label>
</div>
{errors.resume && <span className="error-text">{errors.resume}</span>}
</div>
<div className="form-group">
<label htmlFor="rejectionReason">Rejection Reason (if any)</label>
<select
id="rejectionReason"
name="rejectionReason"
value={formData.rejectionReason}
onChange={handleChange}
>
<option value="">--Select--</option>
<option value="Salary expectations too high">Salary expectations too high</option>
<option value="Insufficient experience">Insufficient experience</option>
<option value="Skill mismatch">Skill mismatch</option>
<option value="Location constraints">Location constraints</option>
<option value="Other">Other</option>
</select>
</div>
</div>
</div>
<div className="form-section">
<h3>Referred By</h3>
<div className="form-row">
<div className="form-group">
<label htmlFor="employeeId">Employee ID <span className="required">*</span></label>
<input
type="text"
id="employeeId"
name="employeeId"
value={formData.employeeId}
onChange={handleChange}
className={errors.employeeId ? 'error' : ''}
/>
{errors.employeeId && <span className="error-text">{errors.employeeId}</span>}
</div>
<div className="form-group">
<label htmlFor="employeeName">Employee Name <span className="required">*</span></label>
<input
type="text"
id="employeeName"
name="employeeName"
value={formData.employeeName}
onChange={handleChange}
className={errors.employeeName ? 'error' : ''}
/>
{errors.employeeName && <span className="error-text">{errors.employeeName}</span>}
</div>
</div>
<div className="form-row">
<div className="form-group">
<label htmlFor="employeeEmail">Employee Email <span className="required">*</span></label>
<input
type="email"
id="employeeEmail"
name="employeeEmail"
value={formData.employeeEmail}
onChange={handleChange}
className={errors.employeeEmail ? 'error' : ''}
/>
{errors.employeeEmail && <span className="error-text">{errors.employeeEmail}</span>}
</div>
</div>
</div>
<div className="form-actions">
<button type="submit" className="submit-btn">Submit Referral</button>
<button type="button" className="reset-btn" onClick={resetForm}>Reset Form</button>
</div>
</form>
</div>
</div>
{/* Success Popup */}
{showPopup && (
<div className="popup">
<div className="popup-content">
<i className="fa fa-check-circle"></i>
<h3>Referral Submitted Successfully!</h3>
<p>The HR team has been notified about your referral.</p>
</div>
</div>
)}
</div>
);
};
export default EmployeeReferralPortal; ..i dont wnat the fields job code, clg name , clg city, rejection reason , and also applyting for and resume msut not be reuiqred fields they must be optionalASSISTANT
To update your frontend (`EmployeeReferralPortal.jsx`) and backend (`app.py`) code so that the following fields are **removed** entirely:
- `jobCode`
- `collegeName`
- `collegeCity`
- `rejectionReason`
and to make the fields:
- `applyingFor`
- `resume`
**optional** instead of required, follow these steps:
---
### 1. Frontend: EmployeeReferralPortal.jsx
**Remove fields completely from the form:**
- Remove all form controls (labels, inputs/selects) related to `jobCode`, `collegeName`, `collegeCity`, and `rejectionReason`.
- Remove these fields from the `formData` initial state.
- Remove from validation rules.
- Make `applyingFor` and `resume` optional by NOT validating that they must be present.
-----
**Detailed changes in React component:**
- **Initial State:** Remove `jobCode`, `collegeName`, `collegeCity`, and `rejectionReason`
```js
const [formData, setFormData] = useState({
candidateFirstName: '',
candidateLastName: '',
email: '',
mobileNumber: '',
countryCode: '+91',
workExperience: '',
applyingFor: '', // Keep, but optional
// jobCode: '', // REMOVE
source: 'Employee Referral',
department: '',
// collegeName: '', // REMOVE
// collegeCity: '', // REMOVE
resume: null, // Keep, but optional
// rejectionReason: '', // REMOVE
employeeId: '',
employeeName: '',
employeeEmail: ''
});
```
- **Remove from validation:**
Change validation logic in `validateForm()`:
```js
const validateForm = () => {
const newErrors = {};
if (!formData.candidateFirstName) newErrors.candidateFirstName = 'First name is required';
if (!formData.candidateLastName) newErrors.candidateLastName = 'Last name is required';
if (!formData.email) {
newErrors.email = 'Email is required';
} else if (!/\S+@\S+\.\S+/.test(formData.email)) {
newErrors.email = 'Email is invalid';
}
if (!formData.mobileNumber) {
newErrors.mobileNumber = 'Mobile number is required';
} else if (!/^\d{10}$/.test(formData.mobileNumber)) {
newErrors.mobileNumber = 'Mobile number should be 10 digits';
}
if (!formData.workExperience) newErrors.workExperience = 'Work experience is required';
// Make 'applyingFor' optional, so no validation here
// if (!formData.applyingFor) newErrors.applyingFor = 'Position is required';
// Remove Job Code validation (no longer present)
// if (!formData.jobCode) newErrors.jobCode = 'Job code is required';
// Remove collegeName and collegeCity validation (fields removed)
// if (!formData.collegeName) newErrors.collegeName = 'College name is required';
// if (!formData.collegeCity) newErrors.collegeCity = 'College city is required';
// Make resume optional: only validate if provided - but since optional, don't require
// if (!formData.resume) newErrors.resume = 'Resume is required';
if (!formData.employeeId) newErrors.employeeId = 'Employee ID is required';
if (!formData.employeeName) newErrors.employeeName = 'Employee name is required';
if (!formData.employeeEmail) newErrors.employeeEmail = 'Employee email is required';
setErrors(newErrors);
return Object.keys(newErrors).length === 0;
};
```
- **Remove the fields from the JSX form render:**
Delete all form groups related to:
```jsx
{/* Remove Job Code */}
{/* Remove College Name */}
{/* Remove College City */}
{/* Remove Rejection Reason */}
```
Specifically, remove these div blocks:
```jsx
{/* Remove jobCode select */}
<div className="form-group">
<label htmlFor="jobCode">Job Code <span className="required">*</span></label>
<select ...>...</select>
</div>
{/* Remove collegeName select */}
<div className="form-group">
<label htmlFor="collegeName">College Name <span className="required">*</span></label>
<select ...>...</select>
</div>
{/* Remove collegeCity select */}
<div className="form-group">
<label htmlFor="collegeCity">College City <span className="required">*</span></label>
<select ...>...</select>
</div>
{/* Remove rejectionReason select */}
<div className="form-group">
<label htmlFor="rejectionReason">Rejection Reason (if any)</label>
<select ...>...</select>
</div>
```
- **Updating where these fields are used, e.g., in exportToExcel you should also remove those fields:**
```js
const exportToExcel = () => {
apiService.downloadExcel();
const worksheet = XLSX.utils.json_to_sheet(allSubmissions.map(item => ({
'Candidate Name': `${item.candidateFirstName} ${item.candidateLastName}`,
'Email': item.email,
'Mobile': `${item.countryCode} ${item.mobileNumber}`,
'Experience': item.workExperience,
'Position': item.applyingFor || '', // optional, so safe
// 'Job Code': item.jobCode, // remove
'Department': item.department,
// 'College': item.collegeName, // remove
// 'College City': item.collegeCity, // remove
'Resume': item.resumeFileName || 'No file',
'Referred By': item.employeeName,
'Employee ID': item.employeeId,
'Employee Email': item.employeeEmail,
'Submission Date': new Date(item.submissionDate).toLocaleString()
})));
// rest of code remains unchanged
};
```
---
### 2. Backend: app.py
- Since you removed fields from frontend and they are optional now, update backend accordingly.
- In `save_to_excel(referral_data)`, remove columns related to removed fields:
Change the dictionary creation from:
```python
excel_data = {
'Candidate Name': f"{referral_data['candidateFirstName']} {referral_data['candidateLastName']}",
'Email': referral_data['email'],
'Mobile': f"{referral_data['countryCode']} {referral_data['mobileNumber']}",
'Experience': referral_data['workExperience'],
'Position': referral_data['applyingFor'],
'Job Code': referral_data['jobCode'], # REMOVE
'Department': referral_data['department'],
'College': referral_data['collegeName'], # REMOVE
'College City': referral_data['collegeCity'], # REMOVE
'Resume': referral_data.get('resumeFileName', 'No file'),
'Referred By': referral_data['employeeName'],
'Employee ID': referral_data['employeeId'],
'Employee Email': referral_data['employeeEmail'],
'Submission Date': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
}
```
To:
```python
excel_data = {
'Candidate Name': f"{referral_data['candidateFirstName']} {referral_data['candidateLastName']}",
'Email': referral_data['email'],
'Mobile': f"{referral_data['countryCode']} {referral_data['mobileNumber']}",
'Experience': referral_data['workExperience'],
'Position': referral_data.get('applyingFor', ''), # Optional, use get with default ''
# 'Job Code': removed
'Department': referral_data.get('department', ''),
# 'College' removed
# 'College City' removed
'Resume': referral_data.get('resumeFileName', 'No file'),
'Referred By': referral_data['employeeName'],
'Employee ID': referral_data['employeeId'],
'Employee Email': referral_data['employeeEmail'],
'Submission Date': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
}
```
- In `submit_referral()`, **do not enforce resume or applyingFor presence**, just accept if present.
You might want to add some defensive coding in case those optional fields are missing from form_data.
- In `send_email_notification()`, update email body lines accordingly, **remove jobCode, collegeName, collegeCity**:
```python
body = f"""
New Candidate Referral Details:
Candidate: {referral_data['candidateFirstName']} {referral_data['candidateLastName']}
Email: {referral_data['email']}
Phone: {referral_data['countryCode']} {referral_data['mobileNumber']}
Experience: {referral_data['workExperience']}
Position: {referral_data.get('applyingFor', 'N/A')}
Department: {referral_data.get('department', 'N/A')}
Referred By:
Name: {referral_data['employeeName']}
ID: {referral_data['employeeId']}
Email: {referral_data['employeeEmail']}
Date: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
"""
```
- Also, in the email attachment part, keep the logic safe if `resumePath` is missing or None.
---
### Summary of what you need to do:
| Change Area | Action |
|------------------------------|-------------------------------------------------------------------------|
| Frontend form data state | Remove `jobCode`, `collegeName`, `collegeCity`, `rejectionReason` |
| Frontend form rendering | Remove fields related to above |
| Frontend validation | Remove validation for removed fields; make `applyingFor` and `resume` optional |
| Frontend export Excel logic | Remove columns related to removed fields |
| Backend `save_to_excel` | Remove columns for removed fields; default optional fields if missing |
| Backend `send_email_notification` | Remove jobCode and college details from email body; safely handle missing optional fields |
| Backend `submit_referral` | Make `applyingFor` and `resume` optional (no required checks) |
---
If you want me to provide the **full updated code** for both frontend and backend or only selective portion changes, please ask!