209 lines
9.0 KiB
HTML
209 lines
9.0 KiB
HTML
{% load i18n %}
|
|
{% load hospital_filters %}
|
|
<section class="bg-white rounded-2xl p-6 shadow-sm border border-slate-100">
|
|
<h3 class="text-xl font-bold text-navy mb-6 flex items-center gap-2">
|
|
<i data-lucide="bot" class="w-6 h-6"></i> {% trans "AI Analysis" %}
|
|
</h3>
|
|
|
|
{% if complaint.emotion %}
|
|
<div class="bg-gradient-to-r from-light to-blue-50 border border-blue-200 rounded-2xl p-6 mb-6">
|
|
<h4 class="font-bold text-navy mb-4 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-4">
|
|
<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> {{ complaint.get_emotion_display }}
|
|
</span>
|
|
<span class="text-slate">{% trans "Confidence" %}: {{ complaint.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">{{ complaint.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: {{ complaint.emotion_intensity_percent }}%"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if complaint.short_description_en %}
|
|
<div class="bg-light/50 border border-slate-200 rounded-2xl p-6 mb-6">
|
|
<h4 class="font-bold text-navy mb-3">{% trans "AI Summary (English)" %}</h4>
|
|
<p class="text-slate">{{ complaint.short_description_en }}</p>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if complaint.short_description_ar %}
|
|
<div class="bg-light/50 border border-slate-200 rounded-2xl p-6 mb-6">
|
|
<h4 class="font-bold text-navy mb-3">{% trans "AI Summary (Arabic)" %}</h4>
|
|
<p class="text-slate" dir="rtl">{{ complaint.short_description_ar }}</p>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if complaint.suggested_actions %}
|
|
<div class="space-y-4">
|
|
<h4 class="font-bold text-navy flex items-center gap-2">
|
|
<i data-lucide="lightbulb" class="w-5 h-5 text-blue-600"></i>
|
|
{% trans "Suggested Actions" %}
|
|
</h4>
|
|
|
|
{% for action in complaint.suggested_actions %}
|
|
<div class="bg-blue-50 border border-blue-200 rounded-xl p-4">
|
|
<div class="flex items-start justify-between gap-4">
|
|
<div class="flex-1">
|
|
<div class="flex items-center gap-2 mb-2 flex-wrap">
|
|
<span class="px-2 py-1
|
|
{% if action.priority == 'high' %}bg-red-100 text-red-700
|
|
{% elif action.priority == 'medium' %}bg-orange-100 text-orange-700
|
|
{% else %}bg-green-100 text-green-700{% endif %}
|
|
rounded-lg text-xs font-bold uppercase">
|
|
<i data-lucide="flag" class="w-3 h-3 inline mr-1"></i>
|
|
{{ action.priority }}
|
|
</span>
|
|
<span class="px-2 py-1 bg-blue-100 text-blue-700 rounded-lg text-xs font-bold">
|
|
<i data-lucide="folder" class="w-3 h-3 inline mr-1"></i>
|
|
{{ action.category|replace:"_: "|title }}
|
|
</span>
|
|
</div>
|
|
<p class="text-slate font-medium">{{ action.action_en }}</p>
|
|
{% if action.action_ar %}
|
|
<p class="text-slate text-sm mt-2" dir="rtl">{{ action.action_ar }}</p>
|
|
{% endif %}
|
|
</div>
|
|
{% if user.is_px_admin or user.is_hospital_admin %}
|
|
<button onclick="createAction('{{ action.action_en|escapejs }}', '{{ action.priority }}', '{{ action.category }}')"
|
|
class="inline-flex items-center gap-2 px-4 py-2 bg-gradient-to-r from-blue to-navy text-white rounded-lg font-semibold hover:from-navy hover:to-blue transition text-sm shadow-lg shadow-blue-200 whitespace-nowrap">
|
|
<i data-lucide="plus-circle" class="w-4 h-4"></i>
|
|
{% trans "Create Action" %}
|
|
</button>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
{% elif complaint.suggested_action_en %}
|
|
<!-- Fallback for old single-action format -->
|
|
<div class="bg-blue-50 border border-blue-200 rounded-2xl p-6">
|
|
<div class="flex items-start justify-between gap-4 mb-3">
|
|
<h4 class="font-bold text-navy flex items-center gap-2">
|
|
<i data-lucide="lightbulb" class="w-5 h-5 text-blue-600"></i>
|
|
{% trans "Suggested Action" %}
|
|
</h4>
|
|
{% if user.is_px_admin or user.is_hospital_admin %}
|
|
<button onclick="createAction('{{ complaint.suggested_action_en|escapejs }}', 'medium', 'process_improvement')"
|
|
class="inline-flex items-center gap-2 px-4 py-2 bg-gradient-to-r from-blue to-navy text-white rounded-lg font-semibold hover:from-navy hover:to-blue transition text-sm shadow-lg shadow-blue-200">
|
|
<i data-lucide="plus-circle" class="w-4 h-4"></i>
|
|
{% trans "Create Action" %}
|
|
</button>
|
|
{% endif %}
|
|
</div>
|
|
<p class="text-slate">{{ complaint.suggested_action_en }}</p>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if not complaint.emotion and not complaint.short_description_en and not complaint.suggested_actions %}
|
|
<div class="text-center py-12">
|
|
<i data-lucide="bot" class="w-16 h-16 mx-auto text-slate-300 mb-4"></i>
|
|
<p class="text-slate">{% trans "No AI analysis available for this complaint" %}</p>
|
|
</div>
|
|
{% endif %}
|
|
</section>
|
|
|
|
<script>
|
|
function createAction(actionText, priority, category) {
|
|
// Show confirmation
|
|
if (!confirm('{% trans "Are you sure you want to create a PX Action from this suggestion?" %}')) {
|
|
return;
|
|
}
|
|
|
|
// Get CSRF token from meta tag (more reliable)
|
|
function getCSRFToken() {
|
|
const metaTag = document.querySelector('[name=csrfmiddlewaretoken]');
|
|
if (metaTag) {
|
|
return metaTag.value;
|
|
}
|
|
|
|
// Fallback to cookie
|
|
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, name.length + 1) === (name + '=')) {
|
|
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return cookieValue;
|
|
}
|
|
|
|
// Create action via AJAX
|
|
const csrftoken = getCSRFToken();
|
|
|
|
if (!csrftoken) {
|
|
showAlert('error', '{% trans "CSRF token not found. Please refresh the page." %}');
|
|
return;
|
|
}
|
|
|
|
fetch('{% url "actions:action_create_from_ai" complaint.id %}', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
'X-CSRFToken': csrftoken,
|
|
},
|
|
body: new URLSearchParams({
|
|
'csrfmiddlewaretoken': csrftoken,
|
|
'action': actionText,
|
|
'priority': priority,
|
|
'category': category
|
|
})
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
// Show success message
|
|
showAlert('success', '{% trans "PX Action created successfully!" %}');
|
|
|
|
// Reload page after short delay to show new action
|
|
setTimeout(() => {
|
|
window.location.reload();
|
|
}, 1500);
|
|
} else {
|
|
// Show error
|
|
showAlert('error', data.error || '{% trans "Failed to create action" %}');
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
showAlert('error', '{% trans "An error occurred while creating the action" %}');
|
|
});
|
|
}
|
|
|
|
function showAlert(type, message) {
|
|
const alert = document.createElement('div');
|
|
const bgColor = type === 'success' ? 'bg-emerald-500' : 'bg-red-500';
|
|
const icon = type === 'success' ? 'check-circle' : 'alert-circle';
|
|
|
|
alert.className = `${bgColor} text-white px-6 py-4 rounded-xl shadow-xl z-50 flex items-center gap-3 fixed top-4 right-4`;
|
|
alert.innerHTML = `
|
|
<i data-lucide="${icon}" class="w-5 h-5"></i>
|
|
<span class="font-semibold">${message}</span>
|
|
<button type="button" onclick="this.parentElement.remove()" class="text-white/80 hover:text-white">
|
|
<i data-lucide="x" class="w-4 h-4"></i>
|
|
</button>
|
|
`;
|
|
|
|
document.body.appendChild(alert);
|
|
lucide.createIcons();
|
|
|
|
setTimeout(() => {
|
|
alert.remove();
|
|
}, 5000);
|
|
}
|
|
</script>
|