← back to Handbag Auth Nextjs

src/components/PriceAlertPanel.tsx

192 lines

'use client'

import { useState, useEffect } from 'react'

interface PriceAlertPanelProps {
  listingId: number
  externalId: string
  currentPrice: number
  brand?: string
  model?: string
}

export function PriceAlertPanel({ listingId, externalId, currentPrice, brand, model }: PriceAlertPanelProps) {
  const [alerts, setAlerts] = useState<any[]>([])
  const [showForm, setShowForm] = useState(false)
  const [targetPrice, setTargetPrice] = useState('')
  const [alertType, setAlertType] = useState<'below' | 'above' | 'change'>('below')
  const [userEmail, setUserEmail] = useState('')
  const [creating, setCreating] = useState(false)

  useEffect(() => {
    fetchAlerts()
  }, [listingId, externalId])

  const fetchAlerts = async () => {
    try {
      const res = await fetch(`/api/price-alerts?listingId=${listingId}&externalId=${externalId}`)
      const data = await res.json()
      if (data.success) {
        setAlerts(data.alerts.filter((a: any) => a.isActive))
      }
    } catch (error) {
      console.error('Failed to fetch alerts:', error)
    }
  }

  const createAlert = async () => {
    if (!targetPrice) return

    setCreating(true)
    try {
      const res = await fetch('/api/price-alerts', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          listingId,
          externalId,
          userEmail: userEmail || null,
          targetPrice: parseFloat(targetPrice),
          alertType,
        }),
      })

      const data = await res.json()
      if (data.success) {
        setAlerts([...alerts, data.alert])
        setTargetPrice('')
        setUserEmail('')
        setShowForm(false)
      }
    } catch (error) {
      console.error('Failed to create alert:', error)
    } finally {
      setCreating(false)
    }
  }

  const deleteAlert = async (alertId: number) => {
    try {
      const res = await fetch(`/api/price-alerts?id=${alertId}`, {
        method: 'DELETE',
      })

      const data = await res.json()
      if (data.success) {
        setAlerts(alerts.filter(a => a.id !== alertId))
      }
    } catch (error) {
      console.error('Failed to delete alert:', error)
    }
  }

  return (
    <div className="bg-white rounded-xl shadow-lg p-6 mb-8">
      <div className="flex items-center justify-between mb-4">
        <div>
          <h3 className="text-xl font-bold text-gray-900">Price Alerts</h3>
          <p className="text-sm text-gray-600">Get notified when prices change</p>
        </div>
        <button
          onClick={() => setShowForm(!showForm)}
          className="px-4 py-2 bg-gradient-to-r from-purple-600 to-blue-500 text-white rounded-lg font-medium hover:shadow-lg transition-all text-sm"
        >
          {showForm ? 'Cancel' : '+ New Alert'}
        </button>
      </div>

      {/* Create Alert Form */}
      {showForm && (
        <div className="bg-gradient-to-br from-purple-50 to-blue-50 rounded-lg p-4 mb-4">
          <div className="grid md:grid-cols-3 gap-3">
            <div>
              <label className="text-xs font-medium text-gray-700 mb-1 block">Alert When Price</label>
              <select
                value={alertType}
                onChange={(e) => setAlertType(e.target.value as any)}
                className="w-full px-3 py-2 bg-white border border-gray-300 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-purple-500"
              >
                <option value="below">Drops Below</option>
                <option value="above">Rises Above</option>
                <option value="change">Changes By 10%</option>
              </select>
            </div>

            <div>
              <label className="text-xs font-medium text-gray-700 mb-1 block">Target Price (USD)</label>
              <input
                type="number"
                placeholder={`e.g. ${Math.round(currentPrice * 0.9)}`}
                value={targetPrice}
                onChange={(e) => setTargetPrice(e.target.value)}
                className="w-full px-3 py-2 bg-white border border-gray-300 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-purple-500"
                style={{ fontSize: '16px' }}
              />
            </div>

            <div>
              <label className="text-xs font-medium text-gray-700 mb-1 block">Email (Optional)</label>
              <input
                type="email"
                placeholder="you@example.com"
                value={userEmail}
                onChange={(e) => setUserEmail(e.target.value)}
                className="w-full px-3 py-2 bg-white border border-gray-300 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-purple-500"
                style={{ fontSize: '16px' }}
              />
            </div>
          </div>

          <button
            onClick={createAlert}
            disabled={creating || !targetPrice}
            className="mt-3 px-4 py-2 bg-purple-600 text-white rounded-lg font-medium hover:bg-purple-700 transition-colors text-sm disabled:opacity-50"
          >
            {creating ? 'Creating...' : 'Create Alert'}
          </button>
        </div>
      )}

      {/* Active Alerts */}
      {alerts.length > 0 ? (
        <div className="space-y-2">
          {alerts.map((alert) => (
            <div
              key={alert.id}
              className="flex items-center justify-between p-3 bg-gray-50 rounded-lg border border-gray-200"
            >
              <div className="flex items-center space-x-3">
                <div className={`w-2 h-2 rounded-full ${alert.notified ? 'bg-green-500' : 'bg-yellow-500'}`} />
                <div>
                  <p className="text-sm font-medium text-gray-900">
                    {alert.alertType === 'below' && `Alert when price drops below $${alert.targetPrice.toLocaleString()}`}
                    {alert.alertType === 'above' && `Alert when price rises above $${alert.targetPrice.toLocaleString()}`}
                    {alert.alertType === 'change' && `Alert when price changes by 10%`}
                  </p>
                  {alert.userEmail && (
                    <p className="text-xs text-gray-500">Email: {alert.userEmail}</p>
                  )}
                </div>
              </div>
              <button
                onClick={() => deleteAlert(alert.id)}
                className="text-red-600 hover:text-red-700 text-sm font-medium"
              >
                Delete
              </button>
            </div>
          ))}
        </div>
      ) : (
        <div className="text-center py-8 text-gray-500">
          <svg className="mx-auto h-12 w-12 text-gray-400 mb-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
            <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9" />
          </svg>
          <p className="text-sm">No active alerts yet</p>
          <p className="text-xs text-gray-400 mt-1">Create an alert to track price changes</p>
        </div>
      )}
    </div>
  )
}