HH/templates/complaints/explanation_form.html
2026-07-11 19:24:28 +03:00

408 lines
25 KiB
HTML

{% load i18n %}
{% load static %}
<!DOCTYPE html>
<html lang="{{ LANGUAGE_CODE|default:'en' }}" dir="{% if LANGUAGE_CODE == 'ar' %}rtl{% else %}ltr{% endif %}">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ complaint.reference_number }} - {% trans "Response" %}</title>
<link rel="stylesheet" href="{% static 'dist/css/tailwind.css' %}">
<link rel="stylesheet" href="{% static 'vendor/fonts/noto-kufi-arabic/arabic.css' %}">
<script src="https://unpkg.com/lucide@latest"></script>
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
body { font-family: 'Inter', 'Noto Kufi Arabic', sans-serif; }
[dir="rtl"] body, [dir="rtl"] input, [dir="rtl"] textarea, [dir="rtl"] select, [dir="rtl"] button {
font-family: 'Noto Kufi Arabic', sans-serif;
}
</style>
</head>
<body class="bg-slate-50 min-h-screen py-8 px-4">
<div class="w-full max-w-3xl mx-auto">
<!-- Back -->
{% if complaint.department %}
<a href="{% url 'organizations:department_detail' complaint.department.id %}" class="inline-flex items-center gap-2 text-sm text-slate hover:text-navy transition mb-4">&larr; {% trans "Back to Department" %}</a>
{% endif %}
<!-- Logo -->
<div class="text-center mb-6">
<img src="{% static 'img/hh-logo.png' %}" alt="Al Hammadi Hospital" class="h-16 w-auto mx-auto inline-block">
</div>
<!-- Complaint Card -->
<div class="bg-white rounded-2xl shadow-sm border border-slate-200 p-6 mb-6">
<!-- Reference + Title -->
<div class="flex items-center justify-between mb-1">
<div class="flex items-center gap-2">
<span class="px-2.5 py-1 rounded-full text-[10px] font-bold uppercase tracking-wider
{% if complaint.status == 'open' %}bg-yellow-100 text-yellow-700
{% elif complaint.status == 'in_progress' %}bg-blue-100 text-blue-700
{% elif complaint.status == 'resolved' %}bg-green-100 text-green-700
{% elif complaint.status == 'closed' %}bg-slate-100 text-slate-600
{% else %}bg-slate-100 text-slate-600{% endif %}">
{{ complaint.get_status_display }}
</span>
<span class="text-sm font-bold text-navy">{{ complaint.reference_number }}</span>
</div>
{% comment %} <a href="{% url 'complaints:complaint_explanation_pdf' complaint_id=complaint.id token=explanation.token %}" target="_blank"
class="inline-flex items-center gap-1.5 px-3 py-1.5 border border-slate-200 rounded-lg text-xs font-semibold text-slate hover:border-navy hover:text-navy transition">
<i data-lucide="download" class="w-3.5 h-3.5"></i>
{% trans "PDF" %}
</a> {% endcomment %}
</div>
<h1 class="text-xl font-bold text-navy mb-4">{{ complaint.title }}</h1>
<!-- Description -->
<div class="border-t border-slate-100 pt-4">
<p class="text-xs font-bold text-slate uppercase mb-2">{% trans "Description" %}</p>
<p class="text-base leading-relaxed text-slate">{{ complaint.description }}</p>
{% if complaint.short_description_en and complaint.short_description_en != complaint.description %}
<p class="text-sm leading-relaxed text-slate/70 mt-3">{{ complaint.short_description_en }}</p>
{% endif %}
</div>
{% if error %}
<div class="mt-4 bg-red-50 border border-red-200 rounded-xl p-4">
<p class="text-sm text-red-700 font-medium">{{ error }}</p>
</div>
{% endif %}
</div>
{% if explanation.request_message %}
<div class="bg-blue-50 border border-blue-200 rounded-xl p-4 mb-6 flex items-start gap-3">
<i data-lucide="info" class="w-4 h-4 text-blue-600 shrink-0 mt-0.5"></i>
<div>
<p class="text-xs font-bold text-blue-700 uppercase mb-1">{% trans "Note from PX Team" %}</p>
<p class="text-sm text-slate-700">{{ explanation.request_message }}</p>
</div>
</div>
{% endif %}
{% if explanation.attachments.exists %}
<div class="bg-white rounded-2xl shadow-sm border border-slate-200 p-4 mb-6">
<p class="text-xs font-bold text-slate/60 uppercase mb-2">{% trans "Attached Documents" %}</p>
<ul class="space-y-1.5">
{% for att in explanation.attachments.all %}
<li>
<a href="{{ att.file.url }}" target="_blank" class="inline-flex items-center gap-2 text-sm text-blue-600 hover:underline">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.172 7l-6.586 6.586a2 2 0 102.828 2.828l6.414-6.586a4 4 0 10-5.656-5.656l-6.415 6.585a6 6 0 108.486 8.486L20.5 13"/></svg>
{{ att.filename }}
</a>
</li>
{% endfor %}
</ul>
</div>
{% endif %}
<!-- Action Choice -->
<div id="action-choice" class="bg-white rounded-2xl shadow-sm border border-slate-200 p-6">
<p class="text-sm font-semibold text-slate mb-4">{% trans "How would you like to respond?" %}</p>
<div class="flex gap-3">
<button type="button" onclick="showReplyForm()" class="flex-1 flex items-center justify-center gap-2 px-4 py-3 bg-navy text-white rounded-xl font-bold text-sm hover:bg-blue transition">
<i data-lucide="message-square" class="w-4 h-4"></i>
{% trans "Submit Reply" %}
</button>
{% if investigate_url %}
<button type="button" onclick="goToInvestigation()" class="flex-1 flex items-center justify-center gap-2 px-4 py-3 border-2 border-slate-200 text-slate-700 rounded-xl font-bold text-sm hover:border-navy hover:text-navy transition">
<i data-lucide="message-square-plus" class="w-4 h-4"></i>
{% trans "Collect Feedback" %}
</button>
{% endif %}
</div>
<button type="button" onclick="showRejectForm()" class="w-full mt-3 flex items-center justify-center gap-2 px-4 py-2.5 border-2 border-red-200 text-red-600 rounded-xl font-bold text-sm hover:border-red-400 hover:bg-red-50 transition">
<i data-lucide="log-out" class="w-4 h-4"></i>
{% trans "Wrong Department" %}
</button>
</div>
<!-- Reject Routing Form -->
<div id="reject-section" style="display:none">
<div class="bg-white rounded-2xl shadow-sm border border-slate-200 p-6 mt-4">
{% if error %}
<div class="bg-red-50 border border-red-200 rounded-xl p-3 mb-4 text-sm text-red-700 font-semibold">
{% trans error %}
</div>
{% endif %}
<form method="post" class="space-y-4">
{% csrf_token %}
<div class="flex items-center gap-2 mb-1">
<i data-lucide="alert-triangle" class="w-5 h-5 text-red-500"></i>
<h2 class="text-base font-bold text-navy">{% trans "Reject Routing" %}</h2>
</div>
<p class="text-sm text-slate">{% trans "Use this if the complaint was sent to the wrong department. The PX team will be notified to re-route it." %}</p>
<div>
<label for="rejection_reason" class="block text-sm font-semibold text-navy mb-2">
{% trans "Reason" %} <span class="text-red-500">*</span>
</label>
<textarea name="rejection_reason" id="rejection_reason" rows="4" required
class="w-full px-4 py-3 border-2 border-slate-200 rounded-xl text-sm text-slate focus:outline-none focus:border-navy focus:ring-2 focus:ring-navy/20 resize-none"
placeholder="{% trans 'Explain why this complaint does not belong to your department...' %}">{{ rejection_reason|default:'' }}</textarea>
</div>
{% if hospital_departments %}
<div>
<label for="suggested_department_id" class="block text-sm font-semibold text-navy mb-2">
{% trans "Suggest Correct Department (optional)" %}
</label>
<select name="suggested_department_id" id="suggested_department_id"
class="w-full px-4 py-3 border-2 border-slate-200 rounded-xl text-sm text-slate focus:outline-none focus:border-navy bg-white">
<option value="">{% trans "Select Department" %}</option>
{% for dept in hospital_departments %}
<option value="{{ dept.id }}">{{ dept.get_localized_name }}</option>
{% endfor %}
</select>
</div>
{% endif %}
<div class="flex gap-3">
<button type="button" onclick="hideRejectForm()" class="flex-1 px-4 py-3 border-2 border-slate-200 text-slate-700 rounded-xl font-bold text-sm hover:border-slate-400 transition">
{% trans "Cancel" %}
</button>
<button type="submit" name="action" value="reject_routing" class="flex-1 px-4 py-3 bg-red-500 text-white rounded-xl font-bold text-sm hover:bg-red-600 transition flex items-center justify-center gap-2"
onclick="return confirm('{% trans "Reject this routing as wrong department?" %}')">
<i data-lucide="log-out" class="w-4 h-4"></i> {% trans "Reject Routing" %}
</button>
</div>
<p class="text-xs text-slate/60 text-center">{% trans "This action cannot be undone." %}</p>
</form>
</div>
</div>
<!-- Reply Form -->
<div id="reply-section" style="display:none">
<div class="bg-white rounded-2xl shadow-sm border border-slate-200 p-6 mt-4">
{% if error %}
<div class="bg-red-50 border border-red-200 rounded-xl p-3 mb-4 text-sm text-red-700 font-semibold">
{% trans error %}
</div>
{% endif %}
<form method="post" enctype="multipart/form-data" class="space-y-4">
{% csrf_token %}
{% if otp_sent %}
<!-- ═══ OTP VERIFICATION BANNER (top, prominent) ═══ -->
<div class="bg-green-50 border border-green-200 rounded-xl p-4">
<div class="flex items-center justify-between mb-3">
<div class="flex items-center gap-2">
<i data-lucide="shield-check" class="w-5 h-5 text-green-600"></i>
<p class="text-sm font-bold text-green-800">{% trans "Verify your submission" %}</p>
</div>
<button type="submit" name="action" value="cancel_otp"
class="text-xs text-slate/60 hover:text-navy underline flex items-center gap-1">
<i data-lucide="pencil" class="w-3 h-3"></i>
{% trans "Edit response" %}
</button>
</div>
<p class="text-sm text-green-700 mb-3">
{% if otp_phone and otp_email %}{% trans "Verification code sent to your phone and email." %}
{% elif otp_phone %}{% trans "Verification code sent to your phone." %}
{% elif otp_email %}{% trans "Verification code sent to your email." %}
{% else %}{% trans "Verification code sent." %}{% endif %}
</p>
{% comment %} {% if dev_otp_code %}
<div class="mb-3 px-3 py-2 bg-yellow-50 border border-dashed border-yellow-400 rounded-lg text-xs text-yellow-800">
<span class="font-bold">DEBUG:</span>
{% trans "verification code is" %}
<span class="font-mono font-bold tracking-widest">{{ dev_otp_code }}</span>
</div>
{% endif %} {% endcomment %}
<div class="flex items-center gap-3">
<input type="text" name="otp_code" id="otpInput" maxlength="6" pattern="[0-9]{6}" autofocus
class="w-32 px-3 py-2 border-2 border-green-300 rounded-lg text-center text-lg font-bold tracking-widest focus:outline-none focus:border-green-600"
placeholder="000000" required
oninput="toggleVerifyBtn()">
<button type="submit" name="action" value="verify_submit" id="verifyBtn"
class="flex-1 px-4 py-2.5 bg-green-600 text-white rounded-xl font-bold text-sm hover:bg-green-700 transition disabled:opacity-40 disabled:cursor-not-allowed flex items-center justify-center gap-2"
disabled>
<i data-lucide="check-circle" class="w-4 h-4"></i>
{% trans "Verify & Submit" %}
</button>
</div>
<div class="flex items-center justify-between mt-3">
<p class="text-xs text-slate/60">{% trans "Enter the 6-digit code to complete your submission." %}</p>
<button type="submit" formnovalidate name="action" value="send_code"
class="text-xs text-green-700 hover:text-green-800 underline">
{% trans "Resend code" %}
</button>
</div>
</div>
<!-- Locked form fields wrapper -->
<div class="relative rounded-xl" style="opacity: 0.5; pointer-events: none;">
<div class="absolute -top-2.5 left-4 px-2 py-0.5 bg-slate-200 text-slate-600 rounded text-[10px] font-bold uppercase tracking-wider flex items-center gap-1 z-10">
<i data-lucide="lock" class="w-3 h-3"></i>
{% trans "Locked" %}
</div>
{% endif %}
<div>
<label for="explanation" class="block text-sm font-semibold text-navy mb-2">
{% trans "Your Response" %} <span class="text-red-500">*</span>
</label>
<textarea
id="explanation"
name="explanation"
rows="6"
required
class="w-full px-4 py-3 border-2 border-slate-200 rounded-xl text-sm text-slate focus:outline-none focus:border-navy focus:ring-2 focus:ring-navy/20 resize-none"
placeholder="{% trans 'Write your response here...' %}"
>{{ final_reply|default:'' }}</textarea>
</div>
<!-- Assessment -->
<div class="bg-slate-50 rounded-xl p-4 space-y-4">
<p class="text-xs font-bold text-slate/60 uppercase tracking-wide">{% trans "Assessment" %}</p>
<!-- Q1: Negligence -->
<div>
<p class="text-sm font-semibold text-slate mb-2">{% trans "Is there any negligence resulting from carelessness?" %}</p>
<div class="flex items-center gap-4">
<label class="flex items-center gap-2 cursor-pointer">
<input type="radio" name="negligence_finding" value="yes" class="w-4 h-4 accent-red-600" {% if negligence_finding == 'yes' %}checked{% endif %} required>
<span class="text-sm font-semibold text-red-700">{% trans "Yes" %}</span>
</label>
<label class="flex items-center gap-2 cursor-pointer">
<input type="radio" name="negligence_finding" value="no" class="w-4 h-4 accent-green-600" {% if negligence_finding == 'no' %}checked{% endif %}>
<span class="text-sm font-semibold text-green-700">{% trans "No" %}</span>
</label>
</div>
</div>
<!-- Q2: Policy issue -->
<div>
<p class="text-sm font-semibold text-slate mb-2">{% trans "Is it resulting from policies or regulations?" %}</p>
<div class="flex items-center gap-4">
<label class="flex items-center gap-2 cursor-pointer">
<input type="radio" name="policy_issue_finding" value="yes" class="w-4 h-4 accent-red-600" {% if policy_issue_finding == 'yes' %}checked{% endif %} required>
<span class="text-sm font-semibold text-red-700">{% trans "Yes" %}</span>
</label>
<label class="flex items-center gap-2 cursor-pointer">
<input type="radio" name="policy_issue_finding" value="no" class="w-4 h-4 accent-green-600" {% if policy_issue_finding == 'no' %}checked{% endif %}>
<span class="text-sm font-semibold text-green-700">{% trans "No" %}</span>
</label>
</div>
</div>
<!-- Q3: Improvement project -->
<div>
<p class="text-sm font-semibold text-slate mb-2">{% trans "Does this complaint require an improvement project?" %}</p>
<div class="flex items-center gap-4 mb-2">
<label class="flex items-center gap-2 cursor-pointer">
<input type="radio" name="requires_improvement_project" value="yes" class="w-4 h-4 accent-amber-600" {% if requires_improvement_project == 'yes' %}checked{% endif %} required onchange="toggleProjectField()">
<span class="text-sm font-semibold text-amber-700">{% trans "Yes" %}</span>
</label>
<label class="flex items-center gap-2 cursor-pointer">
<input type="radio" name="requires_improvement_project" value="no" class="w-4 h-4 accent-slate-400" {% if requires_improvement_project == 'no' %}checked{% endif %} onchange="toggleProjectField()">
<span class="text-sm font-semibold text-slate-500">{% trans "No" %}</span>
</label>
</div>
<div id="projectField" class="{% if requires_improvement_project != 'yes' %}hidden{% endif %}">
<textarea name="improvement_project_note" rows="3"
class="w-full px-3 py-2 border-2 border-slate-200 rounded-lg text-sm text-slate focus:outline-none focus:border-navy resize-none"
placeholder="{% trans 'Describe the required improvement project...' %}">{{ improvement_project_note|default:'' }}</textarea>
</div>
</div>
</div>
<!-- Attachments -->
<div>
<label class="block text-sm font-semibold text-navy mb-2">{% trans "Attachments (Optional)" %}</label>
<input
type="file"
id="attachments"
name="attachments"
multiple
class="block w-full text-sm text-slate file:mr-4 file:py-2 file:px-4 file:rounded-xl file:border-0 file:text-sm file:font-semibold file:bg-slate-100 file:text-navy hover:file:bg-slate-200 file:transition cursor-pointer border-2 border-slate-200 rounded-xl"
>
</div>
<!-- Consent -->
<div class="bg-amber-50 border border-amber-200 rounded-xl p-4">
<label class="flex items-start gap-3 cursor-pointer">
<input type="checkbox" name="consent" id="consentCheckbox" class="mt-0.5 w-5 h-5 accent-navy shrink-0"
{% if consent_checked %}checked{% endif %}
onchange="toggleSubmitBtn()">
<span class="text-sm text-slate-700 leading-relaxed">
{% trans "I confirm that I have reviewed the complaint details. I acknowledge that my reply represents the official department response for this complaint, and I accept full responsibility for its accuracy and content." %}
</span>
</label>
</div>
{% if otp_sent %}
<!-- Close the locked-fields wrapper -->
</div>
{% else %}
<!-- Step 1: Send code (only shown when OTP not yet sent) -->
<button type="submit" name="action" value="send_code" id="sendCodeBtn"
class="w-full flex items-center justify-center gap-2 px-4 py-3 bg-navy text-white rounded-xl font-bold text-sm hover:bg-blue transition disabled:opacity-40 disabled:cursor-not-allowed"
disabled>
<i data-lucide="send" class="w-4 h-4"></i> {% trans "Send Verification Code" %}
</button>
{% endif %}
<p class="text-xs text-slate/60 text-center">{% trans "This link can only be used once." %}</p>
</form>
</div>
</div>
</div>
<script>
lucide.createIcons();
function showReplyForm() {
document.getElementById('action-choice').style.display = 'none';
document.getElementById('reply-section').style.display = 'block';
}
function showRejectForm() {
document.getElementById('action-choice').style.display = 'none';
document.getElementById('reject-section').style.display = 'block';
}
function hideRejectForm() {
document.getElementById('reject-section').style.display = 'none';
document.getElementById('action-choice').style.display = 'block';
}
function goToInvestigation() {
window.location.href = "{{ investigate_url }}";
}
function toggleSubmitBtn() {
var cb = document.getElementById('consentCheckbox');
var btn = document.getElementById('sendCodeBtn');
if (btn) btn.disabled = !cb.checked;
}
function toggleVerifyBtn() {
var input = document.getElementById('otpInput');
var btn = document.getElementById('verifyBtn');
if (btn && input) btn.disabled = input.value.replace(/\s/g, '').length !== 6;
}
function toggleProjectField() {
var yesRadio = document.querySelector('input[name="requires_improvement_project"][value="yes"]');
var field = document.getElementById('projectField');
if (field && yesRadio) field.classList.toggle('hidden', !yesRadio.checked);
}
// Init directly — script is at the bottom of <body>, all elements exist.
// (DOMContentLoaded has already fired by the time this runs, so a listener
// would be dead code.)
toggleSubmitBtn();
toggleVerifyBtn();
toggleProjectField();
// Auto-show reply form if OTP was already sent (e.g. page reload after send_code)
{% if otp_sent %}
showReplyForm();
{% elif show_reject_form %}
showRejectForm();
{% endif %}
</script>
</body>
</html>