Files
admin-edu-space/frontend/public/js/main.js
T

303 lines
8.6 KiB
JavaScript

// 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();
}