Files
ember-market-frontend/app/dashboard/admin/orders/page.tsx
g fe01f31538
Some checks failed
Build Frontend / build (push) Failing after 7s
Refactor UI imports and update component paths
Replaces imports from 'components/ui' with 'components/common' across the app and dashboard pages, and updates model and API imports to use new paths under 'lib'. Removes redundant authentication checks from several dashboard pages. Adds new dashboard components and utility files, and reorganizes hooks and services into the 'lib' directory for improved structure.
2026-01-13 05:02:13 +00:00

246 lines
11 KiB
TypeScript

import React from "react";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/common/card";
import { Package, AlertTriangle, CheckCircle2, XCircle, DollarSign } from "lucide-react";
import { fetchServer } from "@/lib/api";
import OrdersTable from "@/components/admin/OrdersTable";
import { MotionWrapper } from "@/components/common/motion-wrapper";
export const dynamic = 'force-dynamic';
interface Order {
orderId: string | number;
userId: string;
total: number;
createdAt: string;
status: string;
items: Array<{
name: string;
quantity: number;
}>;
vendorUsername?: string;
}
interface SystemStats {
vendors: number;
orders: number;
products: number;
chats: number;
}
export default async function AdminOrdersPage() {
let orders: Order[] = [];
let systemStats: SystemStats | null = null;
let error: string | null = null;
try {
const [ordersData, statsData] = await Promise.all([
fetchServer<Order[]>("/admin/recent-orders"),
fetchServer<SystemStats>("/admin/stats")
]);
orders = ordersData;
systemStats = statsData;
} catch (err) {
console.error("Failed to fetch data:", err);
error = "Failed to load data";
}
if (error) {
return (
<div className="space-y-6 p-1">
<div>
<h1 className="text-3xl font-bold tracking-tight">Recent Orders</h1>
<p className="text-muted-foreground mt-2">Monitor and manage platform orders</p>
</div>
<Card className="border-destructive/50 bg-destructive/10">
<CardContent className="pt-6">
<div className="text-center text-destructive">
<p>{error}</p>
</div>
</CardContent>
</Card>
</div>
);
}
const acknowledgedOrders = orders.filter(o => o.status === 'acknowledged');
const paidOrders = orders.filter(o => o.status === 'paid');
const completedOrders = orders.filter(o => o.status === 'completed');
const cancelledOrders = orders.filter(o => o.status === 'cancelled');
return (
<div className="space-y-8 p-1">
<div>
<h1 className="text-3xl font-bold tracking-tight bg-clip-text text-transparent bg-gradient-to-r from-foreground to-foreground/70">
Recent Orders
</h1>
<p className="text-muted-foreground mt-2 text-lg">
Monitor and manage platform transaction activity
</p>
</div>
<MotionWrapper>
<div className="space-y-8">
{/* Stats Cards */}
<div className="grid gap-4 md:grid-cols-4">
<Card className="bg-background/50 backdrop-blur-sm border-border/40 shadow-sm hover:shadow-md transition-all duration-300">
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium text-muted-foreground">Total Orders</CardTitle>
<div className="p-2 rounded-lg bg-primary/10">
<Package className="h-4 w-4 text-primary" />
</div>
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{systemStats?.orders || 0}</div>
<div className="flex items-center mt-1">
<div className="h-1.5 w-1.5 rounded-full bg-primary mr-2" />
<p className="text-xs text-muted-foreground">Lifetime volume</p>
</div>
</CardContent>
</Card>
<Card className="bg-background/50 backdrop-blur-sm border-border/40 shadow-sm hover:shadow-md transition-all duration-300">
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium text-muted-foreground">Acknowledged</CardTitle>
<div className="p-2 rounded-lg bg-purple-500/10">
<AlertTriangle className="h-4 w-4 text-purple-500" />
</div>
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{acknowledgedOrders.length}</div>
<div className="flex items-center mt-1">
<div className="h-1.5 w-1.5 rounded-full bg-purple-500 mr-2" />
<p className="text-xs text-muted-foreground">Vendor pending</p>
</div>
</CardContent>
</Card>
<Card className="bg-background/50 backdrop-blur-sm border-border/40 shadow-sm hover:shadow-md transition-all duration-300">
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium text-muted-foreground">Paid</CardTitle>
<div className="p-2 rounded-lg bg-emerald-500/10">
<DollarSign className="h-4 w-4 text-emerald-500" />
</div>
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{paidOrders.length}</div>
<div className="flex items-center mt-1">
<div className="h-1.5 w-1.5 rounded-full bg-emerald-500 mr-2" />
<p className="text-xs text-muted-foreground">Processing</p>
</div>
</CardContent>
</Card>
<Card className="bg-background/50 backdrop-blur-sm border-border/40 shadow-sm hover:shadow-md transition-all duration-300">
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium text-muted-foreground">Completed</CardTitle>
<div className="p-2 rounded-lg bg-blue-500/10">
<CheckCircle2 className="h-4 w-4 text-blue-500" />
</div>
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{completedOrders.length}</div>
<div className="flex items-center mt-1">
<div className="h-1.5 w-1.5 rounded-full bg-blue-500 mr-2" />
<p className="text-xs text-muted-foreground">Delivered</p>
</div>
</CardContent>
</Card>
</div>
{/* Orders Table with Pagination */}
<div className="bg-background/50 backdrop-blur-sm rounded-xl border border-border/40 overflow-hidden shadow-sm">
<OrdersTable orders={orders} />
</div>
{/* Order Analytics */}
<div className="grid gap-6 md:grid-cols-2">
<Card className="bg-background/50 backdrop-blur-sm border-border/40 shadow-sm">
<CardHeader>
<CardTitle>Status Distribution</CardTitle>
<CardDescription>Breakdown of active orders</CardDescription>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div className="flex items-center justify-between p-2 rounded-lg hover:bg-muted/30 transition-colors">
<div className="flex items-center space-x-3">
<div className="w-2 h-12 bg-purple-500 rounded-full"></div>
<div>
<p className="font-medium text-sm">Acknowledged</p>
<p className="text-xs text-muted-foreground">Waiting for shipment</p>
</div>
</div>
<span className="font-bold">
{orders.length > 0 ? Math.round((acknowledgedOrders.length / orders.length) * 100) : 0}%
</span>
</div>
<div className="flex items-center justify-between p-2 rounded-lg hover:bg-muted/30 transition-colors">
<div className="flex items-center space-x-3">
<div className="w-2 h-12 bg-emerald-500 rounded-full"></div>
<div>
<p className="font-medium text-sm">Paid</p>
<p className="text-xs text-muted-foreground">Payment confirmed</p>
</div>
</div>
<span className="font-bold">
{orders.length > 0 ? Math.round((paidOrders.length / orders.length) * 100) : 0}%
</span>
</div>
<div className="flex items-center justify-between p-2 rounded-lg hover:bg-muted/30 transition-colors">
<div className="flex items-center space-x-3">
<div className="w-2 h-12 bg-blue-500 rounded-full"></div>
<div>
<p className="font-medium text-sm">Completed</p>
<p className="text-xs text-muted-foreground">Successfully concluded</p>
</div>
</div>
<span className="font-bold">
{orders.length > 0 ? Math.round((completedOrders.length / orders.length) * 100) : 0}%
</span>
</div>
</div>
</CardContent>
</Card>
<Card className="bg-background/50 backdrop-blur-sm border-border/40 shadow-sm">
<CardHeader>
<CardTitle>Activity Summary</CardTitle>
<CardDescription>Recent volume breakdown</CardDescription>
</CardHeader>
<CardContent>
<div className="space-y-6">
<div className="flex items-center justify-between pb-4 border-b border-border/40">
<span className="text-sm text-muted-foreground">Total Displayed Orders</span>
<span className="text-xl font-bold">{orders.length}</span>
</div>
<div className="grid grid-cols-2 gap-4">
<div className="space-y-1">
<span className="text-xs uppercase text-muted-foreground tracking-wider">Active</span>
<p className="text-lg font-semibold">{acknowledgedOrders.length + paidOrders.length}</p>
</div>
<div className="space-y-1">
<span className="text-xs uppercase text-muted-foreground tracking-wider">Finished</span>
<p className="text-lg font-semibold">{completedOrders.length}</p>
</div>
<div className="space-y-1">
<span className="text-xs uppercase text-muted-foreground tracking-wider">Voided</span>
<p className="text-lg font-semibold text-destructive">{cancelledOrders.length}</p>
</div>
<div className="space-y-1">
<span className="text-xs uppercase text-muted-foreground tracking-wider">Success Rate</span>
<p className="text-lg font-semibold text-green-500">
{orders.length > 0 ? Math.round((completedOrders.length / (orders.length - (acknowledgedOrders.length + paidOrders.length))) * 100) || 100 : 0}%
</p>
</div>
</div>
</div>
</CardContent>
</Card>
</div>
</div>
</MotionWrapper>
</div>
);
}