<div class="banner-info">
<div class="container">
<div class="row">
<div class="col-sm-12">
<div class="row-padd mrb-10">
<h3>Careers With Us</h3>
</div>
</div>
</div>
</div>
</div>
<div class="career-sec">
<div class="container">
<div class="row">
<div class="col-sm-12 col-md-8 left">
<div class="inner">
<h3>Welcome to CostMasters “Careers”! </h3>
<p>We are inviting talented professionals & leaders at various levels in the field of Business
Development, .Net Developers, Cost Engineers, Project Management.</p>
<p>To apply, fill the form below.</p>
<div class="career-form">
<h4>Career Form</h4>
<form method="POST" id="submit_careers" action="<?= base_url('careers-with-us/save') ?>"
enctype="multipart/form-data">
<div class="row">
<div class="form-group col-sm-4">
<label>Name<span class="c_red">*</span> :</label>
<input name="c_name" type="text" class="text_field form-control" id="c_name">
<span id="c_name_err" class="error"></span>
</div>
<div class="form-group col-sm-4">
<label>Mobile Number<span class="c_red">*</span> : </label>
<div class="input-group" style="display: flex;">
<input name="c_mobile" type="tel" id="c_mobile" class="text_field form-control" placeholder="">
<div class="input-group-append">
<button type="button" class="btn btn-sm btn-primary c_send-otp-btn"
id="c_send_otp_btn" onclick="sendOtp(this)" style="display:none;">OTP</button>
<i class="fa fa-check-circle text-success" id="c_otp_verified_tick" style="display: none;"></i>
</div>
</div>
<span id="c_mobile_err" class="error"></span>
</div>
<div class="form-group col-sm-4 c_otp-group" id="c_verify_otp" style="display: none;">
<div class="input-group">
<input type="text" class="otp-box" name="c_otp_digit1" id="c_otp_digit1"
maxlength="1" required>
<input type="text" class="otp-box" name="c_otp_digit2" id="c_otp_digit2"
maxlength="1" required>
<input type="text" class="otp-box" name="c_otp_digit3" id="c_otp_digit3"
maxlength="1" required>
<input type="text" class="otp-box" name="c_otp_digit4" id="c_otp_digit4"
maxlength="1" required>
<div class="d-flex align-items-center gap-2">
<button type="button" class="btn btn-sm btn-primary verify c_verify-otp-btn"
id="c_verify_otp_btn" onclick="verifyOtp()" style="display:none;">Verify</button>
<button type="button" class="btn btn-sm btn-primary verify c_cancel-btn"
data-otp-group="c_otp-group" >Cancel</button>
<button type="button" class="btn btn-link" id="c_resendOtpBtn"
style="display: none;" onclick="resendOtp()">Resend OTP</button> </div>
<span id="c_otp_verification"></span>
<p id="c_otp_timer" style=" display: none;">
<span id="c_otpTimer"></span>
</p>
</div>
</div>
<div class="form-group col-sm-4">
<label>E-mail Address<span class="c_red">*</span> :</label>
<input name="c_email" type="email" class="text_field form-control" id="c_email">
<span id="email_err" class="error"></span>
</div>
<div class="form-group col-sm-4">
<label>Attach Resume<span class="c_red">*</span> :</label>
<input class="text_field form-control" type="file" name="c_resume" id="c_resume"
accept=".pdf" onchange="validateFileType()">
<span id="resume_err" class="error"></span>
</div>
<div class="form-group col-sm-8">
<label>Position of Interest<span class="c_red"></span> :</label>
<select name="c_position" id="c_position" class="text_field form-control">
<option value="">--Choose--</option>
<?php foreach ($pos_interest as $pos): ?>
<option value="<?= $pos['pos_name'] ?>"><?= $pos['pos_name'] ?></option>
<?php endforeach; ?>
</select>
<span id="position_err" class="error"></span>
</div>
<div class="form-group col-sm-12">
<label>Message:</label>
<textarea name="c_info" class="text_area form-control" id="c_info"></textarea>
</div>
<input type="hidden" name="contactNo" class="contactNo" value="">
<div class="form-group col-sm-12">
<input name="submit" class="textsubmit btn" id="submitButton" value="Submit Application" type="submit">
</div>
<div class="form-group col-sm-12">
<div id="loading" style="display:none;">
<img src="<?= base_url('assets/frontend/images/ajax-loader.gif'); ?>" width="120" style="display: block; margin: 0px auto;" />
</div>
<div id="message"></div>
</div>
</div>
</form>
</div>
</div>
</div>
<div class="col-sm-12 col-md-4 right">
<div class="info">
<address>
<div>
<p><span>Address:</span><?= $footerContactAddr ?></p>
</div>
</address>
<address>
<div>
<p><span>Email Us:</span><a
href="mailto:hr@costmasters.in">hr@costmasters.in</a></p>
</div>
</address>
<address>
<div>
<p><span>Call Us:</span><a
href="tel:<?= $footerContactPhone ?>">+91-7009077082</a></p>
</div>
</address>
</div>
</div>
</div>
</div>
</div>
<script src="<?= base_url(); ?>assets/plugins/general/jquery/dist/jquery.js" type="text/javascript"></script>
<script>
let otpTimeout;
let isOtpVerified = false;
function validateFileType() {
var fileName = document.getElementById("c_resume").value;
var idxDot = fileName.lastIndexOf(".") + 1;
var extFile = fileName.substr(idxDot, fileName.length).toLowerCase();
if (extFile != "pdf") {
toastr.error("Only .pdf format files are allowed!");
event.returnValue = false;
document.getElementById("c_resume").value = "";
}
}
// Initialize intl-tel-input
let contactInput = document.querySelector("#c_mobile");
let iti = window.intlTelInput(contactInput, {
initialCountry: "in", // Default country
separateDialCode: true,
nationalMode: true,
utilsScript: "https://cdnjs.cloudflare.com/ajax/libs/intl-tel-input/17.0.8/js/utils.js"
});
contactInput.setAttribute("placeholder", "");
// Define country-specific phone number lengths
const phoneLengthByCountry = {
"IN": 10, "US": 10, "GB": 10, "JP": 10,
"AE": 9, "FR": 9, "AU": 9
};
let lastValidNumber = ""
// Restrict input length based on selected country
$("#c_mobile").on("input", function () {
let inputField = document.querySelector("#c_mobile");
if (!inputField) return console.error("Element #c_mobile not found.");
let itiInstance = window.intlTelInputGlobals?.getInstance(inputField);
if (!itiInstance) return console.error("intlTelInput instance not found.");
let countryData = itiInstance.getSelectedCountryData();
let countryCode = countryData.iso2.toUpperCase();
let maxLength = phoneLengthByCountry[countryCode] || 10;
let phoneNumber = $(this).val().replace(/\D/g, ''); // Remove non-numeric characters
$(this).val(phoneNumber.substring(0, maxLength)); // Restrict to country-specific length
let formattedNumber = itiInstance.getNumber();
let isValid = itiInstance.isValidNumber();
if (isValid && formattedNumber !== lastValidNumber) {
lastValidNumber = formattedNumber;
sendOtp(inputField); // Send OTP
$("#book_contact_error").text("").hide();
$("#c_send_otp_btn").prop("disabled", false);
} else {
$("#c_send_otp_btn").prop("disabled", true);
$("#book_contact_error").text("Invalid mobile number for " + countryData.name).css("color", "red").show();
}
});
$("#c_mobile").attr("placeholder", "");
// Validate phone number before form submission
function validatePhoneNumber() {
var contact = $('#c_mobile');
if (contact.length === 0) {
console.error("Phone input field not found!");
return false;
}
var iti = window.intlTelInputGlobals.getInstance(contact[0]);
if (!iti || !iti.isValidNumber()) {
toastr.warning('Please enter a valid contact number.', 'Invalid Contact Number');
contact.addClass('is-invalid');
return false;
} else {
contact.removeClass('is-invalid');
}
var countryCode = iti.getSelectedCountryData().iso2.toUpperCase();
var expectedLength = phoneLengthByCountry[countryCode] || 10;
// Get the national number and remove non-digits
var nationalNumber = iti.getNumber(intlTelInputUtils.numberFormat.NATIONAL).replace(/\D/g, '');
console.log("Raw national number:", nationalNumber, "Length:", nationalNumber.length);
// Optionally remove a leading zero if it exists:
if (nationalNumber.charAt(0) === '0') {
nationalNumber = nationalNumber.substring(1);
console.log("National number after removing leading zero:", nationalNumber, "Length:", nationalNumber.length);
}
if (nationalNumber.length !== expectedLength) {
toastr.warning('Invalid phone number length for ' + iti.getSelectedCountryData().name + '. Expected ' + expectedLength + ' digits.', 'Invalid Contact Number');
contact.addClass('is-invalid');
return false;
}
return true;
}
// Function to send OTP
function sendOtp() {
let contactNo = $('#c_mobile').val().trim();
$.ajax({
type: 'POST',
url: '<?= base_url(); ?>api/send_otp',
data: { contactNo: contactNo },
dataType: 'json',
success: function (response) {
if (response.status === 'true') {
toastr.success('OTP sent successfully.', 'OTP Sent');
clearInterval(otpTimeout);
$('#c_verify_otp').show();
$('#c_send_otp_btn').hide();
$('#c_mobile').attr('readonly', true).css('background-color', '#f5f5f5');
startOtpTimer();
} else {
toastr.error('Failed to send OTP.', 'Error');
}
},
error: function () {
toastr.error('Failed to send OTP.', 'Error');
}
});
}
$(document).on('click', '.c_cancel-btn', function () {
$('.c_otp-group').hide();
$('#c_resendOtpBtn').hide();
$('#c_mobile').attr('readonly', false).css('background-color', '#fff');
$('.otp-box').val('');
if (otpTimeout) {
clearInterval(otpTimeout);
otpTimeout = null; // Reset to prevent future issues
}
$('#c_otp_timer').hide();
});
// Function to start the OTP timer
function startOtpTimer() {
let countdown = 60; // 60 seconds
$('#c_resendOtpBtn').hide();
$('#c_otp_timer').show();
$('#c_otpTimer').text(`Resend OTP in ${countdown} seconds`);
otpTimeout = setInterval(function () {
countdown--;
$('#c_otpTimer').text(`Resend OTP in ${countdown} seconds`);
if (countdown <= 0) {
clearInterval(otpTimeout);
$('#c_otpTimer').text('');
$('#c_resendOtpBtn').show();
}
}, 1000);
}
// Function to resend OTP
function resendOtp() {
let contactNo = $('#c_mobile').val().trim();
if (validatePhoneNumber(contactNo)) {
$.ajax({
type: 'POST',
url: '<?= base_url(); ?>api/send_otp',
data: { contactNo: contactNo },
dataType: 'json',
success: function (response) {
if (response.status === 'true') {
toastr.success('OTP sent successfully.', 'OTP Sent');
clearInterval(otpTimeout);
startOtpTimer(); // Restart timer
} else {
toastr.error('Failed to send OTP.', 'Error');
}
},
error: function () {
toastr.error('Failed to send OTP.', 'Error');
}
});
} else {
toastr.error('Invalid Mobile number.', 'Error');
}
}
function getCombinedOtp() {
return $('.otp-box').map(function() {
return $.trim($(this).val());
}).get().join('');
}
function verifyOtp() {
// Get OTP values from input fields
let otp = getCombinedOtp();
// Validate OTP (4 digits, numeric)
if (otp.length !== 4 || isNaN(otp)) {
toastr.error('Invalid OTP. Please enter a 4-digit numeric OTP.', 'Error');
return;
}
let contact_No = $('#c_mobile').val().trim();
let selectedCountry = iti.getSelectedCountryData();
let countryCode = selectedCountry.iso2;
// Get contact number safely
let contactNo = (typeof iti !== 'undefined') ? iti.getNumber() : '';
if (!contactNo) {
toastr.error('Invalid or missing contact number.', 'Error');
return;
}
// Prevent multiple clicks
$('#c_verifyOtpBtn').prop('disabled', true);
$.ajax({
type: 'POST',
url: '<?= base_url(); ?>api/verify_otp',
data: { countryCode: countryCode || null, contact_no: contact_No, otp: otp },
dataType: 'json',
success: function (response) {
if (response.status === 'true') {
toastr.success('OTP verified successfully!', 'Success');
isOtpVerified = true;
// Hide buttons and disable inputs after successful verification
$('#c_verifyOtpBtn, #c_resendOtpBtn').hide();
$('.c_otp-group').hide();
$('.otp-box').attr('readonly', true).css('background-color', '#f5f5f5');
$('#c_otp_verified_tick').show();
} else {
toastr.error('Invalid OTP. Please try again.', 'Error');
$('#c_verifyOtpBtn').prop('disabled', false);
}
},
error: function () {
toastr.error('OTP verification failed. Please try again later.', 'Error');
$('#c_verifyOtpBtn').prop('disabled', false);
}
});
}
// Handle OTP verification button click
$('#c_verifyOtpBtn').on('click', function () {
verifyOtp();
});
// Function to validate OTP input and trigger verification
function validateOtp() {
const otpValues = getCombinedOtp();
console.log("Entered OTP:", otpValues);
console.log("OTP Length:", otpValues.length);
// Ensure OTP is exactly 4 digits and numeric
if (!/^\d{4}$/.test(otpValues)) {
toastr.error('Invalid OTP. Enter a 4-digit number.', 'Error');
return;
}
let contactInput = document.querySelector("#c_mobile"); // Ensure correct ID
let iti = window.intlTelInputGlobals.getInstance(contactInput);
if (!iti) {
toastr.warning('Phone input is not initialized.', 'Warning');
return;
}
// Get number in NATIONAL format (without country code)
let contactNo = iti.getNumber(intlTelInputUtils.numberFormat.NATIONAL) || contactInput.value.trim();
// Clean up the number: Remove spaces and leading zeros
contactNo = contactNo.replace(/\s+/g, '').replace(/^0+/, '');
console.log("Entered Number (Raw):", contactInput.value);
console.log("National Format Before Processing:", iti.getNumber(intlTelInputUtils.numberFormat.NATIONAL));
console.log("Final Processed Contact Number (Without Country Code):", contactNo);
if (iti.isValidNumber() && contactNo.length > 0) {
// Use the verify button element to trigger verification
let verifyButton = document.getElementById('c_verify_otp_btn');
if (verifyButton) {
verifyOtp(verifyButton);
} else {
toastr.warning('Verification button not found.', 'Warning');
}
} else {
toastr.warning('Invalid or missing contact number.', 'Warning');
}
}
// Add event listeners to OTP input fields
document.querySelectorAll('.otp-box').forEach((box, index, boxes) => {
box.addEventListener('input', function () {
// Move to the next box if a digit is entered
if (this.value.length === 1 && index < boxes.length - 1) {
boxes[index + 1].focus();
}
// Validate OTP when the 4th digit is entered
if (index === boxes.length - 1 && this.value.length === 1) {
validateOtp();
}
});
box.addEventListener('keydown', function (e) {
// Move to the previous box on Backspace if the current box is empty
if (e.key === 'Backspace' && this.value.length === 0 && index > 0) {
boxes[index - 1].focus();
}
});
});
// Attach click event handler to submit button
$("#submitButton").click(function(e) {
e.preventDefault();
// Assume the form is valid initially
let isValid = true;
// Clear previous Toastr notifications
toastr.clear();
// Clear previous error highlights
$(".error-input").removeClass("error-input");
// Initialize an array to store error messages
let errorMessages = [];
// Validate OTP
if (!isOtpVerified) {
isValid = false;
errorMessages.push("Please verify your mobile number by entering the OTP.");
$('#c_otp').addClass("error-input");
}
// Validate Name field
const name = $('#c_name').val().trim();
if (name === "" || !/^[A-Za-z\s]+$/.test(name)) {
isValid = false;
errorMessages.push("Name is required and must contain only letters.");
$('#c_name').addClass("error-input");
}
// ✅ Validate Mobile (International Support)
let mobile = iti.getNumber();
$(".contactNo").val(mobile);
let isMobileValid = iti.isValidNumber();
if (!isMobileValid) {
isValid = false;
errorMessages.push("Enter a valid mobile number.");
$('#c_mobile').addClass("error-input");
}
// Validate Email field
const email = $('#c_email').val().trim();
const emailPattern = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/;
if (!emailPattern.test(email)) {
isValid = false;
errorMessages.push("Enter a valid email address.");
$('#c_email').addClass("error-input");
}
// Validate Position field
const position = $('#c_position').val().trim();
if (position === "") {
isValid = false;
errorMessages.push("Please select a position.");
$('#c_position').addClass("error-input");
}
// Validate Resume file - required and PDF format
const fileInput = $('#c_resume')[0];
const file = fileInput.files[0];
if (!file || file.type !== "application/pdf") {
isValid = false;
errorMessages.push("Only PDF files are allowed for resume.");
$('#c_resume').addClass("error-input");
}
// Show toastr error messages if there are any validation issues
if (!isValid) {
toastr.error("Please correct the errors below.", "Submission Failed");
errorMessages.forEach(function(message) {
toastr.error(message);
});
}
// Submit form if all fields are valid
if (isValid) {
const formData = new FormData($('#submit_careers')[0]);
$('#loading').show();
$.ajax({
type: "POST",
url: $("#submit_careers").attr('action'),
data: formData,
processData: false,
contentType: false,
dataType: 'json',
success: function(data) {
$('#loading').hide();
console.log(data);
if (data.status === false) {
toastr.error("Please correct the errors below.", "Submission Failed");
$.each(data.errors, function(key, value) {
toastr.error(value);
$('#' + key).addClass("error-input"); // Highlight invalid fields from server-side validation
});
} else if (data.status === true) {
toastr.success(data.message, "Success");
$('#submit_careers')[0].reset();
$('#c_otp_verified_tick').hide();
$('#c_mobile').attr('readonly', false).css('background-color', '#fff');
$("html, body").animate({ scrollTop: $("#message").offset().top - 100 }, 1000);
sendEmailAfterSuccess(data.save_data);
}
},
error: function() {
$('#loading').hide();
toastr.error("An error occurred. Please try again later.", "Submission Error");
}
});
}
});
// Remove error highlight on focus
$(document).on("focus", ".error-input", function() {
$(this).removeClass("error-input");
});
// CSS to highlight invalid fields
$("<style>")
.prop("type", "text/css")
.html(`
.error-input {
border: 0.5px solid red !important;
background-color: #ffebeb;
}
`)
.appendTo("head");
// Function to send email after success
function sendEmailAfterSuccess(save_data) {
$.ajax({
type: 'POST',
url: '<?php echo base_url(); ?>careers-with-us/send_email', // Adjust the URL for the email API
data: { save_data: save_data}, // Send both data parameters
dataType: 'json',
success: function (response) {
if (response.status) {
toastr.success(response.message, 'Success'); // Show success toastr message
} else {
toastr.error(response.message, 'Error');
}
},
error: function () {
toastr.error('Error sending email. Please try again later.', 'Email');
}
});
}
</script> |