324 lines
18 KiB
HTML
324 lines
18 KiB
HTML
{% extends "layouts/base.html" %}
|
|
{% load i18n %}
|
|
|
|
{% block title %}{% trans "Communication Request" %} - PX360{% endblock %}
|
|
|
|
{% block extra_css %}
|
|
<style>
|
|
.page-header-gradient {
|
|
background: linear-gradient(135deg, #0d9488 0%, #14b8a6 50%, #2dd4bf 100%);
|
|
color: white; padding: 1.5rem 2rem; border-radius: 1rem; margin-bottom: 1.5rem;
|
|
box-shadow: 0 10px 15px -3px rgba(13, 148, 136, 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;
|
|
}
|
|
.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;
|
|
}
|
|
.section-icon {
|
|
width: 40px; height: 40px; border-radius: 0.75rem;
|
|
display: flex; align-items: center; justify-content: center;
|
|
}
|
|
.detail-row {
|
|
display: flex; padding: 0.75rem 0; border-bottom: 1px solid #f1f5f9;
|
|
}
|
|
.detail-label {
|
|
width: 160px; flex-shrink: 0; font-size: 0.875rem; font-weight: 600; color: #64748b;
|
|
}
|
|
.detail-value {
|
|
font-size: 0.875rem; color: #1e293b;
|
|
}
|
|
@keyframes fadeIn {
|
|
from { opacity: 0; transform: translateY(20px); }
|
|
to { opacity: 1; transform: translateY(0); }
|
|
}
|
|
.animate-in { animation: fadeIn 0.5s ease-out forwards; }
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="p-6 md:p-8 bg-gradient-to-br from-light to-blue-50 min-h-screen">
|
|
<div class="page-header-gradient animate-in">
|
|
<div class="flex flex-col md:flex-row justify-between items-start md:items-center gap-4">
|
|
<div class="flex items-center gap-3">
|
|
<a href="{% url 'px_sources:communication_request_list' %}" class="text-white/80 hover:text-white transition">
|
|
<i data-lucide="arrow-left" class="w-5 h-5"></i>
|
|
</a>
|
|
<div class="section-icon bg-white/20">
|
|
<i data-lucide="message-square" class="w-6 h-6 text-white"></i>
|
|
</div>
|
|
<div>
|
|
<h1 class="text-2xl font-bold">{% trans "Communication Request" %}</h1>
|
|
<p class="text-white/80 text-sm">{{ comm_req.created_at|date:"M d, Y H:i" }}</p>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
{% if comm_req.status == 'pending' %}
|
|
<span class="inline-flex items-center gap-1 px-4 py-2 rounded-full text-sm font-bold bg-yellow-100 text-yellow-700">
|
|
<i data-lucide="clock" class="w-4 h-4"></i> {% trans "Pending" %}
|
|
</span>
|
|
{% elif comm_req.status == 'contacted' %}
|
|
<span class="inline-flex items-center gap-1 px-4 py-2 rounded-full text-sm font-bold bg-blue-100 text-blue-700">
|
|
<i data-lucide="phone" class="w-4 h-4"></i> {% trans "Contacted" %}
|
|
</span>
|
|
{% elif comm_req.status == 'resolved' %}
|
|
<span class="inline-flex items-center gap-1 px-4 py-2 rounded-full text-sm font-bold bg-emerald-100 text-emerald-700">
|
|
<i data-lucide="check-circle" class="w-4 h-4"></i> {% trans "Resolved" %}
|
|
</span>
|
|
{% elif comm_req.status == 'closed' %}
|
|
<span class="inline-flex items-center gap-1 px-4 py-2 rounded-full text-sm font-bold bg-slate-200 text-slate-600">
|
|
<i data-lucide="archive" class="w-4 h-4"></i> {% trans "Closed" %}
|
|
</span>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
|
<div class="lg:col-span-2 space-y-6">
|
|
<div class="section-card animate-in">
|
|
<div class="section-header">
|
|
<div class="section-icon bg-teal-100">
|
|
<i data-lucide="file-text" class="w-5 h-5 text-teal-600"></i>
|
|
</div>
|
|
<h2 class="text-lg font-bold text-navy">{% trans "Request Details" %}</h2>
|
|
</div>
|
|
<div class="p-6">
|
|
<div class="detail-row">
|
|
<div class="detail-label">{% trans "Reason" %}</div>
|
|
<div class="detail-value font-semibold">{{ comm_req.get_reason_display }}</div>
|
|
</div>
|
|
<div class="detail-row">
|
|
<div class="detail-label">{% trans "Source User" %}</div>
|
|
<div class="detail-value">
|
|
{{ comm_req.source_user.user.get_full_name }}
|
|
<span class="text-slate-400 text-xs ml-2">({{ comm_req.source_user.source.name_en }})</span>
|
|
</div>
|
|
</div>
|
|
{% if comm_req.patient_name %}
|
|
<div class="detail-row">
|
|
<div class="detail-label">{% trans "Patient Name" %}</div>
|
|
<div class="detail-value">{{ comm_req.patient_name }}</div>
|
|
</div>
|
|
{% endif %}
|
|
{% if comm_req.patient_phone %}
|
|
<div class="detail-row">
|
|
<div class="detail-label">{% trans "Patient Phone" %}</div>
|
|
<div class="detail-value">{{ comm_req.patient_phone }}</div>
|
|
</div>
|
|
{% endif %}
|
|
{% if comm_req.patient_mrn %}
|
|
<div class="detail-row">
|
|
<div class="detail-label">{% trans "Patient MRN" %}</div>
|
|
<div class="detail-value">{{ comm_req.patient_mrn }}</div>
|
|
</div>
|
|
{% endif %}
|
|
<div class="detail-row border-0">
|
|
<div class="detail-label">{% trans "Message" %}</div>
|
|
<div class="detail-value whitespace-pre-wrap">{{ comm_req.message }}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{% if comm_req.resolution_notes %}
|
|
<div class="section-card animate-in">
|
|
<div class="section-header">
|
|
<div class="section-icon bg-emerald-100">
|
|
<i data-lucide="clipboard-check" class="w-5 h-5 text-emerald-600"></i>
|
|
</div>
|
|
<h2 class="text-lg font-bold text-navy">{% trans "Resolution Notes" %}</h2>
|
|
</div>
|
|
<div class="p-6">
|
|
<p class="text-sm text-slate whitespace-pre-wrap">{{ comm_req.resolution_notes }}</p>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if comm_req.is_resolved_as %}
|
|
<div class="section-card animate-in">
|
|
<div class="section-header">
|
|
<div class="section-icon bg-indigo-100">
|
|
<i data-lucide="link" class="w-5 h-5 text-indigo-600"></i>
|
|
</div>
|
|
<h2 class="text-lg font-bold text-navy">{% trans "Linked Record" %}</h2>
|
|
</div>
|
|
<div class="p-6">
|
|
<div class="flex items-center gap-4">
|
|
<div class="w-12 h-12 rounded-xl bg-indigo-50 flex items-center justify-center">
|
|
{% if comm_req.resolved_as_content_type.model == 'complaint' %}
|
|
<i data-lucide="alert-triangle" class="w-6 h-6 text-indigo-600"></i>
|
|
{% elif comm_req.resolved_as_content_type.model == 'inquiry' %}
|
|
<i data-lucide="help-circle" class="w-6 h-6 text-indigo-600"></i>
|
|
{% elif comm_req.resolved_as_content_type.model == 'observation' %}
|
|
<i data-lucide="eye" class="w-6 h-6 text-indigo-600"></i>
|
|
{% elif comm_req.resolved_as_content_type.model == 'feedback' %}
|
|
<i data-lucide="lightbulb" class="w-6 h-6 text-indigo-600"></i>
|
|
{% else %}
|
|
<i data-lucide="file-text" class="w-6 h-6 text-indigo-600"></i>
|
|
{% endif %}
|
|
</div>
|
|
<div class="flex-1">
|
|
<p class="text-sm font-bold text-navy">{{ comm_req.resolved_as_type_label }}</p>
|
|
<p class="text-xs text-slate-400">{{ comm_req.resolved_as_object_id }}</p>
|
|
</div>
|
|
{% if comm_req.resolved_as_url_name %}
|
|
<a href="{% url comm_req.resolved_as_url_name comm_req.resolved_as_object_id %}"
|
|
class="inline-flex items-center gap-1 px-4 py-2 bg-indigo-600 text-white text-sm font-semibold rounded-lg hover:bg-indigo-700 transition">
|
|
<i data-lucide="external-link" class="w-4 h-4"></i> {% trans "View Record" %}
|
|
</a>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% else %}
|
|
<div class="section-card animate-in">
|
|
<div class="section-header">
|
|
<div class="section-icon bg-orange-100">
|
|
<i data-lucide="plus-circle" class="w-5 h-5 text-orange-600"></i>
|
|
</div>
|
|
<h2 class="text-lg font-bold text-navy">{% trans "Create Record" %}</h2>
|
|
</div>
|
|
<div class="p-6">
|
|
<p class="text-sm text-slate-500 mb-4">{% trans "Convert this communication request into a record:" %}</p>
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<a href="{% url 'complaints:complaint_create' %}?comm_req={{ comm_req.id }}"
|
|
class="flex items-center gap-3 p-3 rounded-xl border-2 border-slate-200 hover:border-red-300 hover:bg-red-50 transition group">
|
|
<div class="w-10 h-10 rounded-lg bg-red-100 flex items-center justify-center group-hover:bg-red-200 transition">
|
|
<i data-lucide="alert-triangle" class="w-5 h-5 text-red-600"></i>
|
|
</div>
|
|
<div>
|
|
<p class="text-sm font-semibold text-navy">{% trans "Complaint" %}</p>
|
|
<p class="text-xs text-slate-400">{% trans "Patient complaint" %}</p>
|
|
</div>
|
|
</a>
|
|
<a href="{% url 'inquiries:inquiry_create' %}?comm_req={{ comm_req.id }}"
|
|
class="flex items-center gap-3 p-3 rounded-xl border-2 border-slate-200 hover:border-blue-300 hover:bg-blue-50 transition group">
|
|
<div class="w-10 h-10 rounded-lg bg-blue-100 flex items-center justify-center group-hover:bg-blue-200 transition">
|
|
<i data-lucide="help-circle" class="w-5 h-5 text-blue-600"></i>
|
|
</div>
|
|
<div>
|
|
<p class="text-sm font-semibold text-navy">{% trans "Inquiry" %}</p>
|
|
<p class="text-xs text-slate-400">{% trans "Patient inquiry" %}</p>
|
|
</div>
|
|
</a>
|
|
<a href="{% url 'observations:observation_create' %}?comm_req={{ comm_req.id }}"
|
|
class="flex items-center gap-3 p-3 rounded-xl border-2 border-slate-200 hover:border-amber-300 hover:bg-amber-50 transition group">
|
|
<div class="w-10 h-10 rounded-lg bg-amber-100 flex items-center justify-center group-hover:bg-amber-200 transition">
|
|
<i data-lucide="eye" class="w-5 h-5 text-amber-600"></i>
|
|
</div>
|
|
<div>
|
|
<p class="text-sm font-semibold text-navy">{% trans "Observation" %}</p>
|
|
<p class="text-xs text-slate-400">{% trans "Safety observation" %}</p>
|
|
</div>
|
|
</a>
|
|
<a href="{% url 'feedback:feedback_create' %}?comm_req={{ comm_req.id }}"
|
|
class="flex items-center gap-3 p-3 rounded-xl border-2 border-slate-200 hover:border-purple-300 hover:bg-purple-50 transition group">
|
|
<div class="w-10 h-10 rounded-lg bg-purple-100 flex items-center justify-center group-hover:bg-purple-200 transition">
|
|
<i data-lucide="lightbulb" class="w-5 h-5 text-purple-600"></i>
|
|
</div>
|
|
<div>
|
|
<p class="text-sm font-semibold text-navy">{% trans "Suggestion" %}</p>
|
|
<p class="text-xs text-slate-400">{% trans "Patient suggestion" %}</p>
|
|
</div>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div class="space-y-6">
|
|
<div class="section-card animate-in">
|
|
<div class="section-header">
|
|
<div class="section-icon bg-blue-100">
|
|
<i data-lucide="settings" class="w-5 h-5 text-blue-600"></i>
|
|
</div>
|
|
<h2 class="text-lg font-bold text-navy">{% trans "Update Status" %}</h2>
|
|
</div>
|
|
<div class="p-6">
|
|
<form method="post">
|
|
{% csrf_token %}
|
|
<div class="mb-4">
|
|
<label class="block text-sm font-semibold text-slate mb-2">{% trans "Status" %}</label>
|
|
<select name="status" class="w-full px-4 py-2.5 border-2 border-slate-200 rounded-xl text-sm focus:border-teal-500 focus:ring-2 focus:ring-teal-500/20 outline-none transition">
|
|
<option value="pending" {% if comm_req.status == 'pending' %}selected{% endif %}>{% trans "Pending" %}</option>
|
|
<option value="contacted" {% if comm_req.status == 'contacted' %}selected{% endif %}>{% trans "Contacted" %}</option>
|
|
<option value="resolved" {% if comm_req.status == 'resolved' %}selected{% endif %}>{% trans "Resolved" %}</option>
|
|
<option value="closed" {% if comm_req.status == 'closed' %}selected{% endif %}>{% trans "Closed" %}</option>
|
|
</select>
|
|
</div>
|
|
<div class="mb-4">
|
|
<label class="block text-sm font-semibold text-slate mb-2">{% trans "Resolution Notes" %}</label>
|
|
<textarea name="resolution_notes" rows="4"
|
|
class="w-full px-4 py-2.5 border-2 border-slate-200 rounded-xl text-sm focus:border-teal-500 focus:ring-2 focus:ring-teal-500/20 outline-none transition resize-none"
|
|
placeholder="{% trans 'Add notes about the resolution...' %}">{{ comm_req.resolution_notes }}</textarea>
|
|
</div>
|
|
<button type="submit"
|
|
class="w-full inline-flex items-center justify-center gap-2 px-6 py-3 bg-teal-600 text-white rounded-xl font-semibold hover:bg-teal-700 transition">
|
|
<i data-lucide="save" class="w-4 h-4"></i>
|
|
{% trans "Save Changes" %}
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="section-card animate-in">
|
|
<div class="section-header">
|
|
<div class="section-icon bg-purple-100">
|
|
<i data-lucide="info" class="w-5 h-5 text-purple-600"></i>
|
|
</div>
|
|
<h2 class="text-lg font-bold text-navy">{% trans "Timeline" %}</h2>
|
|
</div>
|
|
<div class="p-6 space-y-4">
|
|
<div class="flex items-start gap-3">
|
|
<div class="w-8 h-8 rounded-full bg-teal-100 flex items-center justify-center flex-shrink-0 mt-0.5">
|
|
<i data-lucide="plus" class="w-4 h-4 text-teal-600"></i>
|
|
</div>
|
|
<div>
|
|
<p class="text-sm font-semibold text-navy">{% trans "Created" %}</p>
|
|
<p class="text-xs text-slate-400">{{ comm_req.created_at|date:"M d, Y H:i" }}</p>
|
|
<p class="text-xs text-slate-500">{{ comm_req.source_user.user.get_full_name }}</p>
|
|
</div>
|
|
</div>
|
|
|
|
{% if comm_req.contacted_by %}
|
|
<div class="flex items-start gap-3">
|
|
<div class="w-8 h-8 rounded-full bg-blue-100 flex items-center justify-center flex-shrink-0 mt-0.5">
|
|
<i data-lucide="phone" class="w-4 h-4 text-blue-600"></i>
|
|
</div>
|
|
<div>
|
|
<p class="text-sm font-semibold text-navy">{% trans "Contacted" %}</p>
|
|
<p class="text-xs text-slate-400">{{ comm_req.contacted_at|date:"M d, Y H:i" }}</p>
|
|
<p class="text-xs text-slate-500">{{ comm_req.contacted_by.get_full_name }}</p>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if comm_req.status == 'resolved' or comm_req.status == 'closed' %}
|
|
<div class="flex items-start gap-3">
|
|
<div class="w-8 h-8 rounded-full bg-emerald-100 flex items-center justify-center flex-shrink-0 mt-0.5">
|
|
<i data-lucide="check-circle" class="w-4 h-4 text-emerald-600"></i>
|
|
</div>
|
|
<div>
|
|
<p class="text-sm font-semibold text-navy">{{ comm_req.get_status_display }}</p>
|
|
<p class="text-xs text-slate-400">{{ comm_req.modified_at|date:"M d, Y H:i" }}</p>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
lucide.createIcons();
|
|
});
|
|
</script>
|
|
{% endblock %}
|