"use client"; import { useState, useEffect } from "react"; import { useAuth } from "@/contexts/supabase-auth-context"; import { useRouter } from "next/navigation"; import { swal } from "@/lib/sweetalert"; import Link from "next/link"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; import { Button, buttonVariants } from "@/components/ui/button"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Badge } from "@/components/ui/badge"; import { Input } from "@/components/ui/input"; import { Textarea } from "@/components/ui/textarea"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from "@/components/ui/alert-dialog"; import { Label } from "@/components/ui/label"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { Checkbox } from "@/components/ui/checkbox"; import { Collapsible, CollapsibleContent, CollapsibleTrigger, } from "@/components/ui/collapsible"; import { Users, Package, Wrench, Shield, Trash2, Edit, Search, Activity, Mail, Eye, User, ShoppingCart, TrendingUp, TrendingDown, Download, MoreVertical, X, BarChart3, DollarSign, Star, Plus, Zap, Save, RefreshCw, ImageIcon, Tag, Building2, Hash, FileText, AlertCircle, Settings, Clock, Bell, Lock, Copy, Check, Moon, Sun, Monitor, RotateCcw, Lock as LockIcon, Eye as EyeIcon, EyeOff, Loader, LogOut, ChevronDown, } from "lucide-react"; import { adminService, buildService, componentService, userService, } from "@/lib/database"; import { userActivityService, type UserActivity, } from "@/lib/user-activity-service"; import { auditLogService, type AuditLogEntry } from "@/lib/audit-log-service"; import { formatCurrency } from "@/lib/currency"; import { supabase } from "@/lib/supabase"; /* ==================== TYPES ==================== */ interface User { user_id: number; user_name: string; email: string; user_type: "admin" | "user" | "moderator"; created_at: string; } interface Build { build_id: number; build_name: string; user_id: number; total_price: number; date_created: string; users?: User; build_types?: { type_name: string }; } interface Component { component_id: number; component_name: string; component_brand: string | null; component_price: number | null; component_description: string | null; component_image: string | null; component_categories?: { category_name: string }; retailers?: { retailer_name: string }; } interface Purchase { build_id: number; build_name: string; user_id: number; user_name?: string; user_email?: string; total_price: number; date_created: string; email_sent_to_retailer?: boolean; users?: User; build_types?: { type_name: string }; } interface Stats { totalUsers: number; totalBuilds: number; totalComponents: number; totalPurchases: number; totalRevenue: number; activeUsers: number; recentActivity: number; avgBuildPrice: number; userGrowth: number; buildGrowth: number; } interface AdminSettings { theme: "light" | "dark" | "auto"; itemsPerPage: number; autoRefreshInterval: number; defaultExportFormat: "json" | "csv"; enableBulkActionConfirm: boolean; enableActivityLogging: boolean; notificationEmail: string; defaultPriceRange: string; showInactiveUsers: boolean; sessionTimeout: number; requireDeleteConfirm: boolean; dailyActivityReport: boolean; purchaseNotifications: boolean; userRegistrationAlerts: boolean; } /* ==================== FORM STATE TYPES ==================== */ interface NewUserForm { user_name: string; email: string; password: string; user_type: "admin" | "user" | "moderator"; } interface NewComponentForm { component_name: string; component_brand: string; component_price: string; component_description: string; component_image: string; category_id: string; retailer_id: string; } interface EditComponentForm { component_name: string; component_brand: string; component_price: string; component_description: string; component_image: string; } /* ==================== DEFAULT SETTINGS ==================== */ const DEFAULT_SETTINGS: AdminSettings = { theme: "auto", itemsPerPage: 10, autoRefreshInterval: 300000, defaultExportFormat: "json", enableBulkActionConfirm: true, enableActivityLogging: true, notificationEmail: "", defaultPriceRange: "all", showInactiveUsers: false, sessionTimeout: 30, requireDeleteConfirm: true, dailyActivityReport: false, purchaseNotifications: true, userRegistrationAlerts: true, }; /* ==================== MAIN COMPONENT ==================== */ export default function AdminPage() { const { user } = useAuth(); const router = useRouter(); // ==================== SETTINGS STATE ==================== const [settings, setSettings] = useState(DEFAULT_SETTINGS); const [settingsSaved, setSettingsSaved] = useState(false); const [copiedField, setCopiedField] = useState(null); // Settings dialogs const [changePasswordDialog, setChangePasswordDialog] = useState(false); const [passwordForm, setPasswordForm] = useState({ current: "", new: "", confirm: "", }); const [showPasswords, setShowPasswords] = useState({ current: false, new: false, confirm: false, }); const [clearLogsDialog, setClearLogsDialog] = useState(false); const [exportDialog, setExportDialog] = useState(false); // Auto-refresh state const [autoRefreshTimer, setAutoRefreshTimer] = useState(null); // Tab state const [activeTab, setActiveTab] = useState("overview"); // Data state const [users, setUsers] = useState([]); const [builds, setBuilds] = useState([]); const [components, setComponents] = useState([]); const [purchases, setPurchases] = useState([]); const [userActivity, setUserActivity] = useState([]); const [auditLogs, setAuditLogs] = useState([]); const [auditLogsLoading, setAuditLogsLoading] = useState(false); const [stats, setStats] = useState({ totalUsers: 0, totalBuilds: 0, totalComponents: 0, totalPurchases: 0, totalRevenue: 0, activeUsers: 0, recentActivity: 0, avgBuildPrice: 0, userGrowth: 0, buildGrowth: 0, }); // UI state const [loading, setLoading] = useState(true); const [actionLoading, setActionLoading] = useState(false); const [imageUploading, setImageUploading] = useState(false); const [successMessage, setSuccessMessage] = useState(""); const [errorMessage, setErrorMessage] = useState(""); // Search & Filter const [searchTerm, setSearchTerm] = useState(""); const [userTypeFilter, setUserTypeFilter] = useState("all"); const [activityTypeFilter, setActivityTypeFilter] = useState("all"); const [sortBy, setSortBy] = useState("newest"); const [priceRange, setPriceRange] = useState("all"); // Bulk actions const [selectedItems, setSelectedItems] = useState([]); const [bulkAction, setBulkAction] = useState(""); // ==================== DIALOG STATES ==================== const [deleteDialog, setDeleteDialog] = useState<{ open: boolean; type: "user" | "build" | "component" | null; id: number | null; name: string; }>({ open: false, type: null, id: null, name: "" }); const [createUserDialog, setCreateUserDialog] = useState(false); const [newUserForm, setNewUserForm] = useState({ user_name: "", email: "", password: "", user_type: "user", }); const [createComponentDialog, setCreateComponentDialog] = useState(false); const [newComponentForm, setNewComponentForm] = useState({ component_name: "", component_brand: "", component_price: "", component_description: "", component_image: "", category_id: "", retailer_id: "", }); const [editImageDialog, setEditImageDialog] = useState<{ open: boolean; component: Component | null; imageUrl: string; }>({ open: false, component: null, imageUrl: "" }); const [editUserDialog, setEditUserDialog] = useState<{ open: boolean; user: User | null; userType: string; userName: string; email: string; }>({ open: false, user: null, userType: "", userName: "", email: "" }); const [editComponentDialog, setEditComponentDialog] = useState<{ open: boolean; component: Component | null; form: EditComponentForm; }>({ open: false, component: null, form: { component_name: "", component_brand: "", component_price: "", component_description: "", component_image: "", }, }); const [editBuildDialog, setEditBuildDialog] = useState<{ open: boolean; build: Build | null; buildName: string; }>({ open: false, build: null, buildName: "" }); // ==================== INITIALIZE SETTINGS ==================== useEffect(() => { const savedSettings = localStorage.getItem("adminSettings"); if (savedSettings) { try { setSettings(JSON.parse(savedSettings)); } catch (e) { console.error("Failed to load settings:", e); } } }, []); // ==================== AUTO-REFRESH EFFECT ==================== useEffect(() => { if (settings.autoRefreshInterval > 0 && activeTab !== "settings") { const timer = setInterval(() => { loadData(); }, settings.autoRefreshInterval); setAutoRefreshTimer(timer); return () => { if (timer) clearInterval(timer); }; } }, [settings.autoRefreshInterval, activeTab]); useEffect(() => { if (activeTab === "audit") { setAuditLogsLoading(true); auditLogService .getRecent(150) .then(setAuditLogs) .catch(() => setAuditLogs([])) .finally(() => setAuditLogsLoading(false)); } }, [activeTab]); /* ==================== LOAD DATA ==================== */ useEffect(() => { const passwordVerified = typeof window !== "undefined" ? sessionStorage.getItem("admin_password_verified") : null; if (user?.user_type === "admin") { loadData(); return; } if (passwordVerified === "1") { loadData(); return; } router.push("/admin-access"); }, [user, router]); const showSuccess = (msg: string) => { setSuccessMessage(msg); setTimeout(() => setSuccessMessage(""), 3000); swal.success("Success", msg); }; const showError = (msg: string) => { setErrorMessage(msg); setTimeout(() => setErrorMessage(""), 4000); swal.error("Error", msg); }; const loadData = async () => { try { setLoading(true); const [ usersData, buildsData, componentsData, purchasesData, activityResult, ] = await Promise.allSettled([ adminService.getAllUsers(), adminService.getAllBuilds(), adminService.getAllComponents(), adminService.getAllPurchases(), userActivityService.getAllActivity(100), ]); const loadedUsers = usersData.status === "fulfilled" ? (usersData.value as User[]) : []; const loadedBuilds = buildsData.status === "fulfilled" ? (buildsData.value as Build[]) : []; const loadedComponents = componentsData.status === "fulfilled" ? (componentsData.value as Component[]) : []; const loadedPurchases = purchasesData.status === "fulfilled" ? ((purchasesData.value || []) as Purchase[]) : []; const loadedActivity = activityResult.status === "fulfilled" ? activityResult.value || [] : []; setUsers(loadedUsers); setBuilds(loadedBuilds); setComponents(loadedComponents); setPurchases(loadedPurchases); setUserActivity(loadedActivity); calculateStats( loadedUsers, loadedBuilds, loadedComponents, loadedPurchases, loadedActivity, ); } catch (error) { console.error("Error loading admin data:", error); showError("Failed to load data. Please refresh."); } finally { setLoading(false); } }; const calculateStats = ( u: User[], b: Build[], c: Component[], p: Purchase[], a: UserActivity[], ) => { const totalRevenue = b.reduce( (sum, build) => sum + (build.total_price || 0), 0, ); const avgBuildPrice = b.length > 0 ? totalRevenue / b.length : 0; const sevenDaysAgo = new Date(); sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7); const recentActivity = a.filter( (activity) => new Date(activity.created_at) > sevenDaysAgo, ).length; const thirtyDaysAgo = new Date(); thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30); const recentLogins = a.filter( (activity) => activity.activity_type === "login" && new Date(activity.created_at) > thirtyDaysAgo, ); const activeUsers = new Set(recentLogins.map((a) => a.user_id)).size; setStats({ totalUsers: u.length, totalBuilds: b.length, totalComponents: c.length, totalPurchases: p.length, totalRevenue, activeUsers, recentActivity, avgBuildPrice, userGrowth: 12.5, buildGrowth: 8.3, }); }; /* ==================== SETTINGS HANDLERS ==================== */ const handleSaveSettings = () => { try { localStorage.setItem("adminSettings", JSON.stringify(settings)); setSettingsSaved(true); showSuccess("Settings saved successfully!"); setTimeout(() => setSettingsSaved(false), 3000); } catch (error) { console.error("Error saving settings:", error); showError("Failed to save settings."); } }; const handleResetSettings = () => { setSettings(DEFAULT_SETTINGS); localStorage.removeItem("adminSettings"); showSuccess("Settings reset to defaults!"); }; const handleCopyField = (text: string, field: string) => { navigator.clipboard.writeText(text); setCopiedField(field); setTimeout(() => setCopiedField(null), 2000); }; const uploadComponentImage = async ( file: File ): Promise => { if (!file.type.startsWith("image/")) { showError("Please select an image file (e.g. JPG, PNG)."); return null; } setImageUploading(true); try { const ext = file.name.split(".").pop() || "jpg"; const name = `${Date.now()}-${Math.random().toString(36).slice(2, 9)}.${ext}`; const { data, error } = await supabase.storage .from("component-images") .upload(name, file, { cacheControl: "3600", upsert: false, }); if (error) { showError(error.message || "Upload failed."); return null; } const { data: { publicUrl }, } = supabase.storage.from("component-images").getPublicUrl(data.path); return publicUrl; } catch (e) { showError("Upload failed. Please try again."); return null; } finally { setImageUploading(false); } }; // ==================== LOGOUT HANDLER ==================== const handleLogout = async () => { try { setActionLoading(true); // Clear session storage sessionStorage.removeItem("admin_password_verified"); // Call logout from auth context if available // await authService.logout(); showSuccess("Logged out successfully!"); // Redirect to login page setTimeout(() => { router.push("/admin-access"); }, 1000); } catch (error) { console.error("Error logging out:", error); showError("Failed to logout. Please try again."); } finally { setActionLoading(false); } }; // ==================== THEME HANDLER ==================== const handleThemeChange = (newTheme: "light" | "dark" | "auto") => { setSettings({ ...settings, theme: newTheme }); // Apply theme immediately if (newTheme === "dark") { document.documentElement.classList.add("dark"); } else if (newTheme === "light") { document.documentElement.classList.remove("dark"); } else if (newTheme === "auto") { const isDark = window.matchMedia("(prefers-color-scheme: dark)").matches; if (isDark) { document.documentElement.classList.add("dark"); } else { document.documentElement.classList.remove("dark"); } } }; // ==================== PASSWORD HANDLER ==================== const handleChangePassword = async () => { if ( !passwordForm.current.trim() || !passwordForm.new.trim() || !passwordForm.confirm.trim() ) { showError("All password fields are required."); return; } if (passwordForm.new !== passwordForm.confirm) { showError("New passwords do not match."); return; } if (passwordForm.new.length < 8) { showError("New password must be at least 8 characters."); return; } try { setActionLoading(true); // Call your auth service to change password // await authService.changePassword(passwordForm.current, passwordForm.new) setChangePasswordDialog(false); setPasswordForm({ current: "", new: "", confirm: "" }); showSuccess("Password changed successfully!"); } catch (error) { console.error("Error changing password:", error); showError("Failed to change password. Check your current password."); } finally { setActionLoading(false); } }; // ==================== EMAIL NOTIFICATION HANDLER ==================== const handleSendTestEmail = async () => { if (!settings.notificationEmail) { showError("Please enter a notification email address first."); return; } try { setActionLoading(true); // Call your email service // await emailService.sendTestEmail(settings.notificationEmail) showSuccess(`Test email sent to ${settings.notificationEmail}`); } catch (error) { console.error("Error sending test email:", error); showError("Failed to send test email. Please check the email address."); } finally { setActionLoading(false); } }; // ==================== EXPORT HANDLERS ==================== const handleExportAllData = async () => { try { setActionLoading(true); const allData = { users, builds, components, purchases, activity: userActivity, stats, exportedAt: new Date().toISOString(), exportedBy: user?.user_name || "Admin", }; const format = settings.defaultExportFormat; let content: string; let filename: string; let mimeType: string; if (format === "csv") { // Convert to CSV content = convertToCSV(allData); filename = `admin-backup-${new Date().toISOString().split("T")[0]}.csv`; mimeType = "text/csv"; } else { // JSON format content = JSON.stringify(allData, null, 2); filename = `admin-backup-${new Date().toISOString().split("T")[0]}.json`; mimeType = "application/json"; } const blob = new Blob([content], { type: mimeType }); const url = URL.createObjectURL(blob); const link = document.createElement("a"); link.href = url; link.download = filename; link.click(); URL.revokeObjectURL(url); showSuccess(`Data exported successfully as ${filename}`); } catch (error) { console.error("Error exporting data:", error); showError("Failed to export data."); } finally { setActionLoading(false); } }; // ==================== CLEAR LOGS HANDLER ==================== const handleClearActivityLogs = async () => { try { setActionLoading(true); // Call your activity service to clear logs // await userActivityService.clearAllLogs() setUserActivity([]); setClearLogsDialog(false); showSuccess("Activity logs cleared successfully!"); loadData(); } catch (error) { console.error("Error clearing logs:", error); showError("Failed to clear activity logs."); } finally { setActionLoading(false); } }; // ==================== BACKUP & RESTORE ==================== const handleBackupSettings = () => { try { const backup = { settings, backupDate: new Date().toISOString(), backupVersion: "1.0", }; const blob = new Blob([JSON.stringify(backup, null, 2)], { type: "application/json", }); const url = URL.createObjectURL(blob); const link = document.createElement("a"); link.href = url; link.download = `settings-backup-${new Date().toISOString().split("T")[0]}.json`; link.click(); URL.revokeObjectURL(url); showSuccess("Settings backed up successfully!"); } catch (error) { console.error("Error backing up settings:", error); showError("Failed to backup settings."); } }; const handleRestoreSettings = () => { const input = document.createElement("input"); input.type = "file"; input.accept = ".json"; input.onchange = async (e: any) => { try { const file = e.target.files[0]; const text = await file.text(); const backup = JSON.parse(text); if (backup.settings && backup.backupVersion) { setSettings(backup.settings); localStorage.setItem( "adminSettings", JSON.stringify(backup.settings), ); showSuccess("Settings restored successfully!"); } else { showError("Invalid backup file format."); } } catch (error) { console.error("Error restoring settings:", error); showError("Failed to restore settings. Invalid file."); } }; input.click(); }; // ==================== CSV CONVERSION ==================== const convertToCSV = (data: any): string => { const headers = ["Type", "Item", "Value", "Date"]; let csv = headers.join(",") + "\n"; // Add users data.users.forEach((u: User) => { csv += `User,"${u.user_name}","${u.email}","${u.created_at}"\n`; }); // Add builds data.builds.forEach((b: Build) => { csv += `Build,"${b.build_name}","${formatCurrency(b.total_price)}","${b.date_created}"\n`; }); // Add components data.components.forEach((c: Component) => { csv += `Component,"${c.component_name}","${formatCurrency(c.component_price || 0)}","${c.component_brand || "N/A"}"\n`; }); return csv; }; /* ==================== CREATE HANDLERS ==================== */ const handleCreateUser = async () => { if ( !newUserForm.user_name.trim() || !newUserForm.email.trim() || !newUserForm.password.trim() ) { showError("Please fill in all required fields."); return; } try { setActionLoading(true); await userService.create({ user_name: newUserForm.user_name, email: newUserForm.email, password: newUserForm.password, user_type: newUserForm.user_type, }); setCreateUserDialog(false); setNewUserForm({ user_name: "", email: "", password: "", user_type: "user", }); showSuccess(`User "${newUserForm.user_name}" created successfully!`); loadData(); } catch (error) { console.error("Error creating user:", error); showError("Failed to create user. Email may already be in use."); } finally { setActionLoading(false); } }; const handleCreateComponent = async () => { if (!newComponentForm.component_name.trim()) { showError("Component name is required."); return; } try { setActionLoading(true); const categoryId = newComponentForm.category_id ? parseInt(newComponentForm.category_id) : null; const retailerId = newComponentForm.retailer_id ? parseInt(newComponentForm.retailer_id) : null; await componentService.create({ component_name: newComponentForm.component_name, component_brand: newComponentForm.component_brand || null, component_price: newComponentForm.component_price ? parseFloat(newComponentForm.component_price) : null, component_description: newComponentForm.component_description || null, component_image: newComponentForm.component_image || null, category_id: categoryId as number, retailer_id: retailerId as number, }); setCreateComponentDialog(false); setNewComponentForm({ component_name: "", component_brand: "", component_price: "", component_description: "", component_image: "", category_id: "", retailer_id: "", }); showSuccess( `Component "${newComponentForm.component_name}" created successfully!`, ); loadData(); } catch (error) { console.error("Error creating component:", error); showError("Failed to create component. Please try again."); } finally { setActionLoading(false); } }; /* ==================== UPDATE HANDLERS ==================== */ const handleUpdateUser = async () => { if (!editUserDialog.user) return; if (!editUserDialog.userName.trim() || !editUserDialog.email.trim()) { showError("Name and email are required."); return; } try { setActionLoading(true); await userService.update(editUserDialog.user.user_id, { user_name: editUserDialog.userName, email: editUserDialog.email, user_type: editUserDialog.userType as "admin" | "user" | "moderator", }); if (user) auditLogService.log({ adminUserId: user.user_id, action: "user_updated", targetType: "user", targetId: editUserDialog.user.user_id, targetName: editUserDialog.userName, }); setEditUserDialog({ open: false, user: null, userType: "", userName: "", email: "", }); showSuccess("User updated successfully!"); loadData(); } catch (error) { console.error("Error updating user:", error); showError("Failed to update user."); } finally { setActionLoading(false); } }; const handleUpdateComponent = async () => { if (!editComponentDialog.component) return; if (!editComponentDialog.form.component_name.trim()) { showError("Component name is required."); return; } try { setActionLoading(true); await componentService.update( editComponentDialog.component.component_id, { component_name: editComponentDialog.form.component_name, component_brand: editComponentDialog.form.component_brand || null, component_price: editComponentDialog.form.component_price ? parseFloat(editComponentDialog.form.component_price) : null, component_description: editComponentDialog.form.component_description || null, component_image: editComponentDialog.form.component_image || null, }, ); if (user) auditLogService.log({ adminUserId: user.user_id, action: "component_updated", targetType: "component", targetId: editComponentDialog.component.component_id, targetName: editComponentDialog.form.component_name, }); setEditComponentDialog({ open: false, component: null, form: { component_name: "", component_brand: "", component_price: "", component_description: "", component_image: "", }, }); showSuccess("Component updated successfully!"); loadData(); } catch (error) { console.error("Error updating component:", error); showError("Failed to update component."); } finally { setActionLoading(false); } }; const handleUpdateBuildName = async () => { if (!editBuildDialog.build) return; if (!editBuildDialog.buildName.trim()) { showError("Build name is required."); return; } try { setActionLoading(true); await buildService.update(editBuildDialog.build.build_id, { build_name: editBuildDialog.buildName, total_price: editBuildDialog.build.total_price, }); if (user) auditLogService.log({ adminUserId: user.user_id, action: "build_updated", targetType: "build", targetId: editBuildDialog.build.build_id, targetName: editBuildDialog.buildName, }); setEditBuildDialog({ open: false, build: null, buildName: "" }); showSuccess("Build name updated successfully!"); loadData(); } catch (error) { console.error("Error updating build:", error); showError("Failed to update build."); } finally { setActionLoading(false); } }; const handleUpdateImage = async () => { if (!editImageDialog.component) return; try { setActionLoading(true); await componentService.update(editImageDialog.component.component_id, { component_image: editImageDialog.imageUrl || null, }); if (user) auditLogService.log({ adminUserId: user.user_id, action: "component_image_updated", targetType: "component", targetId: editImageDialog.component.component_id, targetName: editImageDialog.component.component_name, }); setEditImageDialog({ open: false, component: null, imageUrl: "" }); showSuccess("Component image updated!"); loadData(); } catch (error) { console.error("Error updating component image:", error); showError("Failed to update component image."); } finally { setActionLoading(false); } }; /* ==================== DELETE HANDLERS ==================== */ const handleDeleteUser = async () => { if (!deleteDialog.id) return; try { await adminService.deleteUser(deleteDialog.id); if (user) auditLogService.log({ adminUserId: user.user_id, action: "user_deleted", targetType: "user", targetId: deleteDialog.id, targetName: deleteDialog.name, }); setDeleteDialog({ open: false, type: null, id: null, name: "" }); showSuccess("User deleted successfully."); loadData(); } catch (error) { console.error("Error deleting user:", error); showError("Failed to delete user."); } }; const handleDeleteBuild = async () => { if (!deleteDialog.id) return; try { await adminService.deleteBuild(deleteDialog.id); if (user) auditLogService.log({ adminUserId: user.user_id, action: "build_deleted", targetType: "build", targetId: deleteDialog.id, targetName: deleteDialog.name, }); setDeleteDialog({ open: false, type: null, id: null, name: "" }); showSuccess("Build deleted successfully."); loadData(); } catch (error) { console.error("Error deleting build:", error); showError("Failed to delete build."); } }; const handleDeleteComponent = async () => { if (!deleteDialog.id) return; try { await adminService.deleteComponent(deleteDialog.id); if (user) auditLogService.log({ adminUserId: user.user_id, action: "component_deleted", targetType: "component", targetId: deleteDialog.id, targetName: deleteDialog.name, }); setDeleteDialog({ open: false, type: null, id: null, name: "" }); showSuccess("Component deleted successfully."); loadData(); } catch (error) { console.error("Error deleting component:", error); showError("Failed to delete component."); } }; /* ==================== BULK ACTIONS ==================== */ const handleBulkAction = async () => { if (!bulkAction || selectedItems.length === 0) return; try { if (bulkAction === "delete") { for (const id of selectedItems) { if (activeTab === "users") await adminService.deleteUser(id); if (activeTab === "builds") await adminService.deleteBuild(id); if (activeTab === "components") await adminService.deleteComponent(id); } if (user) { const action = activeTab === "users" ? "bulk_delete_users" : activeTab === "builds" ? "bulk_delete_builds" : "bulk_delete_components"; auditLogService.log({ adminUserId: user.user_id, action, targetType: activeTab === "users" ? "user" : activeTab === "builds" ? "build" : "component", targetName: `${selectedItems.length} items`, details: { count: selectedItems.length, ids: selectedItems }, }); } showSuccess(`${selectedItems.length} items deleted successfully.`); } setSelectedItems([]); setBulkAction(""); loadData(); } catch (error) { console.error("Error performing bulk action:", error); showError("Bulk action failed on some items."); } }; const toggleSelectItem = (id: number) => { setSelectedItems((prev) => prev.includes(id) ? prev.filter((i) => i !== id) : [...prev, id], ); }; const toggleSelectAll = () => { if (activeTab === "users") setSelectedItems( selectedItems.length === filteredUsers.length ? [] : filteredUsers.map((u) => u.user_id), ); else if (activeTab === "builds") setSelectedItems( selectedItems.length === filteredBuilds.length ? [] : filteredBuilds.map((b) => b.build_id), ); else if (activeTab === "components") setSelectedItems( selectedItems.length === filteredComponents.length ? [] : filteredComponents.map((c) => c.component_id), ); }; /* ==================== EXPORT ==================== */ const handleExport = (type: string) => { const dataMap: Record = { users: { data: users, filename: "users-export.json" }, builds: { data: builds, filename: "builds-export.json" }, components: { data: components, filename: "components-export.json" }, }; const { data, filename } = dataMap[type] || { data: [], filename: "export.json", }; const blob = new Blob([JSON.stringify(data, null, 2)], { type: "application/json", }); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = filename; a.click(); URL.revokeObjectURL(url); }; /* ==================== FILTERING ==================== */ const filteredUsers = users .filter( (u) => (u.user_name.toLowerCase().includes(searchTerm.toLowerCase()) || u.email.toLowerCase().includes(searchTerm.toLowerCase())) && (userTypeFilter === "all" || u.user_type === userTypeFilter), ) .sort((a, b) => { if (sortBy === "newest") return ( new Date(b.created_at).getTime() - new Date(a.created_at).getTime() ); if (sortBy === "oldest") return ( new Date(a.created_at).getTime() - new Date(b.created_at).getTime() ); if (sortBy === "name") return a.user_name.localeCompare(b.user_name); return 0; }); const filteredBuilds = builds .filter( (b) => b.build_name.toLowerCase().includes(searchTerm.toLowerCase()) && (priceRange === "all" || (priceRange === "low" && b.total_price < 30000) || (priceRange === "medium" && b.total_price >= 30000 && b.total_price < 80000) || (priceRange === "high" && b.total_price >= 80000)), ) .sort((a, b) => { if (sortBy === "newest") return ( new Date(b.date_created).getTime() - new Date(a.date_created).getTime() ); if (sortBy === "oldest") return ( new Date(a.date_created).getTime() - new Date(b.date_created).getTime() ); if (sortBy === "price-high") return b.total_price - a.total_price; if (sortBy === "price-low") return a.total_price - b.total_price; return 0; }); const filteredComponents = components.filter( (c) => c.component_name.toLowerCase().includes(searchTerm.toLowerCase()) || (c.component_brand && c.component_brand.toLowerCase().includes(searchTerm.toLowerCase())), ); const filteredActivity = userActivity.filter( (a) => activityTypeFilter === "all" || a.activity_type === activityTypeFilter, ); /* ==================== RENDER ==================== */ if (loading) { return (

Loading admin dashboard...

); } return (
{/* ==================== TOAST NOTIFICATIONS ==================== */} {successMessage && (
{successMessage}
)} {errorMessage && (
{errorMessage}
)} {/* ==================== HEADER ==================== */}

BuildMate

ADMINSTRATOR

{user && (
Signed in as {user.user_name || user.email}
)}
{/* ==================== TABS ==================== */} { setActiveTab(val); setSelectedItems([]); }} > Overview Users Builds Components Purchases Activity Audit Settings {/* ==================== OVERVIEW TAB ==================== */}
} label="Total Users" value={stats.totalUsers} subtext={`${stats.activeUsers} active`} trend={stats.userGrowth} color="blue" /> } label="Total Builds" value={stats.totalBuilds} subtext={`Avg ${formatCurrency(stats.avgBuildPrice)}`} trend={stats.buildGrowth} color="green" /> } label="Components" value={stats.totalComponents} subtext="In database" color="purple" /> } label="Total Revenue" value={formatCurrency(stats.totalRevenue)} subtext={`${stats.totalPurchases} purchases`} color="amber" />
User Distribution
Admins {users.filter((u) => u.user_type === "admin").length}
Moderators {users.filter((u) => u.user_type === "moderator").length}
Regular Users {users.filter((u) => u.user_type === "user").length}
Recent Activity
{stats.recentActivity}

Actions in the last 7 days

{userActivity.slice(0, 3).map((activity) => (
• {activity.activity_type}
))}
Top Builds by Price {builds .sort((a, b) => b.total_price - a.total_price) .slice(0, 3) .map((build) => (
{build.build_name} {formatCurrency(build.total_price)}
))}
Recent Builds Latest PC builds created {builds.slice(0, 5).map((build) => (

{build.build_name}

by {build.users?.user_name || "Unknown"}

{formatCurrency(build.total_price)}

))}
Component Categories Distribution by category {Array.from( new Set( components .map((c) => c.component_categories?.category_name) .filter(Boolean), ), ) .slice(0, 5) .map((category) => { const count = components.filter( (c) => c.component_categories?.category_name === category, ).length; return (
{category} {count}
); })}
{/* ==================== USERS TAB ==================== */}
setSearchTerm(e.target.value)} className="pl-8" />
{selectedItems.length > 0 && ( <> )}
User Management {filteredUsers.length} users found
{filteredUsers.map((u) => (
toggleSelectItem(u.user_id)} />
{u.email.charAt(0).toUpperCase()}
{u.user_name}
{u.email}
{u.user_type} Joined {new Date(u.created_at).toLocaleDateString()}
Actions setEditUserDialog({ open: true, user: u, userType: u.user_type, userName: u.user_name, email: u.email, }) } > Edit User setDeleteDialog({ open: true, type: "user", id: u.user_id, name: u.user_name, }) } className="text-red-600" > Delete User
))} {filteredUsers.length === 0 && (
No users found
)}
{/* ==================== BUILDS TAB ==================== */}
setSearchTerm(e.target.value)} className="pl-8" />
{selectedItems.length > 0 && ( <> )}
Build Management {filteredBuilds.length} builds found
{filteredBuilds.map((build) => (
toggleSelectItem(build.build_id)} />
{build.build_name}
By: {build.users?.user_name || "Unknown"} •{" "} {new Date(build.date_created).toLocaleDateString()}
{build.build_types && ( {build.build_types.type_name} )}
{formatCurrency(build.total_price)}
))} {filteredBuilds.length === 0 && (
No builds found
)}
{/* ==================== COMPONENTS TAB ==================== */}
setSearchTerm(e.target.value)} className="pl-10 bg-white dark:bg-slate-950" />
{[ { id: "1", label: "Processors", icon: , }, { id: "2", label: "Motherboard", icon: , }, { id: "3", label: "Memory (RAM)", icon: , }, { id: "4", label: "Storage", icon: }, { id: "5", label: "Graphics Card", icon: , }, { id: "6", label: "Power Supply", icon: , }, { id: "7", label: "Case", icon: }, { id: "8", label: "Cooling", icon: , }, ].map((cat) => { const categoryItems = filteredComponents.filter( (c) => c.component_categories?.category_name === cat.label, ); return (
{cat.icon}
{cat.label} {categoryItems.length} items registered
{categoryItems.length > 0 ? ( categoryItems.map((item) => ( )) ) : ( )}
Select Component Name Brand Price Actions
toggleSelectItem(item.component_id) } />
{item.component_image && ( )} {item.component_name}
{item.component_brand || "—"} {formatCurrency(item.component_price || 0)}
No {cat.label} found in inventory.
); })}
{/* ==================== PURCHASES TAB ==================== */}
setSearchTerm(e.target.value)} className="pl-8" />
Purchase History All purchases — emails sent to sales.centraljuan.net@gmail.com
{purchases .filter((p) => p.build_name .toLowerCase() .includes(searchTerm.toLowerCase()), ) .map((purchase) => (
{purchase.build_name}
Customer:{" "} {purchase.users?.user_name || "Unknown"} ( {purchase.users?.email || "N/A"})
Build Type:{" "} {purchase.build_types?.type_name || "Custom"}
{new Date( purchase.date_created, ).toLocaleString()}
Email Sent sales.centraljuan.net@gmail.com
{formatCurrency(purchase.total_price)}
))}
{/* ==================== ACTIVITY TAB ==================== */}
User Activity Log Monitor all platform activities ({filteredActivity.length}{" "} records)
{filteredActivity.map((activity) => (
{activity.activity_type} {activity.users?.user_name || "Unknown"} {activity.users?.email || "N/A"}

{activity.activity_description}

{new Date(activity.created_at).toLocaleString()} {activity.ip_address && ( IP: {activity.ip_address} )}
))} {filteredActivity.length === 0 && (
No activity found
)}
{/* ==================== AUDIT LOG TAB ==================== */} Admin Audit Log Who did what: delete user, update component, etc. (last 150 entries) {auditLogsLoading ? (
) : (
{auditLogs.map((entry) => (
{entry.action} {entry.admin_user?.user_name || `User #${entry.admin_user_id}`} {entry.target_type} {entry.target_id != null && ` #${entry.target_id}`} {entry.target_name && ` "${entry.target_name}"`}
{new Date(entry.created_at).toLocaleString()} {entry.details && Object.keys(entry.details).length > 0 && ( · {JSON.stringify(entry.details)} )}
))} {filteredAuditLogs.length === 0 && !auditLogsLoading && (
No audit entries yet. Actions you take (delete user, update component, etc.) will appear here.
)}
)}
{/* ==================== SETTINGS TAB ==================== */}
{/* SETTINGS HEADER */}

Settings

Manage dashboard preferences, notifications, and account

{/* DISPLAY PREFERENCES – collapsible */}
Display Preferences
Theme, items per page, and refresh interval
{/* NOTIFICATIONS & ALERTS – collapsible */}
Notifications & Alerts
Alert email and notification toggles
setSettings({ ...settings, notificationEmail: e.target.value, }) } className="w-full min-w-0" />
setSettings({ ...settings, purchaseNotifications: !!checked, }) } className="shrink-0" />
setSettings({ ...settings, dailyActivityReport: !!checked, }) } className="shrink-0" />
setSettings({ ...settings, userRegistrationAlerts: !!checked, }) } className="shrink-0" />
{/* SECURITY SETTINGS – collapsible */}
Security Settings
Session timeout, confirmations, and password
setSettings({ ...settings, sessionTimeout: parseInt(e.target.value), }) } className="w-full" />

Ask for confirmation before deleting any items

setSettings({ ...settings, requireDeleteConfirm: !!checked, }) } className="shrink-0 mt-1 sm:mt-0" />

Log all admin actions for audit trail

setSettings({ ...settings, enableActivityLogging: !!checked, }) } className="shrink-0 mt-1 sm:mt-0" />
{/* Section label */}

Account & Data

{/* ACCOUNT & SESSION – collapsible */}
Account & Session
Logged-in user and logout

Logged in as:{" "} {user?.user_name || user?.email}

{/* DATA MANAGEMENT – collapsible */}
Data Management
Export, backup, restore, and clear logs

Current Data:{" "} {stats.totalUsers} users • {stats.totalBuilds} builds •{" "} {stats.totalComponents} components

{/* SAVE / RESET BAR */}
{/* ================================================================ ==================== ALL DIALOGS BELOW ========================== ================================================================ */} {/* DELETE CONFIRMATION DIALOG */} setDeleteDialog({ ...deleteDialog, open })} > Are you absolutely sure? This will permanently delete {deleteDialog.type}{" "} "{deleteDialog.name}" . This action cannot be undone. Cancel { if (deleteDialog.type === "user") handleDeleteUser(); if (deleteDialog.type === "build") handleDeleteBuild(); if (deleteDialog.type === "component") handleDeleteComponent(); }} className="bg-red-600 hover:bg-red-700" > Delete {/* BULK DELETE CONFIRMATION */} {bulkAction === "delete" && ( setBulkAction("")}> Delete {selectedItems.length} items? This will permanently delete the selected items. This action cannot be undone. Cancel Delete All )} {/* CHANGE PASSWORD DIALOG */} Change Password Update your admin account password
setPasswordForm({ ...passwordForm, current: e.target.value, }) } />
setPasswordForm({ ...passwordForm, new: e.target.value }) } />
setPasswordForm({ ...passwordForm, confirm: e.target.value, }) } />
{/* CLEAR LOGS DIALOG */} Clear all activity logs? This will permanently delete all activity logs. This action cannot be undone. Cancel Clear Logs {/* CREATE USER DIALOG */} { if (!open) setCreateUserDialog(false); }} > Create New User Add a new user account to the platform.
setNewUserForm({ ...newUserForm, user_name: e.target.value }) } />
setNewUserForm({ ...newUserForm, email: e.target.value }) } />
setNewUserForm({ ...newUserForm, password: e.target.value }) } />
{/* EDIT USER DIALOG */} { if (!open) setEditUserDialog({ open: false, user: null, userType: "", userName: "", email: "", }); }} > Edit User Update details for {editUserDialog.user?.user_name}
setEditUserDialog({ ...editUserDialog, userName: e.target.value, }) } />
setEditUserDialog({ ...editUserDialog, email: e.target.value, }) } />
{/* EDIT BUILD NAME DIALOG */} { if (!open) setEditBuildDialog({ open: false, build: null, buildName: "" }); }} > Edit Build Update the name for this PC build.
setEditBuildDialog({ ...editBuildDialog, buildName: e.target.value, }) } />
{editBuildDialog.build && (
Current Price {formatCurrency(editBuildDialog.build.total_price)}
Created By {editBuildDialog.build.users?.user_name || "Unknown"}

Note: To edit components/price, open the build in the build editor.

)}
{/* CREATE COMPONENT DIALOG */} { if (!open) setCreateComponentDialog(false); }} > Add New Component Add a new PC component to the inventory.
setNewComponentForm({ ...newComponentForm, component_name: e.target.value, }) } />
setNewComponentForm({ ...newComponentForm, component_brand: e.target.value, }) } />
setNewComponentForm({ ...newComponentForm, component_price: e.target.value, }) } />