DEV Community

Daniel Ioni
Daniel Ioni

Posted on

πŸš€ MyZubster Admin Dashboard Guide

πŸš€ MyZubster Admin Dashboard Guide

Complete technical guide to the admin panel – moderation, analytics, and platform management
πŸ“Œ What is the Admin Dashboard?

The MyZubster Admin Dashboard is a centralized control panel for platform administrators. It provides:

βœ… User management – View, moderate, and manage users

βœ… Skill moderation – Approve, reject, or flag skills

βœ… Order monitoring – Track all orders and disputes

βœ… Analytics – Platform metrics and insights

βœ… Commission management – Configure platform fees

βœ… System health – Monitor server status and performance
Enter fullscreen mode Exit fullscreen mode

🧩 Architecture Overview
text

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ MyZubster Admin Dashboard β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ Frontend (React) β”‚ β”‚
β”‚ β”‚ β”‚ β”‚
β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚
β”‚ β”‚ β”‚ Users β”‚ β”‚ Skills β”‚ β”‚ Orders β”‚ β”‚ Analyticsβ”‚ β”‚ β”‚
β”‚ β”‚ β”‚ Panel β”‚ β”‚ Panel β”‚ β”‚ Panel β”‚ β”‚ Panel β”‚ β”‚ β”‚
β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚
β”‚ β”‚ β”‚ β”‚
β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚
β”‚ β”‚ β”‚ Disputes β”‚ β”‚ Reports β”‚ β”‚ Settings β”‚ β”‚ System β”‚ β”‚ β”‚
β”‚ β”‚ β”‚ Panel β”‚ β”‚ Panel β”‚ β”‚ Panel β”‚ β”‚ Health β”‚ β”‚ β”‚
β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”‚ β”‚
β”‚ β–Ό β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ Backend API (Node.js) β”‚ β”‚
β”‚ β”‚ β”‚ β”‚
β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚
β”‚ β”‚ β”‚ /api/ β”‚ β”‚ /api/ β”‚ β”‚ /api/ β”‚ β”‚ /api/ β”‚ β”‚ β”‚
β”‚ β”‚ β”‚ admin/ β”‚ β”‚ admin/ β”‚ β”‚ admin/ β”‚ β”‚ admin/ β”‚ β”‚ β”‚
β”‚ β”‚ β”‚ users β”‚ β”‚ skills β”‚ β”‚ orders β”‚ β”‚ stats β”‚ β”‚ β”‚
β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”‚ β”‚
β”‚ β–Ό β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ Database (SQLite/PostgreSQL) β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ“‚ Complete File Structure
text

marketplace/
β”œβ”€β”€ admin/
β”‚ β”œβ”€β”€ public/
β”‚ β”‚ └── index.html
β”‚ β”œβ”€β”€ src/
β”‚ β”‚ β”œβ”€β”€ App.jsx # Main admin app
β”‚ β”‚ β”œβ”€β”€ index.css # Tailwind styles
β”‚ β”‚ β”œβ”€β”€ components/
β”‚ β”‚ β”‚ β”œβ”€β”€ Dashboard.jsx # Overview dashboard
β”‚ β”‚ β”‚ β”œβ”€β”€ UsersPanel.jsx # User management
β”‚ β”‚ β”‚ β”œβ”€β”€ SkillsPanel.jsx # Skill moderation
β”‚ β”‚ β”‚ β”œβ”€β”€ OrdersPanel.jsx # Order monitoring
β”‚ β”‚ β”‚ β”œβ”€β”€ DisputesPanel.jsx # Dispute resolution
β”‚ β”‚ β”‚ β”œβ”€β”€ AnalyticsPanel.jsx # Platform analytics
β”‚ β”‚ β”‚ β”œβ”€β”€ SettingsPanel.jsx # Platform settings
β”‚ β”‚ β”‚ └── SystemHealth.jsx # Server monitoring
β”‚ β”‚ β”œβ”€β”€ services/
β”‚ β”‚ β”‚ β”œβ”€β”€ adminApi.js # Admin API client
β”‚ β”‚ β”‚ └── auth.js # Admin authentication
β”‚ β”‚ └── utils/
β”‚ β”‚ β”œβ”€β”€ formatters.js # Data formatting helpers
β”‚ β”‚ └── validators.js # Input validation
β”‚ β”œβ”€β”€ package.json
β”‚ └── vite.config.js
β”œβ”€β”€ routes/
β”‚ └── admin.js # Admin API routes
β”œβ”€β”€ middleware/
β”‚ └── admin.js # Admin authentication middleware
└── services/
└── adminService.js # Admin business logic

πŸ”§ Complete Code Walkthrough

  1. Admin Middleware (middleware/admin.js)

File: marketplace/middleware/admin.js
javascript

const { User } = require('../models');

// ============================================
// ADMIN AUTHENTICATION MIDDLEWARE
// ============================================
const adminAuth = async (req, res, next) => {
try {
// Check if user is authenticated
if (!req.user) {
return res.status(401).json({ error: 'Authentication required' });
}

// Check if user has admin role
if (req.user.role !== 'admin' && req.user.role !== 'super_admin') {
  return res.status(403).json({ error: 'Admin privileges required' });
}

// Get full user data
const user = await User.findByPk(req.user.id, {
  attributes: ['id', 'email', 'username', 'role', 'isActive']
});

if (!user) {
  return res.status(404).json({ error: 'User not found' });
}

if (!user.isActive) {
  return res.status(403).json({ error: 'Account deactivated' });
}

req.admin = user;
next();
Enter fullscreen mode Exit fullscreen mode

} catch (error) {
console.error('❌ Admin auth error:', error);
res.status(500).json({ error: 'Internal server error' });
}
};

// ============================================
// SUPER ADMIN MIDDLEWARE
// ============================================
const superAdminAuth = async (req, res, next) => {
try {
await adminAuth(req, res, () => {
if (req.admin.role !== 'super_admin') {
return res.status(403).json({ error: 'Super admin privileges required' });
}
next();
});
} catch (error) {
console.error('❌ Super admin auth error:', error);
res.status(500).json({ error: 'Internal server error' });
}
};

// ============================================
// ADMIN ACTIVITY LOGGING
// ============================================
const logAdminActivity = (action) => {
return async (req, res, next) => {
const startTime = Date.now();

// Store original send function
const originalSend = res.send;

res.send = function(data) {
  // Log admin activity
  const duration = Date.now() - startTime;
  console.log(`πŸ“‹ Admin Activity: ${action}`, {
    adminId: req.admin?.id,
    adminEmail: req.admin?.email,
    method: req.method,
    path: req.path,
    status: res.statusCode,
    duration: `${duration}ms`
  });

  // Call original send
  originalSend.call(this, data);
};

next();
Enter fullscreen mode Exit fullscreen mode

};
};

module.exports = {
adminAuth,
superAdminAuth,
logAdminActivity
};

  1. Admin Routes (routes/admin.js)

File: marketplace/routes/admin.js
javascript

const express = require('express');
const router = express.Router();
const { adminAuth, logAdminActivity } = require('../middleware/admin');
const {
getDashboardStats,
getUsers,
updateUser,
deleteUser,
getSkills,
updateSkill,
deleteSkill,
getOrders,
updateOrder,
getDisputes,
resolveDispute,
getPlatformAnalytics,
updatePlatformSettings,
getSystemHealth
} = require('../services/adminService');

// ============================================
// DASHBOARD
// ============================================
router.get('/dashboard/stats', adminAuth, logAdminActivity('dashboard_stats'), async (req, res) => {
try {
const stats = await getDashboardStats();
res.json(stats);
} catch (error) {
console.error('❌ Error fetching dashboard stats:', error);
res.status(500).json({ error: error.message });
}
});

// ============================================
// USERS MANAGEMENT
// ============================================
router.get('/users', adminAuth, logAdminActivity('list_users'), async (req, res) => {
try {
const { page = 1, limit = 20, search, role, status } = req.query;
const result = await getUsers({ page, limit, search, role, status });
res.json(result);
} catch (error) {
console.error('❌ Error fetching users:', error);
res.status(500).json({ error: error.message });
}
});

router.put('/users/:userId', adminAuth, logAdminActivity('update_user'), async (req, res) => {
try {
const { userId } = req.params;
const updates = req.body;
const user = await updateUser(userId, updates, req.admin.id);
res.json(user);
} catch (error) {
console.error('❌ Error updating user:', error);
res.status(500).json({ error: error.message });
}
});

router.delete('/users/:userId', adminAuth, logAdminActivity('delete_user'), async (req, res) => {
try {
const { userId } = req.params;
const result = await deleteUser(userId, req.admin.id);
res.json(result);
} catch (error) {
console.error('❌ Error deleting user:', error);
res.status(500).json({ error: error.message });
}
});

// ============================================
// SKILLS MANAGEMENT
// ============================================
router.get('/skills', adminAuth, logAdminActivity('list_skills'), async (req, res) => {
try {
const { page = 1, limit = 20, search, category, status } = req.query;
const result = await getSkills({ page, limit, search, category, status });
res.json(result);
} catch (error) {
console.error('❌ Error fetching skills:', error);
res.status(500).json({ error: error.message });
}
});

router.put('/skills/:skillId', adminAuth, logAdminActivity('update_skill'), async (req, res) => {
try {
const { skillId } = req.params;
const updates = req.body;
const skill = await updateSkill(skillId, updates, req.admin.id);
res.json(skill);
} catch (error) {
console.error('❌ Error updating skill:', error);
res.status(500).json({ error: error.message });
}
});

router.delete('/skills/:skillId', adminAuth, logAdminActivity('delete_skill'), async (req, res) => {
try {
const { skillId } = req.params;
const result = await deleteSkill(skillId, req.admin.id);
res.json(result);
} catch (error) {
console.error('❌ Error deleting skill:', error);
res.status(500).json({ error: error.message });
}
});

// ============================================
// ORDERS MANAGEMENT
// ============================================
router.get('/orders', adminAuth, logAdminActivity('list_orders'), async (req, res) => {
try {
const { page = 1, limit = 20, status, from, to } = req.query;
const result = await getOrders({ page, limit, status, from, to });
res.json(result);
} catch (error) {
console.error('❌ Error fetching orders:', error);
res.status(500).json({ error: error.message });
}
});

router.put('/orders/:orderId', adminAuth, logAdminActivity('update_order'), async (req, res) => {
try {
const { orderId } = req.params;
const updates = req.body;
const order = await updateOrder(orderId, updates, req.admin.id);
res.json(order);
} catch (error) {
console.error('❌ Error updating order:', error);
res.status(500).json({ error: error.message });
}
});

// ============================================
// DISPUTES MANAGEMENT
// ============================================
router.get('/disputes', adminAuth, logAdminActivity('list_disputes'), async (req, res) => {
try {
const { page = 1, limit = 20, status } = req.query;
const result = await getDisputes({ page, limit, status });
res.json(result);
} catch (error) {
console.error('❌ Error fetching disputes:', error);
res.status(500).json({ error: error.message });
}
});

router.post('/disputes/:disputeId/resolve', adminAuth, logAdminActivity('resolve_dispute'), async (req, res) => {
try {
const { disputeId } = req.params;
const { resolution, type, amount } = req.body;
const result = await resolveDispute(disputeId, { resolution, type, amount }, req.admin.id);
res.json(result);
} catch (error) {
console.error('❌ Error resolving dispute:', error);
res.status(500).json({ error: error.message });
}
});

// ============================================
// ANALYTICS
// ============================================
router.get('/analytics', adminAuth, logAdminActivity('view_analytics'), async (req, res) => {
try {
const { period = 'month', from, to } = req.query;
const analytics = await getPlatformAnalytics({ period, from, to });
res.json(analytics);
} catch (error) {
console.error('❌ Error fetching analytics:', error);
res.status(500).json({ error: error.message });
}
});

// ============================================
// SETTINGS
// ============================================
router.get('/settings', adminAuth, logAdminActivity('view_settings'), async (req, res) => {
try {
// Get platform settings (from database or environment)
const settings = {
commission: parseFloat(process.env.COMMISSION_PERCENTAGE || '2.0'),
escrowExpiryDays: parseInt(process.env.ESCROW_EXPIRY_DAYS || '30'),
minConfirmations: parseInt(process.env.MIN_CONFIRMATIONS || '10'),
maintenanceMode: process.env.MAINTENANCE_MODE === 'true',
registrationEnabled: process.env.REGISTRATION_ENABLED !== 'false'
};
res.json(settings);
} catch (error) {
console.error('❌ Error fetching settings:', error);
res.status(500).json({ error: error.message });
}
});

router.put('/settings', adminAuth, logAdminActivity('update_settings'), async (req, res) => {
try {
const updates = req.body;
const settings = await updatePlatformSettings(updates, req.admin.id);
res.json(settings);
} catch (error) {
console.error('❌ Error updating settings:', error);
res.status(500).json({ error: error.message });
}
});

// ============================================
// SYSTEM HEALTH
// ============================================
router.get('/system/health', adminAuth, logAdminActivity('system_health'), async (req, res) => {
try {
const health = await getSystemHealth();
res.json(health);
} catch (error) {
console.error('❌ Error fetching system health:', error);
res.status(500).json({ error: error.message });
}
});

module.exports = router;

  1. Admin Service (services/adminService.js)

File: marketplace/services/adminService.js
javascript

const { User, Skill, Order, Escrow, Dispute, sequelize } = require('../models');
const { Op } = require('sequelize');

// ============================================
// GET DASHBOARD STATS
// ============================================
const getDashboardStats = async () => {
try {
const [totalUsers, totalSkills, totalOrders, totalDisputes, revenue] = await Promise.all([
User.count(),
Skill.count({ where: { isActive: true } }),
Order.count(),
Dispute.count({ where: { status: 'open' } }),
Order.sum('amount', { where: { status: 'completed' } })
]);

// Get recent orders
const recentOrders = await Order.findAll({
  limit: 10,
  order: [['createdAt', 'DESC']],
  include: [
    { association: 'buyer', attributes: ['id', 'username'] },
    { association: 'seller', attributes: ['id', 'username'] }
  ]
});

// Get pending skills
const pendingSkills = await Skill.findAll({
  where: { isActive: false },
  limit: 5,
  order: [['createdAt', 'DESC']],
  include: [{ association: 'seller', attributes: ['id', 'username'] }]
});

return {
  stats: {
    totalUsers,
    totalSkills,
    totalOrders,
    openDisputes: totalDisputes,
    totalRevenue: revenue || 0
  },
  recentOrders,
  pendingSkills
};
Enter fullscreen mode Exit fullscreen mode

} catch (error) {
console.error('❌ Error getting dashboard stats:', error);
throw error;
}
};

// ============================================
// GET USERS
// ============================================
const getUsers = async ({ page, limit, search, role, status }) => {
try {
const offset = (page - 1) * limit;
const where = {};

if (search) {
  where[Op.or] = [
    { email: { [Op.like]: `%${search}%` } },
    { username: { [Op.like]: `%${search}%` } },
    { name: { [Op.like]: `%${search}%` } }
  ];
}

if (role && role !== 'all') {
  where.role = role;
}

if (status === 'active') {
  where.isActive = true;
} else if (status === 'inactive') {
  where.isActive = false;
}

const { count, rows } = await User.findAndCountAll({
  where,
  attributes: ['id', 'email', 'username', 'name', 'role', 'isActive', 'rating', 'createdAt'],
  limit,
  offset,
  order: [['createdAt', 'DESC']]
});

return {
  users: rows,
  pagination: {
    total: count,
    page: parseInt(page),
    limit: parseInt(limit),
    pages: Math.ceil(count / limit)
  }
};
Enter fullscreen mode Exit fullscreen mode

} catch (error) {
console.error('❌ Error getting users:', error);
throw error;
}
};

// ============================================
// UPDATE USER
// ============================================
const updateUser = async (userId, updates, adminId) => {
try {
const user = await User.findByPk(userId);
if (!user) {
throw new Error('User not found');
}

// Prevent modifying super admin
if (user.role === 'super_admin') {
  throw new Error('Cannot modify super admin');
}

// Allowed updates
const allowedUpdates = ['role', 'isActive'];
const filteredUpdates = {};
for (const key of allowedUpdates) {
  if (updates[key] !== undefined) {
    filteredUpdates[key] = updates[key];
  }
}

await user.update(filteredUpdates);

// Log activity
await logAdminActivity(adminId, 'update_user', `Updated user ${userId}`);

return user;
Enter fullscreen mode Exit fullscreen mode

} catch (error) {
console.error('❌ Error updating user:', error);
throw error;
}
};

// ============================================
// DELETE USER
// ============================================
const deleteUser = async (userId, adminId) => {
try {
const user = await User.findByPk(userId);
if (!user) {
throw new Error('User not found');
}

if (user.role === 'super_admin') {
  throw new Error('Cannot delete super admin');
}

// Soft delete (deactivate)
await user.update({ isActive: false });

// Log activity
await logAdminActivity(adminId, 'delete_user', `Deactivated user ${userId}`);

return { success: true, message: 'User deactivated successfully' };
Enter fullscreen mode Exit fullscreen mode

} catch (error) {
console.error('❌ Error deleting user:', error);
throw error;
}
};

// ============================================
// GET SKILLS
// ============================================
const getSkills = async ({ page, limit, search, category, status }) => {
try {
const offset = (page - 1) * limit;
const where = {};

if (search) {
  where[Op.or] = [
    { name: { [Op.like]: `%${search}%` } },
    { description: { [Op.like]: `%${search}%` } }
  ];
}

if (category && category !== 'all') {
  where.category = category;
}

if (status === 'active') {
  where.isActive = true;
} else if (status === 'pending') {
  where.isActive = false;
} else if (status === 'flagged') {
  where.isFlagged = true;
}

const { count, rows } = await Skill.findAndCountAll({
  where,
  include: [{ association: 'seller', attributes: ['id', 'username'] }],
  limit,
  offset,
  order: [['createdAt', 'DESC']]
});

return {
  skills: rows,
  pagination: {
    total: count,
    page: parseInt(page),
    limit: parseInt(limit),
    pages: Math.ceil(count / limit)
  }
};
Enter fullscreen mode Exit fullscreen mode

} catch (error) {
console.error('❌ Error getting skills:', error);
throw error;
}
};

// ============================================
// UPDATE SKILL
// ============================================
const updateSkill = async (skillId, updates, adminId) => {
try {
const skill = await Skill.findByPk(skillId);
if (!skill) {
throw new Error('Skill not found');
}

const allowedUpdates = ['isActive', 'isFlagged', 'status'];
const filteredUpdates = {};
for (const key of allowedUpdates) {
  if (updates[key] !== undefined) {
    filteredUpdates[key] = updates[key];
  }
}

await skill.update(filteredUpdates);

// Log activity
await logAdminActivity(adminId, 'update_skill', `Updated skill ${skillId}`);

return skill;
Enter fullscreen mode Exit fullscreen mode

} catch (error) {
console.error('❌ Error updating skill:', error);
throw error;
}
};

// ============================================
// DELETE SKILL
// ============================================
const deleteSkill = async (skillId, adminId) => {
try {
const skill = await Skill.findByPk(skillId);
if (!skill) {
throw new Error('Skill not found');
}

await skill.destroy();

// Log activity
await logAdminActivity(adminId, 'delete_skill', `Deleted skill ${skillId}`);

return { success: true, message: 'Skill deleted successfully' };
Enter fullscreen mode Exit fullscreen mode

} catch (error) {
console.error('❌ Error deleting skill:', error);
throw error;
}
};

// ============================================
// GET ORDERS
// ============================================
const getOrders = async ({ page, limit, status, from, to }) => {
try {
const offset = (page - 1) * limit;
const where = {};

if (status && status !== 'all') {
  where.status = status;
}

if (from) {
  where.createdAt = { [Op.gte]: new Date(from) };
}

if (to) {
  where.createdAt = { ...where.createdAt, [Op.lte]: new Date(to) };
}

const { count, rows } = await Order.findAndCountAll({
  where,
  include: [
    { association: 'buyer', attributes: ['id', 'username'] },
    { association: 'seller', attributes: ['id', 'username'] },
    { association: 'skill', attributes: ['id', 'name'] }
  ],
  limit,
  offset,
  order: [['createdAt', 'DESC']]
});

return {
  orders: rows,
  pagination: {
    total: count,
    page: parseInt(page),
    limit: parseInt(limit),
    pages: Math.ceil(count / limit)
  }
};
Enter fullscreen mode Exit fullscreen mode

} catch (error) {
console.error('❌ Error getting orders:', error);
throw error;
}
};

// ============================================
// GET DISPUTES
// ============================================
const getDisputes = async ({ page, limit, status }) => {
try {
const offset = (page - 1) * limit;
const where = {};

if (status && status !== 'all') {
  where.status = status;
}

const { count, rows } = await Dispute.findAndCountAll({
  where,
  include: [
    { association: 'initiator', attributes: ['id', 'username'] },
    { association: 'arbitrator', attributes: ['id', 'username'] },
    { association: 'escrow' }
  ],
  limit,
  offset,
  order: [['createdAt', 'DESC']]
});

return {
  disputes: rows,
  pagination: {
    total: count,
    page: parseInt(page),
    limit: parseInt(limit),
    pages: Math.ceil(count / limit)
  }
};
Enter fullscreen mode Exit fullscreen mode

} catch (error) {
console.error('❌ Error getting disputes:', error);
throw error;
}
};

// ============================================
// RESOLVE DISPUTE
// ============================================
const resolveDispute = async (disputeId, resolution, adminId) => {
try {
const dispute = await Dispute.findByPk(disputeId);
if (!dispute) {
throw new Error('Dispute not found');
}

if (dispute.status !== 'open') {
  throw new Error('Dispute already resolved');
}

const { resolution: resolutionText, type, amount } = resolution;

// Update dispute
dispute.status = `resolved_${type}`;
dispute.resolution = resolutionText;
dispute.arbitratorId = adminId;
dispute.resolvedAt = new Date();
dispute.resolutionAmount = amount || null;
await dispute.save();

// Process resolution based on type
const escrow = await Escrow.findByPk(dispute.escrowId);
if (escrow) {
  if (type === 'buyer') {
    // Refund buyer
    escrow.status = 'refunded';
    escrow.refundedAt = new Date();
    await escrow.save();

    // Update order
    const order = await Order.findByPk(escrow.orderId);
    if (order) {
      order.status = 'refunded';
      await order.save();
    }
  } else if (type === 'seller') {
    // Release funds to seller
    escrow.status = 'released';
    escrow.releasedAt = new Date();
    await escrow.save();

    const order = await Order.findByPk(escrow.orderId);
    if (order) {
      order.status = 'completed';
      order.completedAt = new Date();
      await order.save();
    }
  }
}

// Log activity
await logAdminActivity(adminId, 'resolve_dispute', `Resolved dispute ${disputeId}`);

return { success: true, dispute };
Enter fullscreen mode Exit fullscreen mode

} catch (error) {
console.error('❌ Error resolving dispute:', error);
throw error;
}
};

// ============================================
// GET ANALYTICS
// ============================================
const getPlatformAnalytics = async ({ period, from, to }) => {
try {
const startDate = from ? new Date(from) : new Date();
const endDate = to ? new Date(to) : new Date();

// Default period: last 30 days
if (!from) {
  startDate.setDate(startDate.getDate() - 30);
}

// Get daily stats
const dailyOrders = await Order.findAll({
  attributes: [
    [sequelize.fn('DATE', sequelize.col('createdAt')), 'date'],
    [sequelize.fn('COUNT', sequelize.col('id')), 'count'],
    [sequelize.fn('SUM', sequelize.col('amount')), 'total']
  ],
  where: {
    createdAt: { [Op.between]: [startDate, endDate] }
  },
  group: [sequelize.fn('DATE', sequelize.col('createdAt'))],
  order: [[sequelize.fn('DATE', sequelize.col('createdAt')), 'ASC']]
});

// Get user growth
const userGrowth = await User.findAll({
  attributes: [
    [sequelize.fn('DATE', sequelize.col('createdAt')), 'date'],
    [sequelize.fn('COUNT', sequelize.col('id')), 'count']
  ],
  where: {
    createdAt: { [Op.between]: [startDate, endDate] }
  },
  group: [sequelize.fn('DATE', sequelize.col('createdAt'))],
  order: [[sequelize.fn('DATE', sequelize.col('createdAt')), 'ASC']]
});

// Get top categories
const topCategories = await Skill.findAll({
  attributes: [
    'category',
    [sequelize.fn('COUNT', sequelize.col('id')), 'count']
  ],
  where: { isActive: true },
  group: ['category'],
  order: [[sequelize.fn('COUNT', sequelize.col('id')), 'DESC']],
  limit: 10
});

// Get revenue trends
const revenueTrend = await Order.findAll({
  attributes: [
    [sequelize.fn('DATE', sequelize.col('createdAt')), 'date'],
    [sequelize.fn('SUM', sequelize.col('amount')), 'total']
  ],
  where: {
    status: 'completed',
    createdAt: { [Op.between]: [startDate, endDate] }
  },
  group: [sequelize.fn('DATE', sequelize.col('createdAt'))],
  order: [[sequelize.fn('DATE', sequelize.col('createdAt')), 'ASC']]
});

return {
  period: {
    from: startDate,
    to: endDate
  },
  dailyOrders,
  userGrowth,
  topCategories,
  revenueTrend,
  summary: {
    totalRevenue: revenueTrend.reduce((sum, item) => sum + parseFloat(item.total || 0), 0),
    totalOrders: dailyOrders.reduce((sum, item) => sum + parseInt(item.count || 0), 0),
    totalUsers: userGrowth.reduce((sum, item) => sum + parseInt(item.count || 0), 0)
  }
};
Enter fullscreen mode Exit fullscreen mode

} catch (error) {
console.error('❌ Error getting analytics:', error);
throw error;
}
};

// ============================================
// SYSTEM HEALTH
// ============================================
const getSystemHealth = async () => {
try {
const startTime = Date.now();

// Check database connection
await sequelize.authenticate();
const dbLatency = Date.now() - startTime;

// Get system info
const os = require('os');
const memoryUsage = process.memoryUsage();

return {
  status: 'healthy',
  timestamp: new Date().toISOString(),
  uptime: process.uptime(),
  memory: {
    used: memoryUsage.heapUsed,
    total: memoryUsage.heapTotal,
    rss: memoryUsage.rss
  },
  cpu: {
    loadAvg: os.loadavg(),
    cores: os.cpus().length
  },
  database: {
    connected: true,
    latency: `${dbLatency}ms`
  },
  version: {
    node: process.version,
    npm: process.env.npm_version || 'unknown'
  }
};
Enter fullscreen mode Exit fullscreen mode

} catch (error) {
console.error('❌ Error checking system health:', error);
return {
status: 'unhealthy',
timestamp: new Date().toISOString(),
error: error.message
};
}
};

// ============================================
// UPDATE PLATFORM SETTINGS
// ============================================
const updatePlatformSettings = async (updates, adminId) => {
try {
// In production, store settings in database
// For now, we'll just log the changes
console.log('πŸ“‹ Platform settings updated:', updates);

// Log activity
await logAdminActivity(adminId, 'update_settings', `Updated platform settings: ${JSON.stringify(updates)}`);

return {
  success: true,
  settings: updates
};
Enter fullscreen mode Exit fullscreen mode

} catch (error) {
console.error('❌ Error updating settings:', error);
throw error;
}
};

// ============================================
// ADMIN ACTIVITY LOGGING HELPER
// ============================================
const logAdminActivity = async (adminId, action, details) => {
// In production, store in a database table
console.log(πŸ“‹ Admin ${adminId} [${action}]: ${details});
};

module.exports = {
getDashboardStats,
getUsers,
updateUser,
deleteUser,
getSkills,
updateSkill,
deleteSkill,
getOrders,
updateOrder: getOrders, // Alias for order management
getDisputes,
resolveDispute,
getPlatformAnalytics,
updatePlatformSettings,
getSystemHealth
};

  1. Admin App (admin/src/App.jsx)

File: admin/src/App.jsx
jsx

import React, { useState, useEffect } from 'react';
import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom';
import { login, getDashboardStats } from './services/adminApi';

// Components
import Dashboard from './components/Dashboard';
import UsersPanel from './components/UsersPanel';
import SkillsPanel from './components/SkillsPanel';
import OrdersPanel from './components/OrdersPanel';
import DisputesPanel from './components/DisputesPanel';
import AnalyticsPanel from './components/AnalyticsPanel';
import SettingsPanel from './components/SettingsPanel';
import SystemHealth from './components/SystemHealth';
import Login from './components/Login';
import Sidebar from './components/Sidebar';
import Header from './components/Header';

function App() {
const [isAuthenticated, setIsAuthenticated] = useState(false);
const [loading, setLoading] = useState(true);
const [user, setUser] = useState(null);
const [stats, setStats] = useState(null);

useEffect(() => {
const token = localStorage.getItem('adminToken');
if (token) {
setIsAuthenticated(true);
fetchStats();
}
setLoading(false);
}, []);

const fetchStats = async () => {
try {
const data = await getDashboardStats();
setStats(data);
} catch (error) {
console.error('Error fetching stats:', error);
}
};

const handleLogin = async (credentials) => {
try {
const response = await login(credentials);
localStorage.setItem('adminToken', response.token);
setUser(response.user);
setIsAuthenticated(true);
await fetchStats();
return { success: true };
} catch (error) {
return { success: false, error: error.message };
}
};

const handleLogout = () => {
localStorage.removeItem('adminToken');
setIsAuthenticated(false);
setUser(null);
};

if (loading) {
return (




Loading...




);
}

if (!isAuthenticated) {
return ;
}

return (







} />
} />
} />
} />
} />
} />
} />
} />
} />





);
}

export default App;

πŸ§ͺ Test Commands
Login as Admin
bash

curl -X POST http://localhost:4000/api/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"admin@myzubster.com","password":"admin123"}'

Get Dashboard Stats
bash

curl -X GET http://localhost:4000/api/admin/dashboard/stats \
-H "Authorization: Bearer $ADMIN_TOKEN"

List Users
bash

curl -X GET http://localhost:4000/api/admin/users?page=1&limit=20 \
-H "Authorization: Bearer $ADMIN_TOKEN"

Update User Role
bash

curl -X PUT http://localhost:4000/api/admin/users/1 \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"role":"moderator"}'

Get Analytics
bash

curl -X GET "http://localhost:4000/api/admin/analytics?period=month" \
-H "Authorization: Bearer $ADMIN_TOKEN"

βœ… Next Steps

Deploy dashboard – Vercel, Netlify, or Docker

Add real-time updates – WebSocket integration

Implement notifications – Email alerts for admins

Add export functionality – CSV/PDF reports

Write tests – Unit tests for admin endpoints
Enter fullscreen mode Exit fullscreen mode

πŸ“š Resources

React Router: reactrouter.com

Tailwind CSS: tailwindcss.com

Recharts: recharts.org
Enter fullscreen mode Exit fullscreen mode

Built with ❀️ for privacy, freedom, and decentralization.

Happy coding! πŸš€

Top comments (0)