You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

173 lines
7.9 KiB

{% extends "admin/base_site.html" %}
{% load i18n unfold %}
{% block breadcrumbs %}{% endblock %}
{% block title %}
{% trans 'Dashboard' %} | {{ site_title|default:_('Django site admin') }}
{% endblock %}
{% block branding %}
{% include "unfold/helpers/site_branding.html" %}
{% endblock %}
{% block content %}
{% include "unfold/helpers/messages.html" %}
<div class="mb-6">
<h1 class="text-2xl font-semibold text-gray-900 dark:text-gray-100">
{% trans 'System Overview' %}
</h1>
</div>
<!-- Top Row: KPI Cards using Unfold Native Components -->
<div class="grid gap-4 mb-8 md:grid-cols-2 lg:grid-cols-3">
{% for item in kpi %}
{% component "unfold/components/card.html" %}
{% component "unfold/components/text.html" %}
{{ item.title }}
{% endcomponent %}
<div class="mt-2">
{% component "unfold/components/title.html" %}
{{ item.metric }}
{% endcomponent %}
</div>
{% if item.footer %}
<div class="mt-4 text-sm">
{{ item.footer|safe }}
</div>
{% endif %}
{% endcomponent %}
{% empty %}
<p class="text-gray-500 dark:text-gray-400 col-span-full">
{% trans "No statistics available for this panel." %}
</p>
{% endfor %}
</div>
<!-- Bottom Row: Top Courses List & Donut Chart -->
{% if top_courses %}
<div class="grid gap-4 md:grid-cols-3 items-start">
<!-- Left Column: Top 5 Courses -->
<div class="md:col-span-2">
{% component "unfold/components/card.html" %}
<div class="border-b border-gray-200 dark:border-gray-700 pb-4 mb-2">
<h3 class="text-lg font-medium text-gray-900 dark:text-white">{% trans "Top 5 Popular Courses" %}</h3>
</div>
<ul class="divide-y divide-gray-200 dark:divide-gray-700">
{% for course in top_courses %}
<li class="py-5 flex items-center justify-between transition-colors">
<div class="flex items-center gap-5">
<!-- UPGRADED PERFECT CIRCLE BADGE -->
<span
class="flex-shrink-0 flex items-center justify-center rounded-full bg-primary-100 text-primary-700 dark:bg-primary-900/30 dark:text-primary-400 font-extrabold text-xl border-2 border-primary-300 dark:border-primary-700"
style="width: 2rem; height: 2rem; min-width: 2rem; min-height: 2rem;">
{{ forloop.counter }}
</span>
<div>
<p class="text-base font-semibold text-gray-900 dark:text-white mb-1">{{ course.title }}</p>
<p class="text-sm text-gray-500 dark:text-gray-400">By
{% if course.professor.fullname %}
{{ course.professor.fullname }}
{% else %}
{{ course.professor.email|default:"Unknown" }}
{% endif %}
</p>
</div>
</div>
<span
class="flex-shrink-0 inline-flex items-center px-4 py-1.5 rounded-full text-sm font-bold bg-primary-100 text-primary-800 dark:bg-primary-900/40 dark:text-primary-300 border border-primary-200 dark:border-primary-700 shadow-sm">
{{ course.participant_count }} {% trans "Participants" %}
</span>
</li>
{% empty %}
<li class="py-4 text-sm text-gray-500">{% trans "No courses found." %}</li>
{% endfor %}
</ul>
{% endcomponent %}
</div>
<!-- Right Column: Success Rate Donut Chart -->
<div>
{% component "unfold/components/card.html" %}
<div class="flex flex-col items-center justify-center text-center py-2">
<h3 class="text-lg font-medium text-gray-900 dark:text-white mb-6">{% trans "Transaction Status" %}
</h3>
{% if tx_stats.total > 0 %}
<!-- Multi-Segment CSS SVG Donut -->
<div class="relative w-40 h-40 mb-8">
<svg class="w-full h-full transform -rotate-90" viewBox="0 0 36 36" xmlns="http://www.w3.org/2000/svg">
<!-- Base Background (Failed - Red) -->
<circle cx="18" cy="18" r="16" fill="none" style="color: #ef4444;" stroke="currentColor"
stroke-width="4" />
<!-- Layer 3: Waiting Approval (Bright Blue) -->
<circle cx="18" cy="18" r="16" fill="none" class="transition-all duration-1000 ease-out"
style="color: #3b82f6;" stroke="currentColor" stroke-width="4" stroke-dasharray="100 100"
stroke-dashoffset="{{ tx_stats.offset_waiting }}" />
<!-- Layer 2: Pending (Yellow) -->
<circle cx="18" cy="18" r="16" fill="none" class="transition-all duration-1000 ease-out"
style="color: #facc15;" stroke="currentColor" stroke-width="4" stroke-dasharray="100 100"
stroke-dashoffset="{{ tx_stats.offset_pending }}" />
<!-- Layer 1: Success (Green) -->
<circle cx="18" cy="18" r="16" fill="none" class="transition-all duration-1000 ease-out"
style="color: #22c55e;" stroke="currentColor" stroke-width="4" stroke-dasharray="100 100"
stroke-dashoffset="{{ tx_stats.offset_success }}" />
</svg>
<div class="absolute inset-0 flex flex-col items-center justify-center">
<span class="text-3xl font-bold text-gray-900 dark:text-white">{{ tx_stats.pct_success }}%</span>
<span class="text-xs text-gray-500">{% trans "Success" %}</span>
</div>
</div>
<!-- Legend -->
<div class="w-full grid grid-cols-2 gap-y-3 gap-x-2 text-sm text-left">
<div class="flex items-center gap-2">
<span class="w-3 h-3 rounded-full flex-shrink-0" style="background-color: #22c55e;"></span>
<span class="text-gray-600 dark:text-gray-300">{% trans "Success" %}: <strong
class="text-gray-900 dark:text-white">{{ tx_stats.pct_success }}%</strong></span>
</div>
<div class="flex items-center gap-2">
<span class="w-3 h-3 rounded-full flex-shrink-0" style="background-color: #facc15;"></span>
<span class="text-gray-600 dark:text-gray-300">{% trans "Pending" %}: <strong
class="text-gray-900 dark:text-white">{{ tx_stats.pct_pending }}%</strong></span>
</div>
<div class="flex items-center gap-2">
<span class="w-3 h-3 rounded-full flex-shrink-0" style="background-color: #3b82f6;"></span>
<span class="text-gray-600 dark:text-gray-300">{% trans "Waiting" %}: <strong
class="text-gray-900 dark:text-white">{{ tx_stats.pct_waiting }}%</strong></span>
</div>
<div class="flex items-center gap-2">
<span class="w-3 h-3 rounded-full flex-shrink-0" style="background-color: #ef4444;"></span>
<span class="text-gray-600 dark:text-gray-300">{% trans "Failed" %}: <strong
class="text-gray-900 dark:text-white">{{ tx_stats.pct_failed }}%</strong></span>
</div>
</div>
{% else %}
<div class="py-12 flex flex-col items-center justify-center">
<span class="material-symbols-outlined text-4xl text-gray-300 dark:text-gray-600 mb-2">payments</span>
<p class="text-sm text-gray-500 dark:text-gray-400">{% trans "No transactions recorded yet." %}</p>
</div>
{% endif %}
</div>
{% endcomponent %}
</div>
</div>
{% endif %}
{% endblock %}