HH/templates/complaints/public_complaint_form.html

297 lines
17 KiB
HTML

{% extends "layouts/public_base.html" %}
{% load i18n static %}
{% block title %}{% trans "Submit a Complaint" %} - PX360{% endblock %}
{% block extra_css %}
<style>
.select-loading {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24'%3E%3Cpath fill='%23005696' d='M12 2a10 10 0 1 0 10 10A10 10 0 0 0 12 2zm0 18a8 8 0 1 1 8-8 8 8 0 0 1-8 8z' opacity='.25'/%3E%3Cpath fill='%23005696' d='M12 2a10 10 0 0 1 10 10h-2a8 8 0 0 0-8-8z'%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 12 12' to='360 12 12' dur='1s' repeatCount='indefinite'/%3E%3C/path%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 0.75rem center;
background-size: 1.25rem;
}
</style>
{% endblock %}
{% block content %}
<div class="complaint-form animate-fade-in">
<form id="public_complaint_form" method="post">
{% csrf_token %}
<div class="mb-6">
<h3 class="text-2xl font-bold text-navy mb-2 flex items-center gap-3">
<i data-lucide="alert-circle" class="w-6 h-6 text-red-600"></i>
{% trans "Submit a Complaint" %}
</h3>
<p class="text-slate text-sm">{% trans "Report an issue with our services. We take all concerns seriously and will investigate thoroughly." %}</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-5">
<div>
<label class="block text-sm font-semibold text-navy mb-2">{% trans "Name" %} <span class="text-red-500">*</span></label>
<input type="text" name="complainant_name" required placeholder="{% trans 'Your full name' %}"
class="w-full px-4 py-3 border border-slate-200 rounded-xl text-navy focus:outline-none focus:ring-2 focus:ring-red/20 form-input">
</div>
<div>
<label class="block text-sm font-semibold text-navy mb-2">{% trans "Relation to Patient" %} <span class="text-red-500">*</span></label>
<select name="relation_to_patient" required
class="w-full px-4 py-3 border border-slate-200 rounded-xl text-navy focus:outline-none focus:ring-2 focus:ring-red/20 bg-white form-input">
<option value="">{% trans "Select Relation" %}</option>
<option value="patient">{% trans "Patient" %}</option>
<option value="relative">{% trans "Relative" %}</option>
<option value="friend">{% trans "Friend" %}</option>
<option value="other">{% trans "Other" %}</option>
</select>
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-5">
<div>
<label class="block text-sm font-semibold text-navy mb-2">{% trans "Email" %}</label>
<input type="email" name="email" placeholder="your@email.com"
class="w-full px-4 py-3 border border-slate-200 rounded-xl text-navy focus:outline-none focus:ring-2 focus:ring-red/20 form-input">
</div>
<div>
<label class="block text-sm font-semibold text-navy mb-2">{% trans "Phone Number" %} <span class="text-red-500">*</span></label>
<input type="tel" name="mobile_number" maxlength="20" required placeholder="{% trans 'Your phone number' %}"
class="w-full px-4 py-3 border border-slate-200 rounded-xl text-navy focus:outline-none focus:ring-2 focus:ring-red/20 form-input">
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-5">
<div>
<label class="block text-sm font-semibold text-navy mb-2">{% trans "Patient Name" %} <span class="text-red-500">*</span></label>
<input type="text" name="patient_name" required placeholder="{% trans 'Name of patient involved' %}"
class="w-full px-4 py-3 border border-slate-200 rounded-xl text-navy focus:outline-none focus:ring-2 focus:ring-red/20 form-input">
</div>
<div>
<label class="block text-sm font-semibold text-navy mb-2">{% trans "National ID / Iqama No." %} <span class="text-red-500">*</span></label>
<input type="text" name="national_id" maxlength="20" required placeholder="{% trans '10-digit National ID or Iqama number' %}"
class="w-full px-4 py-3 border border-slate-200 rounded-xl text-navy focus:outline-none focus:ring-2 focus:ring-red/20 form-input">
</div>
</div>
<div class="mb-5">
<label class="block text-sm font-semibold text-navy mb-2">{% trans "Incident Date" %} <span class="text-red-500">*</span></label>
<input type="date" id="id_incident_date" name="incident_date" max="{% now 'Y-m-d' %}" required
class="w-full px-4 py-3 border border-slate-200 rounded-xl text-navy focus:outline-none focus:ring-2 focus:ring-red/20 form-input">
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-5">
<div>
<label class="block text-sm font-semibold text-navy mb-2">{% trans "Hospital" %} <span class="text-red-500">*</span></label>
<select name="hospital" id="id_hospital" required
class="w-full px-4 py-3 border border-slate-200 rounded-xl text-navy focus:outline-none focus:ring-2 focus:ring-red/20 bg-white form-input">
<option value="">{% trans "Select Hospital" %}</option>
{% for hospital in hospitals %}
<option value="{{ hospital.id }}">{{ hospital.get_localized_name }}</option>
{% endfor %}
</select>
</div>
<div>
<label class="block text-sm font-semibold text-navy mb-2">{% trans "Location Type" %} <span class="text-red-500">*</span></label>
<select name="location_type" id="id_location_type" required
class="w-full px-4 py-3 border border-slate-200 rounded-xl text-navy focus:outline-none focus:ring-2 focus:ring-red/20 bg-white form-input">
<option value="">{% trans "Select Location Type" %}</option>
<option value="OP">{% trans "Outpatient (OP)" %}</option>
<option value="IP">{% trans "Inpatient (IP)" %}</option>
<option value="ER">{% trans "Emergency (ER)" %}</option>
<option value="GENERAL">{% trans "General" %}</option>
</select>
</div>
</div>
<div id="area_container" style="display: none;" class="mb-5">
<label class="block text-sm font-semibold text-navy mb-2">{% trans "Area" %}</label>
<select id="id_area" name="area"
class="w-full px-4 py-3 border border-slate-200 rounded-xl text-navy focus:outline-none focus:ring-2 focus:ring-red/20 bg-white form-input">
<option value="">{% trans "Select Area (optional)" %}</option>
</select>
</div>
<div class="mb-5">
<label class="block text-sm font-semibold text-navy mb-2">{% trans "Category" %} <span class="text-red-500">*</span></label>
<select id="id_category" name="category" required
class="w-full px-4 py-3 border border-slate-200 rounded-xl text-navy focus:outline-none focus:ring-2 focus:ring-red/20 bg-white form-input">
<option value="">{% trans "Select Category" %}</option>
<option value="medical">{% trans "Medical" %}</option>
<option value="nursing">{% trans "Nursing" %}</option>
<option value="administrative">{% trans "Administrative" %}</option>
<option value="support_services">{% trans "Support Services" %}</option>
</select>
</div>
<div id="department_container" style="display: none;" class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-5">
<div>
<label class="block text-sm font-semibold text-navy mb-2">{% trans "Department" %} <span class="text-red-500">*</span></label>
<select id="id_department" name="department" required
class="w-full px-4 py-3 border border-slate-200 rounded-xl text-navy focus:outline-none focus:ring-2 focus:ring-red/20 bg-white form-input">
<option value="">{% trans "Select Department" %}</option>
</select>
</div>
<div id="section_container" style="display: none;">
<label class="block text-sm font-semibold text-navy mb-2">{% trans "Section" %}</label>
<select id="id_section" name="section"
class="w-full px-4 py-3 border border-slate-200 rounded-xl text-navy focus:outline-none focus:ring-2 focus:ring-red/20 bg-white form-input">
<option value="">{% trans "Select Section" %}</option>
</select>
</div>
</div>
<div class="mb-5">
<label class="block text-sm font-semibold text-navy mb-2">{% trans "Complaint Description" %} <span class="text-red-500">*</span></label>
<textarea name="complaint_details" rows="5" required placeholder="{% trans 'Please describe your complaint in detail...' %}"
class="w-full px-4 py-3 border border-slate-200 rounded-xl text-navy focus:outline-none focus:ring-2 focus:ring-red/20 resize-none form-input"></textarea>
</div>
<div class="text-center pt-4 border-t border-slate-100">
<button type="submit" class="bg-gradient-to-r from-red-500 to-red-600 text-white px-8 py-3.5 rounded-xl font-semibold hover:shadow-xl transition inline-flex items-center gap-2 btn-hover" id="submit_btn">
<i data-lucide="send" class="w-5 h-5"></i> {% trans "Submit Complaint" %}
</button>
</div>
</form>
</div>
<script src="{% static 'vendor/sweetalert2/sweetalert2.all.min.js' %}"></script>
{% get_current_language as LANGUAGE_CODE %}
<script>
const CURRENT_LANG = '{{ LANGUAGE_CODE }}';
function localizedLabel(o) { if (!o) return ''; if (CURRENT_LANG === 'ar' && o.name_ar) return o.name_ar; return o.name_en || o.name || o.display_name || ''; }
document.addEventListener('DOMContentLoaded', function() {
if (typeof lucide !== 'undefined') lucide.createIcons();
var incidentDateInput = document.querySelector('input[name="incident_date"]');
if (incidentDateInput) {
incidentDateInput.max = new Date().toISOString().split('T')[0];
}
var categorySel = document.getElementById('id_category');
var deptSel = document.getElementById('id_department');
var sectionSel = document.getElementById('id_section');
var locationTypeSel = document.getElementById('id_location_type');
var hospitalSel = document.getElementById('id_hospital');
var areaSel = document.getElementById('id_area');
function loadAreas(hospitalId, locationType) {
var container = document.getElementById('area_container');
areaSel.innerHTML = '<option value="">{% trans "Select Area (optional)" %}</option>';
if (!hospitalId) { container.style.display = 'none'; return; }
areaSel.classList.add('select-loading');
var url = '/organizations/dropdowns/areas/?hospital=' + encodeURIComponent(hospitalId);
if (locationType) url += '&location_type=' + encodeURIComponent(locationType);
fetch(url)
.then(function(r) { return r.json(); })
.then(function(data) {
(data || []).forEach(function(a) {
var opt = document.createElement('option');
opt.value = a.id;
opt.textContent = localizedLabel(a);
areaSel.appendChild(opt);
});
container.style.display = (data && data.length) ? 'block' : 'none';
})
.catch(function(err) { console.error(err); })
.finally(function() { areaSel.classList.remove('select-loading'); });
}
locationTypeSel.addEventListener('change', function() {
loadAreas(hospitalSel.value, this.value);
});
hospitalSel.addEventListener('change', function() {
loadAreas(this.value, locationTypeSel.value);
if (categorySel.value) {
loadDepartments(categorySel.value);
} else {
deptSel.innerHTML = '<option value="">{% trans "Select Department" %}</option>';
sectionSel.innerHTML = '<option value="">{% trans "Select Section" %}</option>';
document.getElementById('department_container').style.display = 'none';
document.getElementById('section_container').style.display = 'none';
}
});
categorySel.addEventListener('change', function() {
loadDepartments(this.value);
});
deptSel.addEventListener('change', function() {
loadSections(this.value);
});
function loadDepartments(category) {
var container = document.getElementById('department_container');
deptSel.innerHTML = '<option value="">{% trans "Select Department" %}</option>';
sectionSel.innerHTML = '<option value="">{% trans "Select Section" %}</option>';
document.getElementById('section_container').style.display = 'none';
if (!category || !hospitalSel.value) { container.style.display = 'none'; return; }
var url = '/organizations/dropdowns/departments-by-category/?category=' + encodeURIComponent(category) + '&hospital=' + encodeURIComponent(hospitalSel.value);
deptSel.classList.add('select-loading');
fetch(url)
.then(function(r) { return r.json(); })
.then(function(data) {
(data || []).forEach(function(d) {
var opt = document.createElement('option');
opt.value = d.id;
opt.textContent = localizedLabel(d);
deptSel.appendChild(opt);
});
container.style.display = (data && data.length) ? 'grid' : 'none';
})
.catch(function(err) { console.error(err); })
.finally(function() { deptSel.classList.remove('select-loading'); });
}
function loadSections(deptId) {
var container = document.getElementById('section_container');
sectionSel.innerHTML = '<option value="">{% trans "Select Section" %}</option>';
if (!deptId) { container.style.display = 'none'; return; }
sectionSel.classList.add('select-loading');
fetch('/organizations/dropdowns/sections/' + deptId + '/')
.then(function(r) { return r.json(); })
.then(function(data) {
(data || []).forEach(function(s) {
var opt = document.createElement('option');
opt.value = s.id;
opt.textContent = localizedLabel(s);
sectionSel.appendChild(opt);
});
container.style.display = (data && data.length) ? 'block' : 'none';
})
.catch(function(err) { console.error(err); })
.finally(function() { sectionSel.classList.remove('select-loading'); });
}
document.getElementById('public_complaint_form').addEventListener('submit', function(e) {
e.preventDefault();
var btn = document.getElementById('submit_btn');
var originalHTML = btn.innerHTML;
btn.disabled = true;
btn.innerHTML = '<span class="inline-block w-5 h-5 border-2 border-white/30 border-t-white rounded-full animate-spin mr-2"></span>{% trans "Submitting..." %}';
fetch('{% url "complaints:public_complaint_submit" %}', {
method: 'POST',
body: new FormData(this),
headers: { 'X-CSRFToken': document.querySelector('[name="csrfmiddlewaretoken"]').value }
})
.then(function(r) { return r.json(); })
.then(function(data) {
if (data.success) {
Swal.fire({ icon: 'success', title: '{% trans "Submitted Successfully!" %}', text: '{% trans "Your reference number is: " %}' + data.reference_number, confirmButtonColor: '#005696' });
e.target.reset();
document.getElementById('department_container').style.display = 'none';
document.getElementById('section_container').style.display = 'none';
} else {
Swal.fire({ icon: 'error', title: '{% trans "Error" %}', text: data.message || data.errors?.join('\\n') || '{% trans "Failed to submit. Please try again." %}' });
}
})
.catch(function() {
Swal.fire({ icon: 'error', title: '{% trans "Error" %}', text: '{% trans "Failed to submit. Please try again." %}' });
})
.finally(function() { btn.disabled = false; btn.innerHTML = originalHTML; });
});
});
</script>
{% endblock %}