481 lines
25 KiB
HTML
481 lines
25 KiB
HTML
{% extends "layouts/base.html" %}
|
|
{% load i18n %}
|
|
{% load static %}
|
|
{% load social_filters %}
|
|
|
|
{% block title %}{% trans "Analytics Dashboard" %} - {% trans "Social Media Monitoring" %} - PX360{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="p-6 md:p-8 bg-gradient-to-br from-light to-blue-50 min-h-screen">
|
|
<!-- Page Header -->
|
|
<div class="flex flex-col md:flex-row justify-between items-start md:items-center gap-4 mb-8">
|
|
<div class="flex items-center gap-3">
|
|
<div class="flex items-center justify-center w-14 h-14 bg-gradient-to-br from-blue to-indigo-500 rounded-2xl shadow-lg shadow-blue-200">
|
|
<i data-lucide="trending-up" class="w-8 h-8 text-white"></i>
|
|
</div>
|
|
<div>
|
|
<h1 class="text-2xl font-bold text-navy">
|
|
{% trans "Analytics Dashboard" %}
|
|
</h1>
|
|
<p class="text-slate text-sm">{% trans "Social media insights and trends" %}</p>
|
|
</div>
|
|
</div>
|
|
<div class="flex flex-wrap gap-3">
|
|
<a href="{% url 'social:social_comment_list' %}" class="inline-flex items-center gap-2 px-5 py-2.5 bg-white border-2 border-blue-200 text-blue-700 rounded-xl font-semibold hover:bg-blue-50 transition">
|
|
<i data-lucide="layout-grid" class="w-4 h-4"></i> {% trans "Dashboard" %}
|
|
</a>
|
|
<form method="get" class="flex items-center gap-2">
|
|
<input type="date" name="start_date" class="px-4 py-2.5 border-2 border-blue-100 rounded-xl text-navy focus:ring-2 focus:ring-blue focus:border-transparent transition" value="{{ start_date|default:'' }}" placeholder="{% trans 'Date from' %}">
|
|
<span class="text-slate">-</span>
|
|
<input type="date" name="end_date" class="px-4 py-2.5 border-2 border-blue-100 rounded-xl text-navy focus:ring-2 focus:ring-blue focus:border-transparent transition" value="{{ end_date|default:'' }}" placeholder="{% trans 'Date to' %}">
|
|
<button type="submit" class="inline-flex items-center gap-2 px-5 py-2.5 bg-gradient-to-r from-blue to-navy text-white rounded-xl font-semibold hover:from-navy hover:to-blue transition shadow-lg shadow-blue-200">
|
|
<i data-lucide="filter" class="w-4 h-4"></i> {% trans "Filter" %}
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Overview Cards -->
|
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
|
|
<!-- Total Comments -->
|
|
<div class="bg-white rounded-2xl shadow-sm border border-blue-100 p-6 hover:shadow-md transition">
|
|
<div class="flex items-center justify-between mb-4">
|
|
<div>
|
|
<p class="text-xs font-semibold text-slate uppercase mb-1">{% trans "Total Comments" %}</p>
|
|
<p class="text-3xl font-bold text-navy">{{ total_comments }}</p>
|
|
</div>
|
|
<div class="w-14 h-14 bg-gradient-to-br from-blue to-navy rounded-2xl flex items-center justify-center">
|
|
<i data-lucide="message-square" class="w-7 h-7 text-white"></i>
|
|
</div>
|
|
</div>
|
|
<div class="flex items-center gap-2">
|
|
<span class="inline-flex items-center px-2 py-1 bg-emerald-100 text-emerald-700 rounded-lg text-xs font-bold">
|
|
<i data-lucide="check" class="w-3 h-3 mr-1"></i>{{ analyzed_comments }}
|
|
</span>
|
|
<span class="text-xs text-slate">{% trans "analyzed" %}</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Positive -->
|
|
<div class="bg-white rounded-2xl shadow-sm border border-emerald-100 p-6 hover:shadow-md transition">
|
|
<div class="flex items-center justify-between mb-3">
|
|
<div>
|
|
<p class="text-xs font-semibold text-slate uppercase mb-1">{% trans "Positive" %}</p>
|
|
<p class="text-3xl font-bold text-emerald-600">{{ sentiment_distribution|get_sentiment_count:'positive' }}</p>
|
|
</div>
|
|
<div class="w-14 h-14 bg-gradient-to-br from-emerald-500 to-green-500 rounded-2xl flex items-center justify-center">
|
|
<i data-lucide="smile" class="w-7 h-7 text-white"></i>
|
|
</div>
|
|
</div>
|
|
<div class="w-full bg-emerald-100 h-2 rounded-full overflow-hidden mb-2">
|
|
<div class="bg-gradient-to-r from-emerald-500 to-green-500 h-full rounded-full" style="width: {% widthratio sentiment_distribution|get_sentiment_count:'positive' total_comments 100 %}%"></div>
|
|
</div>
|
|
<p class="text-xs text-slate">{% widthratio sentiment_distribution|get_sentiment_count:'positive' total_comments 100 %}% {% trans "of total" %}</p>
|
|
</div>
|
|
|
|
<!-- Negative -->
|
|
<div class="bg-white rounded-2xl shadow-sm border border-red-100 p-6 hover:shadow-md transition">
|
|
<div class="flex items-center justify-between mb-3">
|
|
<div>
|
|
<p class="text-xs font-semibold text-slate uppercase mb-1">{% trans "Negative" %}</p>
|
|
<p class="text-3xl font-bold text-red-600">{{ sentiment_distribution|get_sentiment_count:'negative' }}</p>
|
|
</div>
|
|
<div class="w-14 h-14 bg-gradient-to-br from-red-500 to-rose-500 rounded-2xl flex items-center justify-center">
|
|
<i data-lucide="frown" class="w-7 h-7 text-white"></i>
|
|
</div>
|
|
</div>
|
|
<div class="w-full bg-red-100 h-2 rounded-full overflow-hidden mb-2">
|
|
<div class="bg-gradient-to-r from-red-500 to-rose-500 h-full rounded-full" style="width: {% widthratio sentiment_distribution|get_sentiment_count:'negative' total_comments 100 %}%"></div>
|
|
</div>
|
|
<p class="text-xs text-slate">{% widthratio sentiment_distribution|get_sentiment_count:'negative' total_comments 100 %}% {% trans "of total" %}</p>
|
|
</div>
|
|
|
|
<!-- Avg Engagement -->
|
|
<div class="bg-white rounded-2xl shadow-sm border border-orange-100 p-6 hover:shadow-md transition">
|
|
<div class="flex items-center justify-between mb-4">
|
|
<div>
|
|
<p class="text-xs font-semibold text-slate uppercase mb-1">{% trans "Avg Engagement" %}</p>
|
|
<p class="text-3xl font-bold text-orange-600">{{ engagement_metrics.avg_likes|add:engagement_metrics.avg_replies|floatformat:1 }}</p>
|
|
</div>
|
|
<div class="w-14 h-14 bg-gradient-to-br from-orange-400 to-orange-500 rounded-2xl flex items-center justify-center">
|
|
<i data-lucide="heart-pulse" class="w-7 h-7 text-white"></i>
|
|
</div>
|
|
</div>
|
|
<p class="text-xs text-slate"><i data-lucide="zap" class="w-3 h-3 inline mr-1"></i>{% trans "likes + replies" %}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Charts Row -->
|
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-8">
|
|
<!-- Sentiment Distribution -->
|
|
<div class="bg-white rounded-2xl shadow-sm border border-blue-100 overflow-hidden">
|
|
<div class="px-6 py-5 border-b border-blue-100 bg-gradient-to-r from-blue-50 to-transparent">
|
|
<h3 class="text-lg font-bold text-navy flex items-center gap-2">
|
|
<div class="w-10 h-10 bg-blue-100 rounded-xl flex items-center justify-center">
|
|
<i data-lucide="pie-chart" class="w-5 h-5 text-blue-600"></i>
|
|
</div>
|
|
{% trans "Sentiment Distribution" %}
|
|
</h3>
|
|
</div>
|
|
<div class="p-6">
|
|
<canvas id="sentimentChart" height="200"></canvas>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Platform Distribution -->
|
|
<div class="bg-white rounded-2xl shadow-sm border border-blue-100 overflow-hidden">
|
|
<div class="px-6 py-5 border-b border-blue-100 bg-gradient-to-r from-blue-50 to-transparent">
|
|
<h3 class="text-lg font-bold text-navy flex items-center gap-2">
|
|
<div class="w-10 h-10 bg-indigo-100 rounded-xl flex items-center justify-center">
|
|
<i data-lucide="bar-chart-3" class="w-5 h-5 text-indigo-600"></i>
|
|
</div>
|
|
{% trans "Platform Distribution" %}
|
|
</h3>
|
|
</div>
|
|
<div class="p-6">
|
|
<canvas id="platformChart" height="200"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Daily Trends -->
|
|
<div class="bg-white rounded-2xl shadow-sm border border-blue-100 overflow-hidden mb-8">
|
|
<div class="px-6 py-5 border-b border-blue-100 bg-gradient-to-r from-blue-50 to-transparent">
|
|
<h3 class="text-lg font-bold text-navy flex items-center gap-2">
|
|
<div class="w-10 h-10 bg-emerald-100 rounded-xl flex items-center justify-center">
|
|
<i data-lucide="trending-up" class="w-5 h-5 text-emerald-600"></i>
|
|
</div>
|
|
{% trans "Daily Trends" %}
|
|
</h3>
|
|
</div>
|
|
<div class="p-6">
|
|
<canvas id="trendsChart" height="100"></canvas>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Keywords & Topics -->
|
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-8">
|
|
<!-- Top Keywords -->
|
|
<div class="bg-white rounded-2xl shadow-sm border border-blue-100 overflow-hidden">
|
|
<div class="px-6 py-5 border-b border-blue-100 bg-gradient-to-r from-blue-50 to-transparent">
|
|
<h3 class="text-lg font-bold text-navy flex items-center gap-2">
|
|
<div class="w-10 h-10 bg-yellow-100 rounded-xl flex items-center justify-center">
|
|
<i data-lucide="key" class="w-5 h-5 text-yellow-600"></i>
|
|
</div>
|
|
{% trans "Top Keywords" %}
|
|
</h3>
|
|
</div>
|
|
<div class="p-6">
|
|
{% if top_keywords %}
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
{% for keyword in top_keywords|slice:":12" %}
|
|
<div class="p-4 bg-gradient-to-br from-yellow-50 to-amber-50 rounded-xl border border-yellow-100">
|
|
<div class="flex items-center justify-between mb-2">
|
|
<span class="font-bold text-navy">{{ keyword.keyword }}</span>
|
|
<span class="inline-flex items-center px-2 py-1 bg-yellow-100 text-yellow-700 rounded-lg text-xs font-bold">{{ keyword.count }}</span>
|
|
</div>
|
|
<div class="w-full bg-yellow-100 h-2 rounded-full overflow-hidden">
|
|
<div class="bg-gradient-to-r from-yellow-400 to-amber-400 h-full rounded-full" style="width: {% widthratio keyword.count top_keywords.0.count 100 %}%"></div>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
{% else %}
|
|
<div class="text-center py-12">
|
|
<div class="w-16 h-16 bg-gradient-to-br from-yellow-100 to-amber-100 rounded-full flex items-center justify-center mx-auto mb-4">
|
|
<i data-lucide="key" class="w-8 h-8 text-yellow-500"></i>
|
|
</div>
|
|
<p class="text-slate font-medium">{% trans "No keywords found" %}</p>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Top Topics -->
|
|
<div class="bg-white rounded-2xl shadow-sm border border-blue-100 overflow-hidden">
|
|
<div class="px-6 py-5 border-b border-blue-100 bg-gradient-to-r from-blue-50 to-transparent">
|
|
<h3 class="text-lg font-bold text-navy flex items-center gap-2">
|
|
<div class="w-10 h-10 bg-purple-100 rounded-xl flex items-center justify-center">
|
|
<i data-lucide="hash" class="w-5 h-5 text-purple-600"></i>
|
|
</div>
|
|
{% trans "Top Topics" %}
|
|
</h3>
|
|
</div>
|
|
<div class="p-6">
|
|
{% if top_topics %}
|
|
<div class="space-y-3">
|
|
{% for topic in top_topics|slice:":10" %}
|
|
<div class="flex items-center justify-between p-4 bg-gradient-to-br from-purple-50 to-indigo-50 rounded-xl border border-purple-100">
|
|
<div class="flex items-center gap-3">
|
|
<div class="w-10 h-10 bg-gradient-to-br from-purple-400 to-indigo-500 rounded-xl flex items-center justify-center">
|
|
<i data-lucide="hash" class="w-5 h-5 text-white"></i>
|
|
</div>
|
|
<span class="font-bold text-navy">{{ topic.topic }}</span>
|
|
</div>
|
|
<span class="inline-flex items-center px-3 py-1.5 bg-purple-100 text-purple-700 rounded-xl text-sm font-bold">{{ topic.count }}</span>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
{% else %}
|
|
<div class="text-center py-12">
|
|
<div class="w-16 h-16 bg-gradient-to-br from-purple-100 to-indigo-100 rounded-full flex items-center justify-center mx-auto mb-4">
|
|
<i data-lucide="hash" class="w-8 h-8 text-purple-500"></i>
|
|
</div>
|
|
<p class="text-slate font-medium">{% trans "No topics found" %}</p>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Platform Breakdown -->
|
|
<div class="bg-white rounded-2xl shadow-sm border border-blue-100 overflow-hidden mb-8">
|
|
<div class="px-6 py-5 border-b border-blue-100 bg-gradient-to-r from-blue-50 to-transparent">
|
|
<h3 class="text-lg font-bold text-navy flex items-center gap-2">
|
|
<div class="w-10 h-10 bg-slate-100 rounded-xl flex items-center justify-center">
|
|
<i data-lucide="grid-3x3" class="w-5 h-5 text-slate-600"></i>
|
|
</div>
|
|
{% trans "Platform Breakdown" %}
|
|
</h3>
|
|
</div>
|
|
<div class="overflow-x-auto">
|
|
<table class="w-full">
|
|
<thead class="bg-blue-50">
|
|
<tr>
|
|
<th class="px-6 py-4 text-left text-xs font-bold text-blue-800 uppercase tracking-wider">{% trans "Platform" %}</th>
|
|
<th class="px-6 py-4 text-left text-xs font-bold text-blue-800 uppercase tracking-wider">{% trans "Comments" %}</th>
|
|
<th class="px-6 py-4 text-left text-xs font-bold text-blue-800 uppercase tracking-wider">{% trans "Avg Sentiment" %}</th>
|
|
<th class="px-6 py-4 text-left text-xs font-bold text-blue-800 uppercase tracking-wider">{% trans "Total Likes" %}</th>
|
|
<th class="px-6 py-4 text-left text-xs font-bold text-blue-800 uppercase tracking-wider">{% trans "Total Replies" %}</th>
|
|
<th class="px-6 py-4 text-left text-xs font-bold text-blue-800 uppercase tracking-wider">{% trans "Actions" %}</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="divide-y divide-blue-50">
|
|
{% for platform in platform_distribution %}
|
|
<tr class="hover:bg-blue-50/50 transition">
|
|
<td class="px-6 py-4">
|
|
<a href="{% url 'social:social_platform' platform.platform %}" class="font-bold text-blue-600 hover:text-navy">
|
|
{{ platform.platform_display }}
|
|
</a>
|
|
</td>
|
|
<td class="px-6 py-4">
|
|
<span class="inline-flex items-center px-3 py-1 bg-slate-100 text-slate-700 rounded-lg text-sm font-bold">{{ platform.count }}</span>
|
|
</td>
|
|
<td class="px-6 py-4">
|
|
<span class="inline-flex items-center px-3 py-1 rounded-lg text-sm font-bold {% if platform.avg_sentiment > 0.5 %}bg-emerald-100 text-emerald-700{% elif platform.avg_sentiment < 0.5 %}bg-red-100 text-red-700{% else %}bg-slate-100 text-slate-700{% endif %}">
|
|
{{ platform.avg_sentiment|floatformat:2 }}
|
|
</span>
|
|
</td>
|
|
<td class="px-6 py-4">
|
|
<span class="flex items-center gap-2 text-slate">
|
|
<i data-lucide="heart" class="w-4 h-4 text-red-500"></i>
|
|
<span class="font-medium">{{ platform.total_likes }}</span>
|
|
</span>
|
|
</td>
|
|
<td class="px-6 py-4">
|
|
<span class="flex items-center gap-2 text-slate">
|
|
<i data-lucide="message-square" class="w-4 h-4 text-blue-500"></i>
|
|
<span class="font-medium">{{ platform.total_replies }}</span>
|
|
</span>
|
|
</td>
|
|
<td class="px-6 py-4">
|
|
<a href="{% url 'social:social_platform' platform.platform %}" class="inline-flex items-center gap-2 px-4 py-2 bg-gradient-to-r from-blue to-navy text-white rounded-xl font-semibold hover:from-navy hover:to-blue transition shadow-lg shadow-blue-200 text-sm">
|
|
{% trans "View" %}
|
|
<i data-lucide="arrow-right" class="w-4 h-4"></i>
|
|
</a>
|
|
</td>
|
|
</tr>
|
|
{% empty %}
|
|
<tr>
|
|
<td colspan="6" class="px-6 py-12 text-center">
|
|
<div class="w-16 h-16 bg-gradient-to-br from-blue-100 to-slate-100 rounded-full flex items-center justify-center mx-auto mb-4">
|
|
<i data-lucide="grid-3x3" class="w-8 h-8 text-blue-500"></i>
|
|
</div>
|
|
<p class="text-slate font-medium">{% trans "No data available" %}</p>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Top Entities -->
|
|
<div class="bg-white rounded-2xl shadow-sm border border-blue-100 overflow-hidden">
|
|
<div class="px-6 py-5 border-b border-blue-100 bg-gradient-to-r from-blue-50 to-transparent">
|
|
<h3 class="text-lg font-bold text-navy flex items-center gap-2">
|
|
<div class="w-10 h-10 bg-purple-100 rounded-xl flex items-center justify-center">
|
|
<i data-lucide="tags" class="w-5 h-5 text-purple-600"></i>
|
|
</div>
|
|
{% trans "Top Entities" %}
|
|
</h3>
|
|
</div>
|
|
<div class="p-6">
|
|
{% if top_entities %}
|
|
<div class="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-6 gap-4">
|
|
{% for entity in top_entities|slice:":20" %}
|
|
<div class="bg-gradient-to-br from-purple-50 to-indigo-50 border border-purple-100 rounded-2xl p-4 text-center hover:shadow-md hover:-translate-y-1 transition-all duration-200">
|
|
<div class="w-16 h-16 bg-gradient-to-br from-purple-400 to-indigo-500 rounded-full flex items-center justify-center mx-auto mb-3">
|
|
<i data-lucide="tag" class="w-6 h-6 text-white"></i>
|
|
</div>
|
|
<p class="font-bold text-navy text-sm mb-2 truncate">{{ entity.entity }}</p>
|
|
<span class="inline-flex items-center px-3 py-1.5 bg-purple-100 text-purple-700 rounded-xl text-xs font-bold">{{ entity.count }}</span>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
{% else %}
|
|
<div class="text-center py-12">
|
|
<div class="w-16 h-16 bg-gradient-to-br from-purple-100 to-indigo-100 rounded-full flex items-center justify-center mx-auto mb-4">
|
|
<i data-lucide="tags" class="w-8 h-8 text-purple-500"></i>
|
|
</div>
|
|
<p class="text-slate font-medium">{% trans "No entities found" %}</p>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
lucide.createIcons();
|
|
|
|
// Sentiment Distribution Chart
|
|
const sentimentCtx = document.getElementById('sentimentChart').getContext('2d');
|
|
new Chart(sentimentCtx, {
|
|
type: 'doughnut',
|
|
data: {
|
|
labels: ['Positive', 'Neutral', 'Negative'],
|
|
datasets: [{
|
|
data: [
|
|
{% for item in sentiment_distribution %}{% if item.sentiment == 'positive' %}{{ item.count }}{% endif %}{% endfor %},
|
|
{% for item in sentiment_distribution %}{% if item.sentiment == 'neutral' %}{{ item.count }}{% endif %}{% endfor %},
|
|
{% for item in sentiment_distribution %}{% if item.sentiment == 'negative' %}{{ item.count }}{% endif %}{% endfor %}
|
|
],
|
|
backgroundColor: ['#10b981', '#64748b', '#ef4444'],
|
|
borderWidth: 0
|
|
}]
|
|
},
|
|
options: {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
plugins: {
|
|
legend: {
|
|
position: 'bottom',
|
|
labels: {
|
|
usePointStyle: true,
|
|
padding: 15,
|
|
font: {
|
|
size: 12,
|
|
family: "'Inter', sans-serif"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
// Platform Distribution Chart
|
|
const platformCtx = document.getElementById('platformChart').getContext('2d');
|
|
new Chart(platformCtx, {
|
|
type: 'bar',
|
|
data: {
|
|
labels: [{% for item in platform_distribution %}'{{ item.platform_display }}',{% endfor %}],
|
|
datasets: [{
|
|
label: 'Comments',
|
|
data: [{% for item in platform_distribution %}{{ item.count }},{% endfor %}],
|
|
backgroundColor: '#007bbd',
|
|
borderRadius: 8
|
|
}]
|
|
},
|
|
options: {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
plugins: {
|
|
legend: {
|
|
display: false
|
|
}
|
|
},
|
|
scales: {
|
|
y: {
|
|
beginAtZero: true,
|
|
grid: {
|
|
color: '#f1f5f9'
|
|
}
|
|
},
|
|
x: {
|
|
grid: {
|
|
display: false
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
// Daily Trends Chart
|
|
const trendsCtx = document.getElementById('trendsChart').getContext('2d');
|
|
new Chart(trendsCtx, {
|
|
type: 'line',
|
|
data: {
|
|
labels: [{% for item in daily_trends %}'{{ item.day }}',{% endfor %}],
|
|
datasets: [
|
|
{
|
|
label: 'Total',
|
|
data: [{% for item in daily_trends %}{{ item.count }},{% endfor %}],
|
|
borderColor: '#007bbd',
|
|
backgroundColor: 'rgba(0, 123, 189, 0.1)',
|
|
fill: true,
|
|
tension: 0.4,
|
|
borderRadius: 8
|
|
},
|
|
{
|
|
label: 'Positive',
|
|
data: [{% for item in daily_trends %}{{ item.positive }},{% endfor %}],
|
|
borderColor: '#10b981',
|
|
tension: 0.4,
|
|
borderRadius: 8
|
|
},
|
|
{
|
|
label: 'Negative',
|
|
data: [{% for item in daily_trends %}{{ item.negative }},{% endfor %}],
|
|
borderColor: '#ef4444',
|
|
tension: 0.4,
|
|
borderRadius: 8
|
|
}
|
|
]
|
|
},
|
|
options: {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
plugins: {
|
|
legend: {
|
|
position: 'top',
|
|
labels: {
|
|
usePointStyle: true,
|
|
padding: 15,
|
|
font: {
|
|
size: 12,
|
|
family: "'Inter', sans-serif"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
scales: {
|
|
y: {
|
|
beginAtZero: true,
|
|
grid: {
|
|
color: '#f1f5f9'
|
|
}
|
|
},
|
|
x: {
|
|
grid: {
|
|
display: false
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
});
|
|
</script>
|
|
{% endblock %}
|