anything-vs-anything/src/components/ComparisonHistory.tsx
2025-07-03 00:49:29 +08:00

156 lines
5.3 KiB
TypeScript

'use client';
import { useState, useEffect } from 'react';
import { deleteHistoryItem } from '@/utils/historyStorage';
export interface HistoryItem {
id: string;
item1: string;
item2: string;
description1: string;
description2: string;
result: string;
timestamp: number;
}
interface ComparisonHistoryProps {
onSelectHistory: (item: HistoryItem) => void;
}
export default function ComparisonHistory({ onSelectHistory }: ComparisonHistoryProps) {
const [history, setHistory] = useState<HistoryItem[]>([]);
const [isExpanded, setIsExpanded] = useState(false);
useEffect(() => {
const loadHistory = () => {
try {
const stored = localStorage.getItem('comparison-history');
if (stored) {
const parsed = JSON.parse(stored);
setHistory(parsed.slice(0, 10)); // Keep only last 10 items
}
} catch (error) {
console.error('Error loading history:', error);
}
};
loadHistory();
// Listen for storage changes
const handleStorageChange = () => {
loadHistory();
};
window.addEventListener('storage', handleStorageChange);
// Custom event for same-page updates
window.addEventListener('comparison-history-updated', handleStorageChange);
return () => {
window.removeEventListener('storage', handleStorageChange);
window.removeEventListener('comparison-history-updated', handleStorageChange);
};
}, []);
const clearHistory = () => {
localStorage.removeItem('comparison-history');
setHistory([]);
window.dispatchEvent(new Event('comparison-history-updated'));
};
const handleDeleteItem = (e: React.MouseEvent, itemId: string) => {
e.stopPropagation(); // Prevent triggering the onClick of the parent div
deleteHistoryItem(itemId);
};
const formatDate = (timestamp: number) => {
return new Date(timestamp).toLocaleDateString('en-US', {
month: 'short',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
});
};
if (history.length === 0) {
return null;
}
return (
<div className="bg-white rounded-xl shadow-lg p-6">
<div className="flex items-center justify-between mb-4">
<h2 className="text-xl font-bold text-gray-900">Comparison History</h2>
<div className="flex items-center gap-3">
<button
onClick={() => setIsExpanded(!isExpanded)}
className="text-blue-600 hover:text-blue-800 text-sm font-medium"
>
{isExpanded ? 'Show Less' : `Show All (${history.length})`}
</button>
<button
onClick={clearHistory}
className="text-red-600 hover:text-red-800 text-sm font-medium"
>
Clear History
</button>
</div>
</div>
<div className="space-y-3">
{(isExpanded ? history : history.slice(0, 3)).map((item) => (
<div
key={item.id}
onClick={() => onSelectHistory(item)}
className="p-4 border border-gray-200 rounded-lg hover:border-blue-300 hover:bg-blue-50 cursor-pointer transition-all duration-200 group relative"
>
<div className="flex items-center justify-between mb-2">
<div className="font-medium text-gray-900 flex-1">
<span className="text-blue-600">{item.item1}</span>
<span className="text-gray-400 mx-2">vs</span>
<span className="text-green-600">{item.item2}</span>
</div>
<div className="flex items-center gap-2">
<span className="text-xs text-gray-500">
{formatDate(item.timestamp)}
</span>
<button
onClick={(e) => handleDeleteItem(e, item.id)}
className="opacity-0 group-hover:opacity-100 text-red-500 hover:text-red-700 p-1 rounded transition-all duration-200"
title="Delete this comparison"
>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
</svg>
</button>
</div>
</div>
{(item.description1 || item.description2) && (
<div className="text-sm text-gray-600">
{item.description1 && (
<div className="truncate">
<strong>{item.item1}:</strong> {item.description1}
</div>
)}
{item.description2 && (
<div className="truncate">
<strong>{item.item2}:</strong> {item.description2}
</div>
)}
</div>
)}
</div>
))}
</div>
{!isExpanded && history.length > 3 && (
<div className="text-center mt-4">
<button
onClick={() => setIsExpanded(true)}
className="text-blue-600 hover:text-blue-800 text-sm font-medium"
>
View {history.length - 3} more comparisons...
</button>
</div>
)}
</div>
);
}