PyQt5 Admin Dashboard

Complete implementation of a modern admin dashboard with charts and analytics
Python
import sys
import random
from datetime import datetime, timedelta
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, 
                             QHBoxLayout, QGridLayout, QLabel, QPushButton, 
                             QTableWidget, QTableWidgetItem, QHeaderView,
                             QTabWidget, QProgressBar, QFrame, QSplitter,
                             QLineEdit, QMessageBox, QComboBox, QDateEdit)
from PyQt5.QtCore import Qt, QTimer, QDate
from PyQt5.QtGui import QFont, QPalette, QColor, QLinearGradient, QPainter
from PyQt5.QtChart import QChart, QChartView, QPieSeries, QBarSeries, QBarSet, QBarCategoryAxis, QValueAxis

class GradientWidget(QWidget):
    def __init__(self, color1, color2, parent=None):
        super().__init__(parent)
        self.color1 = color1
        self.color2 = color2

    def paintEvent(self, event):
        painter = QPainter(self)
        gradient = QLinearGradient(0, 0, self.width(), self.height())
        gradient.setColorAt(0.0, self.color1)
        gradient.setColorAt(1.0, self.color2)
        painter.fillRect(self.rect(), gradient)

class StatsCard(QFrame):
    def __init__(self, title, value, subtitle, color1, color2, parent=None):
        super().__init__(parent)
        self.setFrameStyle(QFrame.StyledPanel)
        self.setStyleSheet("""
            QFrame {
                background: qlineargradient(x1:0, y1:0, x2:1, y2:1,
                    stop:0 """ + color1 + """, stop:1 """ + color2 + """);
                border-radius: 10px;
                color: white;
            }
        """)
        self.setMinimumHeight(120)
        
        layout = QVBoxLayout()
        
        # Title
        title_label = QLabel(title)
        title_label.setStyleSheet("font-size: 14px; font-weight: bold; color: white;")
        title_label.setAlignment(Qt.AlignCenter)
        
        # Value
        value_label = QLabel(str(value))
        value_label.setStyleSheet("font-size: 28px; font-weight: bold; color: white;")
        value_label.setAlignment(Qt.AlignCenter)
        
        # Subtitle
        subtitle_label = QLabel(subtitle)
        subtitle_label.setStyleSheet("font-size: 12px; color: rgba(255,255,255,0.8);")
        subtitle_label.setAlignment(Qt.AlignCenter)
        
        layout.addWidget(title_label)
        layout.addWidget(value_label)
        layout.addWidget(subtitle_label)
        self.setLayout(layout)

class AdminDashboard(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Admin Dashboard v1.0")
        self.setGeometry(100, 100, 1400, 900)
        self.setup_ui()
        self.setup_data()
        self.setup_charts()
        
    def setup_ui(self):
        # Central widget
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        
        # Main layout
        main_layout = QVBoxLayout(central_widget)
        
        # Header
        header = self.create_header()
        main_layout.addWidget(header)
        
        # Stats cards
        stats_section = self.create_stats_section()
        main_layout.addWidget(stats_section)
        
        # Main content area
        content_splitter = QSplitter(Qt.Horizontal)
        
        # Left side - Charts and tables
        left_widget = QWidget()
        left_layout = QVBoxLayout(left_widget)
        
        # Tabs for different sections
        self.tabs = QTabWidget()
        
        # Overview Tab
        overview_tab = self.create_overview_tab()
        self.tabs.addTab(overview_tab, "Overview")
        
        # Users Tab
        users_tab = self.create_users_tab()
        self.tabs.addTab(users_tab, "Users")
        
        # Analytics Tab
        analytics_tab = self.create_analytics_tab()
        self.tabs.addTab(analytics_tab, "Analytics")
        
        left_layout.addWidget(self.tabs)
        content_splitter.addWidget(left_widget)
        
        # Right side - Quick actions and recent activity
        right_widget = self.create_sidebar()
        content_splitter.addWidget(right_widget)
        
        content_splitter.setSizes([1000, 400])
        main_layout.addWidget(content_splitter)
        
        # Status bar
        self.statusBar().showMessage("Dashboard loaded successfully | System Ready")
        
    def create_header(self):
        header = QWidget()
        header.setStyleSheet("background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #2c3e50, stop:1 #3498db);")
        header.setFixedHeight(80)
        
        layout = QHBoxLayout(header)
        
        # Title
        title = QLabel("Admin Dashboard")
        title.setStyleSheet("font-size: 28px; font-weight: bold; color: white; padding: 10px;")
        
        # Spacer
        spacer = QWidget()
        spacer.setSizePolicy(QWidget.Expanding, QWidget.Preferred)
        
        # User info
        user_widget = QWidget()
        user_layout = QHBoxLayout(user_widget)
        
        user_icon = QLabel("👤")
        user_icon.setStyleSheet("font-size: 20px;")
        user_name = QLabel("Administrator")
        user_name.setStyleSheet("font-size: 14px; color: white;")
        
        user_layout.addWidget(user_icon)
        user_layout.addWidget(user_name)
        
        layout.addWidget(title)
        layout.addWidget(spacer)
        layout.addWidget(user_widget)
        
        return header
    
    def create_stats_section(self):
        widget = QWidget()
        layout = QGridLayout(widget)
        
        # Create stats cards
        self.total_users_card = StatsCard("Total Users", "1,234", "+12% this month", "#3498db", "#2c3e50")
        self.revenue_card = StatsCard("Revenue", "$45,678", "+8.2% increase", "#27ae60", "#2ecc71")
        self.orders_card = StatsCard("Orders", "567", "23 new today", "#e74c3c", "#c0392b")
        self.conversion_card = StatsCard("Conversion", "3.2%", "+0.5% from last week", "#f39c12", "#d35400")
        
        layout.addWidget(self.total_users_card, 0, 0)
        layout.addWidget(self.revenue_card, 0, 1)
        layout.addWidget(self.orders_card, 0, 2)
        layout.addWidget(self.conversion_card, 0, 3)
        
        return widget
    
    def create_overview_tab(self):
        widget = QWidget()
        layout = QVBoxLayout(widget)
        
        # Charts section
        charts_widget = QWidget()
        charts_layout = QHBoxLayout(charts_widget)
        
        # Pie chart
        self.pie_chart_view = QChartView()
        self.pie_chart_view.setMinimumHeight(300)
        
        # Bar chart
        self.bar_chart_view = QChartView()
        self.bar_chart_view.setMinimumHeight(300)
        
        charts_layout.addWidget(self.pie_chart_view)
        charts_layout.addWidget(self.bar_chart_view)
        
        layout.addWidget(charts_widget)
        
        # Recent activity table
        recent_label = QLabel("Recent Activity")
        recent_label.setStyleSheet("font-size: 18px; font-weight: bold; margin: 10px;")
        layout.addWidget(recent_label)
        
        self.activity_table = QTableWidget()
        self.activity_table.setColumnCount(4)
        self.activity_table.setHorizontalHeaderLabels(["User", "Action", "Time", "Status"])
        self.activity_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        layout.addWidget(self.activity_table)
        
        return widget
    
    def create_users_tab(self):
        widget = QWidget()
        layout = QVBoxLayout(widget)
        
        # User management controls
        controls_layout = QHBoxLayout()
        
        self.search_input = QLineEdit()
        self.search_input.setPlaceholderText("Search users...")
        self.search_input.setStyleSheet("padding: 8px; border-radius: 5px; border: 1px solid #ddd;")
        
        self.filter_combo = QComboBox()
        self.filter_combo.addItems(["All Users", "Active", "Inactive", "Admin"])
        
        add_user_btn = QPushButton("Add User")
        add_user_btn.setStyleSheet("""
            QPushButton {
                background-color: #3498db;
                color: white;
                border: none;
                padding: 8px 16px;
                border-radius: 5px;
                font-weight: bold;
            }
            QPushButton:hover {
                background-color: #2980b9;
            }
        """)
        
        controls_layout.addWidget(QLabel("Search:"))
        controls_layout.addWidget(self.search_input)
        controls_layout.addWidget(QLabel("Filter:"))
        controls_layout.addWidget(self.filter_combo)
        controls_layout.addWidget(add_user_btn)
        controls_layout.addStretch()
        
        layout.addLayout(controls_layout)
        
        # Users table
        self.users_table = QTableWidget()
        self.users_table.setColumnCount(6)
        self.users_table.setHorizontalHeaderLabels(["ID", "Name", "Email", "Role", "Status", "Actions"])
        self.users_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        layout.addWidget(self.users_table)
        
        # Connect signals
        add_user_btn.clicked.connect(self.add_user_dialog)
        
        return widget
    
    def create_analytics_tab(self):
        widget = QWidget()
        layout = QVBoxLayout(widget)
        
        # Date range selector
        date_layout = QHBoxLayout()
        date_layout.addWidget(QLabel("From:"))
        self.from_date = QDateEdit()
        self.from_date.setDate(QDate.currentDate().addDays(-30))
        date_layout.addWidget(self.from_date)
        
        date_layout.addWidget(QLabel("To:"))
        self.to_date = QDateEdit()
        self.to_date.setDate(QDate.currentDate())
        date_layout.addWidget(self.to_date)
        
        update_btn = QPushButton("Update Analytics")
        update_btn.clicked.connect(self.update_analytics)
        date_layout.addWidget(update_btn)
        date_layout.addStretch()
        
        layout.addLayout(date_layout)
        
        # Analytics content
        analytics_label = QLabel("Advanced Analytics")
        analytics_label.setStyleSheet("font-size: 18px; font-weight: bold; margin: 10px;")
        layout.addWidget(analytics_label)
        
        # Placeholder for more analytics content
        analytics_content = QLabel("Advanced analytics charts and metrics will be displayed here...")
        analytics_content.setAlignment(Qt.AlignCenter)
        analytics_content.setStyleSheet("font-size: 16px; color: #7f8c8d; margin: 50px;")
        layout.addWidget(analytics_content)
        
        return widget
    
    def create_sidebar(self):
        widget = QWidget()
        widget.setMaximumWidth(400)
        layout = QVBoxLayout(widget)
        
        # Quick Actions
        quick_actions_frame = QFrame()
        quick_actions_frame.setFrameStyle(QFrame.StyledPanel)
        quick_actions_frame.setStyleSheet("background-color: #f8f9fa; border-radius: 10px; padding: 10px;")
        quick_layout = QVBoxLayout(quick_actions_frame)
        
        quick_title = QLabel("Quick Actions")
        quick_title.setStyleSheet("font-size: 16px; font-weight: bold; margin-bottom: 10px;")
        quick_layout.addWidget(quick_title)
        
        # Action buttons
        actions = [
            ("📊 Generate Report", self.generate_report),
            ("👥 Manage Users", self.manage_users),
            ("⚙️ System Settings", self.system_settings),
            ("🔒 Security", self.security_settings),
            ("📈 View Analytics", self.view_analytics)
        ]
        
        for text, slot in actions:
            btn = QPushButton(text)
            btn.setStyleSheet("""
                QPushButton {
                    text-align: left;
                    padding: 10px;
                    border: 1px solid #ddd;
                    border-radius: 5px;
                    margin: 2px;
                    background-color: white;
                }
                QPushButton:hover {
                    background-color: #e9ecef;
                }
            """)
            btn.clicked.connect(slot)
            quick_layout.addWidget(btn)
        
        layout.addWidget(quick_actions_frame)
        
        # System Status
        status_frame = QFrame()
        status_frame.setFrameStyle(QFrame.StyledPanel)
        status_frame.setStyleSheet("background-color: #f8f9fa; border-radius: 10px; padding: 10px; margin-top: 10px;")
        status_layout = QVBoxLayout(status_frame)
        
        status_title = QLabel("System Status")
        status_title.setStyleSheet("font-size: 16px; font-weight: bold; margin-bottom: 10px;")
        status_layout.addWidget(status_title)
        
        # Status indicators
        status_items = [
            ("Server Load", 65),
            ("Database", 90),
            ("Storage", 45),
            ("Network", 78)
        ]
        
        for name, value in status_items:
            item_layout = QHBoxLayout()
            item_layout.addWidget(QLabel(name))
            progress = QProgressBar()
            progress.setValue(value)
            progress.setStyleSheet("""
                QProgressBar {
                    border: 1px solid #ddd;
                    border-radius: 5px;
                    text-align: center;
                }
                QProgressBar::chunk {
                    background-color: #3498db;
                    border-radius: 4px;
                }
            """)
            item_layout.addWidget(progress)
            status_layout.addLayout(item_layout)
        
        layout.addWidget(status_frame)
        
        # Recent Notifications
        notifications_frame = QFrame()
        notifications_frame.setFrameStyle(QFrame.StyledPanel)
        notifications_frame.setStyleSheet("background-color: #f8f9fa; border-radius: 10px; padding: 10px; margin-top: 10px;")
        notif_layout = QVBoxLayout(notifications_frame)
        
        notif_title = QLabel("Recent Notifications")
        notif_title.setStyleSheet("font-size: 16px; font-weight: bold; margin-bottom: 10px;")
        notif_layout.addWidget(notif_title)
        
        # Sample notifications
        notifications = [
            ("🔔 New user registration", "2 min ago"),
            ("⚠️ System backup completed", "1 hour ago"),
            ("✅ Update available", "2 hours ago"),
            ("📈 Performance alert", "5 hours ago")
        ]
        
        for text, time in notifications:
            notif_layout.addWidget(QLabel(f"{text}
{time}")) layout.addWidget(notifications_frame) layout.addStretch() return widget def setup_data(self): # Sample user data self.users = [ {"id": 1, "name": "John Doe", "email": "john@example.com", "role": "Admin", "status": "Active"}, {"id": 2, "name": "Jane Smith", "email": "jane@example.com", "role": "User", "status": "Active"}, {"id": 3, "name": "Bob Johnson", "email": "bob@example.com", "role": "Moderator", "status": "Inactive"}, {"id": 4, "name": "Alice Brown", "email": "alice@example.com", "role": "User", "status": "Active"}, ] # Sample activity data self.activities = [ {"user": "John Doe", "action": "Login", "time": "10:30 AM", "status": "Success"}, {"user": "Jane Smith", "action": "Password Change", "time": "10:25 AM", "status": "Success"}, {"user": "Bob Johnson", "action": "Login", "time": "09:45 AM", "status": "Failed"}, {"user": "Alice Brown", "action": "Profile Update", "time": "09:30 AM", "status": "Success"}, ] self.populate_users_table() self.populate_activity_table() def setup_charts(self): # Setup pie chart pie_series = QPieSeries() pie_series.append("Active Users", 70) pie_series.append("Inactive Users", 20) pie_series.append("New Users", 10) pie_chart = QChart() pie_chart.addSeries(pie_series) pie_chart.setTitle("User Distribution") pie_chart.setAnimationOptions(QChart.SeriesAnimations) self.pie_chart_view.setChart(pie_chart) # Setup bar chart bar_set = QBarSet("Monthly Revenue") bar_set.append([15000, 28000, 35000, 45000, 32000, 40000]) bar_series = QBarSeries() bar_series.append(bar_set) bar_chart = QChart() bar_chart.addSeries(bar_series) bar_chart.setTitle("Revenue Overview") bar_chart.setAnimationOptions(QChart.SeriesAnimations) categories = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"] axis_x = QBarCategoryAxis() axis_x.append(categories) bar_chart.addAxis(axis_x, Qt.AlignBottom) bar_series.attachAxis(axis_x) axis_y = QValueAxis() axis_y.setRange(0, 50000) bar_chart.addAxis(axis_y, Qt.AlignLeft) bar_series.attachAxis(axis_y) self.bar_chart_view.setChart(bar_chart) def populate_users_table(self): self.users_table.setRowCount(len(self.users)) for row, user in enumerate(self.users): self.users_table.setItem(row, 0, QTableWidgetItem(str(user["id"]))) self.users_table.setItem(row, 1, QTableWidgetItem(user["name"])) self.users_table.setItem(row, 2, QTableWidgetItem(user["email"])) self.users_table.setItem(row, 3, QTableWidgetItem(user["role"])) self.users_table.setItem(row, 4, QTableWidgetItem(user["status"])) # Action buttons cell action_widget = QWidget() action_layout = QHBoxLayout(action_widget) edit_btn = QPushButton("Edit") edit_btn.setStyleSheet("padding: 2px 5px; font-size: 10px;") delete_btn = QPushButton("Delete") delete_btn.setStyleSheet("padding: 2px 5px; font-size: 10px; background-color: #e74c3c; color: white;") action_layout.addWidget(edit_btn) action_layout.addWidget(delete_btn) action_layout.setContentsMargins(2, 2, 2, 2) self.users_table.setCellWidget(row, 5, action_widget) def populate_activity_table(self): self.activity_table.setRowCount(len(self.activities)) for row, activity in enumerate(self.activities): self.activity_table.setItem(row, 0, QTableWidgetItem(activity["user"])) self.activity_table.setItem(row, 1, QTableWidgetItem(activity["action"])) self.activity_table.setItem(row, 2, QTableWidgetItem(activity["time"])) self.activity_table.setItem(row, 3, QTableWidgetItem(activity["status"])) def add_user_dialog(self): QMessageBox.information(self, "Add User", "Add user functionality would be implemented here.") def generate_report(self): QMessageBox.information(self, "Generate Report", "Report generation started...") def manage_users(self): self.tabs.setCurrentIndex(1) # Switch to Users tab QMessageBox.information(self, "Manage Users", "User management panel opened.") def system_settings(self): QMessageBox.information(self, "System Settings", "System settings panel would open here.") def security_settings(self): QMessageBox.information(self, "Security", "Security settings panel would open here.") def view_analytics(self): self.tabs.setCurrentIndex(2) # Switch to Analytics tab def update_analytics(self): QMessageBox.information(self, "Update Analytics", "Analytics data updated for selected date range.") def main(): app = QApplication(sys.argv) # Set application style app.setStyleSheet(""" QMainWindow { background-color: #ecf0f1; } QTabWidget::pane { border: 1px solid #bdc3c7; border-radius: 5px; } QTabBar::tab { background-color: #bdc3c7; padding: 8px 16px; margin-right: 2px; border-top-left-radius: 5px; border-top-right-radius: 5px; } QTabBar::tab:selected { background-color: #3498db; color: white; } """) dashboard = AdminDashboard() dashboard.show() sys.exit(app.exec_()) if __name__ == "__main__": main()