← back to Watches

src/components/WatchList.jsx

171 lines

import React, { useState } from 'react';

function WatchList({ watches, onWatchSelect }) {
  const [searchTerm, setSearchTerm] = useState('');
  const [selectedSeries, setSelectedSeries] = useState('all');

  const series = ['all', ...new Set(watches.map(w => w.series))];

  const filteredWatches = watches.filter(watch => {
    const matchesSearch = watch.model.toLowerCase().includes(searchTerm.toLowerCase()) ||
                         watch.reference.toLowerCase().includes(searchTerm.toLowerCase());
    const matchesSeries = selectedSeries === 'all' || watch.series === selectedSeries;
    return matchesSearch && matchesSeries;
  });

  const calculateAppreciation = (watch) => {
    if (watch.priceHistory.length < 2) return 0;
    const first = watch.priceHistory[0].price;
    const last = watch.priceHistory[watch.priceHistory.length - 1].price;
    return (((last - first) / first) * 100).toFixed(2);
  };

  return (
    <div className="space-y-6">
      {/* Filters */}
      <div className="bg-white rounded-lg shadow-md p-6">
        <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
          <div>
            <label className="block text-sm font-medium text-gray-700 mb-2">
              Search Watches
            </label>
            <input
              type="text"
              placeholder="Search by model or reference..."
              value={searchTerm}
              onChange={(e) => setSearchTerm(e.target.value)}
              className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-omega-red focus:border-transparent"
            />
          </div>
          <div>
            <label className="block text-sm font-medium text-gray-700 mb-2">
              Filter by Series
            </label>
            <select
              value={selectedSeries}
              onChange={(e) => setSelectedSeries(e.target.value)}
              className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-omega-red focus:border-transparent"
            >
              {series.map(s => (
                <option key={s} value={s}>
                  {s === 'all' ? 'All Series' : s}
                </option>
              ))}
            </select>
          </div>
        </div>
      </div>

      {/* Watch Grid */}
      <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
        {filteredWatches.map(watch => {
          const currentPrice = watch.priceHistory[watch.priceHistory.length - 1].price;
          const originalPrice = watch.priceHistory[0].price;
          const appreciation = calculateAppreciation(watch);

          return (
            <div
              key={watch.id}
              onClick={() => onWatchSelect(watch)}
              className="bg-white rounded-lg shadow-md hover:shadow-xl transition-all cursor-pointer overflow-hidden group"
            >
              {/* Watch Image */}
              {watch.imageUrl && (
                <div className="relative h-64 overflow-hidden bg-gray-100">
                  <img
                    src={watch.imageUrl}
                    alt={watch.model}
                    className="w-full h-full object-cover group-hover:scale-110 transition-transform duration-500"
                    onError={(e) => {
                      e.target.src = 'https://images.unsplash.com/photo-1523170335258-f5ed11844a49?w=800';
                    }}
                  />
                  <div className="absolute top-2 right-2 bg-black bg-opacity-70 text-white px-3 py-1 rounded-full text-xs font-semibold">
                    {watch.yearIntroduced}
                  </div>
                </div>
              )}

              <div className="gradient-omega text-white p-4">
                <h3 className="font-bold text-lg mb-1">{watch.model}</h3>
                <p className="text-sm opacity-90">{watch.series}</p>
              </div>

              <div className="p-4">
                {/* Specifications Preview */}
                {watch.specifications && (
                  <div className="mb-4 bg-gray-50 p-3 rounded-lg">
                    <div className="grid grid-cols-2 gap-2 text-xs">
                      <div>
                        <span className="text-gray-500">Case:</span>
                        <span className="ml-1 font-semibold">{watch.specifications.caseSize}</span>
                      </div>
                      <div>
                        <span className="text-gray-500">Movement:</span>
                        <span className="ml-1 font-semibold text-omega-red">
                          {watch.specifications.movement?.split(' ')[1] || 'Auto'}
                        </span>
                      </div>
                      <div>
                        <span className="text-gray-500">Material:</span>
                        <span className="ml-1 font-semibold">
                          {watch.specifications.caseMaterial?.split(' ')[0]}
                        </span>
                      </div>
                      <div>
                        <span className="text-gray-500">WR:</span>
                        <span className="ml-1 font-semibold">{watch.specifications.waterResistance}</span>
                      </div>
                    </div>
                  </div>
                )}

                <div className="mb-4">
                  <p className="text-xs text-gray-500 mb-1">Reference</p>
                  <p className="font-mono text-sm font-semibold">{watch.reference}</p>
                </div>

                <div className="grid grid-cols-2 gap-4 mb-4">
                  <div>
                    <p className="text-xs text-gray-500 mb-1">Original Price</p>
                    <p className="font-semibold">${originalPrice.toLocaleString()}</p>
                  </div>
                  <div>
                    <p className="text-xs text-gray-500 mb-1">Current Price</p>
                    <p className="font-semibold text-omega-red">
                      ${currentPrice.toLocaleString()}
                    </p>
                  </div>
                </div>

                <div className="pt-4 border-t">
                  <div className="flex items-center justify-between">
                    <span className="text-sm text-gray-600">Appreciation</span>
                    <span className={`font-bold text-lg ${
                      parseFloat(appreciation) > 0 ? 'text-green-600' : 'text-red-600'
                    }`}>
                      {appreciation > 0 ? '+' : ''}{appreciation}%
                    </span>
                  </div>
                </div>

                <button className="w-full mt-4 bg-omega-red hover:bg-red-700 text-white font-semibold py-2 rounded-lg transition-colors">
                  View Full Details →
                </button>
              </div>
            </div>
          );
        })}
      </div>

      {filteredWatches.length === 0 && (
        <div className="text-center py-12">
          <p className="text-gray-500 text-lg">No watches found matching your criteria</p>
        </div>
      )}
    </div>
  );
}

export default WatchList;