// Mobile menu toggle
document.addEventListener('DOMContentLoaded', function() {
const mobileMenuBtn = document.getElementById('mobile-menu-btn');
const mobileMenu = document.getElementById('mobile-menu');
if (mobileMenuBtn && mobileMenu) {
mobileMenuBtn.addEventListener('click', function() {
mobileMenu.classList.toggle('hidden');
// Change icon
const icon = mobileMenuBtn.querySelector('i');
if (mobileMenu.classList.contains('hidden')) {
icon.className = 'fas fa-bars text-xl';
} else {
icon.className = 'fas fa-times text-xl';
}
});
}
// Search filters toggle for mobile
const filterToggleBtn = document.getElementById('filter-toggle-btn');
const filtersContainer = document.getElementById('filters-container');
if (filterToggleBtn && filtersContainer) {
filterToggleBtn.addEventListener('click', function() {
filtersContainer.classList.toggle('hidden');
const icon = filterToggleBtn.querySelector('i');
if (filtersContainer.classList.contains('hidden')) {
icon.className = 'fas fa-filter mr-2';
filterToggleBtn.innerHTML = 'Mostrar Filtros';
} else {
icon.className = 'fas fa-times mr-2';
filterToggleBtn.innerHTML = 'Ocultar Filtros';
}
});
}
// Auto-submit form when filters change
const searchForm = document.getElementById('search-form');
if (searchForm) {
const filterSelects = searchForm.querySelectorAll('select[name="area"], select[name="ubicacion"], select[name="tipo_contrato"], select[name="modalidad"], select[name="nivel"], select[name="salario_min"]');
filterSelects.forEach(select => {
select.addEventListener('change', function() {
// Small delay to show the selection visually
setTimeout(() => {
searchForm.submit();
}, 100);
});
});
// Submit on Enter key for search input
const searchInput = searchForm.querySelector('input[name="search"]');
if (searchInput) {
searchInput.addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
e.preventDefault();
searchForm.submit();
}
});
}
}
// Smooth animations
const cards = document.querySelectorAll('.card-hover');
cards.forEach(card => {
card.addEventListener('mouseenter', function() {
this.style.transform = 'translateY(-4px)';
});
card.addEventListener('mouseleave', function() {
this.style.transform = 'translateY(0)';
});
});
// Auto-hide alerts
const alerts = document.querySelectorAll('.alert-auto-hide');
alerts.forEach(alert => {
setTimeout(() => {
alert.style.opacity = '0';
setTimeout(() => {
alert.remove();
}, 300);
}, 5000);
});
// File input preview
const fileInput = document.getElementById('cv_file');
const filePreview = document.getElementById('file-preview');
if (fileInput && filePreview) {
fileInput.addEventListener('change', function(e) {
const file = e.target.files[0];
if (file) {
const fileName = file.name;
const fileSize = (file.size / 1024 / 1024).toFixed(2);
if (file.type === 'application/pdf') {
filePreview.innerHTML = `
${fileName}
${fileSize} MB
`;
filePreview.classList.remove('hidden');
} else {
alert('Por favor, selecciona un archivo PDF vĂ¡lido.');
fileInput.value = '';
filePreview.classList.add('hidden');
}
} else {
filePreview.classList.add('hidden');
}
});
}
// Form validation
const forms = document.querySelectorAll('form');
forms.forEach(form => {
form.addEventListener('submit', function(e) {
const requiredFields = form.querySelectorAll('[required]');
let isValid = true;
requiredFields.forEach(field => {
if (!field.value.trim()) {
isValid = false;
field.classList.add('border-red-500');
field.classList.remove('border-gray-300');
} else {
field.classList.remove('border-red-500');
field.classList.add('border-gray-300');
}
});
if (!isValid) {
e.preventDefault();
showAlert('Por favor, completa todos los campos obligatorios.', 'error');
}
});
});
// Clear search functionality
const clearSearchBtn = document.getElementById('clear-search');
if (clearSearchBtn) {
clearSearchBtn.addEventListener('click', function(e) {
e.preventDefault();
// Redirect to clean index page
window.location.href = 'index.php';
});
}
// Search suggestions (simple implementation)
const searchInput = document.querySelector('input[name="search"]');
if (searchInput) {
let searchTimeout;
searchInput.addEventListener('input', function() {
clearTimeout(searchTimeout);
const query = this.value.trim();
if (query.length >= 3) {
searchTimeout = setTimeout(() => {
// Here you could implement search suggestions
console.log('Searching for:', query);
}, 300);
}
});
}
});
// Show alert function
function showAlert(message, type = 'info') {
const alertTypes = {
success: 'bg-green-100 border-green-400 text-green-700',
error: 'bg-red-100 border-red-400 text-red-700',
warning: 'bg-yellow-100 border-yellow-400 text-yellow-700',
info: 'bg-blue-100 border-blue-400 text-blue-700'
};
const alertClass = alertTypes[type] || alertTypes.info;
const alertHTML = `
${message}
`;
document.body.insertAdjacentHTML('beforeend', alertHTML);
}
// Loading state for buttons
function setButtonLoading(button, isLoading = true) {
if (isLoading) {
button.disabled = true;
const originalText = button.innerHTML;
button.setAttribute('data-original-text', originalText);
button.innerHTML = 'Cargando...';
button.classList.add('opacity-75');
} else {
button.disabled = false;
const originalText = button.getAttribute('data-original-text');
if (originalText) {
button.innerHTML = originalText;
}
button.classList.remove('opacity-75');
}
}
// Format currency (Colombian Pesos)
function formatCurrency(amount) {
if (!amount) return 'No especificado';
return new Intl.NumberFormat('es-CO', {
style: 'currency',
currency: 'COP',
minimumFractionDigits: 0,
maximumFractionDigits: 0
}).format(amount);
}
// Format date
function formatDate(dateString) {
const date = new Date(dateString);
return date.toLocaleDateString('es-CO', {
year: 'numeric',
month: 'long',
day: 'numeric'
});
}
// Copy to clipboard
function copyToClipboard(text) {
navigator.clipboard.writeText(text).then(function() {
showAlert('Copiado al portapapeles', 'success');
}, function() {
showAlert('Error al copiar', 'error');
});
}
// Share job
function shareJob(jobId, jobTitle) {
const url = `${window.location.origin}/job-detail.php?id=${jobId}`;
if (navigator.share) {
navigator.share({
title: jobTitle,
text: `Mira esta oportunidad laboral: ${jobTitle}`,
url: url
});
} else {
copyToClipboard(url);
}
}
// Debounce function for search
function debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}