(() => {
'use strict';
// Get API URL from configuration
const getAPIBaseUrl = () => {
if (window.AIMHSA && window.AIMHSA.Config) {
return window.AIMHSA.Config.getApiBaseUrl();
}
// Fallback to auto-detection
const loc = window.location;
if (loc.port === '8000') {
return `${loc.protocol}//${loc.hostname}:7860`;
} else if (loc.port === '7860' || loc.port === '') {
return loc.origin;
} else {
return 'https://prodevroger-ishingiro.hf.space';
}
};
const API_BASE_URL = getAPIBaseUrl();
// Elements
const professionalName = document.getElementById('professionalName');
const notificationsList = document.getElementById('notificationsList');
const upcomingSessions = document.getElementById('upcomingSessions');
const sessionHistory = document.getElementById('sessionHistory');
const markAllReadBtn = document.getElementById('markAllReadBtn');
const refreshSessionsBtn = document.getElementById('refreshSessionsBtn');
const refreshNotificationsBtn = document.getElementById('refreshNotificationsBtn');
const logoutBtn = document.getElementById('logoutBtn');
const sessionModal = document.getElementById('sessionModal');
const notesModal = document.getElementById('notesModal');
const reportsModal = document.getElementById('reportsModal');
const emergencyModal = document.getElementById('emergencyModal');
const notesForm = document.getElementById('notesForm');
const followUpRequired = document.getElementById('followUpRequired');
const followUpDateGroup = document.getElementById('followUpDateGroup');
// New elements
const totalSessions = document.getElementById('totalSessions');
const unreadNotifications = document.getElementById('unreadNotifications');
const upcomingToday = document.getElementById('upcomingToday');
const highRiskSessions = document.getElementById('highRiskSessions');
const sessionFilter = document.getElementById('sessionFilter');
const historyFilter = document.getElementById('historyFilter');
const viewAllSessionsBtn = document.getElementById('viewAllSessionsBtn');
const viewBookedUsersBtn = document.getElementById('viewBookedUsersBtn');
const addSessionNotesBtn = document.getElementById('addSessionNotesBtn');
const viewReportsBtn = document.getElementById('viewReportsBtn');
const emergencyContactsBtn = document.getElementById('emergencyContactsBtn');
const generateReportBtn = document.getElementById('generateReportBtn');
const reportContent = document.getElementById('reportContent');
const openIntakeBtn = document.getElementById('openIntakeBtn');
const intakeModal = document.getElementById('intakeModal');
const intakeForm = document.getElementById('intakeForm');
// Booked users elements
const bookedUsersList = document.getElementById('bookedUsersList');
const userFilter = document.getElementById('userFilter');
const refreshUsersBtn = document.getElementById('refreshUsersBtn');
const userProfileModal = document.getElementById('userProfileModal');
const userProfileContent = document.getElementById('userProfileContent');
// State
let currentProfessional = null;
let notifications = [];
let sessions = [];
let bookedUsers = [];
let currentSessionId = null;
// Initialize
init();
async function init() {
// Check if professional is logged in
const professionalData = localStorage.getItem('aimhsa_professional');
if (!professionalData) {
// Check if they're logged in as a different type of user
const userData = localStorage.getItem('aimhsa_account');
const adminData = localStorage.getItem('aimhsa_admin');
if (userData && userData !== 'null') {
alert('You are logged in as a regular user. Please logout and login as a professional.');
window.location.href = '/';
return;
}
if (adminData) {
alert('You are logged in as an admin. Please logout and login as a professional.');
window.location.href = '/admin_dashboard.html';
return;
}
window.location.href = '/login';
return;
}
currentProfessional = JSON.parse(professionalData);
professionalName.textContent = currentProfessional.name;
// Load initial data
await loadDashboardData();
await loadNotifications();
await loadSessions();
await loadBookedUsers();
// Set up auto-refresh
setInterval(loadDashboardData, 30000); // Every 30 seconds
setInterval(loadNotifications, 30000); // Every 30 seconds
setInterval(loadSessions, 60000); // Every minute
// Set up event listeners
setupEventListeners();
}
// API Helper
async function api(path, opts = {}) {
const url = API_BASE_URL + path;
const headers = {
'Content-Type': 'application/json',
...opts.headers
};
// Include professional id header if available
if (currentProfessional?.professional_id) {
headers['X-Professional-ID'] = String(currentProfessional.professional_id);
}
const res = await fetch(url, {
headers,
...opts
});
if (!res.ok) {
const txt = await res.text();
throw new Error(txt || res.statusText);
}
return await res.json();
}
function setupEventListeners() {
// Logout
logoutBtn.addEventListener('click', logout);
// Notifications
markAllReadBtn.addEventListener('click', markAllNotificationsRead);
refreshNotificationsBtn.addEventListener('click', loadNotifications);
// Sessions
refreshSessionsBtn.addEventListener('click', loadSessions);
sessionFilter.addEventListener('change', filterSessions);
historyFilter.addEventListener('change', filterSessionHistory);
// Quick actions
viewAllSessionsBtn.addEventListener('click', () => {
sessionFilter.value = 'all';
loadSessions();
});
viewBookedUsersBtn.addEventListener('click', () => {
userFilter.value = 'all';
loadBookedUsers();
});
addSessionNotesBtn.addEventListener('click', openNotesModal);
viewReportsBtn.addEventListener('click', openReportsModal);
emergencyContactsBtn.addEventListener('click', openEmergencyModal);
openIntakeBtn.addEventListener('click', openIntakeModal);
// Booked users
refreshUsersBtn.addEventListener('click', loadBookedUsers);
userFilter.addEventListener('change', filterBookedUsers);
// Modals
document.querySelectorAll('.close').forEach(closeBtn => {
closeBtn.addEventListener('click', closeModals);
});
// Notes form
notesForm.addEventListener('submit', saveSessionNotes);
followUpRequired.addEventListener('change', toggleFollowUpDate);
intakeForm.addEventListener('submit', submitIntakeForm);
// Report generation
generateReportBtn.addEventListener('click', generateReport);
// Close modals when clicking outside
window.addEventListener('click', (e) => {
if (e.target.classList.contains('modal')) {
closeModals();
}
});
}
async function loadDashboardData() {
try {
// Load dashboard stats
const stats = await api('/professional/dashboard-stats');
updateDashboardStats(stats);
} catch (error) {
console.error('Error loading dashboard data:', error);
}
}
async function loadNotifications() {
try {
const data = await api('/professional/notifications');
notifications = data;
displayNotifications(notifications);
} catch (error) {
console.error('Error loading notifications:', error);
notificationsList.innerHTML = '
Error loading notifications
';
}
}
async function loadSessions() {
try {
const data = await api('/professional/sessions');
sessions = data;
displaySessions(sessions);
} catch (error) {
console.error('Error loading sessions:', error);
upcomingSessions.innerHTML = 'Error loading sessions
';
}
}
async function loadBookedUsers() {
try {
const data = await api('/professional/booked-users');
bookedUsers = data.users || [];
displayBookedUsers(bookedUsers);
} catch (error) {
console.error('Error loading booked users:', error);
bookedUsersList.innerHTML = 'Error loading booked users
';
}
}
function updateDashboardStats(stats) {
totalSessions.textContent = stats.totalSessions || 0;
unreadNotifications.textContent = stats.unreadNotifications || 0;
upcomingToday.textContent = stats.upcomingToday || 0;
highRiskSessions.textContent = stats.highRiskCases || 0;
}
function displayNotifications(notificationsData) {
if (!notificationsData || notificationsData.length === 0) {
notificationsList.innerHTML = 'No notifications
';
return;
}
notificationsList.innerHTML = notificationsData.map(notification => `
${notification.title}
${notification.message}
${formatDateTime(notification.createdAt)}
`).join('');
}
function displaySessions(sessionsData) {
if (!sessionsData || sessionsData.length === 0) {
upcomingSessions.innerHTML = 'No sessions found
';
return;
}
upcomingSessions.innerHTML = sessionsData.map(session => `
Session Type:
${session.sessionType}
Scheduled:
${formatDateTime(session.scheduledDatetime)}
Risk Level:
${session.riskLevel}
Risk Score:
${session.riskScore}/100
${session.userPhone ? `
` : ''}
${session.userEmail ? `
` : ''}
${session.userLocation ? `
📍 Location:
${session.userLocation}
` : ''}
View Details
${session.bookingStatus === 'pending' ? `
Accept
Decline
` : ''}
`).join('');
}
function filterSessions() {
const filter = sessionFilter.value;
let filteredSessions = sessions;
switch(filter) {
case 'today':
filteredSessions = sessions.filter(session => isToday(new Date(session.scheduledDatetime * 1000)));
break;
case 'this_week':
filteredSessions = sessions.filter(session => isThisWeek(new Date(session.scheduledDatetime * 1000)));
break;
case 'high_risk':
filteredSessions = sessions.filter(session => session.riskLevel === 'high' || session.riskLevel === 'critical');
break;
}
displaySessions(filteredSessions);
}
function filterSessionHistory() {
const filter = historyFilter.value;
// Implementation for filtering session history
console.log('Filtering session history by:', filter);
}
function displayBookedUsers(usersData) {
if (!usersData || usersData.length === 0) {
bookedUsersList.innerHTML = 'No booked users found
';
return;
}
bookedUsersList.innerHTML = usersData.map(user => `
Email:
${user.email}
Phone:
${user.telephone}
Location:
${user.district}, ${user.province}
Total Bookings:
${user.totalBookings}
Highest Risk Score:
${user.highestRiskScore}/100
Last Booking:
${formatDateTime(user.lastBookingTime)}
View Profile
Sessions
`).join('');
}
function filterBookedUsers() {
const filter = userFilter.value;
let filteredUsers = bookedUsers;
switch(filter) {
case 'high_risk':
filteredUsers = bookedUsers.filter(user =>
user.highestRiskLevel === 'high' || user.highestRiskLevel === 'critical'
);
break;
case 'recent':
const oneWeekAgo = Date.now() - (7 * 24 * 60 * 60 * 1000);
filteredUsers = bookedUsers.filter(user =>
user.lastBookingTime * 1000 > oneWeekAgo
);
break;
case 'multiple_sessions':
filteredUsers = bookedUsers.filter(user => user.totalBookings > 1);
break;
}
displayBookedUsers(filteredUsers);
}
async function markAllNotificationsRead() {
try {
await api('/professional/notifications/mark-all-read', { method: 'POST' });
await loadNotifications();
await loadDashboardData();
} catch (error) {
console.error('Error marking notifications as read:', error);
}
}
async function markNotificationRead(notificationId) {
try {
await api(`/professional/notifications/${notificationId}/read`, { method: 'POST' });
await loadNotifications();
await loadDashboardData();
} catch (error) {
console.error('Error marking notification as read:', error);
}
}
async function acceptSession(bookingId) {
try {
await api(`/professional/sessions/${bookingId}/accept`, { method: 'POST' });
await loadSessions();
await loadDashboardData();
alert('Session accepted successfully');
} catch (error) {
console.error('Error accepting session:', error);
alert('Failed to accept session');
}
}
async function declineSession(bookingId) {
try {
await api(`/professional/sessions/${bookingId}/decline`, { method: 'POST' });
await loadSessions();
await loadDashboardData();
alert('Session declined');
} catch (error) {
console.error('Error declining session:', error);
alert('Failed to decline session');
}
}
async function viewSessionDetails(bookingId) {
try {
currentSessionId = bookingId;
const sessionDetails = await api(`/professional/sessions/${bookingId}`);
// Convert the detailed session data to the format expected by displaySessionDetailsModal
const session = {
bookingId: sessionDetails.bookingId,
convId: sessionDetails.convId,
userAccount: sessionDetails.userAccount,
userName: sessionDetails.userName,
userIp: sessionDetails.userIp,
riskLevel: sessionDetails.riskLevel,
riskScore: sessionDetails.riskScore,
detectedIndicators: sessionDetails.detectedIndicators,
conversationSummary: sessionDetails.conversationSummary,
bookingStatus: sessionDetails.bookingStatus,
scheduledDatetime: sessionDetails.scheduledDatetime,
sessionType: sessionDetails.sessionType,
createdTs: sessionDetails.createdTs,
updatedTs: sessionDetails.updatedTs,
userPhone: sessionDetails.userPhone,
userEmail: sessionDetails.userEmail,
userLocation: sessionDetails.userLocation
};
displaySessionDetailsModal(session, sessionDetails);
} catch (error) {
console.error('Error loading session details:', error);
alert('Failed to load session details');
}
}
async function displaySessionDetailsModal(session, sessionDetails = null) {
const modal = document.getElementById('sessionModal');
const content = document.getElementById('sessionDetails');
let userInfo = null;
// If sessionDetails is provided, extract user information from it
if (sessionDetails) {
userInfo = {
userAccount: sessionDetails.userAccount,
fullName: sessionDetails.userFullName,
email: sessionDetails.userEmail,
telephone: sessionDetails.userPhone,
province: sessionDetails.userProvince,
district: sessionDetails.userDistrict,
userCreatedAt: sessionDetails.userCreatedAt,
totalBookings: sessionDetails.sessions ? sessionDetails.sessions.length : 0,
highestRiskLevel: sessionDetails.riskAssessments && sessionDetails.riskAssessments.length > 0
? sessionDetails.riskAssessments[0].riskLevel : 'unknown',
highestRiskScore: sessionDetails.riskAssessments && sessionDetails.riskAssessments.length > 0
? Math.max(...sessionDetails.riskAssessments.map(r => r.riskScore)) : 0,
firstBookingTime: sessionDetails.sessions && sessionDetails.sessions.length > 0
? Math.min(...sessionDetails.sessions.map(s => s.createdTs)) : null,
lastBookingTime: sessionDetails.sessions && sessionDetails.sessions.length > 0
? Math.max(...sessionDetails.sessions.map(s => s.createdTs)) : null,
sessions: sessionDetails.sessions || [],
riskAssessments: sessionDetails.riskAssessments || [],
conversations: sessionDetails.conversationHistory || []
};
} else {
// Fallback: try to get user info from booked users or API
try {
const user = bookedUsers.find(u => u.userAccount === session.userAccount);
if (user) {
userInfo = user;
} else {
// Try to get from individual user API
userInfo = await api(`/professional/users/${session.userAccount}`);
}
} catch (fallbackError) {
console.error('Error loading user info:', fallbackError);
}
}
content.innerHTML = `
📋 Session Details
Session Type:
${session.sessionType}
Scheduled Time:
${formatDateTime(session.scheduledDatetime)}
Created:
${formatDateTime(session.createdTs)}
Last Updated:
${formatDateTime(session.updatedTs)}
⚠️ Risk Assessment
${session.riskLevel.toUpperCase()}
${session.riskScore}/100
${session.detectedIndicators ? `
Detected Indicators:
${JSON.parse(session.detectedIndicators).slice(0, 5).map(indicator => `
${indicator}
`).join('')}
${JSON.parse(session.detectedIndicators).length > 5 ? `
+${JSON.parse(session.detectedIndicators).length - 5} more
` : ''}
` : ''}
${userInfo ? `
👤 Complete User Profile
📋 Personal Information
Full Name:
${userInfo.fullName || 'Not provided'}
Email Address:
${userInfo.email || 'Not provided'}
Phone Number:
${userInfo.telephone || 'Not provided'}
Location:
${formatLocation(userInfo.district, userInfo.province)}
Account Created:
${userInfo.userCreatedAt ? formatDateTime(userInfo.userCreatedAt) : 'Not available'}
📊 Session Statistics
Total Bookings:
${userInfo.totalBookings || 0}
Highest Risk Level:
${userInfo.highestRiskLevel || 'Unknown'}
Highest Risk Score:
${userInfo.highestRiskScore || 0}/100
First Booking:
${userInfo.firstBookingTime ? formatDateTime(userInfo.firstBookingTime) : 'Not available'}
Last Booking:
${userInfo.lastBookingTime ? formatDateTime(userInfo.lastBookingTime) : 'Not available'}
${userInfo.sessions && userInfo.sessions.length > 0 ? `
📅 Recent Sessions (Last 5)
${userInfo.sessions.slice(0, 5).map(s => `
Risk: ${s.riskLevel} (${s.riskScore}/100)
${formatDateTime(s.scheduledDatetime)}
${s.bookingId === session.bookingId ? '
Current Session
' : ''}
`).join('')}
` : ''}
${userInfo.riskAssessments && userInfo.riskAssessments.length > 0 ? `
📈 Risk Assessment History
${userInfo.riskAssessments.slice(0, 5).map(risk => `
${risk.riskLevel}
${risk.riskScore}/100
${formatDateTime(risk.timestamp)}
`).join('')}
` : ''}
${userInfo.conversations && userInfo.conversations.length > 0 ? `
💬 Recent Conversations
${userInfo.conversations.slice(0, 3).map(conv => `
${conv.preview}
${formatDateTime(conv.timestamp)}
`).join('')}
` : ''}
View Complete Profile
View All Sessions
Add Session Notes
` : ''}
${session.conversationSummary ? `
💭 Conversation Summary
${session.conversationSummary}
` : ''}
${sessionDetails ? `
📋 Additional Session Information
${sessionDetails.conversationHistory && sessionDetails.conversationHistory.length > 0 ? `
💬 Full Conversation
${sessionDetails.conversationHistory.map(msg => `
${msg.content}
${formatDateTime(msg.timestamp)}
`).join('')}
` : ''}
${sessionDetails.sessionNotes && sessionDetails.sessionNotes.notes ? `
📝 Session Notes
${sessionDetails.sessionNotes.notes}
` : ''}
${sessionDetails.sessionNotes && sessionDetails.sessionNotes.treatmentPlan ? `
🎯 Treatment Plan
${sessionDetails.sessionNotes.treatmentPlan}
` : ''}
` : ''}
`;
modal.style.display = 'block';
}
function openNotesModal() {
notesModal.style.display = 'block';
}
function openReportsModal() {
reportsModal.style.display = 'block';
}
function openEmergencyModal() {
emergencyModal.style.display = 'block';
}
async function viewUserProfile(userAccount) {
try {
// Try to get user from booked users first
let user = bookedUsers.find(u => u.userAccount === userAccount);
if (!user) {
// If not found, get from API
user = await api(`/professional/users/${userAccount}`);
}
if (!user) {
alert('User not found');
return;
}
displayUserProfileModal(user);
} catch (error) {
console.error('Error loading user profile:', error);
alert('Failed to load user profile');
}
}
function displayUserProfileModal(user) {
userProfileContent.innerHTML = `
Contact Information
Email: ${user.email}
Phone: ${user.telephone}
Location: ${user.district}, ${user.province}
User Since: ${formatDateTime(user.userCreatedAt)}
Session Statistics
Total Bookings: ${user.totalBookings}
Highest Risk Level: ${user.highestRiskLevel}
Highest Risk Score: ${user.highestRiskScore}/100
First Booking: ${formatDateTime(user.firstBookingTime)}
Last Booking: ${formatDateTime(user.lastBookingTime)}
Recent Sessions
${user.sessions.slice(0, 5).map(session => `
${session.sessionType}
${session.bookingStatus}
Risk: ${session.riskLevel} (${session.riskScore}/100)
Date: ${formatDateTime(session.scheduledDatetime)}
`).join('')}
Risk Assessment History
${user.riskAssessments.slice(0, 5).map(risk => `
${risk.riskLevel}
${risk.riskScore}/100
${formatDateTime(risk.timestamp)}
`).join('')}
Conversation History
${user.conversations.map(conv => `
${conv.preview}
${formatDateTime(conv.timestamp)}
`).join('')}
`;
userProfileModal.style.display = 'block';
}
function viewUserSessions(userAccount) {
// Filter sessions to show only this user's sessions
const userSessions = sessions.filter(session => session.userAccount === userAccount);
displaySessions(userSessions);
// Scroll to sessions section
document.querySelector('.sessions-section').scrollIntoView({ behavior: 'smooth' });
}
function closeModals() {
document.querySelectorAll('.modal').forEach(modal => {
modal.style.display = 'none';
});
}
function openIntakeModal() {
// Prefill from selected session when available
const selected = sessions.find(s => s.bookingId === currentSessionId);
if (selected) {
document.getElementById('intakeUsername').value = selected.userAccount || '';
document.getElementById('intakeEmail').value = '';
document.getElementById('intakeFullName').value = selected.userName || '';
document.getElementById('intakePhone').value = '';
document.getElementById('intakeProvince').value = '';
document.getElementById('intakeDistrict').value = '';
} else {
intakeForm.reset();
}
intakeModal.style.display = 'block';
}
async function submitIntakeForm(e) {
e.preventDefault();
const payload = {
username: document.getElementById('intakeUsername').value.trim(),
email: document.getElementById('intakeEmail').value.trim(),
full_name: document.getElementById('intakeFullName').value.trim(),
phone: document.getElementById('intakePhone').value.trim(),
province: document.getElementById('intakeProvince').value.trim(),
district: document.getElementById('intakeDistrict').value.trim(),
password: document.getElementById('intakePassword').value,
confirm_password: document.getElementById('intakeConfirmPassword').value
};
try {
await api('/professional/users/intake', {
method: 'POST',
body: JSON.stringify(payload)
});
alert('User profile saved');
closeModals();
} catch (err) {
console.error('Intake save failed:', err);
alert('Failed to save user');
}
}
function toggleFollowUpDate() {
followUpDateGroup.style.display = followUpRequired.checked ? 'block' : 'none';
}
async function saveSessionNotes(e) {
e.preventDefault();
try {
if (!currentSessionId) {
alert('Open a session to add notes');
return;
}
const payload = {
notes: document.getElementById('sessionNotes').value,
treatmentPlan: document.getElementById('treatmentPlan').value,
followUpRequired: followUpRequired.checked,
followUpDate: document.getElementById('followUpDate').value || null,
professional_id: currentProfessional?.professional_id
};
await api(`/professional/sessions/${currentSessionId}/notes`, {
method: 'POST',
body: JSON.stringify(payload)
});
alert('Session notes saved successfully');
closeModals();
} catch (err) {
console.error('Error saving notes:', err);
alert('Failed to save notes');
}
}
async function generateReport() {
try {
const report = await api('/professional/reports/generate', {
method: 'POST',
body: JSON.stringify({
period: document.getElementById('reportPeriod').value,
type: document.getElementById('reportType').value
})
});
displayReport(report);
} catch (error) {
console.error('Error generating report:', error);
alert('Failed to generate report');
}
}
function displayReport(report) {
reportContent.innerHTML = `
Report Summary
Total Sessions:
${report.totalSessions}
Unique Users:
${report.uniqueUsers}
High Risk Cases:
${report.highRiskCases}
`;
}
function logout() {
localStorage.removeItem('aimhsa_professional');
window.location.href = '/login';
}
// Utility functions
function formatDateTime(timestamp) {
if (!timestamp) return 'N/A';
const date = new Date(timestamp * 1000);
return date.toLocaleString();
}
function isToday(date) {
const today = new Date();
return date.toDateString() === today.toDateString();
}
function isThisWeek(date) {
const today = new Date();
const weekAgo = new Date(today.getTime() - 7 * 24 * 60 * 60 * 1000);
return date >= weekAgo && date <= today;
}
function getNotificationIcon(type) {
const icons = {
'session': 'fa-calendar-check',
'risk': 'fa-exclamation-triangle',
'user': 'fa-user',
'system': 'fa-cog',
'emergency': 'fa-bell'
};
return icons[type] || 'fa-bell';
}
// Helper functions
function formatLocation(district, province) {
if (!district && !province) return 'Not provided';
if (district && province) return `${district}, ${province}`;
if (district) return district;
if (province) return province;
return 'Not provided';
}
function getRiskBadgeClass(riskLevel) {
const riskClasses = {
'low': 'risk-low',
'medium': 'risk-medium',
'high': 'risk-high',
'critical': 'risk-critical',
'unknown': 'risk-unknown'
};
return riskClasses[riskLevel] || 'risk-unknown';
}
function formatMissingData(value, fallback = 'Not provided') {
return value || fallback;
}
// Global functions for onclick handlers
window.markNotificationRead = markNotificationRead;
window.acceptSession = acceptSession;
window.declineSession = declineSession;
window.viewSessionDetails = viewSessionDetails;
window.viewUserProfile = viewUserProfile;
window.viewUserSessions = viewUserSessions;
// AdminLTE 4 Enhancements
document.addEventListener('DOMContentLoaded', function() {
// Initialize AdminLTE components
if (typeof $ !== 'undefined' && $.fn.DataTable) {
// Initialize DataTables if available
initializeDataTables();
}
// Initialize mobile menu toggle
initializeMobileMenu();
// Initialize tooltips
initializeTooltips();
// Initialize loading states
initializeLoadingStates();
// Initialize animations
initializeAnimations();
// Initialize enhanced notifications
initializeEnhancedNotifications();
});
function initializeDataTables() {
// Enhanced table functionality with AdminLTE styling
const tables = document.querySelectorAll('table');
tables.forEach(table => {
if (typeof $ !== 'undefined' && $.fn.DataTable) {
$(table).DataTable({
responsive: true,
pageLength: 10,
order: [[0, 'desc']], // Sort by first column descending
columnDefs: [
{ targets: [-1], orderable: false } // Actions column
],
language: {
search: "Search:",
lengthMenu: "Show _MENU_ entries per page",
info: "Showing _START_ to _END_ of _TOTAL_ entries",
paginate: {
first: "First",
last: "Last",
next: "Next",
previous: "Previous"
}
}
});
}
});
}
function initializeMobileMenu() {
const mobileToggle = document.getElementById('mobileMenuToggle');
const professionalHeader = document.querySelector('.professional-header');
if (mobileToggle && professionalHeader) {
mobileToggle.addEventListener('click', function() {
professionalHeader.classList.toggle('mobile-open');
});
// Close mobile menu when clicking outside
document.addEventListener('click', function(e) {
if (!professionalHeader.contains(e.target) && !mobileToggle.contains(e.target)) {
professionalHeader.classList.remove('mobile-open');
}
});
}
}
function initializeTooltips() {
// Initialize Bootstrap tooltips if available
if (typeof $ !== 'undefined' && $.fn.tooltip) {
$('[data-toggle="tooltip"]').tooltip();
}
}
function initializeLoadingStates() {
// Add loading states to buttons and forms
const forms = document.querySelectorAll('form');
forms.forEach(form => {
form.addEventListener('submit', function() {
const submitBtn = form.querySelector('button[type="submit"]');
if (submitBtn) {
submitBtn.classList.add('loading');
submitBtn.disabled = true;
// Remove loading state after 3 seconds (adjust as needed)
setTimeout(() => {
submitBtn.classList.remove('loading');
submitBtn.disabled = false;
}, 3000);
}
});
});
// Add loading states to refresh buttons
const refreshButtons = document.querySelectorAll('[id$="Btn"]');
refreshButtons.forEach(btn => {
if (btn.id.includes('refresh') || btn.id.includes('Refresh')) {
btn.addEventListener('click', function() {
btn.classList.add('loading');
btn.disabled = true;
setTimeout(() => {
btn.classList.remove('loading');
btn.disabled = false;
}, 2000);
});
}
});
}
function initializeAnimations() {
// Add fade-in animation to cards
const cards = document.querySelectorAll('.stat-card, .action-btn, .user-card, .session-card, .notification-item');
cards.forEach((card, index) => {
card.classList.add('fade-in');
card.style.animationDelay = `${index * 0.1}s`;
});
// Add bounce-in animation to modals
const modals = document.querySelectorAll('.modal');
modals.forEach(modal => {
modal.addEventListener('show.bs.modal', function() {
const modalContent = modal.querySelector('.modal-content');
if (modalContent) {
modalContent.classList.add('bounce-in');
}
});
});
}
function initializeEnhancedNotifications() {
// Enhanced notification system using AdminLTE toast
window.showProfessionalMessage = function(text, type = 'info') {
if (typeof $ !== 'undefined' && $.fn.toast) {
// Use AdminLTE toast if available
const toastHtml = `
`;
// Create toast container if it doesn't exist
let toastContainer = document.querySelector('.toast-container');
if (!toastContainer) {
toastContainer = document.createElement('div');
toastContainer.className = 'toast-container position-fixed top-0 end-0 p-3';
toastContainer.style.zIndex = '9999';
document.body.appendChild(toastContainer);
}
// Add toast to container
toastContainer.insertAdjacentHTML('beforeend', toastHtml);
// Initialize and show toast
const toastElement = toastContainer.lastElementChild;
$(toastElement).toast({
autohide: true,
delay: 4000
});
$(toastElement).toast('show');
// Remove toast after it's hidden
$(toastElement).on('hidden.bs.toast', function() {
$(this).remove();
});
} else {
// Fallback to alert
alert(text);
}
};
function getToastIcon(type) {
const icons = {
'success': 'check-circle',
'error': 'exclamation-triangle',
'warning': 'exclamation-circle',
'info': 'info-circle',
'loading': 'spinner'
};
return icons[type] || 'info-circle';
}
}
// Enhanced refresh functionality
function refreshAllData() {
const refreshButtons = document.querySelectorAll('[id$="Btn"]');
refreshButtons.forEach(btn => {
if (btn.id.includes('refresh') || btn.id.includes('Refresh')) {
btn.classList.add('loading');
btn.disabled = true;
}
});
// Refresh all data
Promise.all([
loadNotifications(),
loadUpcomingSessions(),
loadSessionHistory(),
loadBookedUsers(),
loadDashboardStats()
]).finally(() => {
refreshButtons.forEach(btn => {
if (btn.id.includes('refresh') || btn.id.includes('Refresh')) {
btn.classList.remove('loading');
btn.disabled = false;
}
});
if (window.showProfessionalMessage) {
window.showProfessionalMessage('All data refreshed successfully', 'success');
}
});
}
// Add refresh functionality to all refresh buttons
document.addEventListener('DOMContentLoaded', function() {
const refreshButtons = document.querySelectorAll('[id$="Btn"]');
refreshButtons.forEach(btn => {
if (btn.id.includes('refresh') || btn.id.includes('Refresh')) {
btn.addEventListener('click', function() {
refreshAllData();
});
}
});
});
// Enhanced modal functionality
function initializeEnhancedModals() {
const modals = document.querySelectorAll('.modal');
modals.forEach(modal => {
// Add AdminLTE modal functionality
if (typeof $ !== 'undefined' && $.fn.modal) {
$(modal).on('show.bs.modal', function() {
const modalContent = $(this).find('.modal-content');
modalContent.addClass('bounce-in');
});
$(modal).on('hidden.bs.modal', function() {
const modalContent = $(this).find('.modal-content');
modalContent.removeClass('bounce-in');
});
}
});
}
// Initialize enhanced modals
document.addEventListener('DOMContentLoaded', function() {
initializeEnhancedModals();
});
})();