1042 lines
46 KiB
HTML
1042 lines
46 KiB
HTML
{% extends 'base.html' %}
|
|
{% load static %}
|
|
|
|
{% block title %}Dashboard Details - Hospital Management{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="content">
|
|
<div class="container-fluid">
|
|
<!-- Page Header -->
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="page-header">
|
|
<div class="page-title">
|
|
<h4>{{ dashboard.name|default:"Executive Overview" }}</h4>
|
|
<h6>{{ dashboard.description|default:"High-level KPIs and performance metrics for executive decision making" }}</h6>
|
|
</div>
|
|
<div class="page-btn">
|
|
<a href="{% url 'analytics:dashboard_list' %}" class="btn btn-secondary me-2">
|
|
<i class="fas fa-arrow-left me-1"></i>Back to Dashboards
|
|
</a>
|
|
<a href="{% url 'analytics:dashboard_update' dashboard.pk|default:1 %}" class="btn btn-primary me-2">
|
|
<i class="fas fa-edit me-1"></i>Edit Dashboard
|
|
</a>
|
|
<div class="btn-group">
|
|
<button type="button" class="btn btn-outline-secondary dropdown-toggle" data-bs-toggle="dropdown">
|
|
<i class="fas fa-cog me-1"></i>Actions
|
|
</button>
|
|
<ul class="dropdown-menu">
|
|
<li><a class="dropdown-item" href="#" onclick="refreshDashboard()"><i class="fas fa-sync me-2"></i>Refresh Data</a></li>
|
|
<li><a class="dropdown-item" href="#" onclick="exportDashboard()"><i class="fas fa-download me-2"></i>Export Dashboard</a></li>
|
|
<li><a class="dropdown-item" href="#" onclick="shareDashboard()"><i class="fas fa-share me-2"></i>Share Dashboard</a></li>
|
|
<li><a class="dropdown-item" href="#" onclick="duplicateDashboard()"><i class="fas fa-copy me-2"></i>Duplicate</a></li>
|
|
<li><hr class="dropdown-divider"></li>
|
|
<li><a class="dropdown-item" href="#" onclick="toggleFullscreen()"><i class="fas fa-expand me-2"></i>Fullscreen Mode</a></li>
|
|
<li><a class="dropdown-item" href="#" onclick="printDashboard()"><i class="fas fa-print me-2"></i>Print Dashboard</a></li>
|
|
<li><hr class="dropdown-divider"></li>
|
|
<li><a class="dropdown-item text-danger" href="{% url 'analytics:dashboard_delete' dashboard.pk|default:1 %}"><i class="fas fa-trash me-2"></i>Delete Dashboard</a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Dashboard Info -->
|
|
<div class="row mb-4">
|
|
<div class="col-12">
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<div class="col-md-8">
|
|
<div class="dashboard-info">
|
|
<div class="d-flex align-items-center mb-3">
|
|
<span class="badge bg-primary me-3">{{ dashboard.dashboard_type|default:"Executive" }}</span>
|
|
<span class="badge bg-success me-3">
|
|
<i class="fas fa-circle me-1" style="font-size: 8px;"></i>Active
|
|
</span>
|
|
<span class="badge bg-info">
|
|
<i class="fas fa-users me-1"></i>Shared
|
|
</span>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="info-item">
|
|
<label class="form-label">Created By:</label>
|
|
<span class="text-muted">{{ dashboard.created_by|default:"Dr. Sarah Johnson" }}</span>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="info-item">
|
|
<label class="form-label">Created Date:</label>
|
|
<span class="text-muted">{{ dashboard.created_at|default:"2024-01-15" }}</span>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="info-item">
|
|
<label class="form-label">Last Updated:</label>
|
|
<span class="text-muted">{{ dashboard.updated_at|default:"2 hours ago" }}</span>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="info-item">
|
|
<label class="form-label">Refresh Interval:</label>
|
|
<span class="text-muted">{{ dashboard.refresh_interval|default:"5 minutes" }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="dashboard-stats">
|
|
<div class="stat-card">
|
|
<div class="stat-icon">
|
|
<i class="fas fa-th-large text-primary"></i>
|
|
</div>
|
|
<div class="stat-content">
|
|
<h5>{{ dashboard.widget_count|default:8 }}</h5>
|
|
<span>Widgets</span>
|
|
</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-icon">
|
|
<i class="fas fa-eye text-success"></i>
|
|
</div>
|
|
<div class="stat-content">
|
|
<h5>{{ dashboard.view_count|default:1247 }}</h5>
|
|
<span>Views</span>
|
|
</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-icon">
|
|
<i class="fas fa-users text-info"></i>
|
|
</div>
|
|
<div class="stat-content">
|
|
<h5>{{ dashboard.user_count|default:15 }}</h5>
|
|
<span>Users</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Dashboard Controls -->
|
|
<div class="row mb-4">
|
|
<div class="col-12">
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<div class="dashboard-controls">
|
|
<div class="row align-items-center">
|
|
<div class="col-md-6">
|
|
<div class="d-flex align-items-center gap-3">
|
|
<div class="form-group mb-0">
|
|
<label class="form-label mb-1">Date Range:</label>
|
|
<select class="form-select form-select-sm" id="dateRange">
|
|
<option value="today">Today</option>
|
|
<option value="yesterday">Yesterday</option>
|
|
<option value="last7days" selected>Last 7 Days</option>
|
|
<option value="last30days">Last 30 Days</option>
|
|
<option value="thismonth">This Month</option>
|
|
<option value="lastmonth">Last Month</option>
|
|
<option value="custom">Custom Range</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group mb-0">
|
|
<label class="form-label mb-1">Auto Refresh:</label>
|
|
<div class="form-check form-switch">
|
|
<input class="form-check-input" type="checkbox" id="autoRefresh" checked>
|
|
<label class="form-check-label" for="autoRefresh">
|
|
<span id="refreshStatus">On</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="d-flex justify-content-end align-items-center gap-2">
|
|
<button type="button" class="btn btn-outline-primary btn-sm" onclick="addWidget()">
|
|
<i class="fas fa-plus me-1"></i>Add Widget
|
|
</button>
|
|
<button type="button" class="btn btn-outline-secondary btn-sm" onclick="editLayout()">
|
|
<i class="fas fa-edit me-1"></i>Edit Layout
|
|
</button>
|
|
<button type="button" class="btn btn-outline-success btn-sm" onclick="refreshDashboard()">
|
|
<i class="fas fa-sync me-1"></i>Refresh
|
|
</button>
|
|
<div class="last-updated">
|
|
<small class="text-muted">
|
|
<i class="fas fa-clock me-1"></i>
|
|
Last updated: <span id="lastUpdated">2 minutes ago</span>
|
|
</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Dashboard Widgets Grid -->
|
|
<div class="dashboard-grid" id="dashboardGrid">
|
|
<!-- Row 1 -->
|
|
<div class="row mb-4">
|
|
<!-- KPI Widget 1 -->
|
|
<div class="col-lg-3 col-md-6 col-sm-12">
|
|
<div class="widget-card kpi-widget">
|
|
<div class="widget-header">
|
|
<h6 class="widget-title">Total Revenue</h6>
|
|
<div class="widget-actions">
|
|
<div class="dropdown">
|
|
<a href="#" class="dropdown-toggle" data-bs-toggle="dropdown">
|
|
<i class="fas fa-ellipsis-v"></i>
|
|
</a>
|
|
<ul class="dropdown-menu">
|
|
<li><a class="dropdown-item" href="#" onclick="editWidget(1)"><i class="fas fa-edit me-2"></i>Edit</a></li>
|
|
<li><a class="dropdown-item" href="#" onclick="refreshWidget(1)"><i class="fas fa-sync me-2"></i>Refresh</a></li>
|
|
<li><a class="dropdown-item" href="#" onclick="exportWidget(1)"><i class="fas fa-download me-2"></i>Export</a></li>
|
|
<li><hr class="dropdown-divider"></li>
|
|
<li><a class="dropdown-item text-danger" href="#" onclick="removeWidget(1)"><i class="fas fa-trash me-2"></i>Remove</a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="widget-content">
|
|
<div class="kpi-value">
|
|
<h3 class="text-success">$2.4M</h3>
|
|
<div class="kpi-change">
|
|
<span class="change-indicator positive">
|
|
<i class="fas fa-arrow-up"></i>
|
|
+12.5%
|
|
</span>
|
|
<small class="text-muted">vs last month</small>
|
|
</div>
|
|
</div>
|
|
<div class="kpi-chart">
|
|
<canvas id="revenueChart" width="100" height="40"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- KPI Widget 2 -->
|
|
<div class="col-lg-3 col-md-6 col-sm-12">
|
|
<div class="widget-card kpi-widget">
|
|
<div class="widget-header">
|
|
<h6 class="widget-title">Patient Visits</h6>
|
|
<div class="widget-actions">
|
|
<div class="dropdown">
|
|
<a href="#" class="dropdown-toggle" data-bs-toggle="dropdown">
|
|
<i class="fas fa-ellipsis-v"></i>
|
|
</a>
|
|
<ul class="dropdown-menu">
|
|
<li><a class="dropdown-item" href="#" onclick="editWidget(2)"><i class="fas fa-edit me-2"></i>Edit</a></li>
|
|
<li><a class="dropdown-item" href="#" onclick="refreshWidget(2)"><i class="fas fa-sync me-2"></i>Refresh</a></li>
|
|
<li><a class="dropdown-item" href="#" onclick="exportWidget(2)"><i class="fas fa-download me-2"></i>Export</a></li>
|
|
<li><hr class="dropdown-divider"></li>
|
|
<li><a class="dropdown-item text-danger" href="#" onclick="removeWidget(2)"><i class="fas fa-trash me-2"></i>Remove</a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="widget-content">
|
|
<div class="kpi-value">
|
|
<h3 class="text-info">1,847</h3>
|
|
<div class="kpi-change">
|
|
<span class="change-indicator positive">
|
|
<i class="fas fa-arrow-up"></i>
|
|
+8.3%
|
|
</span>
|
|
<small class="text-muted">vs last week</small>
|
|
</div>
|
|
</div>
|
|
<div class="kpi-chart">
|
|
<canvas id="visitsChart" width="100" height="40"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- KPI Widget 3 -->
|
|
<div class="col-lg-3 col-md-6 col-sm-12">
|
|
<div class="widget-card kpi-widget">
|
|
<div class="widget-header">
|
|
<h6 class="widget-title">Bed Occupancy</h6>
|
|
<div class="widget-actions">
|
|
<div class="dropdown">
|
|
<a href="#" class="dropdown-toggle" data-bs-toggle="dropdown">
|
|
<i class="fas fa-ellipsis-v"></i>
|
|
</a>
|
|
<ul class="dropdown-menu">
|
|
<li><a class="dropdown-item" href="#" onclick="editWidget(3)"><i class="fas fa-edit me-2"></i>Edit</a></li>
|
|
<li><a class="dropdown-item" href="#" onclick="refreshWidget(3)"><i class="fas fa-sync me-2"></i>Refresh</a></li>
|
|
<li><a class="dropdown-item" href="#" onclick="exportWidget(3)"><i class="fas fa-download me-2"></i>Export</a></li>
|
|
<li><hr class="dropdown-divider"></li>
|
|
<li><a class="dropdown-item text-danger" href="#" onclick="removeWidget(3)"><i class="fas fa-trash me-2"></i>Remove</a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="widget-content">
|
|
<div class="kpi-value">
|
|
<h3 class="text-warning">87%</h3>
|
|
<div class="kpi-change">
|
|
<span class="change-indicator negative">
|
|
<i class="fas fa-arrow-down"></i>
|
|
-2.1%
|
|
</span>
|
|
<small class="text-muted">vs yesterday</small>
|
|
</div>
|
|
</div>
|
|
<div class="progress mt-2">
|
|
<div class="progress-bar bg-warning" role="progressbar" style="width: 87%"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- KPI Widget 4 -->
|
|
<div class="col-lg-3 col-md-6 col-sm-12">
|
|
<div class="widget-card kpi-widget">
|
|
<div class="widget-header">
|
|
<h6 class="widget-title">Patient Satisfaction</h6>
|
|
<div class="widget-actions">
|
|
<div class="dropdown">
|
|
<a href="#" class="dropdown-toggle" data-bs-toggle="dropdown">
|
|
<i class="fas fa-ellipsis-v"></i>
|
|
</a>
|
|
<ul class="dropdown-menu">
|
|
<li><a class="dropdown-item" href="#" onclick="editWidget(4)"><i class="fas fa-edit me-2"></i>Edit</a></li>
|
|
<li><a class="dropdown-item" href="#" onclick="refreshWidget(4)"><i class="fas fa-sync me-2"></i>Refresh</a></li>
|
|
<li><a class="dropdown-item" href="#" onclick="exportWidget(4)"><i class="fas fa-download me-2"></i>Export</a></li>
|
|
<li><hr class="dropdown-divider"></li>
|
|
<li><a class="dropdown-item text-danger" href="#" onclick="removeWidget(4)"><i class="fas fa-trash me-2"></i>Remove</a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="widget-content">
|
|
<div class="kpi-value">
|
|
<h3 class="text-primary">4.8</h3>
|
|
<div class="rating-stars">
|
|
<i class="fas fa-star text-warning"></i>
|
|
<i class="fas fa-star text-warning"></i>
|
|
<i class="fas fa-star text-warning"></i>
|
|
<i class="fas fa-star text-warning"></i>
|
|
<i class="fas fa-star text-warning"></i>
|
|
</div>
|
|
<div class="kpi-change">
|
|
<span class="change-indicator positive">
|
|
<i class="fas fa-arrow-up"></i>
|
|
+0.2
|
|
</span>
|
|
<small class="text-muted">vs last month</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Row 2 -->
|
|
<div class="row mb-4">
|
|
<!-- Chart Widget 1 -->
|
|
<div class="col-lg-8 col-md-12">
|
|
<div class="widget-card chart-widget">
|
|
<div class="widget-header">
|
|
<h6 class="widget-title">Revenue Trends</h6>
|
|
<div class="widget-actions">
|
|
<div class="btn-group btn-group-sm me-2">
|
|
<button type="button" class="btn btn-outline-secondary active" onclick="changeChartPeriod('7d')">7D</button>
|
|
<button type="button" class="btn btn-outline-secondary" onclick="changeChartPeriod('30d')">30D</button>
|
|
<button type="button" class="btn btn-outline-secondary" onclick="changeChartPeriod('90d')">90D</button>
|
|
<button type="button" class="btn btn-outline-secondary" onclick="changeChartPeriod('1y')">1Y</button>
|
|
</div>
|
|
<div class="dropdown">
|
|
<a href="#" class="dropdown-toggle" data-bs-toggle="dropdown">
|
|
<i class="fas fa-ellipsis-v"></i>
|
|
</a>
|
|
<ul class="dropdown-menu">
|
|
<li><a class="dropdown-item" href="#" onclick="editWidget(5)"><i class="fas fa-edit me-2"></i>Edit</a></li>
|
|
<li><a class="dropdown-item" href="#" onclick="refreshWidget(5)"><i class="fas fa-sync me-2"></i>Refresh</a></li>
|
|
<li><a class="dropdown-item" href="#" onclick="exportWidget(5)"><i class="fas fa-download me-2"></i>Export</a></li>
|
|
<li><hr class="dropdown-divider"></li>
|
|
<li><a class="dropdown-item text-danger" href="#" onclick="removeWidget(5)"><i class="fas fa-trash me-2"></i>Remove</a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="widget-content">
|
|
<canvas id="revenueTrendChart" height="300"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Gauge Widget -->
|
|
<div class="col-lg-4 col-md-12">
|
|
<div class="widget-card gauge-widget">
|
|
<div class="widget-header">
|
|
<h6 class="widget-title">Quality Score</h6>
|
|
<div class="widget-actions">
|
|
<div class="dropdown">
|
|
<a href="#" class="dropdown-toggle" data-bs-toggle="dropdown">
|
|
<i class="fas fa-ellipsis-v"></i>
|
|
</a>
|
|
<ul class="dropdown-menu">
|
|
<li><a class="dropdown-item" href="#" onclick="editWidget(6)"><i class="fas fa-edit me-2"></i>Edit</a></li>
|
|
<li><a class="dropdown-item" href="#" onclick="refreshWidget(6)"><i class="fas fa-sync me-2"></i>Refresh</a></li>
|
|
<li><a class="dropdown-item" href="#" onclick="exportWidget(6)"><i class="fas fa-download me-2"></i>Export</a></li>
|
|
<li><hr class="dropdown-divider"></li>
|
|
<li><a class="dropdown-item text-danger" href="#" onclick="removeWidget(6)"><i class="fas fa-trash me-2"></i>Remove</a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="widget-content text-center">
|
|
<div class="gauge-container">
|
|
<canvas id="qualityGauge" width="200" height="200"></canvas>
|
|
<div class="gauge-value">
|
|
<h3 class="text-success">92%</h3>
|
|
<small class="text-muted">Excellent</small>
|
|
</div>
|
|
</div>
|
|
<div class="gauge-legend mt-3">
|
|
<div class="d-flex justify-content-between">
|
|
<span class="badge bg-danger">Poor</span>
|
|
<span class="badge bg-warning">Fair</span>
|
|
<span class="badge bg-info">Good</span>
|
|
<span class="badge bg-success">Excellent</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Row 3 -->
|
|
<div class="row mb-4">
|
|
<!-- Table Widget -->
|
|
<div class="col-lg-6 col-md-12">
|
|
<div class="widget-card table-widget">
|
|
<div class="widget-header">
|
|
<h6 class="widget-title">Top Departments by Revenue</h6>
|
|
<div class="widget-actions">
|
|
<div class="dropdown">
|
|
<a href="#" class="dropdown-toggle" data-bs-toggle="dropdown">
|
|
<i class="fas fa-ellipsis-v"></i>
|
|
</a>
|
|
<ul class="dropdown-menu">
|
|
<li><a class="dropdown-item" href="#" onclick="editWidget(7)"><i class="fas fa-edit me-2"></i>Edit</a></li>
|
|
<li><a class="dropdown-item" href="#" onclick="refreshWidget(7)"><i class="fas fa-sync me-2"></i>Refresh</a></li>
|
|
<li><a class="dropdown-item" href="#" onclick="exportWidget(7)"><i class="fas fa-download me-2"></i>Export</a></li>
|
|
<li><hr class="dropdown-divider"></li>
|
|
<li><a class="dropdown-item text-danger" href="#" onclick="removeWidget(7)"><i class="fas fa-trash me-2"></i>Remove</a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="widget-content">
|
|
<div class="table-responsive">
|
|
<table class="table table-sm">
|
|
<thead>
|
|
<tr>
|
|
<th>Department</th>
|
|
<th>Revenue</th>
|
|
<th>Change</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>
|
|
<div class="d-flex align-items-center">
|
|
<i class="fas fa-heart text-danger me-2"></i>
|
|
Cardiology
|
|
</div>
|
|
</td>
|
|
<td>$485K</td>
|
|
<td>
|
|
<span class="badge bg-success">+15%</span>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<div class="d-flex align-items-center">
|
|
<i class="fas fa-brain text-info me-2"></i>
|
|
Neurology
|
|
</div>
|
|
</td>
|
|
<td>$392K</td>
|
|
<td>
|
|
<span class="badge bg-success">+8%</span>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<div class="d-flex align-items-center">
|
|
<i class="fas fa-bone text-warning me-2"></i>
|
|
Orthopedics
|
|
</div>
|
|
</td>
|
|
<td>$347K</td>
|
|
<td>
|
|
<span class="badge bg-warning">-2%</span>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<div class="d-flex align-items-center">
|
|
<i class="fas fa-lungs text-primary me-2"></i>
|
|
Pulmonology
|
|
</div>
|
|
</td>
|
|
<td>$298K</td>
|
|
<td>
|
|
<span class="badge bg-success">+12%</span>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<div class="d-flex align-items-center">
|
|
<i class="fas fa-user-md text-secondary me-2"></i>
|
|
Emergency
|
|
</div>
|
|
</td>
|
|
<td>$276K</td>
|
|
<td>
|
|
<span class="badge bg-success">+5%</span>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Pie Chart Widget -->
|
|
<div class="col-lg-6 col-md-12">
|
|
<div class="widget-card chart-widget">
|
|
<div class="widget-header">
|
|
<h6 class="widget-title">Patient Distribution by Age Group</h6>
|
|
<div class="widget-actions">
|
|
<div class="dropdown">
|
|
<a href="#" class="dropdown-toggle" data-bs-toggle="dropdown">
|
|
<i class="fas fa-ellipsis-v"></i>
|
|
</a>
|
|
<ul class="dropdown-menu">
|
|
<li><a class="dropdown-item" href="#" onclick="editWidget(8)"><i class="fas fa-edit me-2"></i>Edit</a></li>
|
|
<li><a class="dropdown-item" href="#" onclick="refreshWidget(8)"><i class="fas fa-sync me-2"></i>Refresh</a></li>
|
|
<li><a class="dropdown-item" href="#" onclick="exportWidget(8)"><i class="fas fa-download me-2"></i>Export</a></li>
|
|
<li><hr class="dropdown-divider"></li>
|
|
<li><a class="dropdown-item text-danger" href="#" onclick="removeWidget(8)"><i class="fas fa-trash me-2"></i>Remove</a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="widget-content">
|
|
<canvas id="ageDistributionChart" height="250"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Widget Management Panel -->
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title">Widget Management</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<h6>Available Widgets</h6>
|
|
<div class="available-widgets">
|
|
<div class="widget-option" draggable="true">
|
|
<i class="fas fa-chart-line me-2"></i>
|
|
Line Chart
|
|
</div>
|
|
<div class="widget-option" draggable="true">
|
|
<i class="fas fa-chart-bar me-2"></i>
|
|
Bar Chart
|
|
</div>
|
|
<div class="widget-option" draggable="true">
|
|
<i class="fas fa-chart-pie me-2"></i>
|
|
Pie Chart
|
|
</div>
|
|
<div class="widget-option" draggable="true">
|
|
<i class="fas fa-table me-2"></i>
|
|
Data Table
|
|
</div>
|
|
<div class="widget-option" draggable="true">
|
|
<i class="fas fa-tachometer-alt me-2"></i>
|
|
Gauge
|
|
</div>
|
|
<div class="widget-option" draggable="true">
|
|
<i class="fas fa-calculator me-2"></i>
|
|
KPI Metric
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<h6>Widget Settings</h6>
|
|
<div class="widget-settings">
|
|
<div class="form-group">
|
|
<label class="form-label">Grid Size</label>
|
|
<select class="form-select">
|
|
<option value="12">12 columns</option>
|
|
<option value="6">6 columns</option>
|
|
<option value="4">4 columns</option>
|
|
<option value="3">3 columns</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="form-label">Auto-arrange</label>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" id="autoArrange">
|
|
<label class="form-check-label" for="autoArrange">
|
|
Automatically arrange widgets
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<button type="button" class="btn btn-primary btn-sm" onclick="saveLayout()">
|
|
<i class="fas fa-save me-1"></i>Save Layout
|
|
</button>
|
|
<button type="button" class="btn btn-outline-secondary btn-sm" onclick="resetLayout()">
|
|
<i class="fas fa-undo me-1"></i>Reset Layout
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Initialize dashboard
|
|
initializeDashboard();
|
|
|
|
// Auto-refresh functionality
|
|
const autoRefreshCheckbox = document.getElementById('autoRefresh');
|
|
autoRefreshCheckbox.addEventListener('change', function() {
|
|
const status = document.getElementById('refreshStatus');
|
|
status.textContent = this.checked ? 'On' : 'Off';
|
|
|
|
if (this.checked) {
|
|
startAutoRefresh();
|
|
} else {
|
|
stopAutoRefresh();
|
|
}
|
|
});
|
|
|
|
// Date range change
|
|
document.getElementById('dateRange').addEventListener('change', function() {
|
|
refreshDashboard();
|
|
});
|
|
|
|
// Initialize charts
|
|
initializeCharts();
|
|
|
|
// Start auto-refresh if enabled
|
|
if (autoRefreshCheckbox.checked) {
|
|
startAutoRefresh();
|
|
}
|
|
});
|
|
|
|
let autoRefreshInterval;
|
|
|
|
function initializeDashboard() {
|
|
console.log('Dashboard initialized');
|
|
updateLastUpdated();
|
|
}
|
|
|
|
function initializeCharts() {
|
|
// Initialize revenue trend chart
|
|
const revenueTrendCtx = document.getElementById('revenueTrendChart');
|
|
if (revenueTrendCtx) {
|
|
// Chart.js implementation would go here
|
|
console.log('Revenue trend chart initialized');
|
|
}
|
|
|
|
// Initialize quality gauge
|
|
const qualityGaugeCtx = document.getElementById('qualityGauge');
|
|
if (qualityGaugeCtx) {
|
|
// Gauge chart implementation would go here
|
|
console.log('Quality gauge initialized');
|
|
}
|
|
|
|
// Initialize age distribution chart
|
|
const ageDistributionCtx = document.getElementById('ageDistributionChart');
|
|
if (ageDistributionCtx) {
|
|
// Pie chart implementation would go here
|
|
console.log('Age distribution chart initialized');
|
|
}
|
|
}
|
|
|
|
function refreshDashboard() {
|
|
console.log('Refreshing dashboard...');
|
|
|
|
// Show loading state
|
|
const widgets = document.querySelectorAll('.widget-card');
|
|
widgets.forEach(widget => {
|
|
widget.style.opacity = '0.7';
|
|
});
|
|
|
|
// Simulate refresh delay
|
|
setTimeout(() => {
|
|
widgets.forEach(widget => {
|
|
widget.style.opacity = '1';
|
|
});
|
|
updateLastUpdated();
|
|
console.log('Dashboard refreshed');
|
|
}, 1000);
|
|
}
|
|
|
|
function startAutoRefresh() {
|
|
autoRefreshInterval = setInterval(() => {
|
|
refreshDashboard();
|
|
}, 300000); // 5 minutes
|
|
}
|
|
|
|
function stopAutoRefresh() {
|
|
if (autoRefreshInterval) {
|
|
clearInterval(autoRefreshInterval);
|
|
}
|
|
}
|
|
|
|
function updateLastUpdated() {
|
|
const lastUpdatedElement = document.getElementById('lastUpdated');
|
|
if (lastUpdatedElement) {
|
|
lastUpdatedElement.textContent = 'Just now';
|
|
}
|
|
}
|
|
|
|
function addWidget() {
|
|
alert('Opening widget selection dialog...');
|
|
}
|
|
|
|
function editLayout() {
|
|
alert('Entering layout edit mode...');
|
|
}
|
|
|
|
function editWidget(widgetId) {
|
|
alert(`Editing widget ${widgetId}...`);
|
|
}
|
|
|
|
function refreshWidget(widgetId) {
|
|
console.log(`Refreshing widget ${widgetId}...`);
|
|
}
|
|
|
|
function exportWidget(widgetId) {
|
|
alert(`Exporting widget ${widgetId}...`);
|
|
}
|
|
|
|
function removeWidget(widgetId) {
|
|
if (confirm(`Remove widget ${widgetId} from dashboard?`)) {
|
|
console.log(`Widget ${widgetId} removed`);
|
|
}
|
|
}
|
|
|
|
function changeChartPeriod(period) {
|
|
console.log(`Changing chart period to ${period}`);
|
|
|
|
// Update button states
|
|
const buttons = document.querySelectorAll('.btn-group button');
|
|
buttons.forEach(btn => btn.classList.remove('active'));
|
|
event.target.classList.add('active');
|
|
}
|
|
|
|
function exportDashboard() {
|
|
alert('Exporting dashboard...');
|
|
}
|
|
|
|
function shareDashboard() {
|
|
alert('Opening sharing options...');
|
|
}
|
|
|
|
function duplicateDashboard() {
|
|
if (confirm('Create a copy of this dashboard?')) {
|
|
alert('Dashboard duplicated successfully!');
|
|
}
|
|
}
|
|
|
|
function toggleFullscreen() {
|
|
if (document.fullscreenElement) {
|
|
document.exitFullscreen();
|
|
} else {
|
|
document.documentElement.requestFullscreen();
|
|
}
|
|
}
|
|
|
|
function printDashboard() {
|
|
window.print();
|
|
}
|
|
|
|
function saveLayout() {
|
|
alert('Layout saved successfully!');
|
|
}
|
|
|
|
function resetLayout() {
|
|
if (confirm('Reset dashboard layout to default?')) {
|
|
alert('Layout reset successfully!');
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style>
|
|
.info-item {
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
.info-item label {
|
|
font-weight: 600;
|
|
margin-bottom: 2px;
|
|
display: block;
|
|
}
|
|
|
|
.dashboard-stats {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 15px;
|
|
}
|
|
|
|
.stat-card {
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 15px;
|
|
background: #f8f9fa;
|
|
border-radius: 8px;
|
|
}
|
|
|
|
.stat-icon {
|
|
width: 50px;
|
|
height: 50px;
|
|
border-radius: 50%;
|
|
background: white;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin-right: 15px;
|
|
font-size: 1.5rem;
|
|
}
|
|
|
|
.stat-content h5 {
|
|
font-size: 1.5rem;
|
|
font-weight: 600;
|
|
margin: 0;
|
|
color: #2c3e50;
|
|
}
|
|
|
|
.stat-content span {
|
|
color: #6c757d;
|
|
font-size: 0.875rem;
|
|
}
|
|
|
|
.dashboard-controls {
|
|
background: #f8f9fa;
|
|
border-radius: 8px;
|
|
padding: 15px;
|
|
}
|
|
|
|
.widget-card {
|
|
border: 1px solid #e9ecef;
|
|
border-radius: 12px;
|
|
background: white;
|
|
margin-bottom: 20px;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.widget-card:hover {
|
|
box-shadow: 0 4px 15px rgba(0,0,0,0.1);
|
|
}
|
|
|
|
.widget-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 15px 20px 10px 20px;
|
|
border-bottom: 1px solid #f1f1f1;
|
|
}
|
|
|
|
.widget-title {
|
|
font-size: 0.875rem;
|
|
font-weight: 600;
|
|
margin: 0;
|
|
color: #2c3e50;
|
|
}
|
|
|
|
.widget-actions .dropdown-toggle {
|
|
color: #6c757d;
|
|
text-decoration: none;
|
|
}
|
|
|
|
.widget-content {
|
|
padding: 20px;
|
|
}
|
|
|
|
.kpi-widget .widget-content {
|
|
padding: 15px 20px;
|
|
}
|
|
|
|
.kpi-value h3 {
|
|
font-size: 2rem;
|
|
font-weight: 700;
|
|
margin: 0;
|
|
}
|
|
|
|
.kpi-change {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
margin-top: 5px;
|
|
}
|
|
|
|
.change-indicator {
|
|
font-size: 0.75rem;
|
|
font-weight: 600;
|
|
padding: 2px 6px;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.change-indicator.positive {
|
|
background: #d4edda;
|
|
color: #155724;
|
|
}
|
|
|
|
.change-indicator.negative {
|
|
background: #f8d7da;
|
|
color: #721c24;
|
|
}
|
|
|
|
.kpi-chart {
|
|
margin-top: 10px;
|
|
height: 40px;
|
|
}
|
|
|
|
.rating-stars {
|
|
margin: 5px 0;
|
|
}
|
|
|
|
.gauge-container {
|
|
position: relative;
|
|
display: inline-block;
|
|
}
|
|
|
|
.gauge-value {
|
|
position: absolute;
|
|
top: 50%;
|
|
left: 50%;
|
|
transform: translate(-50%, -50%);
|
|
text-align: center;
|
|
}
|
|
|
|
.gauge-legend {
|
|
margin-top: 15px;
|
|
}
|
|
|
|
.table-widget .table {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.table-widget .table th {
|
|
border-top: none;
|
|
font-weight: 600;
|
|
color: #2c3e50;
|
|
font-size: 0.875rem;
|
|
}
|
|
|
|
.table-widget .table td {
|
|
vertical-align: middle;
|
|
font-size: 0.875rem;
|
|
}
|
|
|
|
.available-widgets {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
|
gap: 10px;
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.widget-option {
|
|
padding: 15px;
|
|
border: 2px dashed #dee2e6;
|
|
border-radius: 8px;
|
|
text-align: center;
|
|
cursor: move;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.widget-option:hover {
|
|
border-color: #007bff;
|
|
background: #f8f9ff;
|
|
}
|
|
|
|
.widget-settings .form-group {
|
|
margin-bottom: 15px;
|
|
}
|
|
|
|
.last-updated {
|
|
white-space: nowrap;
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.dashboard-controls .row {
|
|
flex-direction: column;
|
|
}
|
|
|
|
.dashboard-controls .col-md-6:first-child {
|
|
margin-bottom: 15px;
|
|
}
|
|
|
|
.dashboard-stats {
|
|
flex-direction: row;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.stat-card {
|
|
flex: 1;
|
|
min-width: 150px;
|
|
}
|
|
|
|
.widget-card {
|
|
margin-bottom: 15px;
|
|
}
|
|
|
|
.available-widgets {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
.last-updated {
|
|
margin-top: 10px;
|
|
}
|
|
}
|
|
|
|
@media print {
|
|
.page-header,
|
|
.dashboard-controls,
|
|
.widget-actions,
|
|
.card:last-child {
|
|
display: none !important;
|
|
}
|
|
|
|
.widget-card {
|
|
break-inside: avoid;
|
|
margin-bottom: 20px;
|
|
}
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|