admin dashboard
This commit is contained in:
parent
c913b09edf
commit
58244d6afa
1 changed files with 90 additions and 54 deletions
|
|
@ -1,12 +1,12 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import {
|
||||
Box,
|
||||
Typography,
|
||||
Grid,
|
||||
Paper,
|
||||
Card,
|
||||
CardContent,
|
||||
CardHeader,
|
||||
Box,
|
||||
Typography,
|
||||
Grid,
|
||||
Paper,
|
||||
Card,
|
||||
CardContent,
|
||||
CardHeader,
|
||||
List,
|
||||
ListItem,
|
||||
ListItemText,
|
||||
|
|
@ -22,21 +22,17 @@ import {
|
|||
AttachMoney as MoneyIcon,
|
||||
Class as CategoryIcon
|
||||
} from '@mui/icons-material';
|
||||
import { Link as RouterLink } from 'react-router-dom';
|
||||
import { Link as RouterLink, useNavigate } from 'react-router-dom';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import apiClient from '../../services/api';
|
||||
import { useAdminCategories } from '../../hooks/categoryAdminHooks';
|
||||
import { useAdminOrders, useAdminUsers } from '../../hooks/adminHooks';
|
||||
import { format } from 'date-fns';
|
||||
|
||||
const AdminDashboardPage = () => {
|
||||
const [stats, setStats] = useState({
|
||||
totalProducts: 0,
|
||||
totalUsers: 0,
|
||||
totalOrders: 0,
|
||||
revenue: 0,
|
||||
totalCategories: 0
|
||||
});
|
||||
|
||||
// Fetch products for the stats
|
||||
const navigate = useNavigate();
|
||||
|
||||
// Fetch data with React Query
|
||||
const { data: products, isLoading: productsLoading, error: productsError } = useQuery({
|
||||
queryKey: ['admin-products'],
|
||||
queryFn: async () => {
|
||||
|
|
@ -49,38 +45,68 @@ const AdminDashboardPage = () => {
|
|||
},
|
||||
});
|
||||
|
||||
// Fetch categories
|
||||
const { data: categories, isLoading: categoriesLoading } = useAdminCategories();
|
||||
const { data: orders, isLoading: ordersLoading } = useAdminOrders();
|
||||
const { data: users, isLoading: usersLoading } = useAdminUsers();
|
||||
|
||||
const recentOrders = [
|
||||
{ id: '4532', customer: 'John Doe', date: '2023-04-22', total: 49.99, status: 'Delivered' },
|
||||
{ id: '4531', customer: 'Jane Smith', date: '2023-04-21', total: 89.95, status: 'Processing' },
|
||||
{ id: '4530', customer: 'Bob Johnson', date: '2023-04-20', total: 24.99, status: 'Shipped' },
|
||||
{ id: '4529', customer: 'Alice Brown', date: '2023-04-19', total: 129.99, status: 'Delivered' }
|
||||
];
|
||||
// Calculate total revenue from orders
|
||||
const calculateTotalRevenue = () => {
|
||||
if (!orders || orders.length === 0) return 0;
|
||||
return orders.reduce((sum, order) => {
|
||||
// Only count orders that are completed/paid
|
||||
if (order.payment_completed) {
|
||||
return sum + parseFloat(order.total_amount || 0);
|
||||
}
|
||||
return sum;
|
||||
}, 0);
|
||||
};
|
||||
|
||||
// Update stats when products and categories are loaded
|
||||
// Get recent orders (last 4)
|
||||
const getRecentOrders = () => {
|
||||
if (!orders || orders.length === 0) return [];
|
||||
|
||||
// Sort orders by created_at date (newest first) and take the first 4
|
||||
return orders
|
||||
.sort((a, b) => new Date(b.created_at) - new Date(a.created_at))
|
||||
.slice(0, 4);
|
||||
};
|
||||
|
||||
// Format date
|
||||
const formatDate = (dateString) => {
|
||||
if (!dateString) return '';
|
||||
try {
|
||||
return format(new Date(dateString), 'yyyy-MM-dd');
|
||||
} catch (error) {
|
||||
return dateString;
|
||||
}
|
||||
};
|
||||
|
||||
// Stats state
|
||||
const [stats, setStats] = useState({
|
||||
totalProducts: 0,
|
||||
totalUsers: 0,
|
||||
totalOrders: 0,
|
||||
revenue: 0,
|
||||
totalCategories: 0
|
||||
});
|
||||
|
||||
// Update stats when data is loaded
|
||||
useEffect(() => {
|
||||
if (products) {
|
||||
setStats(prev => ({
|
||||
...prev,
|
||||
totalProducts: products.length,
|
||||
totalUsers: 15,
|
||||
totalOrders: 42,
|
||||
revenue: 2459.99
|
||||
}));
|
||||
}
|
||||
const newStats = {
|
||||
totalProducts: products?.length || 0,
|
||||
totalUsers: users?.length || 0,
|
||||
totalOrders: orders?.length || 0,
|
||||
revenue: calculateTotalRevenue(),
|
||||
totalCategories: categories?.length || 0
|
||||
};
|
||||
setStats(newStats);
|
||||
}, [products, categories, orders, users]);
|
||||
|
||||
if (categories) {
|
||||
setStats(prev => ({
|
||||
...prev,
|
||||
totalCategories: categories.length
|
||||
}));
|
||||
}
|
||||
}, [products, categories]);
|
||||
// Recent orders
|
||||
const recentOrders = getRecentOrders();
|
||||
|
||||
// Placeholder for when we add actual API calls
|
||||
const isLoading = productsLoading || categoriesLoading;
|
||||
const isLoading = productsLoading || categoriesLoading || ordersLoading || usersLoading;
|
||||
const error = productsError;
|
||||
|
||||
if (isLoading) {
|
||||
|
|
@ -200,17 +226,23 @@ const AdminDashboardPage = () => {
|
|||
/>
|
||||
<CardContent sx={{ pt: 0 }}>
|
||||
<List>
|
||||
{recentOrders.map((order, index) => (
|
||||
<React.Fragment key={order.id}>
|
||||
<ListItem>
|
||||
<ListItemText
|
||||
primary={`Order #${order.id} - ${order.customer}`}
|
||||
secondary={`Date: ${order.date} | Total: $${order.total} | Status: ${order.status}`}
|
||||
/>
|
||||
</ListItem>
|
||||
{index < recentOrders.length - 1 && <Divider />}
|
||||
</React.Fragment>
|
||||
))}
|
||||
{recentOrders.length > 0 ? (
|
||||
recentOrders.map((order, index) => (
|
||||
<React.Fragment key={order.id}>
|
||||
<ListItem>
|
||||
<ListItemText
|
||||
primary={`Order #${order.id.substring(0, 8)} - ${order.first_name} ${order.last_name}`}
|
||||
secondary={`Date: ${formatDate(order.created_at)} | Total: $${parseFloat(order.total_amount).toFixed(2)} | Status: ${order.status}`}
|
||||
/>
|
||||
</ListItem>
|
||||
{index < recentOrders.length - 1 && <Divider />}
|
||||
</React.Fragment>
|
||||
))
|
||||
) : (
|
||||
<ListItem>
|
||||
<ListItemText primary="No orders found" />
|
||||
</ListItem>
|
||||
)}
|
||||
</List>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
|
@ -279,7 +311,11 @@ const AdminDashboardPage = () => {
|
|||
>
|
||||
Manage Products
|
||||
</Button>
|
||||
<Button variant="outlined">
|
||||
<Button
|
||||
variant="outlined"
|
||||
component={RouterLink}
|
||||
to="/admin/orders"
|
||||
>
|
||||
View Orders
|
||||
</Button>
|
||||
</Box>
|
||||
|
|
|
|||
Loading…
Reference in a new issue