← back to Watches

src/components/MarketPrice.jsx

86 lines

import React from 'react';
import { motion } from 'framer-motion';

/**
 * Format price with currency symbol and thousands separator
 */
function formatPrice(price, currency = 'USD') {
  if (price === null || price === undefined) return null;

  return new Intl.NumberFormat('en-US', {
    style: 'currency',
    currency,
    minimumFractionDigits: 0,
    maximumFractionDigits: 0
  }).format(price);
}

/**
 * MarketPrice - Displays current market price range
 * @param {Object} priceData - { low, high, currency, source }
 * @param {boolean} compact - Compact mode for cards
 * @param {string} className - Additional CSS classes
 */
export default function MarketPrice({ priceData, compact = false, className = '' }) {
  // Handle missing data
  if (!priceData || (priceData.low === undefined && priceData.high === undefined)) {
    return (
      <div className={`text-gray-500 ${className}`}>
        <span className="text-sm">Price unavailable</span>
      </div>
    );
  }

  const { low, high, currency = 'USD', source } = priceData;
  const lowFormatted = formatPrice(low, currency);
  const highFormatted = formatPrice(high, currency);

  // Single price or range
  const priceDisplay = low === high || !high
    ? lowFormatted
    : `${lowFormatted} - ${highFormatted}`;

  if (compact) {
    return (
      <motion.div
        className={`${className}`}
        initial={{ opacity: 0 }}
        animate={{ opacity: 1 }}
        transition={{ duration: 0.3 }}
      >
        <span className="text-amber-400 font-semibold text-sm">
          {priceDisplay}
        </span>
      </motion.div>
    );
  }

  return (
    <motion.div
      className={`${className}`}
      initial={{ opacity: 0, y: 10 }}
      animate={{ opacity: 1, y: 0 }}
      transition={{ duration: 0.4 }}
    >
      <div className="flex flex-col gap-1">
        <div className="flex items-baseline gap-2">
          <span className="text-gray-400 text-sm">Market Price:</span>
          <motion.span
            className="text-amber-400 font-bold text-lg"
            initial={{ scale: 0.9 }}
            animate={{ scale: 1 }}
            transition={{ type: 'spring', stiffness: 300, damping: 20 }}
          >
            {priceDisplay}
          </motion.span>
        </div>
        {source && (
          <span className="text-gray-500 text-xs">
            via {source}
          </span>
        )}
      </div>
    </motion.div>
  );
}