help@rskworld.in +91 93305 39277
RSK World
  • Home
  • Development
    • Web Development
    • Mobile Apps
    • Software
    • Games
    • Project
  • Technologies
    • Data Science
    • AI Development
    • Cloud Development
    • Blockchain
    • Cyber Security
    • Dev Tools
    • Testing Tools
  • About
  • Contact

Theme Settings

Color Scheme
Display Options
Font Size
100%
Back to Project
RSK World
nlp-text-analysis-bot
/
templates
RSK World
nlp-text-analysis-bot
NLP Text Analysis Bot - Python + NLP + Flask + Machine Learning + Text Analysis + AI
templates
  • admin.html10.8 KB
  • index.html3.4 KB
admin.html
templates/admin.html
Raw Download
Find: Go to:
<!--
Project: Customer Service Bot
Author: RSK World
Website: https://rskworld.in
Contact: info@rskworld.com, support@rskworld.com
Phone: +91 93305 39277
Year: 2026
-->
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Admin Dashboard - Customer Service Bot</title>
    <!-- Icons -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <!-- Google Fonts -->
    <link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;700&display=swap" rel="stylesheet">
    <!-- Charts.js -->
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

    <style>
        :root {
            --bg-color: #0f172a;
            --card-bg: #1e293b;
            --text-color: #e2e8f0;
            --accent: #8b5cf6;
            --danger: #ef4444;
            --success: #22c55e;
            --warning: #f59e0b;
        }

        body {
            font-family: 'Outfit', sans-serif;
            background-color: var(--bg-color);
            color: var(--text-color);
            margin: 0;
            padding: 20px;
        }

        .container {
            max-width: 1200px;
            margin: 0 auto;
        }

        .header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 30px;
            border-bottom: 1px solid rgba(255, 255, 255, 0.1);
            padding-bottom: 20px;
        }

        .header h1 {
            margin: 0;
        }

        .stats-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
            gap: 20px;
            margin-bottom: 40px;
        }

        .stat-card {
            background: var(--card-bg);
            padding: 20px;
            border-radius: 12px;
            border: 1px solid rgba(255, 255, 255, 0.05);
            text-align: center;
        }

        .stat-card h3 {
            margin: 0 0 10px 0;
            color: #94a3b8;
            font-weight: 500;
        }

        .stat-card .number {
            font-size: 2.5rem;
            font-weight: 700;
            color: var(--accent);
        }

        /* Charts Section */
        .charts-container {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 20px;
            margin-bottom: 40px;
        }

        .chart-wrapper {
            background: var(--card-bg);
            padding: 20px;
            border-radius: 12px;
            border: 1px solid rgba(255, 255, 255, 0.05);
            height: 300px;
        }

        .tickets-table {
            width: 100%;
            border-collapse: collapse;
            background: var(--card-bg);
            border-radius: 12px;
            overflow: hidden;
            margin-top: 20px;
        }

        .tickets-table th,
        .tickets-table td {
            padding: 15px;
            text-align: left;
            border-bottom: 1px solid rgba(255, 255, 255, 0.05);
        }

        .tickets-table th {
            background: rgba(0, 0, 0, 0.2);
            font-weight: 600;
            color: #94a3b8;
        }

        .badge {
            padding: 4px 8px;
            border-radius: 6px;
            font-size: 0.8rem;
            font-weight: 600;
        }

        .badge.open {
            background: rgba(34, 197, 94, 0.2);
            color: var(--success);
        }

        .badge.closed {
            background: rgba(148, 163, 184, 0.2);
            color: #94a3b8;
        }

        .badge.priority-High {
            background: rgba(239, 68, 68, 0.2);
            color: var(--danger);
        }

        .badge.priority-Normal {
            background: rgba(59, 130, 246, 0.2);
            color: #60a5fa;
        }

        .badge.priority-Medium {
            background: rgba(245, 158, 11, 0.2);
            color: var(--warning);
        }

        .action-btn {
            background: rgba(255, 255, 255, 0.1);
            border: none;
            color: white;
            text-decoration: none;
            padding: 8px 16px;
            border-radius: 6px;
            cursor: pointer;
            transition: all 0.2s;
            display: inline-flex;
            align-items: center;
            gap: 8px;
            font-size: 0.9rem;
        }

        .action-btn.export {
            background: var(--success);
            color: #fff;
        }

        .action-btn:hover {
            opacity: 0.9;
        }

        .author-footer {
            margin-top: 50px;
            text-align: center;
            color: #64748b;
            font-size: 0.9rem;
        }
    </style>
</head>

<body>
    <div class="container">
        <div class="header">
            <div>
                <h1>Admin Dashboard</h1>
                <p>Manage Support Tickets</p>
            </div>
            <div style="display: flex; gap: 10px;">
                <a href="/admin/export" class="action-btn export"><i class="fas fa-file-csv"></i> Export CSV</a>
                <a href="/" class="action-btn"><i class="fas fa-home"></i> Back to Bot</a>
            </div>
        </div>

        <!-- Stats -->
        <div class="stats-grid">
            <div class="stat-card">
                <h3>Total Tickets</h3>
                <div class="number">{{ stats.total }}</div>
            </div>
            <div class="stat-card">
                <h3>Open Tickets</h3>
                <div class="number" style="color: var(--success);">{{ stats.open }}</div>
            </div>
            <div class="stat-card">
                <h3>High Priority</h3>
                <div class="number" style="color: var(--danger);">{{ stats.high_priority }}</div>
            </div>
        </div>

        <!-- Charts -->
        <div class="charts-container">
            <div class="chart-wrapper">
                <canvas id="statusChart"></canvas>
            </div>
            <div class="chart-wrapper">
                <canvas id="priorityChart"></canvas>
            </div>
        </div>

        <!-- Table -->
        <h2 style="margin-bottom: 20px;">Recent Tickets</h2>
        <table class="tickets-table">
            <thead>
                <tr>
                    <th>ID</th>
                    <th>Issue</th>
                    <th>Contact</th>
                    <th>Priority</th>
                    <th>Status</th>
                    <th>Date</th>
                    <th>Actions</th>
                </tr>
            </thead>
            <tbody>
                {% for ticket in tickets %}
                <tr>
                    <td>#{{ ticket.id }}</td>
                    <td>{{ ticket.issue }}</td>
                    <td>{{ ticket.contact }}</td>
                    <td><span class="badge priority-{{ ticket.priority }}">{{ ticket.priority }}</span></td>
                    <td><span class="badge {{ ticket.status|lower }}">{{ ticket.status }}</span></td>
                    <td>{{ ticket.created_at[:10] }}</td>
                    <td>
                        {% if ticket.status == 'Open' %}
                        <button class="action-btn" style="padding: 6px 12px; background: rgba(255,255,255,0.1);"
                            data-id="{{ ticket.id }}" onclick="closeTicket(this.dataset.id)">Close</button>
                        {% else %}
                        <span style="color: #64748b;">Archived</span>
                        {% endif %}
                    </td>
                </tr>
                {% endfor %}
            </tbody>
        </table>

        <div class="author-footer">
            <p>Admin Panel by <strong>RSK World</strong></p>
            <p>2026 &copy; All Rights Reserved.</p>
        </div>
    </div>

    <!-- Chart Config -->
    <script id="tickets-data" type="application/json">
        {{ tickets | tojson }}
    </script>
    <script>
        // Data for charts
        const tickets = JSON.parse(document.getElementById('tickets-data').textContent);

        const openCount = tickets.filter(t => t.status === 'Open').length;
        const closedCount = tickets.filter(t => t.status === 'Closed').length;

        const highCount = tickets.filter(t => t.priority === 'High').length;
        const medCount = tickets.filter(t => t.priority === 'Medium').length;
        const normCount = tickets.filter(t => t.priority === 'Normal').length;

        // Status Chart
        new Chart(document.getElementById('statusChart'), {
            type: 'doughnut',
            data: {
                labels: ['Open', 'Closed'],
                datasets: [{
                    data: [openCount, closedCount],
                    backgroundColor: ['#22c55e', '#94a3b8'],
                    borderWidth: 0
                }]
            },
            options: {
                responsive: true,
                maintainAspectRatio: false,
                plugins: {
                    legend: { position: 'bottom', labels: { color: '#e2e8f0' } },
                    title: { display: true, text: 'Ticket Status', color: '#e2e8f0' }
                }
            }
        });

        // Priority Chart
        new Chart(document.getElementById('priorityChart'), {
            type: 'bar',
            data: {
                labels: ['High', 'Medium', 'Normal'],
                datasets: [{
                    label: 'Tickets',
                    data: [highCount, medCount, normCount],
                    backgroundColor: ['#ef4444', '#f59e0b', '#3b82f6'],
                    borderWidth: 0
                }]
            },
            options: {
                responsive: true,
                maintainAspectRatio: false,
                scales: {
                    y: { beginAtZero: true, grid: { color: 'rgba(255,255,255,0.1)' }, ticks: { color: '#94a3b8' } },
                    x: { grid: { display: false }, ticks: { color: '#94a3b8' } }
                },
                plugins: {
                    legend: { display: false },
                    title: { display: true, text: 'Ticket Priority Distribution', color: '#e2e8f0' }
                }
            }
        });

        function closeTicket(id) {
            if (confirm('Are you sure you want to close this ticket?')) {
                fetch(`/api/ticket/${id}/close`, { method: 'POST' })
                    .then(res => res.json())
                    .then(data => {
                        if (data.status === 'success') {
                            location.reload();
                        }
                    });
            }
        }
    </script>
</body>

</html>
347 lines•10.8 KB
markup

About RSK World

Founded by Molla Samser, with Designer & Tester Rima Khatun, RSK World is your one-stop destination for free programming resources, source code, and development tools.

Founder: Molla Samser
Designer & Tester: Rima Khatun

Development

  • Game Development
  • Web Development
  • Mobile Development
  • AI Development
  • Development Tools

Legal

  • Terms & Conditions
  • Privacy Policy
  • Disclaimer

Contact Info

Nutanhat, Mongolkote
Purba Burdwan, West Bengal
India, 713147

+91 93305 39277

hello@rskworld.in
support@rskworld.in

© 2026 RSK World. All rights reserved.

Content used for educational purposes only. View Disclaimer