import { useState } from 'react';
import PriceSparkline from './PriceSparkline';
export interface WatchlistItem {
id: number;
product_id: number;
target_price: number | null;
notify_price_drop: boolean;
notify_back_in_stock: boolean;
notify_push_price_drop: boolean;
notify_push_back_in_stock: boolean;
size_override: string | null;
name: string;
brand: string;
slug: string;
image_url: string;
cutout_image_url: string | null;
colorway: string;
lowest_price: number | null;
shop_count: number;
original_price: number | null;
price_7d_ago: number | null;
sparkline: number[];
}
interface Props {
item: WatchlistItem;
onRemove: (productId: number) => void;
onUpdateTargetPrice: (productId: number, price: number | null) => void;
onToggleNotification: (productId: number, field: 'notify_price_drop' | 'notify_back_in_stock' | 'notify_push_price_drop' | 'notify_push_back_in_stock', value: boolean) => void;
pushEnabled: boolean;
onEnablePush: () => void;
onUpdateSizeOverride?: (productId: number, size: string | null) => void;
}
const EU_SIZES = ['36', '37', '37.5', '38', '38.5', '39', '40', '40.5', '41', '42', '42.5', '43', '44', '44.5', '45', '46', '47', '48'];
export default function WatchlistItemCard({ item, onRemove, onUpdateTargetPrice, onToggleNotification, onUpdateSizeOverride, pushEnabled, onEnablePush }: Props) {
const [editingPrice, setEditingPrice] = useState(false);
const [priceInput, setPriceInput] = useState('');
const [editingSize, setEditingSize] = useState(false);
const lowestPrice = item.lowest_price ? parseFloat(String(item.lowest_price)) : null;
const targetPrice = item.target_price ? parseFloat(String(item.target_price)) : null;
const originalPrice = item.original_price ? parseFloat(String(item.original_price)) : null;
const hasDiscount = originalPrice && lowestPrice && lowestPrice < originalPrice;
const price7dAgo = item.price_7d_ago ? parseFloat(String(item.price_7d_ago)) : null;
const priceDelta = (lowestPrice && price7dAgo) ? lowestPrice - price7dAgo : null;
// Status calculation
let statusLabel = '';
let statusClass = '';
if (targetPrice && lowestPrice) {
if (lowestPrice <= targetPrice) {
statusLabel = 'Deal gevonden!';
statusClass = 'bg-green-500/15 text-green-400';
} else if (lowestPrice <= targetPrice * 1.1) {
statusLabel = 'Bijna!';
statusClass = 'bg-yellow-500/15 text-yellow-400';
} else {
statusLabel = 'Wachten';
statusClass = 'bg-text-muted/10 text-text-muted';
}
}
const handleSavePrice = () => {
const price = priceInput ? parseFloat(priceInput) : null;
onUpdateTargetPrice(item.product_id, price);
setEditingPrice(false);
};
const handleSaveSize = (newSize: string | null) => {
if (onUpdateSizeOverride) {
onUpdateSizeOverride(item.product_id, newSize);
}
setEditingSize(false);
setPriceInput('');
};
return (
{
(e.target as HTMLImageElement).src = '/img/sneaker-placeholder.svg';
}}
/>
{statusLabel && (
{statusLabel}
)}
{item.colorway &&
{item.colorway}
}
{lowestPrice ? (
€{lowestPrice.toFixed(2).replace('.', ',')}
) : (
Niet beschikbaar
)}
{item.sparkline.length >= 2 && (
)}
{hasDiscount && (
€{originalPrice!.toFixed(2).replace('.', ',')}
)}
{item.shop_count} shop{Number(item.shop_count) !== 1 ? 's' : ''}
{priceDelta !== null && priceDelta !== 0 && (
{priceDelta < 0 ? (
) : (
)}
{priceDelta < 0 ? '-' : '+'}€{Math.abs(priceDelta).toFixed(2).replace('.', ',')} deze week
)}
{/* Target price */}
{editingPrice ? (
<>
Alert onder €
setPriceInput(e.target.value)}
step="0.01"
min="0"
className="w-20 rounded border border-border/30 bg-bg-elevated px-2 py-1 text-sm text-text focus:border-accent/50 focus:outline-none"
autoFocus
onKeyDown={e => e.key === 'Enter' && handleSavePrice()}
/>
>
) : (
)}
{/* Size override */}
{editingSize ? (
<>
Maat:
>
) : (
)}
{/* Notification toggles */}
{/* Email row */}
Email
{Number(item.shop_count) === 0 && (
)}
{/* Push row */}
Push
{pushEnabled ? (
<>
{Number(item.shop_count) === 0 && (
)}
>
) : (
)}
);
}