/** * Comments functionality for facility management */ document.addEventListener('DOMContentLoaded', function() { console.log('Comments.js loaded'); // Initialize comment modal handlers initializeCommentModals(); // Set up form handlers setupCommentFormHandlers(); }); /** * Initialize comment modals */ function initializeCommentModals() { // Status modal (comments view) const statusModal = document.getElementById('statusModal'); if (statusModal) { statusModal.addEventListener('show.bs.modal', function(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 loadFacilityComments(facilityId); }); } // Edit comment modal const editCommentModal = document.getElementById('editCommentModal'); if (editCommentModal) { editCommentModal.addEventListener('show.bs.modal', function(event) { console.log('Edit comment modal is about to show'); // The button that triggered the modal will pass data via dataset 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 */ function setupCommentFormHandlers() { // Comment form handler const commentForm = document.getElementById('commentForm'); if (commentForm) { setupCommentFormHandler(commentForm); } // Edit comment form handler const editCommentForm = document.getElementById('editCommentForm'); if (editCommentForm) { setupEditCommentFormHandler(editCommentForm); } } /** * Set up a single comment form handler * @param {HTMLFormElement} commentForm - The comment form element */ function setupCommentFormHandler(commentForm) { commentForm.addEventListener('submit', async function(e) { e.preventDefault(); // Prevent duplicate submissions if (this.submitting) { return; } this.submitting = true; // Check if user is authenticated if (!isAuthenticated()) { alert('You must be logged in to add comments'); this.submitting = false; return; } const formData = new FormData(this); // Get form data const commentText = formData.get('commentText'); const facilityId = formData.get('facilityId'); console.log('Comment form data:', { facilityId, commentText }); try { console.log('Sending comment request...'); // Use the API client to add a status comment const data = await window.api.addFacilityStatus(facilityId, commentText); console.log('Comment response:', data); if (data.success) { console.log('Comment added successfully'); // Reset the form this.reset(); // Reload comments to show the new one 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 { this.submitting = false; } }); } /** * Set up a single edit comment form handler * @param {HTMLFormElement} editCommentForm - The edit comment form element */ function setupEditCommentFormHandler(editCommentForm) { editCommentForm.addEventListener('submit', async function(e) { e.preventDefault(); // Prevent duplicate submissions if (this.submitting) { return; } this.submitting = true; // Check if user is authenticated if (!isAuthenticated()) { alert('You must be logged in to edit comments'); this.submitting = false; return; } const formData = new FormData(this); // 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 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 { this.submitting = false; } }); } /** * Creates a comment form dynamically for authenticated users * @param {string} facilityId - The facility ID */ function createCommentFormForAuthenticatedUser(facilityId) { // Check if user is authenticated if (!isAuthenticated()) { return `
Please login to add comments.
`; } // Create the comment form return `
`; } /** * Checks if the current user is authenticated * @returns {boolean} True if authenticated, false otherwise */ function isAuthenticated() { // Use the auth service to check authentication return window.auth.isAuthenticated(); } /** * Loads facility comments from the server * @param {string} facilityId - The facility ID */ async function 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 loaded:', data); if (data.success) { // Render the comments renderComments(data.statuses, facilityId); } else { console.error('Failed to load comments:', data.error); if (commentsContainer) { commentsContainer.innerHTML = `
Failed to load comments: ${data.error || 'Unknown error'}
`; } } } catch (error) { console.error('Error loading comments:', error); const commentsContainer = document.getElementById('commentsContainer'); if (commentsContainer) { commentsContainer.innerHTML = `
Error loading comments: ${error.message}
`; } } } /** * Renders comments in the comments container * @param {Array} comments - Array of comment objects * @param {string} facilityId - The facility ID */ function 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 += 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'; // Format the date const date = new Date(comment.timestamp); const formattedDate = date.toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' }); // Check if the current user is the comment author or an admin const canEdit = isAdmin() || isCurrentUser(comment.username); commentElement.innerHTML = `
${escapeHtml(comment.username)}
${formattedDate}
${canEdit ? ` ` : ''}

${escapeHtml(comment.comment)}

`; commentsList.appendChild(commentElement); }); commentsContainer.appendChild(commentsList); // Re-initialize the comment form handler const commentForm = document.getElementById('commentForm'); if (commentForm) { setupCommentFormHandler(commentForm); } } /** * Deletes a comment * @param {string} commentId - The comment ID * @param {string} facilityId - The facility ID */ async function 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 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 * @returns {boolean} True if admin, false otherwise */ function isAdmin() { // Use the auth service to check if user is admin return window.auth.isAdmin(); } /** * Checks if the given username matches the current user * @param {string} username - The username to check * @returns {boolean} True if current user, false otherwise */ function isCurrentUser(username) { const user = window.auth.getUser(); return user && user.username === username; } /** * Safely escapes HTML special characters to prevent XSS attacks * @param {*} unsafe - The value to escape * @returns {string} The escaped string */ function escapeHtml(unsafe) { if (unsafe === null || unsafe === undefined) { return ''; } return unsafe .toString() .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """) .replace(/'/g, "'"); }