Add admin order details modal and improve admin UI

Introduces an admin-only OrderDetailsModal component for viewing and managing order details, including status updates and transaction info. Updates OrdersTable to support the modal, and enhances the admin dashboard page with lazy loading and skeletons for better UX. Also fixes API client base URL handling for /api prefix.
This commit is contained in:
g
2025-12-17 23:38:17 +00:00
parent 93ec3d3642
commit 2db13cc9b7
5 changed files with 667 additions and 21 deletions

View File

@@ -7,6 +7,7 @@ import { Input } from "@/components/ui/input";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Search, Filter, Eye, ChevronLeft, ChevronRight } from "lucide-react";
import OrderDetailsModal from "./OrderDetailsModal";
interface Order {
orderId: string | number;
@@ -23,6 +24,11 @@ interface Order {
interface OrdersTableProps {
orders: Order[];
/**
* Enable order details modal (admin-only feature)
* @default true
*/
enableModal?: boolean;
}
const getStatusStyle = (status: string) => {
@@ -46,10 +52,16 @@ const getStatusStyle = (status: string) => {
}
};
export default function OrdersTable({ orders }: OrdersTableProps) {
/**
* Admin-only orders table component with order details modal
* This component should only be used in admin contexts
*/
export default function OrdersTable({ orders, enableModal = true }: OrdersTableProps) {
const [currentPage, setCurrentPage] = useState(1);
const [searchTerm, setSearchTerm] = useState("");
const [statusFilter, setStatusFilter] = useState("all");
const [selectedOrderId, setSelectedOrderId] = useState<number | string | null>(null);
const [isModalOpen, setIsModalOpen] = useState(false);
const itemsPerPage = 10;
// Filter orders based on search and status
@@ -83,6 +95,11 @@ export default function OrdersTable({ orders }: OrdersTableProps) {
setCurrentPage(1); // Reset to first page when filtering
};
const handleViewOrder = (orderId: number | string) => {
setSelectedOrderId(orderId);
setIsModalOpen(true);
};
return (
<Card>
<CardHeader>
@@ -153,9 +170,25 @@ export default function OrdersTable({ orders }: OrdersTableProps) {
<TableCell>N/A</TableCell>
<TableCell>{new Date(order.createdAt).toLocaleDateString()}</TableCell>
<TableCell className="text-right">
<Button variant="outline" size="sm">
<Eye className="h-4 w-4" />
</Button>
{enableModal ? (
<Button
variant="outline"
size="sm"
onClick={() => handleViewOrder(order.orderId)}
title="View order details (Admin only)"
>
<Eye className="h-4 w-4" />
</Button>
) : (
<Button
variant="outline"
size="sm"
disabled
title="Order details modal disabled"
>
<Eye className="h-4 w-4" />
</Button>
)}
</TableCell>
</TableRow>
))}
@@ -209,6 +242,15 @@ export default function OrdersTable({ orders }: OrdersTableProps) {
</div>
)}
</CardContent>
{/* Order Details Modal - Admin only */}
{enableModal && selectedOrderId && (
<OrderDetailsModal
orderId={selectedOrderId}
open={isModalOpen}
onOpenChange={setIsModalOpen}
/>
)}
</Card>
);
}