Making the JADA Maintenance Dashboard Task Card Interactive: Wiring UI State to Tab Navigation

During a recent maintenance session on the JADA vessel's digital infrastructure, we needed to improve the user experience of the maintenance hub dashboard. Specifically, the "Total Tasks" summary card—which displays an aggregated count of active maintenance items—needed to become interactive. Clicking it should navigate users directly to the detailed task list rather than requiring them to manually click a separate navigation tab. This post covers the technical approach, infrastructure considerations, and deployment strategy.

Problem Statement

The JADA Maintenance Hub is a single-page application (SPA) hosted on S3 with CloudFront distribution serving traffic to the maintenance.jada.queenofsandiego.com subdomain. The dashboard uses a tab-based navigation pattern with multiple views: Dashboard, Systems, and Tasks. The "Total Tasks" info-card component rendered task count data but was purely presentational—clicking it did nothing. Users had to locate and click the separate "Tasks" tab to see detailed information, creating unnecessary friction.

The request was to make this card clickable and have it switch to the Tasks tab view immediately, reducing cognitive load and creating a more intuitive information hierarchy.

Technical Architecture Overview

The maintenance hub's frontend architecture uses:

  • Tab switching mechanism: A switchTab(tabName) JavaScript function that updates the active view state
  • Data attributes: HTML elements use data-tab attributes to identify tab destinations
  • CSS class toggling: Active tabs receive a visible state; inactive tabs are hidden via CSS
  • State persistence: Browser localStorage stores the last active tab for session continuity

The task data itself is fetched from a Lambda API endpoint and rendered in the Systems tab, while the summary card (showing "Total Tasks 82") is rendered on the main Dashboard tab.

Implementation Details

Step 1: Identify the Target Card Structure

The "Total Tasks" card lives in /tmp/maintenance_index.html (local working copy) and the S3 source at s3://jada-maintenance-hub/index.html. The card is a standard info-card div structure:

<div class="info-card">
  <div class="card-title">Total Tasks</div>
  <div class="card-value">82</div>
</div>

This element was purely presentational. We needed to add interactivity while preserving the visual design.

Step 2: Implement Click Handler

Rather than wrapping the card in an anchor tag (which would cause page navigation), we added an onclick handler that calls the existing switchTab() function:

<div class="info-card" onclick="switchTab('systems')" style="cursor: pointer;">
  <div class="card-title">Total Tasks</div>
  <div class="card-value">82</div>
</div>

Why this approach? The maintenance hub already has a robust tab-switching function that handles:

  • Toggling visibility of tab content panels
  • Updating active nav indicator states
  • Writing the active tab name to localStorage for session persistence
  • Handling edge cases around missing or invalid tab names

Reusing this function ensures consistency with the existing navigation pattern and avoids duplicating state management logic.

Step 3: Add Hover States and Accessibility

Inline cursor: pointer helps signal interactivity, but we also added a dedicated CSS class for hover styling:

.info-card-link:hover {
  background-color: #f0f4f8;
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  transition: all 0.2s ease-in-out;
}

This provides visual feedback and makes the card feel responsive to user interaction. The transform: translateY(-2px) creates subtle lift animation, a common UX pattern for interactive elements.

We also considered adding a title attribute for accessibility, though the semantic meaning is clear from context.

Infrastructure and Deployment Pipeline

File Locations and S3 Path

The maintenance hub is stored in:

s3://jada-maintenance-hub/index.html

The file contains the entire single-page application: HTML structure, embedded CSS in <style> tags, and inline JavaScript. This monolithic approach simplifies deployment and avoids cross-origin issues.

CloudFront Distribution

The S3 bucket is served through a CloudFront distribution (ID: E[DISTRIBUTION_ID]) configured to:

  • Point to the S3 bucket as origin
  • Cache index.html with short TTL (60 seconds) to balance freshness and performance
  • Use Route53 CNAME to map maintenance.jada.queenofsandiego.com to the CloudFront domain

After deploying updates to index.html, we must invalidate the CloudFront cache to ensure users receive the latest version immediately:

aws cloudfront create-invalidation \
  --distribution-id E[DISTRIBUTION_ID] \
  --paths "/*"

This command invalidates all objects in the distribution, forcing CloudFront to fetch fresh content from S3 on the next request.

Deployment Steps

  1. Download current index.html from S3 to local development environment
  2. Make HTML/CSS/JS edits in local file
  3. Test changes locally in browser DevTools (modifying the DOM or using browser console)
  4. Upload modified index.html back to S3 using AWS CLI or console
  5. Invalidate CloudFront cache for the distribution
  6. Verify changes are live by accessing maintenance.jada.queenofsandiego.com in incognito/private browser window (bypasses local cache)

Key Architectural Decisions

Why not use a route or state management library? The maintenance hub is a lightweight dashboard with minimal complexity. It predates more modern SPA frameworks and doesn't justify the additional bundle size or build complexity. The tab-switching pattern is simple enough to manage with vanilla JavaScript.

Why inline the onclick handler instead of using event delegation? For a static card that's rendered on page load, inline onclick is pragmatic and readable. Event delegation would be preferable if we were dynamically creating cards or had many interactive elements, but this dashboard has only a few fixed interactive surfaces.

Why S3 + CloudFront instead of a traditional app server? This architecture provides:

  • High availability: S3 and CloudFront are fully managed AWS services with 99.99% SLA
  • Geographic distribution: CloudFront caches content at 200+ edge locations globally
  • Cost efficiency: No running servers