HH/templates/complaints/inquiry_detail.html
2026-04-08 17:13:35 +03:00

848 lines
38 KiB
HTML

{% extends 'layouts/base.html' %}
{% load i18n %}
{% block title %}{% trans "Inquiry" %} #{{ inquiry.reference_number|truncatechars:15 }} - PX360{% endblock %}
{% block extra_css %}
<style>
:root {
--hh-navy: #005696;
--hh-blue: #007bbd;
--hh-cyan: #06b6d4;
--hh-light: #eef6fb;
--hh-slate: #64748b;
--hh-success: #10b981;
--hh-warning: #f59e0b;
--hh-danger: #ef4444;
}
.detail-card {
background: white;
border-radius: 1rem;
border: 1px solid #e2e8f0;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05);
transition: all 0.3s ease;
}
.detail-card:hover {
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
}
.card-header {
background: linear-gradient(135deg, var(--hh-light), #e0f2fe);
padding: 1.25rem 1.75rem;
border-bottom: 1px solid #bae6fd;
border-radius: 1rem 1rem 0 0;
}
.info-label {
font-size: 0.75rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--hh-slate);
margin-bottom: 0.375rem;
}
.info-value {
font-size: 0.95rem;
color: #1e293b;
font-weight: 500;
}
.timeline {
position: relative;
padding-left: 2rem;
}
.timeline::before {
content: '';
position: absolute;
left: 8px;
top: 0;
bottom: 0;
width: 2px;
background: #e2e8f0;
}
.timeline-item {
position: relative;
padding-bottom: 1.5rem;
}
.timeline-item::before {
content: '';
position: absolute;
left: -1.625rem;
top: 4px;
width: 14px;
height: 14px;
border-radius: 50%;
background: white;
border: 3px solid var(--hh-blue);
z-index: 1;
}
.timeline-item.status_change::before { border-color: var(--hh-warning); }
.timeline-item.response::before { border-color: var(--hh-success); }
.timeline-item.note::before { border-color: var(--hh-navy); }
.btn-primary {
background: linear-gradient(135deg, var(--hh-navy) 0%, var(--hh-blue) 100%);
color: white;
padding: 0.625rem 1.25rem;
border-radius: 0.75rem;
font-weight: 600;
border: none;
cursor: pointer;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
display: inline-flex;
align-items: center;
gap: 0.5rem;
text-decoration: none;
font-size: 0.875rem;
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 8px 16px rgba(0, 86, 150, 0.3);
}
.btn-primary:disabled {
opacity: 0.6;
cursor: not-allowed;
transform: none;
box-shadow: none;
}
.btn-secondary {
background: white;
color: var(--hh-slate);
padding: 0.625rem 1.25rem;
border-radius: 0.75rem;
font-weight: 600;
border: 1px solid #e2e8f0;
cursor: pointer;
transition: all 0.2s ease;
font-size: 0.875rem;
}
.btn-secondary:hover {
background: #f8fafc;
border-color: #cbd5e1;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes spin {
to { transform: rotate(360deg); }
}
.animate-in {
animation: fadeIn 0.5s ease-out forwards;
}
.spinner {
display: inline-block;
width: 1rem;
height: 1rem;
border: 2px solid rgba(255,255,255,0.3);
border-top-color: white;
border-radius: 50%;
animation: spin 0.6s linear infinite;
}
.spinner-dark {
border-color: rgba(0,86,150,0.2);
border-top-color: var(--hh-navy);
}
.ai-suggestion-card {
border: 2px dashed #bae6fd;
border-radius: 0.75rem;
padding: 1rem;
background: linear-gradient(135deg, #f0f9ff, #e0f2fe);
cursor: pointer;
transition: all 0.2s ease;
}
.ai-suggestion-card:hover {
border-color: var(--hh-blue);
background: linear-gradient(135deg, #e0f2fe, #bae6fd);
transform: translateY(-1px);
}
.ai-suggestion-card.selected {
border-style: solid;
border-color: var(--hh-navy);
background: linear-gradient(135deg, #e0f2fe, #bae6fd);
box-shadow: 0 0 0 2px var(--hh-navy);
}
.lang-tab {
padding: 0.5rem 1rem;
font-size: 0.8rem;
font-weight: 600;
border-radius: 0.5rem 0.5rem 0 0;
cursor: pointer;
border: 1px solid #e2e8f0;
border-bottom: none;
background: #f1f5f9;
color: var(--hh-slate);
transition: all 0.2s ease;
}
.lang-tab.active {
background: white;
color: var(--hh-navy);
border-color: #bae6fd;
}
</style>
{% endblock %}
{% block content %}
<div class="px-4 py-6">
<!-- Back Button -->
<div class="mb-6 animate-in">
{% if source_user %}
<a href="{% url 'px_sources:source_user_inquiry_list' %}" class="inline-flex items-center gap-2 px-4 py-2 border border-slate-200 rounded-xl text-slate-600 hover:bg-slate-50 transition text-sm font-semibold">
<i data-lucide="arrow-left" class="w-4 h-4"></i> {% trans "Back to My Inquiries" %}
</a>
{% else %}
<a href="{% url 'inquiries:inquiry_list' %}" class="inline-flex items-center gap-2 px-4 py-2 border border-slate-200 rounded-xl text-slate-600 hover:bg-slate-50 transition text-sm font-semibold">
<i data-lucide="arrow-left" class="w-4 h-4"></i> {% trans "Back to Inquiries" %}
</a>
{% endif %}
</div>
<!-- Inquiry Header -->
<div class="bg-gradient-to-r from-cyan-500 to-teal-500 rounded-2xl p-6 text-white mb-6 animate-in">
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
<div>
<div class="flex flex-wrap items-center gap-3 mb-4">
<h2 class="text-2xl font-bold">{{ inquiry.subject }}</h2>
<span class="px-3 py-1 bg-white/20 rounded-full text-sm font-semibold">
{% trans "Inquiry" %}
</span>
<span class="px-2.5 py-1 rounded-full text-[10px] font-bold uppercase
{% if inquiry.status == 'open' %}bg-yellow-100 text-yellow-700
{% elif inquiry.status == 'in_progress' %}bg-blue-100 text-blue-700
{% elif inquiry.status == 'resolved' %}bg-green-100 text-green-700
{% elif inquiry.status == 'closed' %}bg-slate-100 text-slate-600
{% elif inquiry.status == 'contacted' %}bg-purple-100 text-purple-700
{% elif inquiry.status == 'contacted_no_response' %}bg-slate-100 text-slate-600
{% else %}bg-slate-100 text-slate-600{% endif %}">
{{ inquiry.get_status_display }}
</span>
{% if inquiry.priority %}
<span class="px-2.5 py-1 rounded-full text-[10px] font-bold uppercase
{% if inquiry.priority == 'critical' %}bg-red-500 text-white
{% elif inquiry.priority == 'high' %}bg-orange-100 text-orange-700
{% elif inquiry.priority == 'medium' %}bg-yellow-100 text-yellow-700
{% elif inquiry.priority == 'low' %}bg-green-100 text-green-700
{% else %}bg-slate-100 text-slate-600{% endif %}">
{{ inquiry.get_priority_display }}
</span>
{% endif %}
</div>
<p class="text-white/90 text-sm">{{ inquiry.message|truncatewords:30 }}</p>
</div>
<div class="lg:text-right">
<div class="flex flex-wrap gap-2 justify-start lg:justify-end mb-3">
<span class="px-3 py-1 bg-white/20 rounded-full text-sm">
<i data-lucide="hash" class="w-3 h-3 inline-block mr-1"></i>
{{ inquiry.reference_number|truncatechars:15 }}
</span>
<span class="px-3 py-1 bg-white/20 rounded-full text-sm">
<i data-lucide="calendar" class="w-3 h-3 inline-block mr-1"></i>
{{ inquiry.created_at|date:"Y-m-d" }}
</span>
</div>
{% if can_respond %}
<button onclick="showRespondModal()" class="bg-white text-cyan-600 px-4 py-2 rounded-xl font-bold hover:bg-cyan-50 transition text-sm inline-flex items-center gap-2">
<i data-lucide="message-square" class="w-4 h-4"></i>
{% trans "Respond" %}
</button>
{% endif %}
</div>
</div>
</div>
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
<!-- Main Content -->
<div class="lg:col-span-2 space-y-6">
<!-- Inquiry Details -->
<div class="detail-card animate-in">
<div class="card-header">
<h3 class="text-lg font-bold text-navy flex items-center gap-2 m-0">
<i data-lucide="file-text" class="w-5 h-5"></i>
{% trans "Inquiry Details" %}
</h3>
</div>
<div class="p-6">
<div class="prose prose-sm max-w-none">
<p class="text-slate-700 leading-relaxed">{{ inquiry.message|linebreaks }}</p>
</div>
</div>
</div>
<!-- AI Analysis -->
<div class="detail-card animate-in">
<div class="card-header">
<div class="flex items-center justify-between">
<h3 class="text-lg font-bold text-navy flex items-center gap-2 m-0">
<i data-lucide="bot" class="w-5 h-5"></i> {% trans "AI Analysis" %}
</h3>
{% if can_respond and not inquiry.short_description_en %}
<button id="reanalyzeBtn" onclick="reanalyzeAI()" class="inline-flex items-center gap-1 px-3 py-1.5 bg-white border border-slate-200 rounded-lg text-xs font-semibold text-navy hover:bg-slate-50 transition">
<i data-lucide="refresh-cw" class="w-3 h-3"></i>
{% trans "Re-analyze" %}
</button>
{% endif %}
</div>
</div>
<div class="p-6" id="aiAnalysisContent">
{% if inquiry.short_description_en %}
<!-- Emotion Analysis -->
{% if inquiry.emotion and inquiry.emotion != 'neutral' %}
<div class="bg-gradient-to-r from-light to-blue-50 border border-blue-200 rounded-2xl p-5 mb-6">
<h4 class="font-bold text-navy mb-3 flex items-center gap-2">
<i data-lucide="cpu" class="w-5 h-5"></i> {% trans "Emotion Analysis" %}
</h4>
<div class="flex items-center justify-between mb-3">
<span class="px-4 py-2 bg-navy text-white rounded-xl font-bold flex items-center gap-2">
<i data-lucide="frown" class="w-5 h-5"></i> {{ inquiry.get_emotion_display }}
</span>
<span class="text-slate">{% trans "Confidence" %}: {{ inquiry.emotion_confidence_percent|floatformat:0 }}%</span>
</div>
<div>
<div class="flex justify-between text-sm mb-1">
<span class="text-slate">{% trans "Intensity" %}</span>
<span class="font-semibold">{{ inquiry.emotion_intensity|floatformat:2 }} / 1.0</span>
</div>
<div class="h-2 bg-slate-200 rounded-full overflow-hidden">
<div class="h-full bg-gradient-to-r from-navy to-blue rounded-full" style="width: {{ inquiry.emotion_intensity_percent }}%"></div>
</div>
</div>
</div>
{% endif %}
<!-- AI Summary English -->
{% if inquiry.short_description_en %}
<div class="bg-light/50 border border-slate-200 rounded-2xl p-5 mb-4">
<h4 class="font-bold text-navy mb-2">{% trans "AI Summary (English)" %}</h4>
<p class="text-slate">{{ inquiry.short_description_en }}</p>
</div>
{% endif %}
<!-- AI Summary Arabic -->
{% if inquiry.short_description_ar %}
<div class="bg-light/50 border border-slate-200 rounded-2xl p-5">
<h4 class="font-bold text-navy mb-2">{% trans "AI Summary (Arabic)" %}</h4>
<p class="text-slate" dir="rtl">{{ inquiry.short_description_ar }}</p>
</div>
{% endif %}
{% else %}
<div class="text-center py-8">
<i data-lucide="bot" class="w-12 h-12 mx-auto text-slate-300 mb-3"></i>
<p class="text-slate text-sm">{% trans "AI analysis is running. Please refresh the page shortly." %}</p>
</div>
{% endif %}
</div>
</div>
<!-- Response -->
{% if inquiry.response %}
<div class="detail-card animate-in">
<div class="card-header bg-green-50 border-green-100">
<h3 class="text-lg font-bold text-green-800 flex items-center gap-2 m-0">
<i data-lucide="circle-check" class="w-5 h-5"></i>
{% trans "Response" %}
{% if inquiry.response_sent_at %}
<span class="text-xs font-normal text-green-600 ml-2">
<i data-lucide="send" class="w-3 h-3 inline mr-1"></i>
{% trans "Sent to inquirer" %}
</span>
{% endif %}
</h3>
</div>
<div class="p-6">
<div class="flex items-center gap-3 mb-4 text-sm text-slate-600">
<span class="flex items-center gap-1">
<i data-lucide="user" class="w-4 h-4"></i>
{% if inquiry.responded_by %}{{ inquiry.responded_by.get_full_name|default:inquiry.responded_by.email }}{% endif %}
</span>
<span></span>
<span class="flex items-center gap-1">
<i data-lucide="calendar" class="w-4 h-4"></i>
{% if inquiry.response_sent_at %}{{ inquiry.response_sent_at|date:"Y-m-d H:i" }}{% else %}{{ inquiry.responded_at|date:"Y-m-d H:i" }}{% endif %}
</span>
</div>
{% if inquiry.response_en %}
<div class="mb-4">
<p class="info-label mb-1">English</p>
<div class="prose prose-sm max-w-none">
<p class="text-slate-700 leading-relaxed">{{ inquiry.response_en|linebreaks }}</p>
</div>
</div>
{% endif %}
{% if inquiry.response_ar %}
<div class="mb-2">
<p class="info-label mb-1">العربية</p>
<div class="prose prose-sm max-w-none">
<p class="text-slate-700 leading-relaxed" dir="rtl">{{ inquiry.response_ar|linebreaks }}</p>
</div>
</div>
{% endif %}
{% if not inquiry.response_en and not inquiry.response_ar %}
<div class="prose prose-sm max-w-none">
<p class="text-slate-700 leading-relaxed">{{ inquiry.response|linebreaks }}</p>
</div>
{% endif %}
</div>
</div>
{% endif %}
<!-- Timeline -->
<div class="detail-card animate-in">
<div class="card-header">
<h3 class="text-lg font-bold text-navy flex items-center gap-2 m-0">
<i data-lucide="history" class="w-5 h-5"></i>
{% trans "Timeline" %}
</h3>
</div>
<div class="p-6">
<div class="timeline">
<!-- Created -->
<div class="timeline-item">
<p class="info-label">{% trans "Inquiry Created" %}</p>
<p class="text-sm text-slate-700">
{% trans "Created by" %} {% if inquiry.created_by %}{{ inquiry.created_by.get_full_name|default:inquiry.created_by.email }}{% endif %}
</p>
<p class="text-xs text-slate-500 mt-1">{{ inquiry.created_at|date:"Y-m-d H:i" }}</p>
</div>
<!-- Status Changes -->
{% for update in inquiry.updates.all %}
<div class="timeline-item {{ update.update_type }}">
<p class="info-label">
{% if update.update_type == 'status_change' %}{% trans "Status Changed" %}
{% elif update.update_type == 'response' %}{% trans "Response" %}
{% elif update.update_type == 'communication' %}{% trans "Communication" %}
{% else %}{% trans "Note" %}{% endif %}
</p>
<p class="text-sm text-slate-700">{{ update.message|truncatewords:30 }}</p>
{% if update.created_by %}
<p class="text-xs text-slate-500 mt-1">{% trans "by" %} {{ update.created_by.get_full_name|default:update.created_by.email }}</p>
{% endif %}
<p class="text-xs text-slate-500 mt-1">{{ update.created_at|date:"Y-m-d H:i" }}</p>
</div>
{% endfor %}
</div>
</div>
</div>
</div>
<!-- Sidebar -->
<div class="space-y-6">
<!-- Contact Information -->
<div class="detail-card animate-in">
<div class="card-header">
<h3 class="text-lg font-bold text-navy flex items-center gap-2 m-0">
<i data-lucide="user" class="w-5 h-5"></i>
{% trans "Contact Information" %}
</h3>
</div>
<div class="p-6 space-y-4">
<div>
<p class="info-label">{% trans "Name" %}</p>
<p class="info-value">{{ inquiry.contact_name|default:"-" }}</p>
</div>
<div>
<p class="info-label">{% trans "Phone" %}</p>
<p class="info-value">{{ inquiry.contact_phone|default:"-" }}</p>
</div>
<div>
<p class="info-label">{% trans "Email" %}</p>
<p class="info-value">{{ inquiry.contact_email|default:"-" }}</p>
</div>
</div>
</div>
<!-- Organization -->
<div class="detail-card animate-in">
<div class="card-header">
<h3 class="text-lg font-bold text-navy flex items-center gap-2 m-0">
<i data-lucide="building" class="w-5 h-5"></i>
{% trans "Organization" %}
</h3>
</div>
<div class="p-6 space-y-4">
<div>
<p class="info-label">{% trans "Hospital" %}</p>
<p class="info-value">{{ inquiry.hospital.name }}</p>
</div>
{% if inquiry.department %}
<div>
<p class="info-label">{% trans "Department" %}</p>
<p class="info-value">{{ inquiry.department.name }}</p>
</div>
{% endif %}
<div>
<p class="info-label">{% trans "Category" %}</p>
<p class="info-value">{{ inquiry.get_category_display|default:"-" }}</p>
</div>
{% if inquiry.priority %}
<div>
<p class="info-label">{% trans "Priority" %}</p>
<span class="px-2.5 py-1 rounded-full text-[10px] font-bold uppercase
{% if inquiry.priority == 'critical' %}bg-red-500 text-white
{% elif inquiry.priority == 'high' %}bg-orange-100 text-orange-700
{% elif inquiry.priority == 'medium' %}bg-yellow-100 text-yellow-700
{% elif inquiry.priority == 'low' %}bg-green-100 text-green-700
{% else %}bg-slate-100 text-slate-600{% endif %}">
{{ inquiry.get_priority_display }}
</span>
</div>
{% endif %}
</div>
</div>
<!-- Actions -->
<div class="detail-card animate-in">
<div class="card-header">
<h3 class="text-lg font-bold text-navy flex items-center gap-2 m-0">
<i data-lucide="settings" class="w-5 h-5"></i>
{% trans "Actions" %}
</h3>
</div>
<div class="p-4 space-y-2">
{% if can_respond %}
<button onclick="showRespondModal()" class="w-full btn-primary justify-center">
<i data-lucide="message-square" class="w-4 h-4"></i>
{% trans "Send Response" %}
</button>
{% endif %}
{% if inquiry.status != 'closed' %}
<a href="#" class="flex items-center gap-2 p-3 rounded-lg hover:bg-slate-50 transition text-navy font-medium text-sm">
<i data-lucide="edit" class="w-4 h-4"></i>
{% trans "Edit Inquiry" %}
</a>
{% endif %}
<a href="{% url 'rca:rca_create' %}?related_model=inquiry&related_id={{ inquiry.pk }}"
class="flex items-center gap-2 p-3 rounded-lg hover:bg-purple-50 transition text-purple-700 font-medium text-sm">
<i data-lucide="search" class="w-4 h-4"></i>
{% trans "Initiate RCA" %}
</a>
</div>
</div>
<!-- RCA -->
{% if linked_rcas %}
<div class="detail-card animate-in">
<div class="card-header">
<h3 class="text-lg font-bold text-navy flex items-center gap-2 m-0">
<i data-lucide="search" class="w-5 h-5"></i>
{% trans "Root Cause Analyses" %}
</h3>
</div>
<div class="p-4 space-y-3">
{% for rca in linked_rcas %}
<a href="{% url 'rca:rca_detail' pk=rca.pk %}" class="block p-3 rounded-lg border border-slate-200 hover:border-purple-300 transition group">
<p class="text-sm font-bold text-navy group-hover:text-purple-700 truncate">{{ rca.title }}</p>
<div class="flex items-center gap-2 mt-1">
<span class="px-2 py-0.5 rounded-full text-[10px] font-bold uppercase
{% if rca.status == 'draft' %}bg-slate-100 text-slate-600
{% elif rca.status == 'in_progress' %}bg-blue-100 text-blue-700
{% elif rca.status == 'review' %}bg-yellow-100 text-yellow-700
{% elif rca.status == 'approved' %}bg-green-100 text-green-700
{% elif rca.status == 'closed' %}bg-gray-100 text-gray-600{% endif %}">
{{ rca.get_status_display }}
</span>
<span class="text-[10px] text-slate">{{ rca.created_at|date:"M d, Y" }}</span>
</div>
</a>
{% endfor %}
</div>
</div>
{% endif %}
</div>
</div>
</div>
<!-- Respond Modal -->
<div id="respondModal" class="fixed inset-0 bg-black/50 z-50 hidden flex items-center justify-center p-4">
<div class="bg-white rounded-2xl shadow-2xl w-full max-w-3xl animate-in max-h-[90vh] overflow-y-auto">
<div class="p-6 border-b border-slate-200">
<div class="flex items-center justify-between">
<h3 class="text-xl font-bold text-navy flex items-center gap-2">
<i data-lucide="message-square" class="w-5 h-5"></i>
{% trans "Send Response" %}
</h3>
<button type="button" onclick="closeRespondModal()" class="text-slate-400 hover:text-slate-600 transition">
<i data-lucide="x" class="w-5 h-5"></i>
</button>
</div>
</div>
<form method="post" action="{% url 'inquiries:inquiry_respond' inquiry.pk %}" id="respondForm">
{% csrf_token %}
<div class="p-6">
<!-- Generate AI Response Button -->
<div class="mb-5">
<button type="button" id="generateAiBtn" onclick="generateAIResponse()" class="w-full inline-flex items-center justify-center gap-2 px-4 py-3 bg-gradient-to-r from-purple-500 to-indigo-500 text-white rounded-xl font-bold hover:from-purple-600 hover:to-indigo-600 transition text-sm shadow-lg">
<i data-lucide="sparkles" class="w-4 h-4"></i>
{% trans "Generate AI Response" %}
</button>
</div>
<!-- AI Suggestions (hidden by default) -->
<div id="aiSuggestions" class="hidden mb-5 space-y-3">
<div class="flex items-center gap-2 mb-2">
<i data-lucide="sparkles" class="w-4 h-4 text-purple-500"></i>
<span class="text-sm font-semibold text-navy">{% trans "AI Generated Response (click to use)" %}</span>
</div>
<div id="aiSuggestionEn" onclick="useAISuggestion('en')" class="ai-suggestion-card">
<p class="info-label mb-1">English</p>
<p class="text-sm text-slate-700" id="aiSuggestionEnText"></p>
</div>
<div id="aiSuggestionAr" onclick="useAISuggestion('ar')" class="ai-suggestion-card">
<p class="info-label mb-1">العربية</p>
<p class="text-sm text-slate-700" dir="rtl" id="aiSuggestionArText"></p>
</div>
<button type="button" onclick="useBothAISuggestions()" class="w-full btn-primary justify-center mt-2">
<i data-lucide="check" class="w-4 h-4"></i>
{% trans "Use Both Suggestions" %}
</button>
</div>
<!-- English Response -->
<div class="mb-4">
<label class="block text-sm font-semibold text-navy mb-2">
{% trans "Response (English)" %}
</label>
<textarea name="response_en" id="responseEn" rows="6"
class="w-full px-4 py-3 border-2 border-slate-200 rounded-xl focus:outline-none focus:border-blue focus:ring-2 focus:ring-blue/20 resize-none text-sm"
placeholder="{% trans 'Enter your response in English...' %}">{{ inquiry.response_en|default:"" }}</textarea>
</div>
<!-- Arabic Response -->
<div class="mb-4">
<label class="block text-sm font-semibold text-navy mb-2">
{% trans "Response (Arabic)" %}
</label>
<textarea name="response_ar" id="responseAr" rows="6" dir="rtl"
class="w-full px-4 py-3 border-2 border-slate-200 rounded-xl focus:outline-none focus:border-blue focus:ring-2 focus:ring-blue/20 resize-none text-sm"
placeholder="{% trans 'أدخل ردك باللغة العربية...' %}">{{ inquiry.response_ar|default:"" }}</textarea>
</div>
<p class="text-xs text-slate-400 mt-1">
<i data-lucide="info" class="w-3 h-3 inline mr-1"></i>
{% trans "At least one language is required. The response will be sent to the inquirer via SMS and Email." %}
</p>
</div>
<div class="p-6 border-t border-slate-200 flex gap-3">
<button type="submit" class="btn-primary flex-1 justify-center">
<i data-lucide="send" class="w-4 h-4"></i>
{% trans "Send Response" %}
</button>
<button type="button" onclick="closeRespondModal()" class="btn-secondary">
{% trans "Cancel" %}
</button>
</div>
</form>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
lucide.createIcons();
});
function getCSRFToken() {
const metaTag = document.querySelector('[name=csrfmiddlewaretoken]');
if (metaTag) return metaTag.value;
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
const cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
const cookie = cookies[i].trim();
if (cookie.substring(0, 9) === ('csrftoken' + '=')) {
cookieValue = decodeURIComponent(cookie.substring(9));
break;
}
}
}
return cookieValue;
}
function showRespondModal() {
document.getElementById('respondModal').classList.remove('hidden');
}
function closeRespondModal() {
document.getElementById('respondModal').classList.add('hidden');
}
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape') {
closeRespondModal();
}
});
function generateAIResponse() {
const btn = document.getElementById('generateAiBtn');
const suggestionsDiv = document.getElementById('aiSuggestions');
btn.disabled = true;
btn.innerHTML = '<span class="spinner"></span> {% trans "Generating..." %}';
suggestionsDiv.classList.add('hidden');
fetch('/complaints/api/inquiries/{{ inquiry.pk }}/generate_ai_response/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': getCSRFToken(),
},
credentials: 'same-origin'
})
.then(response => {
if (!response.ok) {
return response.json().then(data => {
throw new Error(data.error || 'Request failed');
});
}
return response.json();
})
.then(data => {
btn.disabled = false;
btn.innerHTML = '<i data-lucide="sparkles" class="w-4 h-4"></i> {% trans "Generate AI Response" %}';
lucide.createIcons();
if (data.success) {
document.getElementById('aiSuggestionEnText').textContent = data.response_en;
document.getElementById('aiSuggestionArText').textContent = data.response_ar;
suggestionsDiv.classList.remove('hidden');
} else {
alert(data.error || '{% trans "Failed to generate response" %}');
}
})
.catch(error => {
console.error('Error:', error);
btn.disabled = false;
btn.innerHTML = '<i data-lucide="sparkles" class="w-4 h-4"></i> {% trans "Generate AI Response" %}';
lucide.createIcons();
alert(error.message || '{% trans "An error occurred while generating response" %}');
});
}
function useAISuggestion(lang) {
if (lang === 'en') {
document.getElementById('responseEn').value = document.getElementById('aiSuggestionEnText').textContent;
document.getElementById('aiSuggestionEn').classList.add('selected');
setTimeout(() => document.getElementById('aiSuggestionEn').classList.remove('selected'), 1500);
} else {
document.getElementById('responseAr').value = document.getElementById('aiSuggestionArText').textContent;
document.getElementById('aiSuggestionAr').classList.add('selected');
setTimeout(() => document.getElementById('aiSuggestionAr').classList.remove('selected'), 1500);
}
}
function useBothAISuggestions() {
useAISuggestion('en');
useAISuggestion('ar');
document.getElementById('aiSuggestionEn').classList.add('selected');
document.getElementById('aiSuggestionAr').classList.add('selected');
}
function reanalyzeAI() {
const btn = document.getElementById('reanalyzeBtn');
const content = document.getElementById('aiAnalysisContent');
btn.disabled = true;
btn.innerHTML = '<span class="spinner spinner-dark"></span> {% trans "Analyzing..." %}';
content.innerHTML = '<div class="text-center py-8"><span class="spinner spinner-dark" style="width:2rem;height:2rem;border-width:3px;"></span><p class="text-slate text-sm mt-3">{% trans "Re-analyzing inquiry with AI..." %}</p></div>';
fetch('/complaints/api/inquiries/{{ inquiry.pk }}/reanalyze_ai/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': getCSRFToken(),
},
credentials: 'same-origin'
})
.then(response => {
if (!response.ok) {
return response.json().then(data => {
throw new Error(data.error || 'Request failed');
});
}
return response.json();
})
.then(data => {
btn.disabled = false;
btn.innerHTML = '<i data-lucide="refresh-cw" class="w-3 h-3"></i> {% trans "Re-analyze" %}';
lucide.createIcons();
if (data.success) {
let html = '';
if (data.emotion && data.emotion !== 'neutral') {
html += '<div class="bg-gradient-to-r from-light to-blue-50 border border-blue-200 rounded-2xl p-5 mb-6">';
html += '<h4 class="font-bold text-navy mb-3 flex items-center gap-2"><i data-lucide="cpu" class="w-5 h-5"></i> {% trans "Emotion Analysis" %}</h4>';
html += '<div class="flex items-center justify-between mb-3">';
html += '<span class="px-4 py-2 bg-navy text-white rounded-xl font-bold flex items-center gap-2"><i data-lucide="frown" class="w-5 h-5"></i> ' + escapeHtml(data.emotion_display) + '</span>';
html += '<span class="text-slate">{% trans "Confidence" %}: ' + data.emotion_confidence_percent.toFixed(0) + '%</span>';
html += '</div>';
html += '<div>';
html += '<div class="flex justify-between text-sm mb-1"><span class="text-slate">{% trans "Intensity" %}</span><span class="font-semibold">' + data.emotion_intensity.toFixed(2) + ' / 1.0</span></div>';
html += '<div class="h-2 bg-slate-200 rounded-full overflow-hidden"><div class="h-full bg-gradient-to-r from-navy to-blue rounded-full" style="width: ' + data.emotion_intensity_percent + '%"></div></div>';
html += '</div></div>';
}
if (data.short_description_en) {
html += '<div class="bg-light/50 border border-slate-200 rounded-2xl p-5 mb-4">';
html += '<h4 class="font-bold text-navy mb-2">{% trans "AI Summary (English)" %}</h4>';
html += '<p class="text-slate">' + escapeHtml(data.short_description_en) + '</p>';
html += '</div>';
}
if (data.short_description_ar) {
html += '<div class="bg-light/50 border border-slate-200 rounded-2xl p-5">';
html += '<h4 class="font-bold text-navy mb-2">{% trans "AI Summary (Arabic)" %}</h4>';
html += '<p class="text-slate" dir="rtl">' + escapeHtml(data.short_description_ar) + '</p>';
html += '</div>';
}
if (!html) {
html = '<div class="text-center py-8"><i data-lucide="check-circle" class="w-10 h-10 mx-auto text-green-500 mb-3"></i><p class="text-slate text-sm">{% trans "AI analysis complete" %}</p></div>';
}
content.innerHTML = html;
lucide.createIcons();
} else {
content.innerHTML = '<div class="text-center py-8"><i data-lucide="alert-circle" class="w-10 h-10 mx-auto text-red-500 mb-3"></i><p class="text-slate text-sm">' + escapeHtml(data.error || '{% trans "Analysis failed" %}') + '</p></div>';
lucide.createIcons();
}
})
.catch(error => {
console.error('Error:', error);
btn.disabled = false;
btn.innerHTML = '<i data-lucide="refresh-cw" class="w-3 h-3"></i> {% trans "Re-analyze" %}';
lucide.createIcons();
content.innerHTML = '<div class="text-center py-8"><i data-lucide="alert-circle" class="w-10 h-10 mx-auto text-red-500 mb-3"></i><p class="text-slate text-sm">' + escapeHtml(error.message || '{% trans "An error occurred" %}') + '</p></div>';
lucide.createIcons();
});
}
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
</script>
{% endblock %}