Backend (server.py): - Fix N+1 query in /api/diagrams/<id>/parts with batch cross-ref query - Add LIMIT safety nets to 15 endpoints (50-5000 per data type) - Add pagination to /api/vehicles, /api/model-year-engine, /api/vehicles/<id>/parts, /api/admin/export - Optimize search_vehicles() EXISTS subquery to JOIN - Restrict static route to /static/* subdir (security fix) - Add detailed=true support to /api/brands and /api/models Frontend: - Extract shared CSS into shared.css (variables, reset, buttons, forms, scrollbar) - Create shared nav.js component (logo + navigation links, auto-highlights) - Update all 4 HTML pages to use shared CSS and nav - Update JS to handle paginated API responses Data quality: - Fix cross-reference source field: map 72K records from catalog names to actual brands - Fix aftermarket_parts manufacturer_id: correct 8K records with wrong brand attribution - Delete 98MB backup file, orphan records, and garbage cross-references - Add import scripts for DAR, FRAM, WIX, MOOG, Cartek catalogs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
110 lines
4.3 KiB
JavaScript
110 lines
4.3 KiB
JavaScript
/**
|
|
* nav.js -- Shared navigation component for AutoParts DB
|
|
*
|
|
* Injects a consistent header/nav bar into <div id="shared-nav"></div>.
|
|
* Auto-highlights the current page link based on window.location.pathname.
|
|
*
|
|
* The injected header includes a <div id="shared-nav-extra"></div> slot
|
|
* that pages can populate with additional header content (search bars, stats, etc.)
|
|
* after this script runs.
|
|
*/
|
|
(function () {
|
|
'use strict';
|
|
|
|
var path = window.location.pathname;
|
|
|
|
function isActive(href) {
|
|
var h = href.replace(/\/+$/, '') || '/';
|
|
var p = path.replace(/\/+$/, '') || '/';
|
|
if (h === p) return true;
|
|
if ((h === '/' || h === '/index.html') && (p === '/' || p === '/index.html')) return true;
|
|
if ((h === '/admin.html' || h === '/admin') && (p === '/admin.html' || p === '/admin')) return true;
|
|
if ((h === '/diagramas' || h === '/diagrams.html') && (p === '/diagramas' || p === '/diagrams.html')) return true;
|
|
if ((h === '/customer-landing.html') && (p === '/customer-landing.html')) return true;
|
|
return false;
|
|
}
|
|
|
|
var navLinks = [
|
|
{ label: 'Cat\u00e1logo', href: '/' },
|
|
{ label: 'Diagramas', href: '/diagramas' },
|
|
{ label: 'Admin', href: '/admin' }
|
|
];
|
|
|
|
var linksHTML = navLinks.map(function (link) {
|
|
var baseStyle = 'text-decoration: none; font-size: 0.9rem; font-weight: 500; transition: color 0.2s;';
|
|
if (isActive(link.href)) {
|
|
baseStyle += ' color: var(--accent);';
|
|
} else {
|
|
baseStyle += ' color: var(--text-secondary);';
|
|
}
|
|
return '<a href="' + link.href + '" style="' + baseStyle + '"'
|
|
+ ' onmouseover="this.style.color=\'var(--accent)\'"'
|
|
+ ' onmouseout="' + (isActive(link.href) ? '' : 'this.style.color=\'var(--text-secondary)\'') + '"'
|
|
+ '>' + link.label + '</a>';
|
|
}).join('');
|
|
|
|
var html = ''
|
|
+ '<header id="shared-nav-header" style="'
|
|
+ 'background: rgba(18, 18, 26, 0.95);'
|
|
+ 'backdrop-filter: blur(20px);'
|
|
+ '-webkit-backdrop-filter: blur(20px);'
|
|
+ 'border-bottom: 1px solid var(--border);'
|
|
+ 'padding: 1rem 2rem;'
|
|
+ 'position: fixed;'
|
|
+ 'top: 0; left: 0; right: 0;'
|
|
+ 'z-index: 1000;'
|
|
+ '">'
|
|
+ '<div style="'
|
|
+ 'max-width: 1600px;'
|
|
+ 'margin: 0 auto;'
|
|
+ 'display: flex;'
|
|
+ 'justify-content: space-between;'
|
|
+ 'align-items: center;'
|
|
+ 'gap: 2rem;'
|
|
+ '">'
|
|
// Logo
|
|
+ '<a href="/" style="'
|
|
+ 'display: flex;'
|
|
+ 'align-items: center;'
|
|
+ 'gap: 0.75rem;'
|
|
+ 'text-decoration: none;'
|
|
+ 'flex-shrink: 0;'
|
|
+ '">'
|
|
+ '<div style="'
|
|
+ 'width: 42px; height: 42px;'
|
|
+ 'background: linear-gradient(135deg, var(--accent) 0%, #ff4500 100%);'
|
|
+ 'border-radius: 10px;'
|
|
+ 'display: flex; align-items: center; justify-content: center;'
|
|
+ 'font-size: 1.5rem;'
|
|
+ 'box-shadow: 0 4px 20px var(--accent-glow);'
|
|
+ '">\u2699\uFE0F</div>'
|
|
+ '<span style="'
|
|
+ 'font-family: Orbitron, sans-serif;'
|
|
+ 'font-size: 1.3rem;'
|
|
+ 'font-weight: 700;'
|
|
+ 'background: linear-gradient(135deg, #fff 0%, var(--accent) 100%);'
|
|
+ '-webkit-background-clip: text;'
|
|
+ '-webkit-text-fill-color: transparent;'
|
|
+ 'background-clip: text;'
|
|
+ '">AUTOPARTS DB</span>'
|
|
+ '</a>'
|
|
// Slot for extra page-specific content (search bars, stats, etc.)
|
|
+ '<div id="shared-nav-extra" style="display: contents;"></div>'
|
|
// Nav links
|
|
+ '<nav id="shared-nav-links" style="'
|
|
+ 'display: flex;'
|
|
+ 'gap: 1.5rem;'
|
|
+ 'align-items: center;'
|
|
+ 'flex-shrink: 0;'
|
|
+ '">'
|
|
+ linksHTML
|
|
+ '</nav>'
|
|
+ '</div>'
|
|
+ '</header>';
|
|
|
|
var target = document.getElementById('shared-nav');
|
|
if (target) {
|
|
target.innerHTML = html;
|
|
}
|
|
})();
|