Making the JADA Maintenance Hub Dashboard Actionable: Clickable Stat Cards and Tab Navigation

What Was Done

The JADA Maintenance Hub's primary dashboard displayed a "Total Tasks" stat card showing task counts, but it was purely informational—clicking it did nothing. This created friction for users who needed to quickly pivot from the overview dashboard to the detailed task list. We implemented clickable stat cards that programmatically switch tabs when clicked, eliminating an extra navigation step and improving user workflow efficiency.

Specifically, the "Total Tasks" card now functions as a direct navigation element to the Systems tab (where the task table lives), reducing cognitive load and accelerating task management workflows on a vessel where time at the helm is premium.

Technical Details

Understanding the Dashboard Architecture

The maintenance hub lives as a static HTML/CSS/JavaScript application served from an S3 bucket with CloudFront distribution caching. The dashboard uses a tab-based interface with the following structure:

  • File location: S3 bucket (maintenance subdomain) → index.html
  • Rendering pattern: Tab navigation via switchTab(tabName) JavaScript function
  • Active tabs: "Dashboard" (default), "Systems", "Bilge", "Engine", etc.
  • Tab switching logic: Data attributes on tab buttons with data-tab="systems" trigger conditional rendering

The stat cards (including Total Tasks, Active Alerts, Upcoming Services) are rendered on the Dashboard tab as read-only display elements. The actual task table—a sortable, detailed view with task names, due dates, and status—lives in the Systems tab.

DOM Structure and CSS Classes

The Total Tasks card was originally wrapped in a simple div with class info-card:

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

The issue: no affordance signaling interactivity. Users had no visual or semantic cue that this element was clickable.

Implementation: Adding Click Handlers and Visual Feedback

We took a progressive enhancement approach:

  1. Wrapped the card in semantic HTML: Changed the outer div to a button element with onclick="switchTab('systems')", or maintained div and added role-based accessibility attributes if styling constraints required it.
  2. Added CSS class for linkable state: Created a new info-card-link class that extends info-card with interactive styling:
    .info-card-link {
      cursor: pointer;
      transition: all 0.2s ease;
      border: 2px solid transparent;
    }
    
    .info-card-link:hover {
      border-color: #0066cc;
      background-color: rgba(0, 102, 204, 0.05);
      transform: translateY(-2px);
      box-shadow: 0 4px 12px rgba(0, 102, 204, 0.15);
    }
    
    .info-card-link:active {
      transform: translateY(0);
      box-shadow: 0 2px 6px rgba(0, 102, 204, 0.1);
    }

    This provides immediate visual feedback—a subtle blue border, slight lift on hover, and darkened shadow—making the clickable state obvious without jarring the dashboard aesthetic.

  3. Wired the tab switch function: The existing switchTab() function (already in the codebase for tab button navigation) handles the actual tab switching. No new function needed; we simply reused the existing pattern for consistency.

Infrastructure and Deployment

S3 and CloudFront Setup

The maintenance hub is served through a CloudFront distribution with the following architecture:

  • Origin: S3 bucket (maintenance subdomain, specific bucket name withheld for security)
  • Distribution ID: Retrieved via AWS CLI; used for cache invalidation
  • Cache behavior: Default TTL of 3600 seconds (1 hour) for index.html and assets
  • DNS: Route53 A record pointing to CloudFront distribution domain name

Deployment workflow:

# Download current index.html from S3
aws s3 cp s3://[maintenance-bucket]/index.html ./index.html

# Make edits locally (update HTML/CSS/JS)

# Upload updated file back to S3
aws s3 cp ./index.html s3://[maintenance-bucket]/index.html

# Invalidate CloudFront cache to force edge nodes to fetch fresh content
aws cloudfront create-invalidation --distribution-id [DIST_ID] --paths "/*"

Why CloudFront? Serves the dashboard from edge locations geographically closer to users (and the vessel). Reduces latency for dashboard loads and tab switches. The 1-hour TTL balances freshness with cache hit rates—updates propagate globally within an hour, but repeated loads serve from cache.

Local Development Workflow

Because the dashboard lives in S3/CloudFront (not a local Git repo), development involves:

  1. Download index.html from S3 to a temporary directory
  2. Edit locally in an editor with syntax highlighting
  3. Test in a browser (inline in the file or via a simple HTTP server: python3 -m http.server 8000)
  4. Upload back to S3 and invalidate CloudFront

This differs from the typical Git-based workflow but is appropriate here: the dashboard is a single-file application with no build step, and versioning happens implicitly through S3 object versions.

Key Design Decisions

1. Reuse Existing Tab Switch Function

Rather than creating a new navigation function, we leveraged switchTab('systems'), already used by tab buttons. Benefits:

  • Consistency: same code path for all tab switching
  • Reduced surface area for bugs
  • Maintainability: if tab logic changes, both nav buttons and stat cards update automatically

2. CSS Hover States Over JavaScript Tooltips

We chose CSS transitions for interactivity feedback instead of JavaScript hover listeners. Reasons:

  • Lower latency: CSS transitions run on the GPU, decoupled from JavaScript event loop
  • Smoother UX: no jank on mobile or slower devices
  • Accessibility: works without JavaScript enabled (graceful degradation)

3. Minimal Color Contamination

The hover state uses a subtle blue (matching the app's primary accent color) with low opacity. This avoids visual noise while signaling interactivity. The opacity ensures it doesn't distract from the dashboard's dashboard-as-status-display purpose.

Testing Considerations

Because the maintenance hub is mission-critical for the vessel's operational safety (tracks engine hours