← back to Wine Finder Next
components/WhereToBuy.tsx
128 lines
'use client'
interface Retailer {
retailer: string
price: number
url: string
availability: string
logo?: string
}
interface WhereToBuyProps {
retailers: Retailer[]
wineName: string
}
export default function WhereToBuy({ retailers, wineName }: WhereToBuyProps) {
// Sort retailers by price (lowest first)
const sortedRetailers = [...retailers].sort((a, b) => a.price - b.price)
const bestPrice = sortedRetailers[0]
const getAvailabilityColor = (availability: string) => {
const lower = availability.toLowerCase()
if (lower.includes('in stock')) return 'bg-green-100 text-green-700 border-green-300'
if (lower.includes('limited')) return 'bg-yellow-100 text-yellow-700 border-yellow-300'
return 'bg-gray-100 text-gray-700 border-gray-300'
}
return (
<section className="bg-white rounded-3xl shadow-wine-lg p-6 sm:p-8 animate-slide-up">
<h2 className="text-2xl sm:text-3xl font-bold text-gray-900 mb-2">
Where to Buy
</h2>
<p className="text-gray-600 mb-6">
Compare prices from trusted wine retailers
</p>
<div className="space-y-4">
{sortedRetailers.map((retailer, index) => {
const isBestPrice = retailer.price === bestPrice.price
return (
<div
key={index}
className={`relative border-2 rounded-2xl p-5 sm:p-6 transition-all duration-300 hover:shadow-wine ${
isBestPrice
? 'border-gold-400 bg-gradient-to-br from-gold-50 to-yellow-50'
: 'border-gray-200 bg-white hover:border-wine-300'
}`}
>
{/* Best Price Badge */}
{isBestPrice && (
<div className="absolute -top-3 left-6 px-4 py-1 bg-gradient-to-r from-gold-500 to-gold-600 text-white text-sm font-bold rounded-full shadow-gold">
🏆 Best Price
</div>
)}
<div className="flex flex-col sm:flex-row sm:items-center justify-between gap-4">
<div className="flex items-center gap-4">
{/* Retailer Logo/Icon */}
<div className="flex-shrink-0 w-12 h-12 sm:w-16 sm:h-16 bg-white rounded-xl flex items-center justify-center text-3xl sm:text-4xl shadow-md">
{retailer.logo || '🏪'}
</div>
{/* Retailer Info */}
<div>
<h3 className="text-lg sm:text-xl font-bold text-gray-900 mb-1">
{retailer.retailer}
</h3>
<span
className={`inline-block px-3 py-1 rounded-full text-xs sm:text-sm font-semibold border ${getAvailabilityColor(
retailer.availability
)}`}
>
{retailer.availability}
</span>
</div>
</div>
{/* Price & CTA */}
<div className="flex items-center gap-4 sm:flex-row-reverse">
<a
href={retailer.url}
target="_blank"
rel="noopener noreferrer"
className={`px-6 py-3 rounded-full font-bold text-white text-center transition-all duration-300 hover:shadow-lg transform hover:scale-105 whitespace-nowrap min-h-[44px] flex items-center justify-center ${
isBestPrice
? 'bg-gradient-to-r from-gold-500 to-gold-600 hover:from-gold-600 hover:to-gold-700'
: 'bg-gradient-to-r from-wine-600 to-burgundy-600 hover:from-wine-700 hover:to-burgundy-700'
}`}
aria-label={`Buy ${wineName} from ${retailer.retailer}`}
>
Buy Now →
</a>
<div className="text-right">
<div className="text-sm text-gray-500 mb-1">Price</div>
<div
className={`text-2xl sm:text-3xl font-bold ${
isBestPrice ? 'text-gold-700' : 'text-gray-900'
}`}
>
${retailer.price.toFixed(2)}
</div>
</div>
</div>
</div>
</div>
)
})}
</div>
{/* Price Comparison Summary */}
{sortedRetailers.length > 1 && (
<div className="mt-6 p-4 bg-purple-50 rounded-xl border border-purple-200">
<div className="flex items-center justify-between text-sm">
<span className="text-gray-700">
💡 Price difference between lowest and highest:
</span>
<span className="font-bold text-purple-700">
${(sortedRetailers[sortedRetailers.length - 1].price - sortedRetailers[0].price).toFixed(2)}
</span>
</div>
</div>
)}
</section>
)
}