284 lines
14 KiB
HTML
284 lines
14 KiB
HTML
{% extends 'layouts/base.html' %}
|
|
{% load social_filters %}
|
|
{% load social_icons %}
|
|
{% load action_icons %}
|
|
{% load star_rating %}
|
|
|
|
{% block title %}Comments - {{ platform_name }}{% endblock %}
|
|
{% block page_title %}{{ platform_name }} Comments{% endblock %}
|
|
{% block page_subtitle %}View and manage comments from {{ account.name }}{% endblock %}
|
|
|
|
{% block content %}
|
|
|
|
<!-- Header Actions -->
|
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
|
<a href="{% url 'social:dashboard' %}" class="btn btn-outline-secondary">
|
|
<i class="bi bi-arrow-left me-2"></i>
|
|
Back to Dashboard
|
|
</a>
|
|
<div class="d-flex gap-2">
|
|
<a href="{% url 'social:sync' platform_type %}" class="btn btn-primary">
|
|
<i class="bi bi-arrow-repeat me-2"></i>
|
|
Sync Now
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Filter Section -->
|
|
<div class="card mb-4">
|
|
<div class="card-body">
|
|
<form method="get">
|
|
<div class="row g-3">
|
|
<div class="col-lg-4">
|
|
<div class="position-relative">
|
|
<i class="bi bi-search position-absolute top-50 start-0 translate-middle-y ms-3 text-muted"></i>
|
|
<input type="text"
|
|
name="search"
|
|
placeholder="Search comments..."
|
|
value="{{ search_query|default:'' }}"
|
|
class="form-control ps-5">
|
|
</div>
|
|
</div>
|
|
<div class="col-lg-8">
|
|
<div class="d-flex gap-2 flex-wrap">
|
|
<select name="sentiment" class="form-select w-auto">
|
|
<option value="">All Sentiments</option>
|
|
<option value="positive" {% if sentiment_filter == 'positive' %}selected{% endif %}>Positive</option>
|
|
<option value="neutral" {% if sentiment_filter == 'neutral' %}selected{% endif %}>Neutral</option>
|
|
<option value="negative" {% if sentiment_filter == 'negative' %}selected{% endif %}>Negative</option>
|
|
</select>
|
|
<select name="sync_via_webhook" class="form-select w-auto">
|
|
<option value="">All Sync Methods</option>
|
|
<option value="true" {% if sync_filter == 'true' %}selected{% endif %}>Real-time Only</option>
|
|
<option value="false" {% if sync_filter == 'false' %}selected{% endif %}>Polling Only</option>
|
|
</select>
|
|
{% if platform_type == 'META' %}
|
|
<select name="source_platform" class="form-select w-auto">
|
|
<option value="">All Sources</option>
|
|
<option value="FB" {% if request.GET.source_platform == 'FB' %}selected{% endif %}>Facebook</option>
|
|
<option value="IG" {% if request.GET.source_platform == 'IG' %}selected{% endif %}>Instagram</option>
|
|
</select>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="d-flex justify-content-between align-items-center mt-3 pt-3 border-top">
|
|
<div class="d-flex gap-2 flex-wrap">
|
|
{% if search_query %}
|
|
<span class="badge bg-primary">
|
|
<i class="bi bi-search me-1"></i>
|
|
Search: {{ search_query|truncatechars:20 }}
|
|
<a href="{% url 'social:comments_list' platform_type %}" class="text-white ms-1">
|
|
<i class="bi bi-x-lg"></i>
|
|
</a>
|
|
</span>
|
|
{% endif %}
|
|
{% if sentiment_filter %}
|
|
<span class="badge bg-primary">
|
|
<i class="bi bi-emoji-smile me-1"></i>
|
|
Sentiment: {{ sentiment_filter|capfirst }}
|
|
<a href="?{% if search_query %}search={{ search_query }}{% endif %}{% if sync_filter %}&sync_via_webhook={{ sync_filter }}{% endif %}{% if request.GET.source_platform %}&source_platform={{ request.GET.source_platform }}{% endif %}" class="text-white ms-1">
|
|
<i class="bi bi-x-lg"></i>
|
|
</a>
|
|
</span>
|
|
{% endif %}
|
|
{% if sync_filter %}
|
|
<span class="badge bg-primary">
|
|
<i class="bi bi-arrow-repeat me-1"></i>
|
|
Sync: {% if sync_filter == 'true' %}Real-time{% else %}Polling{% endif %}
|
|
<a href="?{% if search_query %}search={{ search_query }}{% endif %}{% if sentiment_filter %}&sentiment={{ sentiment_filter }}{% endif %}{% if request.GET.source_platform %}&source_platform={{ request.GET.source_platform }}{% endif %}" class="text-white ms-1">
|
|
<i class="bi bi-x-lg"></i>
|
|
</a>
|
|
</span>
|
|
{% endif %}
|
|
</div>
|
|
<div class="d-flex gap-2">
|
|
<button type="submit" class="btn btn-primary">
|
|
<i class="bi bi-funnel me-2"></i>
|
|
Apply Filters
|
|
</button>
|
|
<a href="{% url 'social:comments_list' platform_type %}" class="btn btn-outline-secondary">
|
|
<i class="bi bi-x-lg me-2"></i>
|
|
Clear
|
|
</a>
|
|
<a href="{% url 'social:export_comments_csv' platform_type %}{% if search_query %}?search={{ search_query }}{% endif %}{% if sentiment_filter %}{% if search_query %}&{% else %}?{% endif %}sentiment={{ sentiment_filter }}{% endif %}{% if sync_filter %}{% if search_query or sentiment_filter %}&{% else %}?{% endif %}sync_via_webhook={{ sync_filter }}{% endif %}{% if request.GET.source_platform %}{% if search_query or sentiment_filter or sync_filter %}&{% else %}?{% endif %}source_platform={{ request.GET.source_platform }}{% endif %}" class="btn btn-success">
|
|
<i class="bi bi-download me-2"></i>
|
|
Export CSV
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Results Info -->
|
|
{% if page_obj %}
|
|
<div class="card mb-3">
|
|
<div class="card-body d-flex justify-content-between align-items-center">
|
|
<div class="text-muted">
|
|
Showing <strong>{{ page_obj.start_index }}</strong> to <strong>{{ page_obj.end_index }}</strong> of <strong>{{ page_obj.paginator.count }}</strong> comments
|
|
</div>
|
|
<div class="small text-muted">
|
|
<i class="bi bi-info-circle me-1"></i>
|
|
Use filters to narrow down results
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- Comments List -->
|
|
{% if page_obj %}
|
|
<div class="d-flex flex-column gap-3">
|
|
{% for comment in page_obj %}
|
|
<a href="{% url 'social:comment_detail' platform_type comment.comment_id %}" class="card text-decoration-none hover-lift">
|
|
<div class="card-body">
|
|
<div class="d-flex gap-3">
|
|
<!-- Author Avatar -->
|
|
<div class="avatar avatar-lg bg-primary flex-shrink-0">
|
|
{{ comment.author_name|slice:":1"|upper }}
|
|
</div>
|
|
|
|
<!-- Content -->
|
|
<div class="flex-grow-1">
|
|
<div class="d-flex justify-content-between mb-2">
|
|
<div>
|
|
<h5 class="mb-1">{{ comment.author_name }}</h5>
|
|
<p class="text-muted small">{{ comment.text|truncatewords:20 }}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Badges -->
|
|
<div class="d-flex gap-2 flex-wrap mt-2">
|
|
{% if comment.is_reply %}
|
|
<span class="badge bg-info">
|
|
<i class="bi bi-reply me-1"></i> Reply
|
|
</span>
|
|
{% endif %}
|
|
{% if comment.is_replied %}
|
|
<span class="badge bg-success">
|
|
<i class="bi bi-check-circle me-1"></i> Replied
|
|
</span>
|
|
{% endif %}
|
|
{% if comment.synced_via_webhook %}
|
|
<span class="badge badge-soft-success">
|
|
<i class="bi bi-circle-fill me-1"></i>
|
|
Real-time
|
|
</span>
|
|
{% endif %}
|
|
{% if comment.rating %}
|
|
<span class="badge bg-warning text-dark">
|
|
<i class="bi bi-star-fill me-1"></i> {{ comment.rating }}
|
|
</span>
|
|
{% endif %}
|
|
{% if comment.ai_analysis and comment.ai_analysis.actionable_insights.requires_followup %}
|
|
<span class="badge bg-danger">
|
|
<i class="bi bi-bell me-1"></i> Follow-up
|
|
</span>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Right Side Info -->
|
|
<div class="d-flex flex-column align-items-end gap-2 flex-shrink-0">
|
|
<!-- Sentiment -->
|
|
{% if comment.ai_analysis %}
|
|
<span class="badge {% if comment.ai_analysis.sentiment.classification.en == 'positive' %}bg-success{% elif comment.ai_analysis.sentiment.classification.en == 'negative' %}bg-danger{% else %}bg-secondary{% endif %}">
|
|
{{ comment.ai_analysis.sentiment.classification.en|capfirst }}
|
|
</span>
|
|
{% else %}
|
|
<span class="small text-muted">Pending</span>
|
|
{% endif %}
|
|
|
|
<!-- Score -->
|
|
{% if comment.ai_analysis and comment.ai_analysis.business_intelligence.patient_satisfaction_score %}
|
|
<span class="badge {% if comment.ai_analysis.business_intelligence.patient_satisfaction_score >= 80 %}bg-success{% elif comment.ai_analysis.business_intelligence.patient_satisfaction_score >= 60 %}bg-warning text-dark{% else %}bg-danger{% endif %}">
|
|
{{ comment.ai_analysis.business_intelligence.patient_satisfaction_score }}%
|
|
</span>
|
|
{% endif %}
|
|
|
|
<!-- Engagement -->
|
|
<div class="d-flex gap-2 small text-muted">
|
|
{% if comment.like_count > 0 %}
|
|
<span>
|
|
<i class="bi bi-heart-fill text-danger me-1"></i>
|
|
{{ comment.like_count }}
|
|
</span>
|
|
{% endif %}
|
|
{% if comment.reply_count > 0 %}
|
|
<span>
|
|
<i class="bi bi-chat-fill text-primary me-1"></i>
|
|
{{ comment.reply_count }}
|
|
</span>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</a>
|
|
{% endfor %}
|
|
</div>
|
|
|
|
<!-- Pagination -->
|
|
{% if page_obj.has_other_pages %}
|
|
<nav class="mt-4" aria-label="Comments pagination">
|
|
<ul class="pagination justify-content-center">
|
|
{% if page_obj.has_previous %}
|
|
<li class="page-item">
|
|
<a class="page-link" href="?page={{ page_obj.previous_page_number }}{% if search_query %}&search={{ search_query }}{% endif %}{% if sentiment_filter %}&sentiment={{ sentiment_filter }}{% endif %}{% if sync_filter %}&sync_via_webhook={{ sync_filter }}{% endif %}{% if request.GET.source_platform %}&source_platform={{ request.GET.source_platform }}{% endif %}">
|
|
<i class="bi bi-chevron-left"></i> Previous
|
|
</a>
|
|
</li>
|
|
{% endif %}
|
|
|
|
{% for page_num in page_obj.paginator.page_range %}
|
|
{% if page_num == page_obj.number %}
|
|
<li class="page-item active">
|
|
<span class="page-link">{{ page_num }}</span>
|
|
</li>
|
|
{% else %}
|
|
<li class="page-item">
|
|
<a class="page-link" href="?page={{ page_num }}{% if search_query %}&search={{ search_query }}{% endif %}{% if sentiment_filter %}&sentiment={{ sentiment_filter }}{% endif %}{% if sync_filter %}&sync_via_webhook={{ sync_filter }}{% endif %}{% if request.GET.source_platform %}&source_platform={{ request.GET.source_platform }}{% endif %}">
|
|
{{ page_num }}
|
|
</a>
|
|
</li>
|
|
{% endif %}
|
|
{% endfor %}
|
|
|
|
{% if page_obj.has_next %}
|
|
<li class="page-item">
|
|
<a class="page-link" href="?page={{ page_obj.next_page_number }}{% if search_query %}&search={{ search_query }}{% endif %}{% if sentiment_filter %}&sentiment={{ sentiment_filter }}{% endif %}{% if sync_filter %}&sync_via_webhook={{ sync_filter }}{% endif %}{% if request.GET.source_platform %}&source_platform={{ request.GET.source_platform }}{% endif %}">
|
|
Next <i class="bi bi-chevron-right"></i>
|
|
</a>
|
|
</li>
|
|
{% endif %}
|
|
</ul>
|
|
</nav>
|
|
{% endif %}
|
|
|
|
{% else %}
|
|
<!-- Empty State -->
|
|
<div class="card text-center py-5">
|
|
<div class="card-body">
|
|
<div class="avatar avatar-xl bg-primary mx-auto mb-3">
|
|
<i class="bi bi-chat-dots"></i>
|
|
</div>
|
|
<h4 class="mb-2">No Comments Found</h4>
|
|
<p class="text-muted mb-4">
|
|
{% if search_query %}
|
|
No comments match your search criteria. Try adjusting your filters.
|
|
{% elif sync_filter %}
|
|
No comments with selected sync method.
|
|
{% else %}
|
|
No comments found for this account. Try syncing to fetch new comments.
|
|
{% endif %}
|
|
</p>
|
|
<a href="{% url 'social:sync' platform_type %}" class="btn btn-primary">
|
|
<i class="bi bi-arrow-repeat me-2"></i>
|
|
Sync Now
|
|
</a>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% endblock %} |