128 lines
No EOL
4.2 KiB
JavaScript
128 lines
No EOL
4.2 KiB
JavaScript
import { useEffect, useState } from 'react'
|
|
import { useNavigate } from 'react-router-dom'
|
|
import { useApp } from '../context/AppContext.jsx'
|
|
import { useApi } from '../hooks/useApi.js'
|
|
|
|
export function Orders() {
|
|
const [orders, setOrders] = useState([])
|
|
const [loading, setLoading] = useState(true)
|
|
const navigate = useNavigate()
|
|
const { user } = useApp()
|
|
const { getOrders } = useApi()
|
|
|
|
useEffect(() => {
|
|
if (!user) {
|
|
navigate('/login')
|
|
return
|
|
}
|
|
fetchOrders()
|
|
}, [user, navigate])
|
|
|
|
const fetchOrders = async () => {
|
|
try {
|
|
const data = await getOrders()
|
|
setOrders(data)
|
|
} catch (error) {
|
|
console.error('Error fetching orders:', error)
|
|
} finally {
|
|
setLoading(false)
|
|
}
|
|
}
|
|
|
|
const getStatusColor = (status) => {
|
|
const colors = {
|
|
pending: 'bg-yellow-900 text-yellow-200 border-yellow-700',
|
|
processing: 'bg-blue-900 text-blue-200 border-blue-700',
|
|
shipped: 'bg-purple-900 text-purple-200 border-purple-700',
|
|
delivered: 'bg-green-900 text-green-200 border-green-700',
|
|
cancelled: 'bg-red-900 text-red-200 border-red-700',
|
|
}
|
|
return colors[status] || 'bg-gray-900 text-gray-200 border-gray-700'
|
|
}
|
|
|
|
if (loading) {
|
|
return (
|
|
<div className="text-center py-12">
|
|
<div className="text-gray-400">Loading orders...</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<div>
|
|
<h1 className="text-3xl font-bold text-white mb-8">My Orders</h1>
|
|
|
|
{orders.length === 0 ? (
|
|
<div className="text-center py-12">
|
|
<p className="text-gray-400 mb-8">You have no orders yet</p>
|
|
<button
|
|
onClick={() => navigate('/products')}
|
|
className="bg-blue-600 hover:bg-blue-700 text-white px-6 py-2 rounded-lg transition-colors"
|
|
>
|
|
Browse Products
|
|
</button>
|
|
</div>
|
|
) : (
|
|
<div className="space-y-6">
|
|
{orders.map((order) => (
|
|
<div
|
|
key={order.id}
|
|
className="bg-gray-800 rounded-lg border border-gray-700 overflow-hidden"
|
|
>
|
|
<div className="p-4 border-b border-gray-700 flex justify-between items-center">
|
|
<div>
|
|
<h3 className="text-lg font-semibold text-white">
|
|
Order #{order.id}
|
|
</h3>
|
|
<p className="text-sm text-gray-400">
|
|
{new Date(order.created_at).toLocaleDateString()}
|
|
</p>
|
|
</div>
|
|
<span
|
|
className={`px-3 py-1 rounded-full text-sm font-medium border ${getStatusColor(
|
|
order.status
|
|
)}`}
|
|
>
|
|
{order.status.charAt(0).toUpperCase() + order.status.slice(1)}
|
|
</span>
|
|
</div>
|
|
|
|
<div className="p-4">
|
|
{order.items.map((item) => (
|
|
<div
|
|
key={item.id}
|
|
className="flex justify-between items-center py-2 border-b border-gray-700 last:border-b-0"
|
|
>
|
|
<div>
|
|
<p className="text-white font-medium">Product #{item.product_id}</p>
|
|
<p className="text-sm text-gray-400">
|
|
Quantity: {item.quantity}
|
|
</p>
|
|
</div>
|
|
<p className="text-white font-bold">
|
|
${(item.price * item.quantity).toFixed(2)}
|
|
</p>
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
<div className="p-4 bg-gray-750 border-t border-gray-700 flex justify-between items-center">
|
|
<div className="text-sm text-gray-400">
|
|
{order.shipping_address && (
|
|
<span>Ship to: {order.shipping_address}</span>
|
|
)}
|
|
</div>
|
|
<div className="text-xl">
|
|
<span className="text-gray-400">Total:</span>{' '}
|
|
<span className="text-white font-bold">
|
|
${parseFloat(order.total_amount).toFixed(2)}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
)
|
|
} |