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

194 lines
7.9 KiB
TypeScript

'use client';
import { useState, useEffect } from 'react';
interface ComparisonFormProps {
onSubmit: (item1: string, item2: string, description1: string, description2: string) => void;
isLoading: boolean;
selectedExample?: { item1: string; item2: string } | null;
onExampleUsed?: () => void;
}
export default function ComparisonForm({ onSubmit, isLoading, selectedExample, onExampleUsed }: ComparisonFormProps) {
const [item1, setItem1] = useState('');
const [item2, setItem2] = useState('');
const [description1, setDescription1] = useState('');
const [description2, setDescription2] = useState('');
const [showDescriptions, setShowDescriptions] = useState(false);
// Handle selected example
useEffect(() => {
if (selectedExample) {
setItem1(selectedExample.item1);
setItem2(selectedExample.item2);
onExampleUsed?.();
}
}, [selectedExample, onExampleUsed]);
const examples = [
{ item1: 'iPhone 15 Pro', item2: 'Samsung Galaxy S24 Ultra', category: 'Smartphones' },
{ item1: 'React', item2: 'Vue.js', category: 'Frontend Frameworks' },
{ item1: 'Tesla Model 3', item2: 'BMW i4', category: 'Electric Cars' },
{ item1: 'Netflix', item2: 'Disney+', category: 'Streaming Services' },
{ item1: 'MacBook Pro', item2: 'ThinkPad X1 Carbon', category: 'Laptops' },
{ item1: 'Coffee', item2: 'Tea', category: 'Beverages' }
];
const getRandomExample = () => {
return examples[Math.floor(Math.random() * examples.length)];
};
const fillRandomExample = () => {
const example = getRandomExample();
setItem1(example.item1);
setItem2(example.item2);
};
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (item1.trim() && item2.trim()) {
onSubmit(item1.trim(), item2.trim(), description1.trim(), description2.trim());
}
};
return (
<div className="space-y-6">
<div className="text-center mb-6">
<h2 className="text-2xl font-bold text-gray-900 mb-2">Start Your Comparison</h2>
<p className="text-gray-600 mb-4">Enter any two items you want to compare - products, services, concepts, or ideas</p>
<button
type="button"
onClick={fillRandomExample}
className="text-blue-600 hover:text-blue-800 text-sm font-medium underline"
>
Try a random example
</button>
</div>
<form onSubmit={handleSubmit} className="space-y-6">
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label htmlFor="item1" className="block text-sm font-medium text-gray-700 mb-2">
First Item
</label>
<div className="relative">
<input
type="text"
id="item1"
value={item1}
onChange={(e) => setItem1(e.target.value)}
placeholder="e.g., iPhone 15 Pro, React, Tesla Model 3"
className={`w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200 ${isLoading ? 'bg-gray-50 cursor-not-allowed' : 'bg-white'}`}
disabled={isLoading}
required
/>
{isLoading && (
<div className="absolute inset-0 flex items-center justify-center bg-gray-50 bg-opacity-75 rounded-lg">
<div className="animate-spin rounded-full h-5 w-5 border-b-2 border-blue-600"></div>
</div>
)}
</div>
</div>
<div>
<label htmlFor="item2" className="block text-sm font-medium text-gray-700 mb-2">
Second Item
</label>
<div className="relative">
<input
type="text"
id="item2"
value={item2}
onChange={(e) => setItem2(e.target.value)}
placeholder="e.g., Samsung Galaxy S24, Vue.js, BMW i4"
className={`w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200 ${isLoading ? 'bg-gray-50 cursor-not-allowed' : 'bg-white'}`}
disabled={isLoading}
required
/>
{isLoading && (
<div className="absolute inset-0 flex items-center justify-center bg-gray-50 bg-opacity-75 rounded-lg">
<div className="animate-spin rounded-full h-5 w-5 border-b-2 border-blue-600"></div>
</div>
)}
</div>
</div>
</div>
<div className="text-center">
<button
type="button"
onClick={() => setShowDescriptions(!showDescriptions)}
className="text-blue-600 hover:text-blue-800 text-sm font-medium"
>
{showDescriptions ? 'Hide' : 'Add'} additional descriptions
</button>
</div>
{showDescriptions && (
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label htmlFor="description1" className="block text-sm font-medium text-gray-700 mb-2">
Description for {item1 || 'First Item'}
</label>
<div className="relative">
<textarea
id="description1"
value={description1}
onChange={(e) => setDescription1(e.target.value)}
placeholder="Additional details, specifications, or context about the first item..."
rows={3}
className={`w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200 ${isLoading ? 'bg-gray-50 cursor-not-allowed' : 'bg-white'}`}
disabled={isLoading}
/>
{isLoading && (
<div className="absolute inset-0 flex items-center justify-center bg-gray-50 bg-opacity-75 rounded-lg">
<div className="animate-spin rounded-full h-5 w-5 border-b-2 border-blue-600"></div>
</div>
)}
</div>
</div>
<div>
<label htmlFor="description2" className="block text-sm font-medium text-gray-700 mb-2">
Description for {item2 || 'Second Item'}
</label>
<div className="relative">
<textarea
id="description2"
value={description2}
onChange={(e) => setDescription2(e.target.value)}
placeholder="Additional details, specifications, or context about the second item..."
rows={3}
className={`w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200 ${isLoading ? 'bg-gray-50 cursor-not-allowed' : 'bg-white'}`}
disabled={isLoading}
/>
{isLoading && (
<div className="absolute inset-0 flex items-center justify-center bg-gray-50 bg-opacity-75 rounded-lg">
<div className="animate-spin rounded-full h-5 w-5 border-b-2 border-blue-600"></div>
</div>
)}
</div>
</div>
</div>
)}
<div className="text-center">
<button
type="submit"
disabled={isLoading || !item1.trim() || !item2.trim()}
className="px-8 py-4 bg-blue-600 text-white font-medium rounded-lg hover:bg-blue-700 focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed transition-all duration-200 flex items-center justify-center gap-2 mx-auto"
>
{isLoading ? (
<>
<div className="animate-spin rounded-full h-5 w-5 border-b-2 border-white"></div>
Analyzing & Comparing...
</>
) : (
'Compare Now'
)}
</button>
</div>
</form>
</div>
);
}