diff --git a/components/dashboard/BuyerOrderInfo.tsx b/components/dashboard/BuyerOrderInfo.tsx index af1c231..aa95cb4 100644 --- a/components/dashboard/BuyerOrderInfo.tsx +++ b/components/dashboard/BuyerOrderInfo.tsx @@ -10,22 +10,23 @@ import { TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip"; -import { getCookie } from "@/lib/client-utils"; -import axios from "axios"; +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: Array<{ - productId: string; - quantity: number; - pricePerUnit: number; - totalItemPrice: number; - }>; + products: OrderProduct[]; } interface BuyerOrderInfoProps { @@ -33,17 +34,26 @@ interface BuyerOrderInfoProps { 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); - const tooltipDelayRef = useRef(null); - // Fetch data without unnecessary dependencies to reduce render cycles + /** + * Fetch buyer orders from the API + */ const fetchBuyerOrders = useCallback(async (force = false) => { // Prevent multiple simultaneous fetches if (isFetchingRef.current) return; @@ -62,27 +72,12 @@ export default function BuyerOrderInfo({ buyerId, chatId }: BuyerOrderInfoProps) setLoading(true); try { - const authToken = getCookie("Authorization"); + // Use clientFetch to handle auth and API routing automatically + const response = await clientFetch(`/chats/${chatId}/orders?limit=10`); - if (!authToken) { - isFetchingRef.current = false; - setLoading(false); - return; - } - - const authAxios = axios.create({ - baseURL: process.env.NEXT_PUBLIC_API_URL, - headers: { - Authorization: `Bearer ${authToken}` - } - }); - - // Use the new endpoint that works with sub-users - const response = await authAxios.get(`/chats/${chatId}/orders?limit=10`); // Limit to fewer orders for faster response - - if (response.data && response.data.orders) { - setOrders(response.data.orders); - setHasOrders(response.data.orders.length > 0); + if (response && response.orders) { + setOrders(response.orders); + setHasOrders(response.orders.length > 0); } else { setHasOrders(false); } @@ -95,48 +90,44 @@ export default function BuyerOrderInfo({ buyerId, chatId }: BuyerOrderInfoProps) setLoading(false); isFetchingRef.current = false; } - }, [chatId]); // Minimize dependencies even further + }, [chatId, orders.length, hasOrders]); - // Start fetching immediately when component mounts + // Fetch orders 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]); + /** + * Navigate to order details page + */ const handleViewOrder = (orderId: string) => { router.push(`/dashboard/orders/${orderId}`); }; - // Handle hover with immediate tooltip opening + /** + * Handle mouse enter on the button to start loading data + */ const handleButtonMouseEnter = () => { - // Start fetching data, but don't wait for it to complete if (!isFetchingRef.current) { - queueMicrotask(() => { - fetchBuyerOrders(); - }); + queueMicrotask(() => fetchBuyerOrders()); } }; - // Handle tooltip state change + /** + * Handle tooltip state change, load data if opening + */ const handleTooltipOpenChange = (open: boolean) => { setIsTooltipOpen(open); if (open && !isFetchingRef.current) { - queueMicrotask(() => { - fetchBuyerOrders(); - }); + queueMicrotask(() => fetchBuyerOrders()); } }; - // Format the price as currency + /** + * Format price as currency + */ const formatPrice = (price: number) => { return `£${price.toFixed(2)}`; }; @@ -146,13 +137,26 @@ export default function BuyerOrderInfo({ buyerId, chatId }: BuyerOrderInfoProps) return null; } - // Precompute product count for button display (only if we have orders) + // 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 ( @@ -211,13 +215,10 @@ export default function BuyerOrderInfo({ buyerId, chatId }: BuyerOrderInfoProps) Order #{order.orderId} - + {order.status.toUpperCase()}