Making the JADA Maintenance Dashboard Cards Interactive: Linking UI State to Backend Tasks
What Was Done
During this development session, we implemented clickable functionality on the "Total Tasks" card in the JADA Maintenance Hub dashboard, enabling users to navigate directly to the Tasks tab with a single click. This required modifying the dashboard's frontend HTML, updating CloudFront cache, and establishing a clear pattern for interactive dashboard elements.
The Problem
The JADA Maintenance Hub displays a prominent "Total Tasks 82" info card at the top of the dashboard. This card was purely informational—clicking it did nothing. Users viewing the dashboard had to manually locate and click the "Tasks" tab navigation to see the actual task list, creating unnecessary friction in a tool designed for rapid boat maintenance tracking.
Technical Details
File Location and Storage Strategy
The maintenance hub frontend lives in an S3 bucket rather than in the local repository. This is a critical architectural choice:
- S3 Bucket: The index.html file is stored in an S3 bucket dedicated to the maintenance subdomain, allowing rapid iteration without full site redeployment
- CloudFront Distribution: A CloudFront distribution sits in front of this S3 bucket, caching the HTML and providing CDN performance. This requires explicit cache invalidation after updates
- DNS Resolution: Route53 directs the maintenance subdomain to the CloudFront distribution endpoint
This architecture means: local file edits → S3 upload → CloudFront invalidation → user cache refresh. It's not a direct git-based deployment.
HTML Structure and Tab Navigation System
The dashboard uses a tab-based navigation pattern with a custom switch function. Examining the index.html revealed:
function switchTab(tabName) {
// Hide all tab content
const tabs = document.querySelectorAll('.tab-content');
tabs.forEach(tab => tab.style.display = 'none');
// Show selected tab
const selectedTab = document.getElementById(tabName + '-tab');
if (selectedTab) {
selectedTab.style.display = 'block';
}
}
The Tasks tab was identified by the ID systems-tab (note: the naming here reflects an earlier architectural decision to call the tasks container "systems"). This function is the central navigation mechanism—calling switchTab('systems') hides all other tabs and displays the tasks table.
CSS and Interactive States
The original Total Tasks card used the info-card class with static styling. To make it interactive without breaking existing styles, we:
- Created a new CSS class
info-card-linkthat extends the base card styling with interactive affordances - Added cursor pointer on hover
- Implemented a subtle background color transition to indicate interactivity
.info-card-link {
cursor: pointer;
transition: background-color 0.3s ease;
user-select: none;
}
.info-card-link:hover {
background-color: rgba(76, 175, 80, 0.1);
}
The rgba(76, 175, 80, 0.1) color matches the existing green accent color used elsewhere in the dashboard, maintaining visual consistency.
HTML Implementation
The Total Tasks card markup was wrapped with an onclick handler:
<div class="info-card info-card-link" onclick="switchTab('systems')">
<div class="card-label">Total Tasks</div>
<div class="card-value">82</div>
</div>
This approach is better than wrapping in an <a> tag because:
- Maintains semantic HTML (the card isn't a link to an external resource)
- Avoids browser navigation behavior (no page refresh)
- Keeps the styling consistent with surrounding cards
- Allows for SPA-style state changes without URL modification
Infrastructure and Deployment Process
S3 Upload
Files are synced to S3 using AWS CLI or S3-compatible tools:
aws s3 cp index.html s3://maintenance-hub-bucket/index.html
The bucket has versioning enabled, allowing rollback if needed. CORS is configured to allow requests from the parent domain.
CloudFront Cache Invalidation
Simply uploading to S3 is insufficient—CloudFront caches aggressively. After the S3 upload, we must invalidate the distribution:
aws cloudfront create-invalidation --distribution-id YOUR_DIST_ID --paths "/*"
This invalidates all paths in the distribution. The wildcard is necessary because the HTML file is at the root, and cache headers may vary.
Why this matters: Without invalidation, users see the old cached version for up to 24 hours (the default TTL). Invalidation takes 2–3 minutes to propagate globally.
Key Architectural Decisions
Why onclick instead of event listeners?
In this case, inline onclick is acceptable because:
- The dashboard's existing code uses inline click handlers for other interactive elements
- The function is globally available (defined in a script block, no module bundling)
- Adding event listeners would require ensuring the DOM is fully loaded and managing delegation
For a more complex application, delegated event listeners would be preferred.
Tab ID naming: Why "systems-tab" for tasks?
The existing codebase uses "systems" as the ID for the tasks container. This reflects an earlier design decision to group all task-related maintenance items under a "Systems" heading. Renaming would require updating multiple references throughout the JavaScript, so we kept the existing naming convention.
Why not use data attributes?
The switchTab function accepts a simple string ID, making it flexible. We could have added data-tab="systems" attributes and built a more declarative system, but the existing pattern works and changing it would risk breaking other parts of the dashboard that rely on the current structure.
Testing and Validation
After deployment:
- Cleared browser cache (Ctrl+Shift+Delete)
- Navigated to the maintenance hub URL
- Verified the Total Tasks card displayed with hover styling
- Clicked the card and confirmed the Tasks tab appeared, showing the task table with 82 rows
- Clicked other tabs to ensure tab switching still worked correctly
What's Next
This pattern establishes a template for other dashboard cards. The Cost Summary, Upcoming Maintenance, and Engine Hours cards could all be made clickable to their respective detail views using the same approach. We should document the info-card-link class in the dashboard's CSS guide for future developers.
Additionally, consider adding keyboard navigation (Enter/Space keys) for accessibility, and storing the selected tab in sessionStorage so users return to their last-viewed tab on page refresh.