feat: PL24 multi-brand support & Corgi integration

## PL24 Improvements
- Add JLR (Jaguar/Land Rover) 3-step parts flow (vin_illus → vin_bomdetails)
- Enhance Ford parser with comprehensive category/subcategory handling
- Extend Hyundai-Kia parser with improved part extraction and hotspot support
- Add dedicated Kia parser for brand-specific parsing
- Add Kia scraper service for specialized scraping
- Improve legacy scraper with better error handling

## New Features
- Add Corgi API integration (corgi.service.ts, corgi.types.ts)
- Add NHTSA WMI fetch script for VIN decoding
- Add 90+ new schema images for parts visualization

## Bug Fixes & Improvements
- Update VIN decoder service with better brand detection
- Improve vehicles service with enhanced data handling
- Update parser factory with Kia support

## Assets
- Add new schema images for multiple vehicle brands
- Update UI screenshots (categories, parts, vehicles pages)
- Add debug hotspots utility for development

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Semih
2026-01-29 19:22:04 +01:00
parent 757905f41c
commit 895416f1aa
122 changed files with 5544 additions and 226 deletions

View File

@@ -0,0 +1,101 @@
// Debug script for hotspots issue
// Run this in browser console on the category parts page
(function debugHotspots() {
console.log('=== HOTSPOTS DEBUG SCRIPT ===');
// Try to find React fiber
const rootElement = document.getElementById('__next');
if (!rootElement) {
console.error('Could not find React root');
return;
}
// Find React internal state
const fiberKey = Object.keys(rootElement).find(key => key.startsWith('__reactFiber'));
if (!fiberKey) {
console.error('Could not find React fiber');
return;
}
console.log('Looking for component state...');
// Walk the fiber tree to find state
function findStateInFiber(fiber, depth = 0) {
if (depth > 50) return null;
// Check memoizedState for hooks
let hookState = fiber.memoizedState;
while (hookState) {
if (hookState.memoizedState && typeof hookState.memoizedState === 'object') {
const state = hookState.memoizedState;
// Look for our data structure
if (state && state.subGroups && Array.isArray(state.subGroups)) {
return { data: state, source: 'hook state' };
}
if (state && state.vehicle && state.category) {
return { data: state, source: 'hook state' };
}
}
hookState = hookState.next;
}
// Check child
if (fiber.child) {
const result = findStateInFiber(fiber.child, depth + 1);
if (result) return result;
}
// Check sibling
if (fiber.sibling) {
const result = findStateInFiber(fiber.sibling, depth + 1);
if (result) return result;
}
return null;
}
const fiber = rootElement[fiberKey];
const result = findStateInFiber(fiber);
if (result) {
console.log('Found data:', result.source);
const data = result.data;
console.log('\n=== SubGroups Info ===');
if (data.subGroups) {
data.subGroups.forEach((sg, i) => {
console.log(`SubGroup ${i}: id=${sg.id}, name="${sg.name?.split('\r')[0]}", hotspots=${sg.hotspots?.length || 'NONE'}`);
});
} else {
console.log('No subGroups found in data');
}
console.log('\n=== Main data.hotspots ===');
console.log('data.hotspots count:', data.hotspots?.length || 'NONE');
return data;
} else {
console.log('Could not find component state. Manual inspection needed.');
console.log('\nTry this instead:');
console.log('1. Open React DevTools');
console.log('2. Find CategoryPartsPage component');
console.log('3. Look at "data" state hook');
console.log('4. Check subGroups[0].hotspots vs subGroups[1].hotspots');
}
})();
// Also add click listener to track subgroup selection
document.querySelectorAll('button').forEach(btn => {
if (btn.textContent && btn.querySelector('.ml-2')) {
// This looks like a subgroup button
btn.addEventListener('click', () => {
console.log('[DEBUG] Clicked subgroup button:', btn.textContent?.trim());
});
}
});
console.log('\n=== INSTRUCTIONS ===');
console.log('1. Click different subgroup tabs');
console.log('2. Watch the console for [DEBUG] logs');
console.log('3. Check if hotspotsLength changes');

File diff suppressed because one or more lines are too long