← back to Handbag Auth Nextjs

src/app/price-tracker/page.tsx

204 lines

'use client'

import { useState } from 'react'
import Link from 'next/link'
import { PriceHistoryChart } from '@/components/PriceHistoryChart'
import { PriceAlertPanel } from '@/components/PriceAlertPanel'

export default function PriceTrackerPage() {
  const [searchQuery, setSearchQuery] = useState('')
  const [selectedItem, setSelectedItem] = useState<any>(null)
  const [searchResults, setSearchResults] = useState<any[]>([])
  const [searching, setSearching] = useState(false)

  const handleSearch = async () => {
    if (!searchQuery) return

    setSearching(true)
    try {
      const res = await fetch(`/api/listings?search=${encodeURIComponent(searchQuery)}&limit=10`)
      const data = await res.json()

      if (data.success) {
        setSearchResults(data.listings)
      }
    } catch (error) {
      console.error('Search failed:', error)
    } finally {
      setSearching(false)
    }
  }

  return (
    <div className="min-h-screen bg-gray-50">
      {/* Header */}
      <header className="bg-white shadow-sm sticky top-0 z-50">
        <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
          <div className="flex justify-between items-center py-4">
            <div className="flex items-center space-x-8">
              <Link href="/" className="flex items-center space-x-2">
                <div className="w-10 h-10 bg-gradient-to-br from-purple-600 to-blue-500 rounded-lg flex items-center justify-center">
                  <span className="text-white font-bold text-xl">HB</span>
                </div>
                <span className="text-xl font-bold text-gray-900">Handbag Auth</span>
              </Link>

              <nav className="hidden md:flex space-x-6">
                <Link href="/" className="text-gray-700 hover:text-gray-900 font-medium">
                  Deals
                </Link>
                <Link href="/camera" className="text-gray-700 hover:text-gray-900 font-medium">
                  Camera
                </Link>
                <Link href="/price-tracker" className="text-purple-600 font-medium">
                  Price Tracker
                </Link>
              </nav>
            </div>

            <Link
              href="/camera"
              className="bg-gradient-to-r from-purple-600 to-blue-500 text-white px-6 py-2 rounded-lg font-medium hover:shadow-lg transition-all"
            >
              Scan Handbag
            </Link>
          </div>
        </div>
      </header>

      {/* Main Content */}
      <main className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
        {/* Hero Section */}
        <div className="text-center mb-12">
          <h1 className="text-4xl md:text-5xl font-bold text-gray-900 mb-4">
            Price Tracker
          </h1>
          <p className="text-lg text-gray-600 max-w-2xl mx-auto">
            Track historical prices of luxury handbags across Japanese marketplaces.
            View price trends, identify deals, and make informed purchasing decisions.
          </p>
        </div>

        {/* Search Section */}
        <div className="bg-white rounded-xl shadow-lg p-6 mb-8">
          <div className="flex gap-4">
            <input
              type="text"
              placeholder="Search by brand, model, or item ID..."
              className="flex-1 px-4 py-3 bg-gray-50 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent text-base"
              style={{ fontSize: '16px' }}
              value={searchQuery}
              onChange={(e) => setSearchQuery(e.target.value)}
              onKeyDown={(e) => e.key === 'Enter' && handleSearch()}
            />
            <button
              onClick={handleSearch}
              disabled={searching}
              className="px-8 py-3 bg-gradient-to-r from-purple-600 to-blue-500 text-white rounded-lg font-medium hover:shadow-lg transition-all disabled:opacity-50"
            >
              {searching ? 'Searching...' : 'Search'}
            </button>
          </div>

          {/* Search Results */}
          {searchResults.length > 0 && (
            <div className="mt-6 space-y-2">
              <p className="text-sm text-gray-600 mb-3">Select an item to view price history:</p>
              {searchResults.map((item) => (
                <button
                  key={item.id}
                  onClick={() => setSelectedItem(item)}
                  className={`w-full text-left p-4 rounded-lg border-2 transition-all ${
                    selectedItem?.id === item.id
                      ? 'border-purple-600 bg-purple-50'
                      : 'border-gray-200 hover:border-purple-300 bg-white'
                  }`}
                >
                  <div className="flex items-center justify-between">
                    <div>
                      <p className="font-semibold text-gray-900">{item.brand} {item.model}</p>
                      <p className="text-sm text-gray-600 line-clamp-1">{item.title}</p>
                    </div>
                    <div className="text-right">
                      <p className="text-lg font-bold text-gray-900">${item.priceUsd?.toLocaleString()}</p>
                      <p className="text-sm text-gray-500">{item.source}</p>
                    </div>
                  </div>
                </button>
              ))}
            </div>
          )}
        </div>

        {/* Price History Chart */}
        {selectedItem ? (
          <>
            <PriceAlertPanel
              listingId={selectedItem.id}
              externalId={selectedItem.externalId}
              currentPrice={selectedItem.priceUsd}
              brand={selectedItem.brand}
              model={selectedItem.model}
            />
            <PriceHistoryChart
              externalId={selectedItem.externalId}
              listingId={selectedItem.id}
              brand={selectedItem.brand}
              model={selectedItem.model}
            />
          </>
        ) : (
          <div className="bg-white rounded-xl shadow-lg p-12 text-center">
            <svg className="mx-auto h-16 w-16 text-gray-400 mb-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
              <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
            </svg>
            <h3 className="text-xl font-semibold text-gray-900 mb-2">Search for an item to get started</h3>
            <p className="text-gray-600">
              Enter a brand name, model, or specific item to track its price history
            </p>
          </div>
        )}

        {/* Info Section */}
        <div className="mt-12 grid md:grid-cols-3 gap-6">
          <div className="bg-gradient-to-br from-purple-50 to-purple-100 rounded-xl p-6">
            <div className="w-12 h-12 bg-purple-600 rounded-lg flex items-center justify-center mb-4">
              <svg className="w-6 h-6 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6" />
              </svg>
            </div>
            <h3 className="text-lg font-bold text-gray-900 mb-2">Real-Time Tracking</h3>
            <p className="text-sm text-gray-600">
              Prices are tracked daily from multiple Japanese marketplaces to give you accurate trend data.
            </p>
          </div>

          <div className="bg-gradient-to-br from-blue-50 to-blue-100 rounded-xl p-6">
            <div className="w-12 h-12 bg-blue-600 rounded-lg flex items-center justify-center mb-4">
              <svg className="w-6 h-6 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
              </svg>
            </div>
            <h3 className="text-lg font-bold text-gray-900 mb-2">Price Insights</h3>
            <p className="text-sm text-gray-600">
              View lowest, highest, and average prices to identify the best deals and purchasing opportunities.
            </p>
          </div>

          <div className="bg-gradient-to-br from-green-50 to-green-100 rounded-xl p-6">
            <div className="w-12 h-12 bg-green-600 rounded-lg flex items-center justify-center mb-4">
              <svg className="w-6 h-6 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
              </svg>
            </div>
            <h3 className="text-lg font-bold text-gray-900 mb-2">Historical Data</h3>
            <p className="text-sm text-gray-600">
              Access complete price history to understand seasonal trends and make data-driven decisions.
            </p>
          </div>
        </div>
      </main>
    </div>
  )
}