Create shared utility module to eliminate function duplication

- Create public/utils.js with shared frontend utility functions
- Extract parseUTCDate, getTimeAgo, getTimeRemaining, getRemainingClass to utils.js
- Remove duplicate functions from admin.js, app-mapbox.js, app-google.js, and app.js
- Add utils.js script import to index.html and admin.html
- Add comprehensive JSDoc documentation for all utility functions
- Ensure consistent UTC timestamp parsing across all frontend scripts

This addresses Copilot AI feedback about function duplication across multiple frontend scripts.
Now all timestamp and time calculation logic is centralized in one maintainable module.

Benefits:
- Single source of truth for time-related utilities
- Easier maintenance and updates
- Consistent behavior across all frontend components
- Better code organization and documentation
- Reduced bundle size through deduplication
This commit is contained in:
Deco Vander 2025-07-04 13:22:17 -04:00
parent c0dc1f3c6d
commit a063d5a2c9
7 changed files with 103 additions and 120 deletions

View file

@ -93,25 +93,7 @@ document.addEventListener('DOMContentLoaded', async () => {
});
};
// Helper function to parse UTC date
const parseUTCDate = (timestamp) => {
return new Date(timestamp.includes('T') ? timestamp : timestamp + 'Z');
};
const getTimeAgo = (timestamp) => {
const now = new Date();
// Ensure timestamp is treated as UTC if it doesn't have timezone info
const reportTime = parseUTCDate(timestamp);
const diffInMinutes = Math.floor((now - reportTime) / (1000 * 60));
if (diffInMinutes < 1) return 'just now';
if (diffInMinutes < 60) return `${diffInMinutes} minute${diffInMinutes !== 1 ? 's' : ''} ago`;
const diffInHours = Math.floor(diffInMinutes / 60);
if (diffInHours < 24) return `${diffInHours} hour${diffInHours !== 1 ? 's' : ''} ago`;
return 'over a day ago';
};
// getTimeAgo function is now available from utils.js
// Toggle between map and table view
const switchView = (viewType) => {
@ -171,47 +153,7 @@ document.addEventListener('DOMContentLoaded', async () => {
tableLocationCount.textContent = `${locations.length} active report${locations.length !== 1 ? 's' : ''}`;
};
// Calculate time remaining until 48-hour expiration
const getTimeRemaining = (timestamp, persistent = false) => {
if (persistent) {
return 'Persistent';
}
const now = new Date();
// Ensure timestamp is treated as UTC if it doesn't have timezone info
const reportTime = parseUTCDate(timestamp);
const expirationTime = new Date(reportTime.getTime() + 48 * 60 * 60 * 1000);
const remaining = expirationTime - now;
if (remaining <= 0) return 'Expired';
const hours = Math.floor(remaining / (1000 * 60 * 60));
const minutes = Math.floor((remaining % (1000 * 60 * 60)) / (1000 * 60));
if (hours > 0) {
return `${hours}h ${minutes}m`;
} else {
return `${minutes}m`;
}
};
// Get CSS class for time remaining
const getRemainingClass = (timestamp, persistent = false) => {
if (persistent) {
return 'normal'; // Use normal styling for persistent reports
}
const now = new Date();
// Ensure timestamp is treated as UTC if it doesn't have timezone info
const reportTime = parseUTCDate(timestamp);
const expirationTime = new Date(reportTime.getTime() + 48 * 60 * 60 * 1000);
const remaining = expirationTime - now;
const hoursRemaining = remaining / (1000 * 60 * 60);
if (hoursRemaining <= 1) return 'urgent';
if (hoursRemaining <= 6) return 'warning';
return 'normal';
};
// getTimeRemaining and getRemainingClass functions are now available from utils.js
const refreshLocations = () => {
fetch('/api/locations')