fix: resolve VIN decode cache race, fuzzy matching, and silent failure (refs #229)
All checks were successful
Deploy to Staging / Build Images (pull_request) Successful in 6m31s
Deploy to Staging / Deploy to Staging (pull_request) Successful in 52s
Deploy to Staging / Verify Staging (pull_request) Successful in 9s
Deploy to Staging / Notify Staging Ready (pull_request) Successful in 8s
Deploy to Staging / Notify Staging Failure (pull_request) Has been skipped

Prevent lower-confidence Gemini results from overwriting higher-confidence
cache entries, add reverse-contains matching so values like "X5 xDrive35i"
match DB option "X5", and show amber hint when dropdown matching fails.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Eric Gullickson
2026-02-19 20:14:54 -06:00
parent d96736789e
commit 361f58d7c6
2 changed files with 50 additions and 3 deletions

View File

@@ -114,6 +114,7 @@ export const VehicleForm: React.FC<VehicleFormProps> = ({
const [isDecoding, setIsDecoding] = useState(false);
const [showUpgradeDialog, setShowUpgradeDialog] = useState(false);
const [decodeError, setDecodeError] = useState<string | null>(null);
const [decodeHint, setDecodeHint] = useState<string | null>(null);
// VIN OCR capture hook
const vinOcr = useVinOcr();
@@ -524,6 +525,7 @@ export const VehicleForm: React.FC<VehicleFormProps> = ({
setIsDecoding(true);
setDecodeError(null);
setDecodeHint(null);
try {
const decoded = await vehiclesApi.decodeVin(vin);
@@ -588,6 +590,21 @@ export const VehicleForm: React.FC<VehicleFormProps> = ({
setValue('transmission', decoded.transmission.value);
}
// Check if decode returned data but matching failed for key fields
const hasMatchedValue = decoded.year.value || decoded.make.value || decoded.model.value;
const hasSourceValue = decoded.year.sourceValue || decoded.make.sourceValue || decoded.model.sourceValue;
if (!hasMatchedValue && hasSourceValue) {
const parts = [
decoded.year.sourceValue,
decoded.make.sourceValue,
decoded.model.sourceValue,
decoded.trimLevel.sourceValue
].filter(Boolean);
setDecodeHint(
`Could not match VIN data to dropdowns. Decoded as: ${parts.join(' ')}. Please select values manually.`
);
}
setLoadingDropdowns(false);
isVinDecoding.current = false;
} catch (error: any) {
@@ -671,6 +688,9 @@ export const VehicleForm: React.FC<VehicleFormProps> = ({
{decodeError && (
<p className="mt-1 text-sm text-red-600 dark:text-red-400">{decodeError}</p>
)}
{decodeHint && (
<p className="mt-1 text-sm text-amber-600 dark:text-amber-400">{decodeHint}</p>
)}
{vinOcr.error && (
<p className="mt-1 text-sm text-red-600 dark:text-red-400">{vinOcr.error}</p>
)}