"use client"; import React, { useState, useEffect, useCallback, useRef } from "react"; import { Package, ShoppingBag, Info, ExternalLink, Loader2 } from "lucide-react"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip"; import { clientFetch } from "@/lib/client-utils"; import { useRouter } from "next/navigation"; interface OrderProduct { productId: string; quantity: number; pricePerUnit: number; totalItemPrice: number; } interface Order { _id: string; orderId: number; status: string; totalPrice: number; orderDate: string; products: OrderProduct[]; } interface BuyerOrderInfoProps { buyerId: string; chatId: string; } /** * Component that displays order information for a buyer in a chat * Shows a tooltip with recent orders and allows navigation to order details */ export default function BuyerOrderInfo({ buyerId, chatId }: BuyerOrderInfoProps) { const router = useRouter(); // State const [loading, setLoading] = useState(false); const [orders, setOrders] = useState([]); const [hasOrders, setHasOrders] = useState(null); const [isTooltipOpen, setIsTooltipOpen] = useState(false); // Refs to prevent unnecessary re-renders and API calls const lastFetchedRef = useRef(0); const isFetchingRef = useRef(false); /** * Fetch buyer orders from the API */ const fetchBuyerOrders = useCallback(async (force = false) => { // Prevent multiple simultaneous fetches if (isFetchingRef.current) return; // Don't fetch if we already know there are no orders if (hasOrders === false && !force) return; // Don't fetch if we already have orders and data was fetched less than 10 seconds ago const now = Date.now(); if (!force && orders.length > 0 && now - lastFetchedRef.current < 10000) return; // Only continue if we have a chatId if (!chatId) return; isFetchingRef.current = true; setLoading(true); try { // Use clientFetch to handle auth and API routing automatically const response = await clientFetch(`/chats/${chatId}/orders?limit=10`); if (response && response.orders) { setOrders(response.orders); setHasOrders(response.orders.length > 0); } else { setHasOrders(false); } lastFetchedRef.current = Date.now(); } catch (error) { console.error("Error fetching buyer orders:", error); setHasOrders(false); } finally { setLoading(false); isFetchingRef.current = false; } }, [chatId, orders.length, hasOrders]); // Fetch orders when component mounts useEffect(() => { if (chatId) { fetchBuyerOrders(); } }, [chatId, fetchBuyerOrders]); /** * Navigate to order details page */ const handleViewOrder = (orderId: string) => { router.push(`/dashboard/orders/${orderId}`); }; /** * Handle mouse enter on the button to start loading data */ const handleButtonMouseEnter = () => { if (!isFetchingRef.current) { queueMicrotask(() => fetchBuyerOrders()); } }; /** * Handle tooltip state change, load data if opening */ const handleTooltipOpenChange = (open: boolean) => { setIsTooltipOpen(open); if (open && !isFetchingRef.current) { queueMicrotask(() => fetchBuyerOrders()); } }; /** * Format price as currency */ const formatPrice = (price: number) => { return `£${price.toFixed(2)}`; }; // If we know there are no orders, don't show the component at all if (hasOrders === false) { return null; } // Calculate total products across all orders const productCount = orders.length > 0 ? orders.reduce((total, order) => { return total + order.products.reduce((sum, product) => sum + product.quantity, 0); }, 0) : 0; /** * Get badge variant based on order status */ const getStatusBadgeVariant = (status: string) => { switch (status) { case "paid": return "paid"; case "unpaid": return "unpaid"; case "shipped": return "shipped"; case "completed": return "completed"; default: return "secondary"; } }; return (
Recent Orders from this Customer
{loading ? ( // Show loading state
Loading orders...
) : orders.length === 0 ? ( // Show no orders state
No orders found for this customer
) : ( // Show orders
{orders.map((order) => (
handleViewOrder(order._id)} >
Order #{order.orderId}
{order.status.toUpperCase()}
{order.products.length} {order.products.length === 1 ? 'product' : 'products'} · {formatPrice(order.totalPrice)}
{new Date(order.orderDate).toLocaleDateString()}
))}
)}
); }