feat: implementacion de dashboards por rol, soporte de clases virtuales concurrentes en importador de sheets y cartelera del dia
This commit is contained in:
@@ -0,0 +1,303 @@
|
||||
// Main JavaScript file for Edu-Space Admin
|
||||
|
||||
$(document).ready(function() {
|
||||
// Initialize tooltips
|
||||
var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
|
||||
var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
|
||||
return new bootstrap.Tooltip(tooltipTriggerEl);
|
||||
});
|
||||
|
||||
// Initialize popovers
|
||||
var popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'));
|
||||
var popoverList = popoverTriggerList.map(function (popoverTriggerEl) {
|
||||
return new bootstrap.Popover(popoverTriggerEl);
|
||||
});
|
||||
|
||||
// Auto-hide alerts after 5 seconds
|
||||
setTimeout(function() {
|
||||
$('.alert.fade').alert('close');
|
||||
}, 5000);
|
||||
|
||||
// Confirm delete actions
|
||||
$('.delete-confirm').on('click', function(e) {
|
||||
if (!confirm('Are you sure you want to delete this item? This action cannot be undone.')) {
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// Form validation enhancements
|
||||
$('form').on('submit', function() {
|
||||
var form = $(this);
|
||||
var submitBtn = form.find('button[type="submit"]');
|
||||
|
||||
// Show loading state
|
||||
submitBtn.prop('disabled', true);
|
||||
var originalText = submitBtn.html();
|
||||
submitBtn.html('<i class="bi bi-hourglass-split me-2"></i>Loading...');
|
||||
|
||||
// Re-enable after 10 seconds in case of error
|
||||
setTimeout(function() {
|
||||
submitBtn.prop('disabled', false);
|
||||
submitBtn.html(originalText);
|
||||
}, 10000);
|
||||
});
|
||||
|
||||
// Copy to clipboard functionality
|
||||
$('.copy-to-clipboard').on('click', function() {
|
||||
var text = $(this).data('text');
|
||||
if (!text) {
|
||||
text = $(this).text();
|
||||
}
|
||||
|
||||
navigator.clipboard.writeText(text).then(function() {
|
||||
showToast('Copied to clipboard!', 'success');
|
||||
}).catch(function() {
|
||||
showToast('Failed to copy to clipboard', 'error');
|
||||
});
|
||||
});
|
||||
|
||||
// Quick search functionality
|
||||
$('#quickSearch').on('input', function() {
|
||||
var searchTerm = $(this).val().toLowerCase();
|
||||
|
||||
$('.searchable-item').each(function() {
|
||||
var item = $(this);
|
||||
var text = item.text().toLowerCase();
|
||||
|
||||
if (text.includes(searchTerm)) {
|
||||
item.show();
|
||||
} else {
|
||||
item.hide();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Initialize datepickers
|
||||
$('.datetimepicker').each(function() {
|
||||
$(this).flatpickr({
|
||||
enableTime: true,
|
||||
dateFormat: "Y-m-d H:i",
|
||||
time_24hr: true,
|
||||
minDate: "today"
|
||||
});
|
||||
});
|
||||
|
||||
$('.datepicker').each(function() {
|
||||
$(this).flatpickr({
|
||||
dateFormat: "Y-m-d",
|
||||
minDate: "today"
|
||||
});
|
||||
});
|
||||
|
||||
// Auto-save functionality for multi-step forms
|
||||
$('.auto-save').on('change input', function() {
|
||||
var form = $(this).closest('form');
|
||||
var formData = form.serialize();
|
||||
|
||||
// Save to localStorage
|
||||
localStorage.setItem('autosave_' + form.attr('id'), formData);
|
||||
showToast('Draft saved automatically', 'info');
|
||||
});
|
||||
|
||||
// Restore auto-saved data
|
||||
$('form.auto-save-restore').each(function() {
|
||||
var form = $(this);
|
||||
var savedData = localStorage.getItem('autosave_' + form.attr('id'));
|
||||
|
||||
if (savedData) {
|
||||
// Show restore prompt
|
||||
if (confirm('Found unsaved changes. Would you like to restore them?')) {
|
||||
var params = new URLSearchParams(savedData);
|
||||
params.forEach(function(value, key) {
|
||||
form.find('[name="' + key + '"]').val(value);
|
||||
});
|
||||
showToast('Draft restored', 'info');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Print functionality
|
||||
$('.btn-print').on('click', function() {
|
||||
window.print();
|
||||
});
|
||||
|
||||
// Export functionality
|
||||
$('.btn-export').on('click', function() {
|
||||
var format = $(this).data('format');
|
||||
var url = $(this).data('url');
|
||||
|
||||
if (format === 'excel') {
|
||||
window.open(url + '?export=excel', '_blank');
|
||||
} else if (format === 'pdf') {
|
||||
window.open(url + '?export=pdf', '_blank');
|
||||
} else if (format === 'csv') {
|
||||
window.open(url + '?export=csv', '_blank');
|
||||
}
|
||||
});
|
||||
|
||||
// Keyboard shortcuts
|
||||
$(document).on('keydown', function(e) {
|
||||
// Ctrl/Cmd + K for search
|
||||
if ((e.ctrlKey || e.metaKey) && e.key === 'k') {
|
||||
e.preventDefault();
|
||||
$('#quickSearch').focus();
|
||||
}
|
||||
|
||||
// Escape to close modals
|
||||
if (e.key === 'Escape') {
|
||||
$('.modal.show').modal('hide');
|
||||
}
|
||||
});
|
||||
|
||||
// Initialize tooltips dynamically for AI-generated content
|
||||
initializeDynamicTooltips();
|
||||
});
|
||||
|
||||
// Utility functions
|
||||
|
||||
function showToast(message, type = 'info') {
|
||||
var toastHtml = `
|
||||
<div class="toast align-items-center text-white bg-${type === 'error' ? 'danger' : type} border-0" role="alert">
|
||||
<div class="d-flex">
|
||||
<div class="toast-body">
|
||||
${message}
|
||||
</div>
|
||||
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast"></button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
var toastContainer = $('.toast-container');
|
||||
var toastElement = $(toastHtml);
|
||||
toastContainer.append(toastElement);
|
||||
|
||||
var toast = new bootstrap.Toast(toastElement[0]);
|
||||
toast.show();
|
||||
|
||||
// Remove toast element after it's hidden
|
||||
toastElement.on('hidden.bs.toast', function() {
|
||||
$(this).remove();
|
||||
});
|
||||
}
|
||||
|
||||
function confirmAction(message, callback) {
|
||||
if (confirm(message)) {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
function formatDateTime(dateTimeString) {
|
||||
var date = new Date(dateTimeString);
|
||||
return date.toLocaleString();
|
||||
}
|
||||
|
||||
function formatDate(dateString) {
|
||||
var date = new Date(dateString);
|
||||
return date.toLocaleDateString();
|
||||
}
|
||||
|
||||
function formatTime(timeString) {
|
||||
var date = new Date(timeString);
|
||||
return date.toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'});
|
||||
}
|
||||
|
||||
function debounce(func, wait) {
|
||||
let timeout;
|
||||
return function executedFunction(...args) {
|
||||
const later = () => {
|
||||
clearTimeout(timeout);
|
||||
func(...args);
|
||||
};
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(later, wait);
|
||||
};
|
||||
}
|
||||
|
||||
function initializeDynamicTooltips() {
|
||||
// Initialize tooltips for dynamically generated content
|
||||
$('[data-bs-toggle="tooltip"]:not([aria-describedby])').each(function() {
|
||||
new bootstrap.Tooltip(this);
|
||||
});
|
||||
}
|
||||
|
||||
// API Helper functions
|
||||
function apiCall(url, method = 'GET', data = null) {
|
||||
return $.ajax({
|
||||
url: url,
|
||||
method: method,
|
||||
data: data,
|
||||
headers: {
|
||||
'X-CSRFToken': csrfToken || ''
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function handleApiError(xhr) {
|
||||
if (xhr.responseJSON && xhr.responseJSON.message) {
|
||||
showToast(xhr.responseJSON.message, 'error');
|
||||
} else {
|
||||
showToast('An error occurred. Please try again.', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
// Form validation helpers
|
||||
function validateForm(form) {
|
||||
var isValid = true;
|
||||
var errors = [];
|
||||
|
||||
form.find('[required]').each(function() {
|
||||
var field = $(this);
|
||||
if (!field.val()) {
|
||||
isValid = false;
|
||||
errors.push(field.attr('data-label') || field.attr('name'));
|
||||
field.addClass('is-invalid');
|
||||
} else {
|
||||
field.removeClass('is-invalid');
|
||||
}
|
||||
});
|
||||
|
||||
if (!isValid) {
|
||||
showToast('Please fill in the required fields: ' + errors.join(', '), 'error');
|
||||
}
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
// Image preview functionality
|
||||
function previewImage(input, previewElement) {
|
||||
if (input.files && input.files[0]) {
|
||||
var reader = new FileReader();
|
||||
|
||||
reader.onload = function(e) {
|
||||
previewElement.attr('src', e.target.result);
|
||||
};
|
||||
|
||||
reader.readAsDataURL(input.files[0]);
|
||||
}
|
||||
}
|
||||
|
||||
// Export to CSV function
|
||||
function exportToCSV(data, filename) {
|
||||
var csv = '';
|
||||
var headers = Object.keys(data[0]);
|
||||
|
||||
// Add headers
|
||||
csv += headers.join(',') + '\n';
|
||||
|
||||
// Add data
|
||||
data.forEach(function(row) {
|
||||
headers.forEach(function(header, index) {
|
||||
if (index > 0) csv += ',';
|
||||
csv += '"' + (row[header] || '') + '"';
|
||||
});
|
||||
csv += '\n';
|
||||
});
|
||||
|
||||
// Create download link
|
||||
var hiddenElement = document.createElement('a');
|
||||
hiddenElement.href = 'data:text/csv;charset=utf-8,' + encodeURI(csv);
|
||||
hiddenElement.target = '_blank';
|
||||
hiddenElement.download = filename + '.csv';
|
||||
hiddenElement.click();
|
||||
}
|
||||
Reference in New Issue
Block a user