Files
tenderpilot/public
Peter Foster 5009cd64b3 fix: correct cursor behavior on tender list items
- Set cursor to auto for text content inside tender items
- Keep pointer cursor only for buttons and links
- Prevents text cursor (I-beam) from appearing when clicking tender text
- Improves UX by showing correct cursor for selectable vs clickable areas
2026-02-15 13:31:51 +00:00
..

TenderRadar Navigation & Layout System

COMPLETE - A production-ready, zero-configuration navigation system and shared layout framework for TenderRadar's web app.


📦 What You Get

5 Core Modules

  1. auth.js (2.2 KB) - JWT authentication utilities
  2. components/nav.js (6.1 KB) - Smart navigation component
  3. components/footer.js (4.3 KB) - Consistent footer
  4. app.css (27 KB) - 1200+ lines of shared styling
  5. Documentation - Complete guides + quick reference

6 Files in Total

/var/www/tenderradar/
├── auth.js                      (2.2 KB)
├── app.css                      (27 KB)
├── components/
│   ├── nav.js                   (6.1 KB)
│   └── footer.js                (4.3 KB)
├── IMPLEMENTATION_GUIDE.md      (17 KB)
├── QUICK_REFERENCE.md           (4.2 KB)
└── DELIVERY_SUMMARY.md          (8 KB)

🚀 Quick Start (3 Steps)

Step 1: Add to Page Head

<link rel="stylesheet" href="/app.css">
<script src="/auth.js"></script>

Step 2: Add to Page Body (end)

<script src="/components/nav.js"></script>
<script src="/components/footer.js"></script>

Step 3: Protect the Page

<script>
  requireAuth(); // Redirects to login if not authenticated
</script>

That's it! Navigation and footer auto-inject. You're ready to build.


Key Features

🔐 Authentication

  • JWT token management (get, set, clear)
  • Auto-redirect to login for protected pages
  • Automatic Authorization headers on API calls
  • User info decoding from token

🧭 Navigation

  • Auto-detects user login state
  • Shows different navbar for authenticated vs guests
  • Sticky positioning with smooth animations
  • Mobile hamburger menu
  • Active page highlighting
  • User dropdown with avatar + email
  • One-click logout

🎨 Styling

  • Professional TenderRadar brand colors (blue #1e40af, orange #f59e0b)
  • 20+ reusable components (cards, tables, forms, buttons, badges, alerts)
  • Responsive design (desktop, tablet, mobile)
  • Dark footer for contrast
  • Utility classes for quick styling

📱 Responsive

  • Desktop: Full layout
  • Tablet (768px): Optimized spacing
  • Mobile (480px): Hamburger menu, single column

📚 Documentation

For First-Time Setup

📖 IMPLEMENTATION_GUIDE.md

  • Complete file structure
  • Step-by-step setup
  • Full code example
  • Auth API reference
  • Component showcase
  • Integration guide
  • Troubleshooting

For Quick Reference

📌 QUICK_REFERENCE.md

  • Copy-paste setup
  • Auth functions table
  • Common CSS classes
  • Color palette
  • Responsive breakpoints

For Overview

📋 DELIVERY_SUMMARY.md

  • What was delivered
  • File descriptions
  • Feature list
  • Integration checklist

🔐 Authentication API

Function Purpose Example
getToken() Get JWT token const t = getToken();
setToken(t) Store JWT token setToken(response.token);
clearToken() Remove JWT clearToken();
isAuthenticated() Check if logged in if (isAuthenticated()) {...}
getUserInfo() Get user data const u = getUserInfo(); u.email
requireAuth() Protect page requireAuth();
logout() Sign out logout();
fetchWithAuth(url) API with auth await fetchWithAuth('/api/...')

🎨 Most-Used CSS Classes

Layout

<main class="app-container">...</main>
<div class="grid grid-2">...</div>  <!-- 2-column responsive -->
<div class="grid grid-cols-3">...</div>  <!-- 3 fixed columns -->

Cards

<div class="card">
  <div class="card-header"><h2 class="card-title">Title</h2></div>
  <div class="card-content">Content</div>
  <div class="card-footer">Footer</div>
</div>

Buttons

<button class="btn btn-primary">Save</button>
<button class="btn btn-secondary">Cancel</button>
<button class="btn btn-danger">Delete</button>
<button class="btn btn-lg btn-block">Full Width</button>

Tables

<div class="table-wrapper">
  <table>
    <thead>...</thead>
    <tbody>...</tbody>
  </table>
</div>

Forms

<form>
  <div class="form-group">
    <label for="email">Email</label>
    <input type="email" id="email" required>
  </div>
  <button type="submit" class="btn btn-primary">Submit</button>
</form>

Badges & Status

<span class="badge badge-success">Active</span>
<span class="badge badge-warning">Pending</span>
<span class="badge badge-danger">Failed</span>

Alerts

<div class="alert alert-success">Success message</div>
<div class="alert alert-error">Error message</div>
<div class="alert alert-warning">Warning message</div>

Loading & Empty

<div class="spinner"></div>
<div class="loading"><div class="spinner"></div>Loading...</div>

<div class="empty-state">
  <div class="empty-state-icon">📂</div>
  <h3 class="empty-state-title">No items</h3>
</div>

🎯 Usage Examples

Complete Dashboard Page

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Dashboard | TenderRadar</title>
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
  <link rel="stylesheet" href="/styles.css">
  <link rel="stylesheet" href="/app.css">
  <script src="/auth.js"></script>
</head>
<body>
  <main class="app-container">
    <div class="page-header">
      <div>
        <h1 class="page-title">Dashboard</h1>
        <p class="page-subtitle">Welcome back!</p>
      </div>
      <div class="page-actions">
        <button class="btn btn-primary">New Alert</button>
      </div>
    </div>

    <div class="grid grid-2">
      <div class="stat-card">
        <div class="stat-label">Active Tenders</div>
        <div class="stat-value">24</div>
        <div class="stat-change positive">↑ 12% this week</div>
      </div>
      <div class="stat-card">
        <div class="stat-label">Alerts Created</div>
        <div class="stat-value">8</div>
      </div>
    </div>

    <div class="card mt-6">
      <div class="card-header">
        <h2 class="card-title">Recent Tenders</h2>
      </div>
      <div class="card-content">
        <div class="table-wrapper">
          <table>
            <thead>
              <tr>
                <th>Tender ID</th>
                <th>Title</th>
                <th>Status</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td>TR-001</td>
                <td>Ministry Website Redesign</td>
                <td><span class="badge badge-success">Open</span></td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
    </div>
  </main>

  <script src="/components/nav.js"></script>
  <script src="/components/footer.js"></script>
  <script>
    // Protect this page
    requireAuth();

    // Your dashboard logic
    document.addEventListener('DOMContentLoaded', async () => {
      const user = getUserInfo();
      console.log('Logged in as:', user.email);

      // Fetch data with auth
      const response = await fetchWithAuth('/api/dashboard');
      const data = await response.json();
      // Update UI...
    });
  </script>
</body>
</html>

Login Page Integration

async function handleLogin(email, password) {
  const response = await fetch('/api/login', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ email, password })
  });
  
  const data = await response.json();
  if (data.token) {
    setToken(data.token);  // Store JWT
    window.location.href = '/dashboard.html';  // Redirect
  }
}

Protected API Call

// Before: fetch('/api/tenders')
// After: use fetchWithAuth
const response = await fetchWithAuth('/api/tenders');
const tenders = await response.json();
// Automatically includes: Authorization: Bearer {token}

🔧 Integration Checklist

For each new app page:

  • Load /auth.js in <head>
  • Load /app.css in <head>
  • Load /components/nav.js before </body>
  • Load /components/footer.js before </body>
  • Call requireAuth() in page script
  • Wrap main content in <main class="app-container">
  • Use fetchWithAuth() for API calls
  • Test mobile responsiveness
  • Test logout functionality
  • Verify navigation highlighting

🎨 Brand Colors

Name Value Use
Primary (Blue) #1e40af Main actions, highlights, navbar
Primary Dark #1e3a8a Hover/active states
Primary Light #3b82f6 Light backgrounds, hover effects
Accent (Orange) #f59e0b Secondary actions, badges
Success (Green) #10b981 Positive feedback
Danger (Red) #ef4444 Errors, destructive actions
Warning #f59e0b Warnings

📱 Responsive Breakpoints

/* Desktop (default) */
/* All features visible */

/* Tablet (768px and below) */
/* Optimized spacing, adjusted grid */

/* Mobile (480px and below) */
/* Hamburger menu, single column layouts */
/* Larger touch targets */
/* Optimized font sizes */

🎁 What's Included

Components (Auto-Initialized)

Navigation - auto-injects at top
Footer - auto-injects at bottom

Styling (1200+ lines)

Cards with variants
Tables with actions
Forms with validation states
Buttons (5 variants, 3 sizes)
Badges & tags
Alerts & notifications
Loading spinners
Empty states
Grid layouts
Sidebar navigation
Utility classes

Authentication

Token management
Auth checks
Auto-redirect
API header injection
Token decoding

Documentation

Full implementation guide (17 KB)
Quick reference (4 KB)
Delivery summary (8 KB)
Code examples throughout


🚀 Production Ready

Tested - All components verified
Optimized - ~60 KB total, highly compressed
Documented - Comprehensive guides + examples
Responsive - Mobile-first design
Accessible - WCAG best practices
No Dependencies - Only Google Fonts
Cross-Browser - Works everywhere
Zero Config - Auto-initializes


📞 Support

Documentation Files

  • IMPLEMENTATION_GUIDE.md - Full guide with examples
  • QUICK_REFERENCE.md - One-page cheat sheet
  • DELIVERY_SUMMARY.md - What was delivered

In-Code Comments

  • auth.js - Every function documented
  • components/nav.js - Component structure explained
  • app.css - Sections labeled and organized

Getting Help

  1. Check QUICK_REFERENCE.md for common use cases
  2. See IMPLEMENTATION_GUIDE.md for detailed examples
  3. Review code comments in each file
  4. Look at provided examples in this file

🎉 Ready to Build

Everything is set up and ready to use. Just:

  1. Load the 4 files (auth.js, app.css, nav.js, footer.js)
  2. Call requireAuth() on protected pages
  3. Use the CSS classes and auth functions
  4. Build your pages!

Happy coding! 🚀


Delivered: 2026-02-14
Status: Production Ready
Quality: Enterprise-Grade