"use client" import { useEffect, useState, useRef } from "react" import { useRouter } from "next/navigation" import toast from "react-hot-toast" import { ShoppingCart, Search, Filter, Calendar, Download, Loader2, AlertCircle, ShoppingBag, User, CheckCircle2, Clock, MoreHorizontal, Eye, ExternalLink, Copy, ChevronLeft, ChevronRight } from "lucide-react" interface ShopifyOrder { id: number name: string email: string created_at: string total_price: string currency: string financial_status: string fulfillment_status: string | null customer: { first_name: string last_name: string email: string } | null line_items: unknown[] } export default function OrdersPage() { const router = useRouter() const [orders, setOrders] = useState([]) const [loading, setLoading] = useState(true) const [error, setError] = useState("") const [searchTerm, setSearchTerm] = useState("") const [openMenuId, setOpenMenuId] = useState(null) const [storeDomain, setStoreDomain] = useState(null) const [statusFilter, setStatusFilter] = useState("all") const menuRefs = useRef<{ [key: number]: HTMLDivElement | null }>({}) useEffect(() => { const fetchStoreInfo = async () => { try { const res = await fetch("/api/stores") if (res.ok) { const data = await res.json() const activeStore = data.stores?.find((s: { isActive: boolean }) => s.isActive) if (activeStore?.shopifyDomain) { const cleanDomain = activeStore.shopifyDomain.replace(/^https?:\/\//, "").replace(/\/$/, "") setStoreDomain(cleanDomain) } } } catch { // Silent fail } } const fetchOrders = async () => { try { const res = await fetch("/api/shopify/orders") if (!res.ok) throw new Error("Failed to fetch orders") const data = await res.json() setOrders(data.orders || []) setError("") } catch { setError("Could not load orders. Please ensure your Shopify store is connected.") } finally { setLoading(false) } } // Fetch store info and orders fetchStoreInfo() fetchOrders() // Auto-refresh every 15 seconds to catch webhook updates const interval = setInterval(() => { fetchOrders() }, 15000) // 15 seconds return () => clearInterval(interval) }, []) // Close menu when clicking outside useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if (openMenuId !== null) { const menuElement = menuRefs.current[openMenuId] if (menuElement && !menuElement.contains(event.target as Node)) { setOpenMenuId(null) } } } if (openMenuId !== null) { document.addEventListener("mousedown", handleClickOutside) return () => document.removeEventListener("mousedown", handleClickOutside) } }, [openMenuId]) const handleMenuToggle = (orderId: number) => { setOpenMenuId(openMenuId === orderId ? null : orderId) } const handleViewDetails = (order: ShopifyOrder) => { router.push(`/dashboard/orders/${order.id}`) setOpenMenuId(null) } const handleViewInShopify = (orderId: number) => { if (storeDomain) { window.open(`https://${storeDomain}/admin/orders/${orderId}`, "_blank") } else { toast.error("Store domain not found. Please check your store configuration.") } setOpenMenuId(null) } const handleCopyOrderId = (orderId: number) => { navigator.clipboard.writeText(orderId.toString()) toast.success("Order ID copied to clipboard") setOpenMenuId(null) } const handleExport = () => { const csvHeaders = ["Order #", "Customer", "Email", "Date", "Total", "Currency", "Payment Status", "Fulfillment Status"] const csvRows = filteredOrders.map(o => [ o.name, o.customer ? `"${o.customer.first_name} ${o.customer.last_name}"` : "", o.email || "", new Date(o.created_at).toLocaleDateString(), o.total_price, o.currency, o.financial_status, o.fulfillment_status || "unfulfilled" ]) const csvContent = [ csvHeaders.join(","), ...csvRows.map(row => row.join(",")) ].join("\n") const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" }) const link = document.createElement("a") const url = URL.createObjectURL(blob) link.setAttribute("href", url) link.setAttribute("download", `orders-${new Date().toISOString().split("T")[0]}.csv`) link.style.visibility = "hidden" document.body.appendChild(link) link.click() document.body.removeChild(link) toast.success("Orders exported successfully") } const filteredOrders = orders.filter(o => { const matchesSearch = o.name.toLowerCase().includes(searchTerm.toLowerCase()) || (o.customer && `${o.customer.first_name} ${o.customer.last_name}`.toLowerCase().includes(searchTerm.toLowerCase())) const matchesStatus = statusFilter === "all" || (statusFilter === "fulfilled" && o.fulfillment_status === "fulfilled") || (statusFilter === "unfulfilled" && (!o.fulfillment_status || o.fulfillment_status !== "fulfilled")) || (statusFilter === "paid" && o.financial_status === "paid") || (statusFilter === "unpaid" && o.financial_status !== "paid") return matchesSearch && matchesStatus }) const getStatusStyles = (status: string | null) => { switch (status) { case "fulfilled": return "bg-emerald-500/20 text-emerald-400" case "partial": return "bg-yellow-500/20 text-yellow-400" default: return "bg-blue-500/20 text-blue-400" } } return (

Orders

Track and manage your Shopify orders for fulfillment.

{/* Search and Filter Controls */}
setSearchTerm(e.target.value)} className="w-full h-10 md:h-11 pl-10 md:pl-11 pr-4 bg-white/5 border border-white/10 rounded-xl focus:outline-none focus:ring-2 focus:ring-indigo-500/30 focus:border-indigo-500/50 text-white placeholder:text-slate-500 text-sm font-medium transition-all" />
{/* Orders Grid */}
{loading ? (

Fetching latest orders...

) : error ? (

{error}

) : filteredOrders.length === 0 ? (

No orders found.

) : (
{filteredOrders.map((order) => (
handleViewDetails(order)} > {/* Order Header */}

{order.name}

{new Date(order.created_at).toLocaleDateString()} • {new Date(order.created_at).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })}

e.stopPropagation()} ref={(el) => { menuRefs.current[order.id] = el }}> {openMenuId === order.id && (
)}
{/* Customer Info */} {order.customer && (

{order.customer.first_name} {order.customer.last_name}

{order.email}

)} {/* Order Details */}
Total {order.total_price} {order.currency}
{order.financial_status === "paid" && } Payment: {order.financial_status} {order.fulfillment_status === "fulfilled" ? : } {order.fulfillment_status || "Unfulfilled"}
))}
)}
) }