Update the table

This commit is contained in:
g
2025-02-07 16:52:28 +00:00
parent 2654accf80
commit 88bd061697

View File

@@ -1,30 +1,81 @@
"use client"; "use client";
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Eye } from "lucide-react"; import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import {
Eye,
Loader,
CheckCircle,
XCircle,
ChevronLeft,
ChevronRight,
} from "lucide-react";
import Link from "next/link"; import Link from "next/link";
import { fetchWithAuthClient } from "@/lib/client-utils"; // ✅ Import client-safe API helper import { fetchWithAuthClient } from "@/lib/client-utils";
import { toast } from "sonner"; import { toast } from "sonner";
// ✅ Define the Order Type // ✅ Define Order Type
interface Order { interface Order {
_id: string; _id: string;
date: string; orderId: number;
totalPrice: number;
status: string; status: string;
totalPrice: number;
escrowExpiresAt: string;
telegramUsername: string;
}
interface OrdersResponse {
orders: Order[];
page: number;
totalPages: number;
} }
export default function OrderTable() { export default function OrderTable() {
const [orders, setOrders] = useState<Order[] | null>(null); const [orders, setOrders] = useState<Order[] | null>(null);
const [loading, setLoading] = useState<boolean>(true); const [loading, setLoading] = useState<boolean>(true);
const [statusFilter, setStatusFilter] = useState<string>("all"); // ✅ Status Filter
const [currentPage, setCurrentPage] = useState<number>(1);
const [totalPages, setTotalPages] = useState<number>(1);
// ✅ Fetch Orders with Pagination & Filtering
useEffect(() => { useEffect(() => {
const fetchOrders = async () => { const fetchOrders = async () => {
try { try {
const data: Order[] = await fetchWithAuthClient("/orders"); setLoading(true);
setOrders(data); const query = new URLSearchParams({
page: currentPage.toString(),
limit: "10",
});
if (statusFilter !== "all") {
query.append("status", statusFilter);
}
const response: OrdersResponse = await fetchWithAuthClient(
`/orders?${query.toString()}`
);
if (response.orders) {
setOrders(response.orders);
setTotalPages(response.totalPages);
} else {
throw new Error("Invalid API response format");
}
} catch (error) { } catch (error) {
toast.error("Failed to fetch orders."); toast.error("Failed to fetch orders.");
console.error("Error fetching orders:", error); console.error("Error fetching orders:", error);
@@ -34,38 +85,73 @@ export default function OrderTable() {
}; };
fetchOrders(); fetchOrders();
}, []); }, [statusFilter, currentPage]);
return ( return (
<div className="rounded-lg border dark:border-zinc-700 shadow-sm overflow-hidden"> <div className="rounded-lg border dark:border-zinc-700 shadow-sm overflow-hidden">
{/* ✅ Filtering UI */}
<div className="p-4 flex justify-between items-center border-b dark:border-zinc-700">
<h2 className="text-lg font-semibold text-gray-900 dark:text-white">
Orders
</h2>
<Select value={statusFilter} onValueChange={setStatusFilter}>
<SelectTrigger className="w-32">
<SelectValue placeholder="Filter Status" />
</SelectTrigger>
<SelectContent>
<SelectItem value="all">All</SelectItem>
<SelectItem value="paid">Paid</SelectItem>
<SelectItem value="unpaid">Unpaid</SelectItem>
<SelectItem value="shipped">Shipped</SelectItem>
<SelectItem value="completed">Completed</SelectItem>
</SelectContent>
</Select>
</div>
<Table> <Table>
<TableHeader className="bg-gray-50 dark:bg-zinc-800/50"> <TableHeader className="bg-gray-50 dark:bg-zinc-800/50">
<TableRow> <TableRow>
<TableHead className="w-[150px]">Order ID</TableHead> <TableHead className="w-[150px] text-center">Order ID</TableHead>{" "}
<TableHead className="text-center">Date</TableHead> {/* Center-aligned */}
<TableHead className="text-center">Total</TableHead> <TableHead className="text-center">Total (£)</TableHead>
<TableHead className="text-center">Status</TableHead> <TableHead className="text-center">Status</TableHead>
<TableHead className="text-center">Buyer</TableHead>
<TableHead className="text-right">Action</TableHead> <TableHead className="text-right">Action</TableHead>
</TableRow> </TableRow>
</TableHeader> </TableHeader>
<TableBody> <TableBody>
{loading ? ( {loading ? (
Array.from({ length: 3 }).map((_, index) => ( <TableRow>
<TableRow key={index}> <TableCell colSpan={6} className="text-center py-4">
<TableCell>Loading...</TableCell> <Loader className="h-5 w-5 animate-spin" />
<TableCell className="text-center">Loading...</TableCell> </TableCell>
<TableCell className="text-center">Loading...</TableCell> </TableRow>
<TableCell className="text-center">Loading...</TableCell>
<TableCell className="text-right">Loading...</TableCell>
</TableRow>
))
) : orders && orders.length > 0 ? ( ) : orders && orders.length > 0 ? (
orders.map((order) => ( orders.map((order) => (
<TableRow key={order._id} className="transition-colors hover:bg-gray-50 dark:hover:bg-zinc-800/70"> <TableRow
<TableCell className="font-medium">{order._id.slice(-6)}</TableCell> key={order._id}
<TableCell className="text-center">{new Date(order.date).toLocaleDateString()}</TableCell> className="transition-colors hover:bg-gray-50 dark:hover:bg-zinc-800/70"
<TableCell className="text-center">£{order.totalPrice.toFixed(2)}</TableCell> >
<TableCell className="text-center">{order.status}</TableCell> <TableCell className="font-medium text-center">
#{order.orderId}
</TableCell>
<TableCell className="text-center">
£{order.totalPrice.toFixed(2)}
</TableCell>
<TableCell className="text-center">
{order.status === "paid" ? (
<div className="text-green-500 flex items-center justify-center">
<CheckCircle className="h-4 w-4 mr-1" /> Paid
</div>
) : (
<div className="text-red-500 flex items-center justify-center">
<XCircle className="h-4 w-4 mr-1" /> {order.status}
</div>
)}
</TableCell>
<TableCell className="text-center">
@{order.telegramUsername}
</TableCell>
<TableCell className="text-right"> <TableCell className="text-right">
<Link href={`/dashboard/orders/${order._id}`}> <Link href={`/dashboard/orders/${order._id}`}>
<Button size="sm" variant="ghost"> <Button size="sm" variant="ghost">
@@ -77,13 +163,35 @@ export default function OrderTable() {
)) ))
) : ( ) : (
<TableRow> <TableRow>
<TableCell colSpan={5} className="h-24 text-center"> <TableCell colSpan={6} className="h-24 text-center">
No orders found. No orders found.
</TableCell> </TableCell>
</TableRow> </TableRow>
)} )}
</TableBody> </TableBody>
</Table> </Table>
<div className="p-4 flex justify-between items-center border-t dark:border-zinc-700">
<Button
variant="outline"
size="sm"
disabled={currentPage === 1}
onClick={() => setCurrentPage((prev) => Math.max(prev - 1, 1))}
>
<ChevronLeft className="h-4 w-4" /> Previous
</Button>
<span className="text-sm text-gray-500 dark:text-gray-400">
Page {currentPage} of {totalPages}
</span>
<Button
variant="outline"
size="sm"
disabled={currentPage >= totalPages}
onClick={() => setCurrentPage((prev) => prev + 1)}
>
Next <ChevronRight className="h-4 w-4" />
</Button>
</div>
</div> </div>
); );
} }