/** * Comments functionality for facility management */ // Create a namespace for comments functionality const CommentsManager = { // Track initialization states state: { isInitializing: false, isInitialized: false, isDomReady: false, isAuthReady: false }, /** * Initialize comments functionality */ initialize() { if (this.state.isInitialized) return; console.log('Initializing comments...'); // Initialize comment modal handlers this.initializeCommentModals(); // Set up form handlers this.setupCommentFormHandlers(); console.log('Comments initialized with auth state:', { isAuthenticated: this.isAuthenticated(), user: window.simpleAuth.getUser() }); this.state.isInitialized = true; }, /** * Check if we can initialize */ checkInitialize() { if (this.state.isDomReady && this.state.isAuthReady && !this.state.isInitializing) { this.state.isInitializing = true; this.initialize(); this.state.isInitializing = false; } }, /** * Check if user is authenticated */ isAuthenticated() { return window.simpleAuth && window.simpleAuth.isAuthenticated(); }, /** * Initialize comment modals */ initializeCommentModals() { // Status modal (comments view) const statusModal = document.getElementById('statusModal'); if (statusModal) { statusModal.addEventListener('show.bs.modal', (event) => { console.log('Comments modal is about to show'); // Get the button that triggered the modal const button = event.relatedTarget; // Get the facility ID from the data attribute const facilityId = button.getAttribute('data-facility-id'); console.log('Facility ID for comments:', facilityId); if (!facilityId) { console.error('No facility ID found for comments'); return; } // Set the facility ID in the comment form const commentForm = document.getElementById('commentForm'); if (commentForm) { const facilityIdInput = commentForm.querySelector('#commentFacilityId'); if (facilityIdInput) { facilityIdInput.value = facilityId; } } // Load facility comments this.loadFacilityComments(facilityId); }); } // Edit comment modal const editCommentModal = document.getElementById('editCommentModal'); if (editCommentModal) { editCommentModal.addEventListener('show.bs.modal', (event) => { console.log('Edit comment modal is about to show'); const button = event.relatedTarget; const commentId = button.getAttribute('data-comment-id'); const commentText = button.getAttribute('data-comment-text'); console.log('Comment ID:', commentId, 'Comment text:', commentText); // Set the comment ID and text in the form const editForm = document.getElementById('editCommentForm'); if (editForm) { const commentIdInput = editForm.querySelector('#editCommentId'); const commentTextArea = editForm.querySelector('#editCommentText'); if (commentIdInput && commentTextArea) { commentIdInput.value = commentId; commentTextArea.value = commentText; } } }); } }, /** * Set up comment form handlers */ setupCommentFormHandlers() { // Comment form handler const commentForm = document.getElementById('commentForm'); if (commentForm) { this.setupCommentFormHandler(commentForm); } // Edit comment form handler const editCommentForm = document.getElementById('editCommentForm'); if (editCommentForm) { this.setupEditCommentFormHandler(editCommentForm); } }, /** * Set up a single comment form handler */ setupCommentFormHandler(commentForm) { commentForm.addEventListener('submit', async (e) => { e.preventDefault(); // Prevent duplicate submissions if (commentForm.submitting) { return; } commentForm.submitting = true; // Check if user is authenticated if (!this.isAuthenticated()) { alert('You must be logged in to add comments'); commentForm.submitting = false; return; } const formData = new FormData(commentForm); // Get form data const statusComment = formData.get('commentText'); const facilityId = formData.get('facilityId'); console.log('Comment form data:', { facilityId, statusComment }); try { console.log('Sending comment request...'); // Use the API client to add a status comment const data = await window.api.addFacilityStatus(facilityId, statusComment); console.log('Comment response:', data); if (data.success) { console.log('Comment added successfully'); // Reset the form commentForm.reset(); // Reload comments to show the new one this.loadFacilityComments(facilityId); } else { console.error('Comment failed:', data.error); alert(data.error || 'Failed to add comment'); } } catch (error) { console.error('Error adding comment:', error); alert('Failed to add comment: ' + error.message); } finally { commentForm.submitting = false; } }); }, /** * Set up a single edit comment form handler */ setupEditCommentFormHandler(editCommentForm) { editCommentForm.addEventListener('submit', async (e) => { e.preventDefault(); // Prevent duplicate submissions if (editCommentForm.submitting) { return; } editCommentForm.submitting = true; // Check if user is authenticated if (!this.isAuthenticated()) { alert('You must be logged in to edit comments'); editCommentForm.submitting = false; return; } const formData = new FormData(editCommentForm); // Get form data const commentText = formData.get('editCommentText'); const commentId = formData.get('commentId'); const facilityId = document.getElementById('commentFacilityId').value; console.log('Edit comment form data:', { commentId, facilityId, commentText }); try { console.log('Sending edit comment request...'); // Use the API client to update a status comment const data = await window.api.updateFacilityStatus(commentId, commentText, facilityId); console.log('Edit comment response:', data); if (data.success) { console.log('Comment edited successfully'); // Close the edit modal const editModal = bootstrap.Modal.getInstance(document.getElementById('editCommentModal')); if (editModal) { editModal.hide(); } // Reload comments to show the updated one this.loadFacilityComments(facilityId); } else { console.error('Edit comment failed:', data.error); alert(data.error || 'Failed to edit comment'); } } catch (error) { console.error('Error editing comment:', error); alert('Failed to edit comment: ' + error.message); } finally { editCommentForm.submitting = false; } }); }, /** * Creates a comment form dynamically for authenticated users */ createCommentFormForAuthenticatedUser(facilityId) { // Add detailed logging of auth state console.log('Creating comment form with auth state:', { simpleAuthExists: !!window.simpleAuth, simpleAuthMethods: window.simpleAuth ? Object.keys(window.simpleAuth) : null, token: window.simpleAuth ? window.simpleAuth.getToken() : null, user: window.simpleAuth ? window.simpleAuth.getUser() : null, localStorage: { token: localStorage.getItem('token'), user: localStorage.getItem('user') } }); // First check if simpleAuth is available if (!window.simpleAuth) { console.warn('SimpleAuth not initialized yet'); return `
Loading authentication status...
`; } // Validate authentication state try { const token = window.simpleAuth.getToken(); const user = window.simpleAuth.getUser(); const isAuthenticated = window.simpleAuth.isAuthenticated(); console.log('Authentication validation:', { hasToken: !!token, hasUser: !!user, isAuthenticated: isAuthenticated }); if (!isAuthenticated || !token || !user) { console.log('User not authenticated:', { isAuthenticated, token: !!token, user: !!user }); return `
Please login to add comments.
`; } // User is authenticated, create the comment form console.log('User is authenticated, creating comment form'); return `
`; } catch (error) { console.error('Error checking authentication:', error); return `
Error checking authentication status. Please try refreshing the page.
`; } }, /** * Loads facility comments from the server */ async loadFacilityComments(facilityId) { try { console.log('Loading comments for facility:', facilityId); // Show loading indicator const commentsContainer = document.getElementById('commentsContainer'); if (commentsContainer) { commentsContainer.innerHTML = `
Loading...

Loading comments...

`; } // Use the API client to get facility statuses const data = await window.api.getFacilityStatuses(facilityId); console.log('Comments API response:', data); // Validate the response if (!data || typeof data !== 'object') { throw new Error('Invalid response from server'); } if (!data.success) { throw new Error(data.error || 'Failed to load comments'); } if (!Array.isArray(data.statuses)) { throw new Error('Invalid comments data format'); } // Render the comments this.renderComments(data.statuses, facilityId); } catch (error) { console.error('Error loading comments:', error); console.error('Error stack:', error.stack); const commentsContainer = document.getElementById('commentsContainer'); if (commentsContainer) { commentsContainer.innerHTML = `
${error.message}
`; } } }, /** * Renders comments in the comments container */ renderComments(comments, facilityId) { const commentsContainer = document.getElementById('commentsContainer'); if (!commentsContainer) return; // Clear the container commentsContainer.innerHTML = ''; // Add the comment form for authenticated users commentsContainer.innerHTML += this.createCommentFormForAuthenticatedUser(facilityId); // If no comments, show a message if (!comments || comments.length === 0) { commentsContainer.innerHTML += `
No comments yet. Be the first to add a comment!
`; return; } // Create the comments list const commentsList = document.createElement('div'); commentsList.className = 'comments-list mt-4'; // Add each comment comments.forEach(comment => { const commentElement = document.createElement('div'); commentElement.className = 'comment-item card mb-3 border-0 shadow-sm'; // Check if the current user is the comment author or an admin const canEdit = this.isAdmin() || this.isCurrentUser(comment.username); commentElement.innerHTML = `
${this.escapeHtml(comment.username)}
${canEdit ? ` ` : ''}

${this.escapeHtml(comment.statusComment)}

`; commentsList.appendChild(commentElement); }); commentsContainer.appendChild(commentsList); // Re-initialize the comment form handler const commentForm = document.getElementById('commentForm'); if (commentForm) { this.setupCommentFormHandler(commentForm); } }, /** * Deletes a comment */ async deleteComment(commentId, facilityId) { // Confirm deletion if (!confirm('Are you sure you want to delete this comment?')) { return; } try { console.log('Deleting comment:', commentId, 'for facility:', facilityId); // Use the API client to delete a status comment const data = await window.api.deleteFacilityStatus(commentId, facilityId); console.log('Delete comment response:', data); if (data.success) { console.log('Comment deleted successfully'); // Reload comments to reflect the deletion this.loadFacilityComments(facilityId); } else { console.error('Delete comment failed:', data.error); alert(data.error || 'Failed to delete comment'); } } catch (error) { console.error('Error deleting comment:', error); alert('Failed to delete comment: ' + error.message); } }, /** * Checks if the current user is an admin */ isAdmin() { return window.simpleAuth && window.simpleAuth.isAdmin(); }, /** * Checks if the given username matches the current user */ isCurrentUser(username) { const user = window.simpleAuth && window.simpleAuth.getUser(); return user && user.username === username; }, /** * Safely escapes HTML special characters to prevent XSS attacks */ escapeHtml(unsafe) { if (unsafe === null || unsafe === undefined) { return ''; } return unsafe .toString() .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """) .replace(/'/g, "'"); } }; // Listen for DOM ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => { CommentsManager.state.isDomReady = true; CommentsManager.checkInitialize(); }); } else { CommentsManager.state.isDomReady = true; CommentsManager.checkInitialize(); } // Listen for simpleAuth ready if (window.simpleAuth) { CommentsManager.state.isAuthReady = true; CommentsManager.checkInitialize(); } else { window.addEventListener('simpleAuthReady', () => { console.log('SimpleAuth is now ready'); CommentsManager.state.isAuthReady = true; CommentsManager.checkInitialize(); }); // Fallback timeout in case the event doesn't fire setTimeout(() => { if (!CommentsManager.state.isAuthReady && window.simpleAuth) { console.log('SimpleAuth found via timeout check'); CommentsManager.state.isAuthReady = true; CommentsManager.checkInitialize(); } }, 1000); } // Export the CommentsManager to the window object window.CommentsManager = CommentsManager;