"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 { getCookie } from "@/lib/client-utils"; import { clientFetch } from "@/lib/client-utils"; import { useRouter } from "next/navigation"; interface Order { _id: string; orderId: number; status: string; totalPrice: number; orderDate: string; products: Array<{ productId: string; quantity: number; pricePerUnit: number; totalItemPrice: number; }>; } interface BuyerOrderInfoProps { buyerId: string; chatId: string; } export default function BuyerOrderInfo({ buyerId, chatId }: BuyerOrderInfoProps) { const router = useRouter(); const [loading, setLoading] = useState(false); const [orders, setOrders] = useState([]); const [hasOrders, setHasOrders] = useState(null); const [isTooltipOpen, setIsTooltipOpen] = useState(false); const lastFetchedRef = useRef(0); const isFetchingRef = useRef(false); const tooltipDelayRef = useRef(null); // Fetch data without unnecessary dependencies to reduce render cycles 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 instead of direct axios calls // This ensures the request goes through Next.js API rewrites 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]); // Minimize dependencies even further // Start fetching immediately when component mounts useEffect(() => { if (chatId) { // Immediately attempt to fetch in the background fetchBuyerOrders(); } return () => { // Clean up any pending timeouts if (tooltipDelayRef.current) { clearTimeout(tooltipDelayRef.current); } }; }, [chatId, fetchBuyerOrders]); const handleViewOrder = (orderId: string) => { router.push(`/dashboard/orders/${orderId}`); }; // Handle hover with immediate tooltip opening const handleButtonMouseEnter = () => { // Start fetching data, but don't wait for it to complete if (!isFetchingRef.current) { queueMicrotask(() => { fetchBuyerOrders(); }); } }; // Handle tooltip state change const handleTooltipOpenChange = (open: boolean) => { setIsTooltipOpen(open); if (open && !isFetchingRef.current) { queueMicrotask(() => { fetchBuyerOrders(); }); } }; // Format the 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; } // Precompute product count for button display (only if we have orders) const productCount = orders.length > 0 ? orders.reduce((total, order) => { return total + order.products.reduce((sum, product) => sum + product.quantity, 0); }, 0) : 0; 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()}
))}
)}
); }