411 lines
21 KiB
HTML
411 lines
21 KiB
HTML
{% extends "layouts/base.html" %}
|
|
{% load i18n %}
|
|
|
|
{% block title %}{{ platform_name }} - {% trans "Comment Detail" %} - PX360{% endblock %}
|
|
|
|
{% block extra_css %}
|
|
<style>
|
|
.page-header-gradient {
|
|
background: linear-gradient(135deg, #005696 0%, #0069a8 50%, #007bbd 100%);
|
|
color: white;
|
|
padding: 1.5rem 2rem;
|
|
border-radius: 1rem;
|
|
margin-bottom: 1.5rem;
|
|
box-shadow: 0 10px 15px -3px rgba(0, 86, 150, 0.2);
|
|
}
|
|
.section-card {
|
|
background: white;
|
|
border-radius: 1rem;
|
|
border: 2px solid #e2e8f0;
|
|
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
|
overflow: hidden;
|
|
transition: all 0.3s ease;
|
|
}
|
|
.section-card:hover {
|
|
border-color: #005696;
|
|
box-shadow: 0 10px 25px -5px rgba(0, 86, 150, 0.15);
|
|
}
|
|
.section-header {
|
|
padding: 1rem 1.5rem;
|
|
border-bottom: 2px solid #e2e8f0;
|
|
background: linear-gradient(to right, #f8fafc, #f1f5f9);
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.75rem;
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
<!-- Page Header -->
|
|
<div class="page-header-gradient">
|
|
<div>
|
|
<a href="{% url 'social:comments_list' platform_type=platform_type %}" class="inline-flex items-center text-white/80 hover:text-white mb-2 text-sm font-medium transition">
|
|
<i data-lucide="arrow-left" class="w-4 h-4 mr-2"></i>
|
|
{% trans "Back to Comments" %}
|
|
</a>
|
|
<h1 class="text-2xl font-bold flex items-center gap-3">
|
|
<i data-lucide="message-square-text" class="w-7 h-7"></i>
|
|
{{ platform_name }}
|
|
</h1>
|
|
<p class="text-blue-100 text-sm mt-1">{% trans "Comment Detail & AI Analysis" %}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
|
<!-- Left Column: Comment + Replies -->
|
|
<div class="lg:col-span-2 space-y-6">
|
|
<!-- Original Comment -->
|
|
<div class="section-card">
|
|
<div class="section-header">
|
|
<div class="w-10 h-10 rounded-lg bg-navy/10 flex items-center justify-center">
|
|
<i data-lucide="message-square" class="w-5 h-5 text-navy"></i>
|
|
</div>
|
|
<h3 class="font-bold text-navy">{% trans "Original Comment" %}</h3>
|
|
</div>
|
|
<div class="p-6">
|
|
<div class="flex items-start gap-4 mb-4">
|
|
<div class="w-12 h-12 rounded-full bg-gradient-to-br from-navy to-blue flex items-center justify-center flex-shrink-0">
|
|
<span class="text-white font-bold">{{ comment.author_name|first|upper|default:"?" }}</span>
|
|
</div>
|
|
<div class="flex-1 min-w-0">
|
|
<div class="flex items-center gap-2 flex-wrap">
|
|
<h4 class="font-bold text-navy">{{ comment.author_name }}</h4>
|
|
{% if comment.rating %}
|
|
<span class="inline-flex items-center gap-0.5 text-yellow-500 font-bold text-xs">
|
|
<i data-lucide="star" class="w-3.5 h-3.5 fill-current"></i>
|
|
{{ comment.rating }}/5
|
|
</span>
|
|
{% endif %}
|
|
</div>
|
|
<p class="text-xs text-slate mt-0.5">{{ comment.created_at|date:"M d, Y H:i" }}</p>
|
|
</div>
|
|
</div>
|
|
<div class="bg-slate-50 rounded-xl p-4">
|
|
<p class="text-slate-800 text-sm leading-relaxed">{{ comment.text|linebreaksbr }}</p>
|
|
</div>
|
|
|
|
<!-- Engagement Metrics -->
|
|
<div class="flex gap-4 mt-4">
|
|
{% if comment.like_count > 0 %}
|
|
<div class="inline-flex items-center gap-1.5 px-3 py-1.5 bg-blue-50 rounded-lg text-xs font-semibold text-blue-700">
|
|
<i data-lucide="thumbs-up" class="w-3.5 h-3.5"></i>
|
|
{{ comment.like_count }} {% trans "likes" %}
|
|
</div>
|
|
{% endif %}
|
|
{% if comment.reply_count > 0 %}
|
|
<div class="inline-flex items-center gap-1.5 px-3 py-1.5 bg-purple-50 rounded-lg text-xs font-semibold text-purple-700">
|
|
<i data-lucide="corner-up-left" class="w-3.5 h-3.5"></i>
|
|
{{ comment.reply_count }} {% trans "replies" %}
|
|
</div>
|
|
{% endif %}
|
|
{% if comment.synced_via_webhook %}
|
|
<div class="inline-flex items-center gap-1.5 px-3 py-1.5 bg-green-50 rounded-lg text-xs font-semibold text-green-700">
|
|
<i data-lucide="zap" class="w-3.5 h-3.5"></i>
|
|
{% trans "Real-time" %}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- AI Analysis -->
|
|
{% if comment.is_analyzed %}
|
|
<div class="section-card">
|
|
<div class="section-header">
|
|
<div class="w-10 h-10 rounded-lg bg-purple-100 flex items-center justify-center">
|
|
<i data-lucide="brain" class="w-5 h-5 text-purple-600"></i>
|
|
</div>
|
|
<h3 class="font-bold text-navy">{% trans "AI Analysis" %}</h3>
|
|
</div>
|
|
<div class="p-6 space-y-6">
|
|
<!-- Sentiment -->
|
|
{% with sentiment=comment.ai_analysis.sentiment %}
|
|
{% if sentiment %}
|
|
<div>
|
|
<h4 class="text-xs font-bold text-slate uppercase mb-3">{% trans "Sentiment" %}</h4>
|
|
<div class="flex flex-wrap gap-3">
|
|
{% with classification=sentiment.classification.en %}
|
|
{% if classification == 'positive' %}
|
|
<span class="inline-flex items-center gap-1.5 px-4 py-2 rounded-xl bg-green-100 text-green-700 font-bold text-sm">
|
|
<i data-lucide="smile" class="w-4 h-4"></i> {% trans "Positive" %}
|
|
</span>
|
|
{% elif classification == 'negative' %}
|
|
<span class="inline-flex items-center gap-1.5 px-4 py-2 rounded-xl bg-red-100 text-red-700 font-bold text-sm">
|
|
<i data-lucide="frown" class="w-4 h-4"></i> {% trans "Negative" %}
|
|
</span>
|
|
{% elif classification == 'neutral' %}
|
|
<span class="inline-flex items-center gap-1.5 px-4 py-2 rounded-xl bg-slate-100 text-slate-600 font-bold text-sm">
|
|
<i data-lucide="meh" class="w-4 h-4"></i> {% trans "Neutral" %}
|
|
</span>
|
|
{% endif %}
|
|
{% endwith %}
|
|
{% if sentiment.score is not None %}
|
|
<span class="px-3 py-2 bg-slate-50 rounded-xl text-xs text-slate">
|
|
{% trans "Score:" %} <strong>{{ sentiment.score|floatformat:2 }}</strong>
|
|
</span>
|
|
{% endif %}
|
|
{% if sentiment.confidence is not None %}
|
|
<span class="px-3 py-2 bg-slate-50 rounded-xl text-xs text-slate">
|
|
{% trans "Confidence:" %} <strong>{{ sentiment.confidence|floatformat:2 }}</strong>
|
|
</span>
|
|
{% endif %}
|
|
{% if sentiment.urgency_level and sentiment.urgency_level.en %}
|
|
<span class="inline-flex items-center gap-1 px-3 py-2 rounded-xl text-xs font-bold
|
|
{% if sentiment.urgency_level.en == 'high' %}bg-red-100 text-red-700
|
|
{% elif sentiment.urgency_level.en == 'medium' %}bg-amber-100 text-amber-700
|
|
{% else %}bg-slate-100 text-slate-600{% endif %}">
|
|
<i data-lucide="alert-circle" class="w-3.5 h-3.5"></i>
|
|
{% trans "Urgency:" %} {{ sentiment.urgency_level.en|title }}
|
|
</span>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
{% endwith %}
|
|
|
|
<!-- Summary -->
|
|
{% with summaries=comment.ai_analysis.summaries %}
|
|
{% if summaries.en or summaries.ar %}
|
|
<div>
|
|
<h4 class="text-xs font-bold text-slate uppercase mb-3">{% trans "Summary" %}</h4>
|
|
{% if summaries.en %}
|
|
<div class="bg-blue-50 rounded-xl p-4 mb-2">
|
|
<p class="text-sm text-slate-800 leading-relaxed">{{ summaries.en }}</p>
|
|
</div>
|
|
{% endif %}
|
|
{% if summaries.ar %}
|
|
<div class="bg-blue-50 rounded-xl p-4" dir="rtl">
|
|
<p class="text-sm text-slate-800 leading-relaxed">{{ summaries.ar }}</p>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
{% endwith %}
|
|
|
|
<!-- Keywords -->
|
|
{% with keywords=comment.ai_analysis.keywords %}
|
|
{% if keywords.en or keywords.ar %}
|
|
<div>
|
|
<h4 class="text-xs font-bold text-slate uppercase mb-3">{% trans "Keywords" %}</h4>
|
|
<div class="flex flex-wrap gap-2">
|
|
{% for kw in keywords.en %}
|
|
<span class="px-3 py-1 bg-navy/10 text-navy rounded-full text-xs font-semibold">{{ kw }}</span>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
{% endwith %}
|
|
|
|
<!-- Topics -->
|
|
{% with topics=comment.ai_analysis.topics %}
|
|
{% if topics.en or topics.ar %}
|
|
<div>
|
|
<h4 class="text-xs font-bold text-slate uppercase mb-3">{% trans "Topics" %}</h4>
|
|
<div class="flex flex-wrap gap-2">
|
|
{% for topic in topics.en %}
|
|
<span class="px-3 py-1 bg-purple-100 text-purple-700 rounded-full text-xs font-semibold">{{ topic }}</span>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
{% endwith %}
|
|
|
|
<!-- Emotions -->
|
|
{% with emotions=comment.ai_analysis.emotions %}
|
|
{% if emotions %}
|
|
<div>
|
|
<h4 class="text-xs font-bold text-slate uppercase mb-3">{% trans "Emotions" %}</h4>
|
|
<div class="flex flex-wrap gap-2">
|
|
{% for emotion, score in emotions.items %}
|
|
<span class="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-semibold
|
|
{% if score|floatformat:2|add:0 > 0.7 %}bg-red-100 text-red-700
|
|
{% elif score|floatformat:2|add:0 > 0.4 %}bg-amber-100 text-amber-700
|
|
{% else %}bg-navy/10 text-navy{% endif %}">
|
|
<span class="capitalize">{{ emotion }}</span>
|
|
<span class="font-bold">{{ score|floatformat:2 }}</span>
|
|
</span>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
{% endwith %}
|
|
|
|
<!-- Actionable Insights -->
|
|
{% with insights=comment.ai_analysis.actionable_insights %}
|
|
{% if insights.primary_concern or insights.affected_department %}
|
|
<div>
|
|
<h4 class="text-xs font-bold text-slate uppercase mb-3">{% trans "Actionable Insights" %}</h4>
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-3">
|
|
{% if insights.primary_concern and insights.primary_concern.en %}
|
|
<div class="bg-amber-50 rounded-xl p-3">
|
|
<p class="text-xs font-bold text-amber-700 uppercase mb-1">{% trans "Primary Concern" %}</p>
|
|
<p class="text-sm text-slate-800">{{ insights.primary_concern.en }}</p>
|
|
</div>
|
|
{% endif %}
|
|
{% if insights.affected_department and insights.affected_department.en %}
|
|
<div class="bg-blue-50 rounded-xl p-3">
|
|
<p class="text-xs font-bold text-blue-700 uppercase mb-1">{% trans "Affected Department" %}</p>
|
|
<p class="text-sm text-slate-800">{{ insights.affected_department.en }}</p>
|
|
</div>
|
|
{% endif %}
|
|
{% if insights.requires_followup %}
|
|
<div class="bg-red-50 rounded-xl p-3">
|
|
<p class="text-xs font-bold text-red-700 uppercase mb-1">{% trans "Requires Follow-up" %}</p>
|
|
<p class="text-sm text-slate-800">
|
|
{% if insights.followup_priority and insights.followup_priority.en %}
|
|
{{ insights.followup_priority.en|title }}
|
|
{% else %}
|
|
{% trans "Yes" %}
|
|
{% endif %}
|
|
</p>
|
|
</div>
|
|
{% endif %}
|
|
{% if insights.recommended_actions and insights.recommended_actions.en %}
|
|
<div class="bg-green-50 rounded-xl p-3">
|
|
<p class="text-xs font-bold text-green-700 uppercase mb-1">{% trans "Recommended Actions" %}</p>
|
|
<ul class="text-sm text-slate-800 list-disc list-inside space-y-0.5">
|
|
{% for action in insights.recommended_actions.en %}
|
|
<li>{{ action }}</li>
|
|
{% endfor %}
|
|
</ul>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
{% endwith %}
|
|
</div>
|
|
</div>
|
|
{% else %}
|
|
<!-- No AI Analysis -->
|
|
<div class="section-card p-8 text-center">
|
|
<div class="inline-flex items-center justify-center w-16 h-16 bg-slate-100 rounded-full mb-3">
|
|
<i data-lucide="brain" class="w-8 h-8 text-slate-400"></i>
|
|
</div>
|
|
<h3 class="font-bold text-navy mb-1">{% trans "AI Analysis Pending" %}</h3>
|
|
<p class="text-sm text-slate">{% trans "This comment has not been analyzed yet" %}</p>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- Replies -->
|
|
{% if replies %}
|
|
<div class="section-card">
|
|
<div class="section-header">
|
|
<div class="w-10 h-10 rounded-lg bg-blue-100 flex items-center justify-center">
|
|
<i data-lucide="corner-up-left" class="w-5 h-5 text-blue-600"></i>
|
|
</div>
|
|
<h3 class="font-bold text-navy">{% trans "Replies" %} ({{ replies|length }})</h3>
|
|
</div>
|
|
<div class="p-6 space-y-4">
|
|
{% for reply in replies %}
|
|
<div class="flex items-start gap-3 {% if not forloop.last %}pb-4 border-b border-slate-100{% endif %}">
|
|
<div class="w-10 h-10 rounded-full bg-blue-100 flex items-center justify-center flex-shrink-0">
|
|
<span class="text-blue-700 font-bold text-sm">{{ reply.author_name|first|upper|default:"?" }}</span>
|
|
</div>
|
|
<div class="flex-1 min-w-0">
|
|
<div class="flex items-center gap-2">
|
|
<span class="font-bold text-navy text-sm">{{ reply.author_name }}</span>
|
|
<span class="text-xs text-slate">{{ reply.created_at|date:"M d, Y H:i" }}</span>
|
|
</div>
|
|
<p class="text-sm text-slate-700 mt-1">{{ reply.text }}</p>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<!-- Right Column: Reply Form -->
|
|
<div class="lg:col-span-1">
|
|
<div class="section-card sticky top-6">
|
|
<div class="section-header">
|
|
<div class="w-10 h-10 rounded-lg bg-green-100 flex items-center justify-center">
|
|
<i data-lucide="reply" class="w-5 h-5 text-green-600"></i>
|
|
</div>
|
|
<h3 class="font-bold text-navy">{% trans "Post Reply" %}</h3>
|
|
</div>
|
|
<div class="p-6">
|
|
<form method="post">
|
|
{% csrf_token %}
|
|
<div class="mb-4">
|
|
<label class="block text-sm font-bold text-slate mb-2">{% trans "Your Reply" %}</label>
|
|
<textarea name="text" rows="5" required
|
|
class="w-full px-4 py-2.5 border-2 border-slate-200 rounded-xl text-sm focus:border-navy focus:ring-2 focus:ring-navy/20 outline-none transition resize-none"
|
|
placeholder="{% trans 'Type your reply...' %}"></textarea>
|
|
</div>
|
|
{% if messages %}
|
|
<div class="mb-4 space-y-2">
|
|
{% for message in messages %}
|
|
<div class="px-4 py-2 rounded-xl text-xs font-semibold
|
|
{% if message.tags == 'success' %}bg-green-50 text-green-700
|
|
{% elif message.tags == 'error' %}bg-red-50 text-red-700
|
|
{% elif message.tags == 'warning' %}bg-amber-50 text-amber-700
|
|
{% else %}bg-blue-50 text-blue-700{% endif %}">
|
|
{{ message }}
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
{% endif %}
|
|
<button type="submit" class="w-full px-4 py-3 bg-navy text-white rounded-xl font-bold text-sm hover:bg-blue transition flex items-center justify-center gap-2">
|
|
<i data-lucide="send" class="w-4 h-4"></i>
|
|
{% trans "Post Reply" %}
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Comment Metadata -->
|
|
<div class="section-card mt-6">
|
|
<div class="section-header">
|
|
<div class="w-10 h-10 rounded-lg bg-slate-100 flex items-center justify-center">
|
|
<i data-lucide="info" class="w-5 h-5 text-slate-600"></i>
|
|
</div>
|
|
<h3 class="font-bold text-navy">{% trans "Details" %}</h3>
|
|
</div>
|
|
<div class="p-6 space-y-3 text-sm">
|
|
<div class="flex justify-between">
|
|
<span class="text-slate">{% trans "Platform" %}</span>
|
|
<span class="font-bold text-navy">{{ platform_name }}</span>
|
|
</div>
|
|
<div class="flex justify-between">
|
|
<span class="text-slate">{% trans "Comment ID" %}</span>
|
|
<span class="font-bold text-slate-800 text-xs">{{ comment.comment_id|truncatechars:20 }}</span>
|
|
</div>
|
|
{% if comment.source_platform %}
|
|
<div class="flex justify-between">
|
|
<span class="text-slate">{% trans "Source" %}</span>
|
|
<span class="font-bold text-navy">{{ comment.source_platform }}</span>
|
|
</div>
|
|
{% endif %}
|
|
<div class="flex justify-between">
|
|
<span class="text-slate">{% trans "Posted" %}</span>
|
|
<span class="font-bold text-navy">{{ comment.created_at|date:"M d, Y" }}</span>
|
|
</div>
|
|
<div class="flex justify-between">
|
|
<span class="text-slate">{% trans "Collected" %}</span>
|
|
<span class="font-bold text-navy">{{ comment.added_at|date:"M d, Y" }}</span>
|
|
</div>
|
|
{% if comment.media_url %}
|
|
<div class="pt-3 border-t border-slate-100">
|
|
<a href="{{ comment.media_url }}" target="_blank" class="inline-flex items-center gap-1.5 text-blue-600 hover:text-navy text-xs font-bold">
|
|
<i data-lucide="external-link" class="w-3.5 h-3.5"></i>
|
|
{% trans "View Media" %}
|
|
</a>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block extra_js %}
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
lucide.createIcons();
|
|
});
|
|
</script>
|
|
{% endblock %}
|