OrderDetail.jsx 7.88 KB
import React, { useState, useEffect } from 'react'
import { useParams, Link } from 'react-router-dom'
import { orderService } from '../services/api/orderService'
import LoadingSpinner from '../components/common/LoadingSpinner'
import { formatDate, formatPrice, formatDateTime } from '../utils/formatters'

const OrderDetail = () => {
  const { id } = useParams()
  const [order, setOrder] = useState(null)
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState(null)
  const [cancelling, setCancelling] = useState(false)

  useEffect(() => {
    loadOrder()
  }, [id])

  const loadOrder = async () => {
    try {
      setLoading(true)
      const orderData = await orderService.getOrder(id)
      setOrder(orderData)
    } catch (err) {
      setError('Order not found')
      console.error('Order detail error:', err)
    } finally {
      setLoading(false)
    }
  }

  const handleCancelOrder = async () => {
    if (!window.confirm('Are you sure you want to cancel this order?')) {
      return
    }

    setCancelling(true)
    try {
      await orderService.cancelOrder(id)
      setOrder(prev => ({ ...prev, status: 'cancelled' }))
      alert('Order cancelled successfully')
    } catch (err) {
      alert('Failed to cancel order')
    } finally {
      setCancelling(false)
    }
  }

  const getStatusInfo = (status) => {
    const statusInfo = {
      pending: {
        color: 'status-pending',
        description: 'Your order is being processed',
        steps: ['Order Placed', 'Processing', 'Shipping', 'Delivery']
      },
      confirmed: {
        color: 'status-confirmed',
        description: 'Your order has been confirmed',
        steps: ['Order Placed', 'Processing ✓', 'Shipping', 'Delivery']
      },
      shipped: {
        color: 'status-shipped',
        description: 'Your order has been shipped',
        steps: ['Order Placed', 'Processing ✓', 'Shipping ✓', 'Delivery']
      },
      delivered: {
        color: 'status-delivered',
        description: 'Your order has been delivered',
        steps: ['Order Placed', 'Processing ✓', 'Shipping ✓', 'Delivery ✓']
      },
      cancelled: {
        color: 'status-cancelled',
        description: 'Your order has been cancelled',
        steps: ['Order Cancelled']
      }
    }
    return statusInfo[status] || statusInfo.pending
  }

  if (loading) {
    return <LoadingSpinner />
  }

  if (error || !order) {
    return (
      <div className="order-detail">
        <div className="container">
          <div className="error-state">
            <h2>Order Not Found</h2>
            <p>{error || 'The order you are looking for does not exist.'}</p>
            <Link to="/orders" className="back-button">
              Back to Orders
            </Link>
          </div>
        </div>
      </div>
    )
  }

  const statusInfo = getStatusInfo(order.status)

  return (
    <div className="order-detail">
      <div className="container">
        <div className="order-header">
          <div className="breadcrumb">
            <Link to="/orders">Orders</Link> / <span>Order #{order.orderNumber}</span>
          </div>
          
          <div className="header-main">
            <div className="order-title">
              <h1>Order #{order.orderNumber}</h1>
              <p>Placed on {formatDate(order.createdAt)}</p>
            </div>
            
            <div className="order-status-main">
              <span className={`status-badge ${statusInfo.color}`}>
                {order.status.charAt(0).toUpperCase() + order.status.slice(1)}
              </span>
              <p>{statusInfo.description}</p>
            </div>
          </div>
        </div>

        <div className="order-content">
          <div className="order-main">
            {/* Order Progress */}
            <div className="order-progress">
              <h3>Order Progress</h3>
              <div className="progress-steps">
                {statusInfo.steps.map((step, index) => (
                  <div key={index} className="progress-step">
                    <div className="step-indicator"></div>
                    <span className="step-label">{step}</span>
                  </div>
                ))}
              </div>
            </div>

            {/* Order Items */}
            <div className="order-items-section">
              <h3>Order Items ({order.items.length})</h3>
              <div className="order-items">
                {order.items.map(item => (
                  <div key={item._id} className="order-item">
                    <div className="item-image">
                      <img 
                        src={item.product.image} 
                        alt={item.product.name}
                        onError={(e) => {
                          e.target.src = '/placeholder-image.jpg'
                        }}
                      />
                    </div>
                    <div className="item-details">
                      <h4>{item.product.name}</h4>
                      <p className="item-category">{item.product.category}</p>
                      <p className="item-quantity">Quantity: {item.quantity}</p>
                      <p className="item-price">Price: {formatPrice(item.price)}</p>
                    </div>
                    <div className="item-total">
                      {formatPrice(item.price * item.quantity)}
                    </div>
                  </div>
                ))}
              </div>
            </div>

            {/* Order Actions */}
            {order.status === 'pending' && (
              <div className="order-actions-section">
                <h3>Order Actions</h3>
                <button 
                  onClick={handleCancelOrder}
                  disabled={cancelling}
                  className="cancel-order-btn"
                >
                  {cancelling ? 'Cancelling...' : 'Cancel Order'}
                </button>
              </div>
            )}
          </div>

          <div className="order-sidebar">
            {/* Shipping Information */}
            <div className="info-card">
              <h3>Shipping Information</h3>
              <div className="info-content">
                <p><strong>{order.shippingAddress.firstName} {order.shippingAddress.lastName}</strong></p>
                <p>{order.shippingAddress.address}</p>
                <p>
                  {order.shippingAddress.city}, {order.shippingAddress.state} {order.shippingAddress.zipCode}
                </p>
                <p>{order.shippingAddress.country}</p>
                <p>Phone: {order.shippingAddress.phone}</p>
              </div>
            </div>

            {/* Payment Information */}
            <div className="info-card">
              <h3>Payment Information</h3>
              <div className="info-content">
                <p><strong>Payment Method</strong></p>
                <p>Credit Card ending in {order.paymentMethod.last4}</p>
                <p>Total: {formatPrice(order.total)}</p>
              </div>
            </div>

            {/* Order Summary */}
            <div className="info-card">
              <h3>Order Summary</h3>
              <div className="order-summary">
                <div className="summary-row">
                  <span>Subtotal:</span>
                  <span>{formatPrice(order.subtotal)}</span>
                </div>
                <div className="summary-row">
                  <span>Shipping:</span>
                  <span>{formatPrice(order.shipping)}</span>
                </div>
                <div className="summary-row">
                  <span>Tax:</span>
                  <span>{formatPrice(order.tax)}</span>
                </div>
                <div className="summary-row total">
                  <strong>Total:</strong>
                  <strong>{formatPrice(order.total)}</strong>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  )
}

export default OrderDetail