π 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
π§© 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
- 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();
} 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();
};
};
module.exports = {
adminAuth,
superAdminAuth,
logAdminActivity
};
- 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;
- 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
};
} 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)
}
};
} 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;
} 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' };
} 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)
}
};
} 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;
} 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' };
} 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)
}
};
} 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)
}
};
} 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 };
} 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)
}
};
} 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'
}
};
} 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
};
} 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
};
- 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
π Resources
React Router: reactrouter.com
Tailwind CSS: tailwindcss.com
Recharts: recharts.org
Built with β€οΈ for privacy, freedom, and decentralization.
Happy coding! π
Top comments (0)