HH/templates/complaints/complaint_form.html

533 lines
24 KiB
HTML

{% extends base_layout %}
{% load i18n %}
{% load static %}
{% block title %}{{ _("New Complaint")}} - PX360{% endblock %}
{% block extra_css %}
<style>
.form-section {
background: #fff;
border: 1px solid #dee2e6;
border-radius: 8px;
padding: 25px;
margin-bottom: 20px;
}
.form-section-title {
font-size: 1.1rem;
font-weight: 600;
color: #495057;
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 2px solid #667eea;
}
.required-field::after {
content: " *";
color: #dc3545;
}
.complaint-type-card {
border: 2px solid #dee2e6;
border-radius: 8px;
padding: 20px;
cursor: pointer;
transition: all 0.3s ease;
text-align: center;
}
.complaint-type-card:hover {
border-color: #667eea;
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.15);
}
.complaint-type-card.active {
border-color: #667eea;
background-color: rgba(102, 126, 234, 0.05);
}
.complaint-type-icon {
font-size: 2.5rem;
margin-bottom: 10px;
}
</style>
{% endblock %}
{% block content %}
<div class="container-fluid">
<!-- Page Header -->
<div class="mb-4">
{% if source_user %}
<a href="{% url 'px_sources:source_user_complaint_list' %}" class="btn btn-outline-secondary btn-sm mb-3">
<i class="bi bi-arrow-left me-1"></i> {{ _("Back to My Complaints")}}
</a>
{% else %}
<a href="{% url 'complaints:complaint_list' %}" class="btn btn-outline-secondary btn-sm mb-3">
<i class="bi bi-arrow-left me-1"></i> {{ _("Back to Complaints")}}
</a>
{% endif %}
<h2 class="mb-1">
<i class="bi bi-plus-circle text-primary me-2"></i>
{{ _("Create New Complaint")}}
</h2>
<p class="text-muted mb-0">{{ _("File a new patient complaint with SLA tracking")}}</p>
</div>
<form method="post" action="{% url 'complaints:complaint_create' %}" id="complaintForm" novalidate>
{% csrf_token %}
<div class="row">
<div class="col-lg-8">
<!-- Complaint Type Selection -->
<div class="form-section">
<h5 class="form-section-title">
<i class="bi bi-tag me-2"></i>{{ _("Feedback Type")}}
</h5>
<div class="row">
<div class="col-md-6">
<div class="complaint-type-card {% if form.complaint_type.value == 'complaint' or not form.complaint_type.value %}active{% endif %}"
data-value="complaint" id="complaintTypeComplaint">
<i class="bi bi-exclamation-triangle text-danger complaint-type-icon"></i>
<h6>{{ _("Complaint")}}</h6>
<small class="text-muted">{{ _("Report an issue or concern")}}</small>
</div>
</div>
<div class="col-md-6">
<div class="complaint-type-card {% if form.complaint_type.value == 'appreciation' %}active{% endif %}"
data-value="appreciation" id="complaintTypeAppreciation">
<i class="bi bi-heart text-success complaint-type-icon"></i>
<h6>{{ _("Appreciation")}}</h6>
<small class="text-muted">{{ _("Share positive feedback")}}</small>
</div>
</div>
</div>
<input type="hidden" name="complaint_type" id="complaintTypeInput"
value="{% if form.complaint_type.value %}{{ form.complaint_type.value }}{% else %}complaint{% endif %}">
</div>
<!-- Patient Information -->
<div class="form-section">
<h5 class="form-section-title">
<i class="bi bi-person-fill me-2"></i>{{ _("Patient Information")}}
</h5>
<div class="row">
<div class="col-md-6 mb-3">
<label for="{{ form.relation_to_patient.id_for_label }}" class="form-label required-field">
{{ form.relation_to_patient.label }}
</label>
{{ form.relation_to_patient }}
{% if form.relation_to_patient.errors %}
<div class="invalid-feedback d-block">
{% for error in form.relation_to_patient.errors %}
<small class="text-danger">{{ error }}</small>
{% endfor %}
</div>
{% endif %}
</div>
<div class="col-md-6 mb-3">
<label for="{{ form.patient_name.id_for_label }}" class="form-label required-field">
{{ form.patient_name.label }}
</label>
{{ form.patient_name }}
{% if form.patient_name.errors %}
<div class="invalid-feedback d-block">
{% for error in form.patient_name.errors %}
<small class="text-danger">{{ error }}</small>
{% endfor %}
</div>
{% endif %}
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="{{ form.national_id.id_for_label }}" class="form-label required-field">
{{ form.national_id.label }}
</label>
{{ form.national_id }}
{% if form.national_id.errors %}
<div class="invalid-feedback d-block">
{% for error in form.national_id.errors %}
<small class="text-danger">{{ error }}</small>
{% endfor %}
</div>
{% endif %}
</div>
<div class="col-md-6 mb-3">
<label for="{{ form.incident_date.id_for_label }}" class="form-label required-field">
{{ form.incident_date.label }}
</label>
{{ form.incident_date }}
{% if form.incident_date.errors %}
<div class="invalid-feedback d-block">
{% for error in form.incident_date.errors %}
<small class="text-danger">{{ error }}</small>
{% endfor %}
</div>
{% endif %}
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="{{ form.encounter_id.id_for_label }}" class="form-label">
{{ form.encounter_id.label }}
</label>
{{ form.encounter_id }}
</div>
</div>
</div>
<!-- Organization Information -->
<div class="form-section">
<h5 class="form-section-title">
<i class="bi bi-building me-2"></i>{{ _("Organization & Location")}}
</h5>
<div class="row">
<div class="col-md-6 mb-3">
<label for="{{ form.complaint_source_type.id_for_label }}" class="form-label">
{{ form.complaint_source_type.label }}
</label>
{{ form.complaint_source_type }}
{% if form.complaint_source_type.errors %}
<div class="invalid-feedback d-block">
{% for error in form.complaint_source_type.errors %}
<small class="text-danger">{{ error }}</small>
{% endfor %}
</div>
{% endif %}
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="{{ form.hospital.id_for_label }}" class="form-label required-field">
{{ form.hospital.label }}
</label>
{{ form.hospital }}
{% if form.hospital.errors %}
<div class="invalid-feedback d-block">
{% for error in form.hospital.errors %}
<small class="text-danger">{{ error }}</small>
{% endfor %}
</div>
{% endif %}
</div>
<div class="col-md-6 mb-3">
<label for="{{ form.department.id_for_label }}" class="form-label">
{{ form.department.label }}
</label>
{{ form.department }}
{% if form.department.errors %}
<div class="invalid-feedback d-block">
{% for error in form.department.errors %}
<small class="text-danger">{{ error }}</small>
{% endfor %}
</div>
{% endif %}
</div>
</div>
<!-- Location Hierarchy -->
<div class="row">
<div class="col-md-4 mb-3">
<label for="{{ form.location.id_for_label }}" class="form-label required-field">
{{ form.location.label }}
</label>
{{ form.location }}
{% if form.location.errors %}
<div class="invalid-feedback d-block">
{% for error in form.location.errors %}
<small class="text-danger">{{ error }}</small>
{% endfor %}
</div>
{% endif %}
</div>
<div class="col-md-4 mb-3">
<label for="{{ form.main_section.id_for_label }}" class="form-label required-field">
{{ form.main_section.label }}
</label>
{{ form.main_section }}
{% if form.main_section.errors %}
<div class="invalid-feedback d-block">
{% for error in form.main_section.errors %}
<small class="text-danger">{{ error }}</small>
{% endfor %}
</div>
{% endif %}
</div>
<div class="col-md-4 mb-3">
<label for="{{ form.subsection.id_for_label }}" class="form-label required-field">
{{ form.subsection.label }}
</label>
{{ form.subsection }}
{% if form.subsection.errors %}
<div class="invalid-feedback d-block">
{% for error in form.subsection.errors %}
<small class="text-danger">{{ error }}</small>
{% endfor %}
</div>
{% endif %}
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="{{ form.staff.id_for_label }}" class="form-label">
{{ form.staff.label }}
</label>
{{ form.staff }}
{% if form.staff.errors %}
<div class="invalid-feedback d-block">
{% for error in form.staff.errors %}
<small class="text-danger">{{ error }}</small>
{% endfor %}
</div>
{% endif %}
</div>
<div class="col-md-6 mb-3">
<label for="{{ form.staff_name.id_for_label }}" class="form-label">
{{ form.staff_name.label }}
</label>
{{ form.staff_name }}
{% if form.staff_name.errors %}
<div class="invalid-feedback d-block">
{% for error in form.staff_name.errors %}
<small class="text-danger">{{ error }}</small>
{% endfor %}
</div>
{% endif %}
</div>
</div>
</div>
<!-- Complaint Details -->
<div class="form-section">
<h5 class="form-section-title">
<i class="bi bi-file-text me-2"></i>{{ _("Complaint Details")}}
</h5>
<div class="mb-3">
<label for="{{ form.description.id_for_label }}" class="form-label required-field">
{{ form.description.label }}
</label>
{{ form.description }}
{% if form.description.errors %}
<div class="invalid-feedback d-block">
{% for error in form.description.errors %}
<small class="text-danger">{{ error }}</small>
{% endfor %}
</div>
{% endif %}
</div>
<div class="mb-3">
<label for="{{ form.expected_result.id_for_label }}" class="form-label">
{{ form.expected_result.label }}
</label>
{{ form.expected_result }}
{% if form.expected_result.errors %}
<div class="invalid-feedback d-block">
{% for error in form.expected_result.errors %}
<small class="text-danger">{{ error }}</small>
{% endfor %}
</div>
{% endif %}
</div>
</div>
</div>
<!-- Sidebar -->
<div class="col-lg-4">
<!-- AI Information -->
<div class="alert alert-info">
<h6 class="alert-heading">
<i class="bi bi-robot me-2"></i>{{ _("AI Classification")}}
</h6>
<p class="mb-0 small">
{{ _("AI will automatically analyze and classify your feedback:")}}
</p>
<ul class="mb-0 mt-2 small">
<li><strong>{{ _("Title") }}:</strong> {{ _("AI-generated title")}}</li>
<li><strong>{{ _("Category") }}:</strong> {{ _("AI-determined category")}}</li>
<li><strong>{{ _("Severity") }}:</strong> {{ _("AI-calculated severity")}}</li>
<li><strong>{{ _("Priority") }}:</strong> {{ _("AI-calculated priority")}}</li>
</ul>
</div>
<!-- SLA Information -->
<div class="alert alert-info">
<h6 class="alert-heading">
<i class="bi bi-clock me-2"></i>{{ _("SLA Information")}}
</h6>
<p class="mb-0 small">
{{ _("SLA deadline will be automatically calculated based on severity")}}:
</p>
<ul class="mb-0 mt-2 small">
<li><strong>{{ _("Critical") }}:</strong> {{ _("4 hours")}}</li>
<li><strong>{{ _("High") }}:</strong> {{ _("24 hours")}}</li>
<li><strong>{{ _("Medium") }}:</strong> {{ _("72 hours")}}</li>
<li><strong>{{ _("Low") }}:</strong> {{ _("168 hours (7 days)")}}</li>
</ul>
</div>
<!-- Action Buttons -->
<div class="d-grid gap-2">
<button type="submit" class="btn btn-primary btn-lg">
<i class="bi bi-check-circle me-2"></i>{{ _("Create Complaint")}}
</button>
{% if source_user %}
<a href="{% url 'px_sources:source_user_complaint_list' %}" class="btn btn-outline-secondary">
<i class="bi bi-x-circle me-2"></i>{{ _("Cancel") }}
</a>
{% else %}
<a href="{% url 'complaints:complaint_list' %}" class="btn btn-outline-secondary">
<i class="bi bi-x-circle me-2"></i>{{ _("Cancel") }}
</a>
{% endif %}
</div>
</div>
</div>
</form>
</div>
{% endblock %}
{% block extra_js %}
<script>
document.addEventListener('DOMContentLoaded', function() {
const hospitalSelect = document.getElementById('hospitalSelect');
const departmentSelect = document.getElementById('departmentSelect');
const staffSelect = document.getElementById('staffSelect');
const locationSelect = document.getElementById('locationSelect');
const mainSectionSelect = document.getElementById('mainSectionSelect');
const subsectionSelect = document.getElementById('subsectionSelect');
const complaintTypeCards = document.querySelectorAll('.complaint-type-card');
const complaintTypeInput = document.getElementById('complaintTypeInput');
// Complaint type selection
complaintTypeCards.forEach(card => {
card.addEventListener('click', function() {
complaintTypeCards.forEach(c => c.classList.remove('active'));
this.classList.add('active');
complaintTypeInput.value = this.dataset.value;
});
});
// Hospital change handler - reload form with selected hospital
if (hospitalSelect) {
hospitalSelect.addEventListener('change', function() {
const hospitalId = this.value;
const form = document.getElementById('complaintForm');
const actionUrl = form.action;
// Create URL with hospital_id parameter
const url = new URL(actionUrl, window.location);
url.searchParams.set('hospital', hospitalId);
// Reload form with selected hospital
window.location.href = url.toString();
});
}
// Location change handler - load sections
if (locationSelect) {
locationSelect.addEventListener('change', function() {
const locationId = this.value;
// Clear section dropdowns
mainSectionSelect.innerHTML = '<option value="">{{ _("Select Section")}}</option>';
subsectionSelect.innerHTML = '<option value="">{{ _("Select Subsection")}}</option>';
if (locationId) {
// Load main sections via AJAX
fetch(`/organizations/ajax/main-sections/?location_id=${locationId}`)
.then(response => response.json())
.then(data => {
mainSectionSelect.innerHTML = '<option value="">{{ _("Select Section")}}</option>';
data.sections.forEach(section => {
const option = document.createElement('option');
option.value = section.id;
option.textContent = section.name;
mainSectionSelect.appendChild(option);
});
})
.catch(error => {
console.error('Error loading sections:', error);
});
}
});
}
// Main Section change handler - load subsections
if (mainSectionSelect) {
mainSectionSelect.addEventListener('change', function() {
const sectionId = this.value;
const locationId = locationSelect.value;
// Clear subsection dropdown
subsectionSelect.innerHTML = '<option value="">{{ _("Select Subsection")}}</option>';
if (sectionId && locationId) {
// Load subsections via AJAX
fetch(`/organizations/ajax/subsections/?location_id=${locationId}&main_section_id=${sectionId}`)
.then(response => response.json())
.then(data => {
subsectionSelect.innerHTML = '<option value="">{{ _("Select Subsection")}}</option>';
data.subsections.forEach(subsection => {
const option = document.createElement('option');
option.value = subsection.id;
option.textContent = subsection.name;
subsectionSelect.appendChild(option);
});
})
.catch(error => {
console.error('Error loading subsections:', error);
});
}
});
}
// Department change handler - load staff
if (departmentSelect) {
departmentSelect.addEventListener('change', function() {
const departmentId = this.value;
// Clear staff dropdown
staffSelect.innerHTML = '<option value="">{{ _("Select staff")}}</option>';
if (departmentId) {
// Load staff via minimal AJAX
fetch(`/complaints/ajax/physicians/?department_id=${departmentId}`)
.then(response => response.json())
.then(data => {
staffSelect.innerHTML = '<option value="">{{ _("Select staff")}}</option>';
data.staff.forEach(staff => {
const option = document.createElement('option');
option.value = staff.id;
option.textContent = `${staff.first_name} ${staff.last_name} (${staff.job_title || staff.staff_type})`;
staffSelect.appendChild(option);
});
})
.catch(error => {
console.error('Error loading staff:', error);
});
}
});
}
// Form validation
const form = document.getElementById('complaintForm');
form.addEventListener('submit', function(e) {
if (!form.checkValidity()) {
e.preventDefault();
e.stopPropagation();
}
form.classList.add('was-validated');
});
});
</script>
{% endblock %}