"use client"; import React, { useEffect, useState, useCallback } from "react"; import { getCustomers, CustomerStats } from "@/services/customerService"; import { formatCurrency } from "@/utils/format"; import { useRouter } from "next/navigation"; import { toast } from "sonner"; import Layout from "@/components/layout/layout"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; import { ChevronLeft, ChevronRight, Loader2, Users, ArrowUpDown, MessageCircle, UserPlus, MoreHorizontal, Search, X } from "lucide-react"; import { Badge } from "@/components/ui/badge"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, } from "@/components/ui/dropdown-menu"; export default function CustomerManagementPage() { const router = useRouter(); const [customers, setCustomers] = useState([]); const [filteredCustomers, setFilteredCustomers] = useState([]); const [searchQuery, setSearchQuery] = useState(""); const [loading, setLoading] = useState(true); const [page, setPage] = useState(1); const [totalPages, setTotalPages] = useState(1); const [itemsPerPage, setItemsPerPage] = useState(25); const [selectedCustomer, setSelectedCustomer] = useState(null); const [sortConfig, setSortConfig] = useState<{ column: "totalOrders" | "totalSpent" | "lastOrderDate"; direction: "asc" | "desc"; }>({ column: "totalSpent", direction: "desc" }); const fetchCustomers = useCallback(async () => { try { setLoading(true); const response = await getCustomers(page, itemsPerPage); // Sort customers based on current sort config let sortedCustomers = [...response.customers]; sortedCustomers.sort((a, b) => { if (sortConfig.column === "totalOrders") { return sortConfig.direction === "asc" ? a.totalOrders - b.totalOrders : b.totalOrders - a.totalOrders; } else if (sortConfig.column === "totalSpent") { return sortConfig.direction === "asc" ? a.totalSpent - b.totalSpent : b.totalSpent - a.totalSpent; } else if (sortConfig.column === "lastOrderDate") { // Handle null lastOrderDate values if (!a.lastOrderDate && !b.lastOrderDate) return 0; if (!a.lastOrderDate) return sortConfig.direction === "asc" ? -1 : 1; if (!b.lastOrderDate) return sortConfig.direction === "asc" ? 1 : -1; // Both have valid dates return sortConfig.direction === "asc" ? new Date(a.lastOrderDate).getTime() - new Date(b.lastOrderDate).getTime() : new Date(b.lastOrderDate).getTime() - new Date(a.lastOrderDate).getTime(); } return 0; }); setCustomers(sortedCustomers); setFilteredCustomers(sortedCustomers); setTotalPages(Math.ceil(response.total / itemsPerPage)); } catch (err) { toast.error("Failed to fetch customers"); console.error(err); } finally { setLoading(false); } }, [page, itemsPerPage, sortConfig]); useEffect(() => { fetchCustomers(); }, [fetchCustomers]); useEffect(() => { const authToken = document.cookie .split("; ") .find((row) => row.startsWith("Authorization=")) ?.split("=")[1]; if (!authToken) { router.push("/login"); } }, [router]); // Add filter function to filter customers when search query changes useEffect(() => { if (!searchQuery.trim()) { setFilteredCustomers(customers); } else { const query = searchQuery.toLowerCase().trim(); const filtered = customers.filter(customer => { const usernameMatch = customer.telegramUsername?.toLowerCase().includes(query); const userIdMatch = customer.telegramUserId.toString().includes(query); return usernameMatch || userIdMatch; }); setFilteredCustomers(filtered); } }, [searchQuery, customers]); const handlePageChange = (newPage: number) => { setPage(newPage); }; const handleItemsPerPageChange = (value: string) => { setItemsPerPage(parseInt(value, 10)); setPage(1); // Reset to first page when changing items per page }; const handleSort = (column: "totalOrders" | "totalSpent" | "lastOrderDate") => { setSortConfig(prev => ({ column, direction: prev.column === column && prev.direction === "asc" ? "desc" : "asc" })); }; const clearSearch = () => { setSearchQuery(""); }; // Format date with time const formatDate = (dateString: string | null | undefined) => { if (!dateString) return "N/A"; try { const date = new Date(dateString); return new Intl.DateTimeFormat('en-GB', { day: '2-digit', month: 'short', year: 'numeric', hour: '2-digit', minute: '2-digit' }).format(date); } catch (error) { return "N/A"; } }; return (

Customer Management

Show:
setSearchQuery(e.target.value)} className="pl-10 pr-10 py-2 w-full bg-black/40 border-zinc-700 text-white" /> {searchQuery && ( )}
{loading ? "Loading..." : searchQuery ? `Found ${filteredCustomers.length} matching customers` : `Showing ${filteredCustomers.length} of ${totalPages * itemsPerPage} customers`}
{loading ? (
) : filteredCustomers.length === 0 ? (

{searchQuery ? "No customers matching your search" : "No customers found"}

{searchQuery ? "Try a different search term or clear the search" : "Once you have customers placing orders, they will appear here."}

{searchQuery && ( )}
) : (
Customer handleSort("totalOrders")} >
Orders
handleSort("totalSpent")} >
Total Spent
handleSort("lastOrderDate")} >
Last Order
Status
{filteredCustomers.map((customer) => ( setSelectedCustomer(customer)} >
@{customer.telegramUsername || "Unknown"} {!customer.hasOrders && ( New )}
ID: {customer.telegramUserId}
{customer.totalOrders} {formatCurrency(customer.totalSpent)} {customer.lastOrderDate ? formatDate(customer.lastOrderDate) : "N/A"} {customer.hasOrders ? (
{customer.ordersByStatus.paid} Paid {customer.ordersByStatus.completed} Completed {customer.ordersByStatus.shipped} Shipped
) : ( No orders yet )}
))}
)}
Page {page} of {totalPages}
{totalPages > 2 && ( {Array.from({ length: totalPages }, (_, i) => i + 1).map((pageNum) => ( handlePageChange(pageNum)} className={`cursor-pointer ${pageNum === page ? 'bg-zinc-800 text-white' : 'text-gray-300'}`} > Page {pageNum} ))} )}
{/* Customer Details Dialog */} {selectedCustomer && ( !open && setSelectedCustomer(null)}> Customer Details
{/* Customer Information */}

Customer Information

Username:
@{selectedCustomer.telegramUsername || "Unknown"}
Telegram ID:
{selectedCustomer.telegramUserId}
Chat ID:
{selectedCustomer.chatId}
{/* Order Statistics */}

Order Statistics

Total Orders:
{selectedCustomer.totalOrders}
Total Spent:
{formatCurrency(selectedCustomer.totalSpent)}
First Order:
{formatDate(selectedCustomer.firstOrderDate)}
Last Order:
{formatDate(selectedCustomer.lastOrderDate)}
{/* Order Status Breakdown */}

Order Status Breakdown

Paid

{selectedCustomer.ordersByStatus.paid}

Acknowledged

{selectedCustomer.ordersByStatus.acknowledged}

Shipped

{selectedCustomer.ordersByStatus.shipped}

Completed

{selectedCustomer.ordersByStatus.completed}

)}
); }