import React, { useState, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import axios from 'axios'; import { LayoutDashboard, Package, Wrench, ShoppingCart, Users, BarChart3, Settings, AlertTriangle, TrendingUp, DollarSign, Calendar, Download, Plus, Edit, Trash2, Eye, ChevronRight, Search, Filter, RefreshCw, FileText, FileSpreadsheet } from 'lucide-react'; import { Button } from '../components/ui/button'; import { Input } from '../components/ui/input'; import { Badge } from '../components/ui/badge'; import { Separator } from '../components/ui/separator'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '../components/ui/tabs'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '../components/ui/select'; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger, DialogFooter, } from '../components/ui/dialog'; import { Label } from '../components/ui/label'; import { Textarea } from '../components/ui/textarea'; import { useAuth } from '../context/AuthContext'; import { toast } from 'sonner'; const API = `${process.env.REACT_APP_BACKEND_URL}/api`; const statusColors = { pending: 'bg-yellow-500', processing: 'bg-blue-500', layaway: 'bg-purple-500', shipped: 'bg-cyan-500', delivered: 'bg-green-500', cancelled: 'bg-red-500', refunded: 'bg-orange-500', on_hold: 'bg-gray-500' }; const AdminDashboard = () => { const { user, token, isAuthenticated } = useAuth(); const navigate = useNavigate(); const [activeTab, setActiveTab] = useState('dashboard'); const [loading, setLoading] = useState(true); // Dashboard data const [dashboardData, setDashboardData] = useState(null); // Products state const [products, setProducts] = useState([]); const [productDialog, setProductDialog] = useState(false); const [editingProduct, setEditingProduct] = useState(null); const [productForm, setProductForm] = useState({ name: '', description: '', price: '', category: '', image_url: '', stock: '', brand: '' }); // Services state const [services, setServices] = useState([]); const [serviceDialog, setServiceDialog] = useState(false); const [editingService, setEditingService] = useState(null); const [serviceForm, setServiceForm] = useState({ name: '', description: '', price: '', duration: '', image_url: '', category: '' }); // Orders state const [orders, setOrders] = useState([]); const [orderStatusFilter, setOrderStatusFilter] = useState('all'); const [selectedOrder, setSelectedOrder] = useState(null); const [newStatus, setNewStatus] = useState(''); const [statusNotes, setStatusNotes] = useState(''); const [trackingNumber, setTrackingNumber] = useState(''); // Inventory state const [inventory, setInventory] = useState([]); const [adjustDialog, setAdjustDialog] = useState(false); const [adjustProduct, setAdjustProduct] = useState(null); const [adjustQty, setAdjustQty] = useState(0); const [adjustNotes, setAdjustNotes] = useState(''); // Reports state const [reportPeriod, setReportPeriod] = useState('monthly'); const [salesReport, setSalesReport] = useState(null); // Bookings state const [bookings, setBookings] = useState([]); useEffect(() => { if (isAuthenticated && user?.role === 'admin') { fetchDashboardData(); } }, [isAuthenticated, user, token]); useEffect(() => { if (activeTab === 'products') fetchProducts(); if (activeTab === 'services') fetchServices(); if (activeTab === 'orders') fetchOrders(); if (activeTab === 'inventory') fetchInventory(); if (activeTab === 'reports') fetchReports(); if (activeTab === 'bookings') fetchBookings(); }, [activeTab]); const fetchDashboardData = async () => { try { const response = await axios.get(`${API}/admin/dashboard`, { headers: { Authorization: `Bearer ${token}` } }); setDashboardData(response.data); } catch (error) { console.error('Failed to fetch dashboard:', error); toast.error('Failed to load dashboard data'); } finally { setLoading(false); } }; const fetchProducts = async () => { try { const response = await axios.get(`${API}/admin/products?include_inactive=true`, { headers: { Authorization: `Bearer ${token}` } }); setProducts(response.data); } catch (error) { toast.error('Failed to load products'); } }; const fetchServices = async () => { try { const response = await axios.get(`${API}/admin/services?include_inactive=true`, { headers: { Authorization: `Bearer ${token}` } }); setServices(response.data); } catch (error) { toast.error('Failed to load services'); } }; const fetchOrders = async () => { try { const params = orderStatusFilter !== 'all' ? `?status=${orderStatusFilter}` : ''; const response = await axios.get(`${API}/admin/orders${params}`, { headers: { Authorization: `Bearer ${token}` } }); setOrders(response.data); } catch (error) { toast.error('Failed to load orders'); } }; const fetchInventory = async () => { try { const response = await axios.get(`${API}/admin/inventory`, { headers: { Authorization: `Bearer ${token}` } }); setInventory(response.data); } catch (error) { toast.error('Failed to load inventory'); } }; const fetchReports = async () => { try { const response = await axios.get(`${API}/admin/reports/sales?period=${reportPeriod}`, { headers: { Authorization: `Bearer ${token}` } }); setSalesReport(response.data); } catch (error) { toast.error('Failed to load reports'); } }; const fetchBookings = async () => { try { const response = await axios.get(`${API}/admin/bookings`, { headers: { Authorization: `Bearer ${token}` } }); setBookings(response.data); } catch (error) { toast.error('Failed to load bookings'); } }; // Product CRUD const handleProductSubmit = async () => { try { const data = { ...productForm, price: parseFloat(productForm.price), stock: parseInt(productForm.stock) || 10 }; if (editingProduct) { await axios.put(`${API}/admin/products/${editingProduct.id}`, data, { headers: { Authorization: `Bearer ${token}` } }); toast.success('Product updated'); } else { await axios.post(`${API}/admin/products`, data, { headers: { Authorization: `Bearer ${token}` } }); toast.success('Product created'); } setProductDialog(false); setEditingProduct(null); setProductForm({ name: '', description: '', price: '', category: '', image_url: '', stock: '', brand: '' }); fetchProducts(); } catch (error) { toast.error('Failed to save product'); } }; const handleDeleteProduct = async (id) => { if (!window.confirm('Are you sure you want to delete this product?')) return; try { await axios.delete(`${API}/admin/products/${id}`, { headers: { Authorization: `Bearer ${token}` } }); toast.success('Product deleted'); fetchProducts(); } catch (error) { toast.error('Failed to delete product'); } }; // Service CRUD const handleServiceSubmit = async () => { try { const data = { ...serviceForm, price: parseFloat(serviceForm.price) }; if (editingService) { await axios.put(`${API}/admin/services/${editingService.id}`, data, { headers: { Authorization: `Bearer ${token}` } }); toast.success('Service updated'); } else { await axios.post(`${API}/admin/services`, data, { headers: { Authorization: `Bearer ${token}` } }); toast.success('Service created'); } setServiceDialog(false); setEditingService(null); setServiceForm({ name: '', description: '', price: '', duration: '', image_url: '', category: '' }); fetchServices(); } catch (error) { toast.error('Failed to save service'); } }; const handleDeleteService = async (id) => { if (!window.confirm('Are you sure you want to delete this service?')) return; try { await axios.delete(`${API}/admin/services/${id}`, { headers: { Authorization: `Bearer ${token}` } }); toast.success('Service deleted'); fetchServices(); } catch (error) { toast.error('Failed to delete service'); } }; // Order status update const handleUpdateOrderStatus = async () => { if (!selectedOrder || !newStatus) return; try { await axios.put(`${API}/admin/orders/${selectedOrder}/status`, { status: newStatus, notes: statusNotes, tracking_number: trackingNumber || null }, { headers: { Authorization: `Bearer ${token}` } }); toast.success('Order status updated'); setSelectedOrder(null); setNewStatus(''); setStatusNotes(''); setTrackingNumber(''); fetchOrders(); } catch (error) { toast.error('Failed to update order'); } }; // Inventory adjustment const handleAdjustInventory = async () => { if (!adjustProduct) return; try { await axios.post(`${API}/admin/inventory/${adjustProduct.id}/adjust`, { quantity_change: adjustQty, notes: adjustNotes }, { headers: { Authorization: `Bearer ${token}` } }); toast.success('Inventory adjusted'); setAdjustDialog(false); setAdjustProduct(null); setAdjustQty(0); setAdjustNotes(''); fetchInventory(); } catch (error) { toast.error('Failed to adjust inventory'); } }; // Export reports const handleExportCSV = async (type) => { try { const response = await axios.get(`${API}/admin/reports/export/csv?report_type=${type}&period=${reportPeriod}`, { headers: { Authorization: `Bearer ${token}` }, responseType: 'blob' }); const url = window.URL.createObjectURL(new Blob([response.data])); const link = document.createElement('a'); link.href = url; link.setAttribute('download', `${type}_report.csv`); document.body.appendChild(link); link.click(); link.remove(); toast.success('CSV exported'); } catch (error) { toast.error('Failed to export CSV'); } }; const handleExportPDF = async (type) => { try { const response = await axios.get(`${API}/admin/reports/export/pdf?report_type=${type}&period=${reportPeriod}`, { headers: { Authorization: `Bearer ${token}` }, responseType: 'blob' }); const url = window.URL.createObjectURL(new Blob([response.data])); const link = document.createElement('a'); link.href = url; link.setAttribute('download', `${type}_report.pdf`); document.body.appendChild(link); link.click(); link.remove(); toast.success('PDF exported'); } catch (error) { toast.error('Failed to export PDF'); } }; if (!isAuthenticated || user?.role !== 'admin') { return (
You need admin privileges to access this page.
Manage your store
${dashboardData.stats.total_revenue.toFixed(2)}
{dashboardData.stats.total_orders}
{dashboardData.stats.total_products}
{dashboardData.stats.total_users}
Orders
{dashboardData.stats.today_orders}
Revenue
${(dashboardData.stats.today_revenue || 0).toFixed(2)}
Revenue
${(dashboardData.stats.monthly_revenue || 0).toFixed(2)}
Pending Bookings
{dashboardData.stats.pending_bookings}
{order.id.slice(0, 8)}...
{new Date(order.created_at).toLocaleString()}
| Product | Category | Price | Stock | Status | Actions |
|---|---|---|---|---|---|
|
|
{product.category} | ${product.price.toFixed(2)} | {product.stock} |
|
|
| Service | Category | Duration | Price | Status | Actions |
|---|---|---|---|---|---|
|
|
{service.category} | {service.duration} | ${service.price.toFixed(2)} |
|
|
Order ID
{order.id.slice(0, 8)}...
Customer
{order.user_name}
Date
{new Date(order.created_at).toLocaleDateString()}
Total
${order.total.toFixed(2)}
| Product | Category | Stock | Threshold | Status | Actions |
|---|---|---|---|---|---|
| {product.name} | {product.category} | {product.stock} | {product.low_stock_threshold} |
|
Service
{booking.service_name}
Customer
{booking.name}
{booking.email}
Phone
{booking.phone}
Preferred Date
{booking.preferred_date}
Notes: {booking.notes}
}Total Orders
{salesReport.summary.total_orders}
Total Revenue
${salesReport.summary.total_revenue.toFixed(2)}
Products Sold
{salesReport.summary.total_products_sold}
Avg Order Value
${salesReport.summary.average_order_value.toFixed(2)}
| Period | Orders | Revenue | Products Sold | Services Booked |
|---|---|---|---|---|
| {row.period} | {row.orders} | ${row.revenue.toFixed(2)} | {row.products_sold} | {row.services_booked || 0} |