Add returning customers stat to admin users page
Introduces a new 'Returning Customers' card to the admin users dashboard, showing the count and percentage of users with more than one order. Also updates the grid layout to accommodate the new card and imports the necessary icon.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -44,3 +44,4 @@ public/git-info.json
|
||||
*/git-info.json
|
||||
public/git-info.json
|
||||
public/git-info.json
|
||||
public/git-info.json
|
||||
|
||||
@@ -7,7 +7,7 @@ import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
|
||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
|
||||
import { Search, Ban, UserCheck, Package, DollarSign, Loader2 } from "lucide-react";
|
||||
import { Search, Ban, UserCheck, Package, DollarSign, Loader2, Repeat } from "lucide-react";
|
||||
import { fetchClient } from "@/lib/api-client";
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
|
||||
@@ -69,6 +69,7 @@ export default function AdminUsersPage() {
|
||||
});
|
||||
|
||||
const usersWithOrders = users.filter(u => u.totalOrders > 0);
|
||||
const returningCustomers = users.filter(u => u.totalOrders > 1);
|
||||
const blockedUsers = users.filter(u => u.isBlocked);
|
||||
const totalSpent = users.reduce((sum, u) => sum + u.totalSpent, 0);
|
||||
const totalOrders = users.reduce((sum, u) => sum + u.totalOrders, 0);
|
||||
@@ -81,7 +82,7 @@ export default function AdminUsersPage() {
|
||||
</div>
|
||||
|
||||
{/* Stats Cards */}
|
||||
<div className="grid gap-4 md:grid-cols-4">
|
||||
<div className="grid gap-4 md:grid-cols-5">
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Total Users</CardTitle>
|
||||
@@ -135,6 +136,26 @@ export default function AdminUsersPage() {
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Returning Customers</CardTitle>
|
||||
<Repeat className="h-4 w-4 text-muted-foreground" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{loading ? (
|
||||
<div className="flex items-center justify-center py-4">
|
||||
<Loader2 className="h-6 w-6 animate-spin text-muted-foreground" />
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<div className="text-2xl font-bold">{returningCustomers.length}</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{usersWithOrders.length > 0 ? Math.round((returningCustomers.length / usersWithOrders.length) * 100) : 0}% of customers
|
||||
</p>
|
||||
</>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Blocked Users</CardTitle>
|
||||
|
||||
@@ -12,7 +12,6 @@ import { fetchClient } from "@/lib/api-client";
|
||||
import { BarChart as RechartsBarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, LineChart, Line, ComposedChart } from 'recharts';
|
||||
import { formatGBP } from "@/utils/format";
|
||||
|
||||
// API response data structure
|
||||
interface AnalyticsData {
|
||||
vendors?: {
|
||||
total?: number;
|
||||
|
||||
Reference in New Issue
Block a user