Add AI status badges to show verification status on prices

- Add ai_status column to price_history table (verified/corrected/null)
- Track AI verification status through scraper and scheduler
- Display badges next to prices:
  - ✓ AI (green): AI verified the price is correct
  -  AI (orange): AI corrected an incorrect price
- Show badges on Dashboard product cards and ProductDetail page
- Add legend explaining badges in Settings when AI Verification is enabled

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
clucraft 2026-01-23 09:45:45 -05:00
parent 3d91489f12
commit ccbc188487
11 changed files with 173 additions and 23 deletions

View file

@ -0,0 +1,60 @@
import { AIStatus } from '../api/client';
interface AIStatusBadgeProps {
status: AIStatus;
size?: 'small' | 'normal';
}
export default function AIStatusBadge({ status, size = 'normal' }: AIStatusBadgeProps) {
if (!status) return null;
const isSmall = size === 'small';
const fontSize = isSmall ? '0.65rem' : '0.75rem';
const padding = isSmall ? '0.1rem 0.3rem' : '0.15rem 0.4rem';
if (status === 'verified') {
return (
<span
style={{
display: 'inline-flex',
alignItems: 'center',
gap: '0.2rem',
fontSize,
padding,
borderRadius: '0.25rem',
backgroundColor: 'rgba(16, 185, 129, 0.15)',
color: '#10b981',
fontWeight: 500,
}}
title="AI verified this price is correct"
>
<span style={{ fontSize: isSmall ? '0.7rem' : '0.8rem' }}></span>
AI
</span>
);
}
if (status === 'corrected') {
return (
<span
style={{
display: 'inline-flex',
alignItems: 'center',
gap: '0.2rem',
fontSize,
padding,
borderRadius: '0.25rem',
backgroundColor: 'rgba(245, 158, 11, 0.15)',
color: '#f59e0b',
fontWeight: 500,
}}
title="AI corrected this price (original scrape was incorrect)"
>
<span style={{ fontSize: isSmall ? '0.7rem' : '0.8rem' }}></span>
AI
</span>
);
}
return null;
}

View file

@ -2,6 +2,7 @@ import { useState, useEffect } from 'react';
import { Link } from 'react-router-dom';
import { Product } from '../api/client';
import Sparkline from './Sparkline';
import AIStatusBadge from './AIStatusBadge';
interface ProductCardProps {
product: Product;
@ -502,9 +503,12 @@ export default function ProductCard({ product, onDelete, onRefresh, isSelected,
</span>
) : (
<>
<span className="product-current-price">
{formatPrice(product.current_price, product.currency)}
</span>
<div style={{ display: 'flex', alignItems: 'center', gap: '0.375rem' }}>
<span className="product-current-price">
{formatPrice(product.current_price, product.currency)}
</span>
<AIStatusBadge status={product.ai_status} size="small" />
</div>
{product.price_change_7d !== null && product.price_change_7d !== undefined && (
<span className={`product-price-change ${priceChangeClass}`}>
{formatPriceChange(product.price_change_7d)} (7d)