859 lines
34 KiB
HTML
859 lines
34 KiB
HTML
{% extends "layouts/base.html" %}
|
|
{% load i18n %}
|
|
|
|
{% block title %}{% trans "New Complaint" %} - PX360{% endblock %}
|
|
|
|
{% block extra_css %}
|
|
<style>
|
|
:root {
|
|
--hh-navy: #005696;
|
|
--hh-blue: #007bbd;
|
|
--hh-light: #eef6fb;
|
|
--hh-slate: #64748b;
|
|
--hh-success: #10b981;
|
|
--hh-warning: #f59e0b;
|
|
--hh-danger: #ef4444;
|
|
--hh-shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
|
|
--hh-shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
|
--hh-shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
|
}
|
|
|
|
/* Page Header */
|
|
.page-header {
|
|
background: linear-gradient(135deg, var(--hh-navy) 0%, #0069a8 50%, var(--hh-blue) 100%);
|
|
color: white;
|
|
padding: 2rem 2.5rem;
|
|
border-radius: 1rem;
|
|
margin-bottom: 2rem;
|
|
box-shadow: var(--hh-shadow-lg);
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.page-header::before {
|
|
content: '';
|
|
position: absolute;
|
|
top: 0;
|
|
right: 0;
|
|
width: 200px;
|
|
height: 200px;
|
|
background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 70%);
|
|
pointer-events: none;
|
|
}
|
|
|
|
.back-link {
|
|
color: rgba(255,255,255,0.85);
|
|
text-decoration: none;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
font-weight: 500;
|
|
margin-bottom: 1rem;
|
|
transition: color 0.2s ease;
|
|
}
|
|
|
|
.back-link:hover {
|
|
color: white;
|
|
}
|
|
|
|
/* Form Sections */
|
|
.form-section {
|
|
background: white;
|
|
border-radius: 1rem;
|
|
border: 1px solid #e2e8f0;
|
|
padding: 1.5rem;
|
|
margin-bottom: 1.5rem;
|
|
box-shadow: var(--hh-shadow-md);
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.form-section:hover {
|
|
box-shadow: var(--hh-shadow-lg);
|
|
transform: translateY(-2px);
|
|
}
|
|
|
|
.form-section-header {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.75rem;
|
|
margin-bottom: 1.5rem;
|
|
padding-bottom: 1rem;
|
|
border-bottom: 2px solid var(--hh-light);
|
|
}
|
|
|
|
.form-section-header h2 {
|
|
color: var(--hh-navy);
|
|
font-weight: 700;
|
|
font-size: 1.25rem;
|
|
margin: 0;
|
|
}
|
|
|
|
.section-icon {
|
|
width: 40px;
|
|
height: 40px;
|
|
border-radius: 0.75rem;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
background: linear-gradient(135deg, var(--hh-light), #e0f2fe);
|
|
}
|
|
|
|
/* Form Controls - Django Widget Styling */
|
|
.form-control, .form-select {
|
|
width: 100%;
|
|
padding: 0.75rem 1rem;
|
|
border: 2px solid #cbd5e1;
|
|
border-radius: 0.75rem;
|
|
font-size: 0.95rem;
|
|
transition: all 0.2s;
|
|
background: white;
|
|
color: #1e293b;
|
|
font-family: 'Inter', sans-serif;
|
|
}
|
|
|
|
.form-control:focus, .form-select:focus {
|
|
outline: none;
|
|
border-color: var(--hh-blue);
|
|
box-shadow: 0 0 0 4px rgba(0, 123, 189, 0.1);
|
|
transform: translateY(-1px);
|
|
}
|
|
|
|
.form-control.error, .form-select.error {
|
|
border-color: var(--hh-danger);
|
|
}
|
|
|
|
.form-control.error:focus, .form-select.error:focus {
|
|
box-shadow: 0 0 0 4px rgba(239, 68, 68, 0.1);
|
|
}
|
|
|
|
/* Textarea specific */
|
|
textarea.form-control {
|
|
resize: vertical;
|
|
min-height: 120px;
|
|
}
|
|
|
|
/* Date input specific */
|
|
input[type="date"].form-control {
|
|
min-height: auto;
|
|
}
|
|
|
|
.form-label {
|
|
display: block;
|
|
margin-bottom: 0.5rem;
|
|
font-weight: 600;
|
|
color: #1e293b;
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
.form-error {
|
|
color: var(--hh-danger);
|
|
font-size: 0.875rem;
|
|
margin-top: 0.5rem;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.25rem;
|
|
}
|
|
|
|
/* Complaint Type Cards */
|
|
.type-card {
|
|
border: 2px solid #e2e8f0;
|
|
border-radius: 1.5rem;
|
|
padding: 1.5rem;
|
|
text-align: center;
|
|
cursor: pointer;
|
|
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
background: white;
|
|
}
|
|
|
|
.type-card:hover {
|
|
transform: translateY(-4px);
|
|
box-shadow: 0 12px 25px -5px rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
.type-card.active {
|
|
border-color: var(--hh-blue);
|
|
background: linear-gradient(135deg, var(--hh-light) 0%, #e0f2fe 100%);
|
|
}
|
|
|
|
.type-card-icon {
|
|
width: 64px;
|
|
height: 64px;
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin: 0 auto 1rem;
|
|
transition: transform 0.3s ease;
|
|
}
|
|
|
|
.type-card:hover .type-card-icon {
|
|
transform: scale(1.1);
|
|
}
|
|
|
|
.type-card-icon.complaint {
|
|
background: linear-gradient(135deg, #fee2e2, #fecaca);
|
|
}
|
|
|
|
.type-card-icon.appreciation {
|
|
background: linear-gradient(135deg, #dcfce7, #bbf7d0);
|
|
}
|
|
|
|
/* Info Cards */
|
|
.info-card {
|
|
border-radius: 1rem;
|
|
padding: 1.5rem;
|
|
border: 2px solid;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.info-card:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow: var(--hh-shadow-lg);
|
|
}
|
|
|
|
.info-card.ai {
|
|
background: linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%);
|
|
border-color: #bfdbfe;
|
|
}
|
|
|
|
.info-card.sla {
|
|
background: linear-gradient(135deg, #fff7ed 0%, #fed7aa 100%);
|
|
border-color: #fdba74;
|
|
}
|
|
|
|
.info-card-header {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.75rem;
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.info-card-icon {
|
|
width: 40px;
|
|
height: 40px;
|
|
border-radius: 0.75rem;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.info-card.ai .info-card-icon {
|
|
background: #dbeafe;
|
|
}
|
|
|
|
.info-card.sla .info-card-icon {
|
|
background: #fed7aa;
|
|
}
|
|
|
|
.info-list {
|
|
list-style: none;
|
|
padding: 0;
|
|
margin: 0;
|
|
}
|
|
|
|
.info-list li {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
gap: 0.75rem;
|
|
margin-bottom: 0.75rem;
|
|
font-size: 0.875rem;
|
|
}
|
|
|
|
.info-list-icon {
|
|
width: 24px;
|
|
height: 24px;
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.info-card.ai .info-list-icon {
|
|
background: #dbeafe;
|
|
}
|
|
|
|
.info-card.sla .info-list-icon {
|
|
background: white;
|
|
}
|
|
|
|
/* Buttons */
|
|
.btn-submit {
|
|
background: linear-gradient(135deg, var(--hh-navy) 0%, var(--hh-blue) 100%);
|
|
color: white;
|
|
padding: 1rem 2rem;
|
|
border-radius: 1rem;
|
|
font-weight: 700;
|
|
font-size: 1rem;
|
|
border: none;
|
|
cursor: pointer;
|
|
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 0.5rem;
|
|
width: 100%;
|
|
box-shadow: 0 4px 12px rgba(0, 86, 150, 0.25);
|
|
}
|
|
|
|
.btn-submit:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 8px 20px rgba(0, 86, 150, 0.35);
|
|
}
|
|
|
|
.btn-submit:disabled {
|
|
background: #94a3b8;
|
|
cursor: not-allowed;
|
|
transform: none;
|
|
box-shadow: none;
|
|
}
|
|
|
|
.btn-cancel {
|
|
background: #f1f5f9;
|
|
color: #475569;
|
|
padding: 1rem 2rem;
|
|
border-radius: 1rem;
|
|
font-weight: 700;
|
|
font-size: 1rem;
|
|
border: 2px solid #e2e8f0;
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 0.5rem;
|
|
width: 100%;
|
|
text-decoration: none;
|
|
}
|
|
|
|
.btn-cancel:hover {
|
|
background: #e2e8f0;
|
|
border-color: #cbd5e1;
|
|
transform: translateY(-1px);
|
|
}
|
|
|
|
/* Required mark */
|
|
.required-mark {
|
|
color: var(--hh-danger);
|
|
}
|
|
|
|
/* Animations */
|
|
@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="px-4 py-6">
|
|
<!-- Page Header -->
|
|
<div class="page-header animate-in">
|
|
<div>
|
|
{% if source_user %}
|
|
<a href="{% url 'px_sources:source_user_complaint_list' %}" class="back-link">
|
|
<i data-lucide="arrow-left" class="w-4 h-4"></i>
|
|
{% trans "Back to My Complaints" %}
|
|
</a>
|
|
{% else %}
|
|
<a href="{% url 'complaints:complaint_list' %}" class="back-link">
|
|
<i data-lucide="arrow-left" class="w-4 h-4"></i>
|
|
{% trans "Back to Complaints" %}
|
|
</a>
|
|
{% endif %}
|
|
<h1 class="text-2xl font-bold mb-2">
|
|
<i data-lucide="plus-circle" class="w-7 h-7 inline-block me-2"></i>
|
|
{% trans "Create New Complaint" %}
|
|
</h1>
|
|
<p class="text-white/90">{% trans "File a new patient complaint with SLA tracking" %}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<form method="post" action="{% url 'complaints:complaint_create' %}" id="complaintForm" novalidate>
|
|
{% csrf_token %}
|
|
|
|
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
|
<!-- Main Form Content -->
|
|
<div class="lg:col-span-2 space-y-6">
|
|
<!-- Complaint Type Selection -->
|
|
<div class="form-section animate-in">
|
|
<div class="form-section-header">
|
|
<div class="section-icon">
|
|
<i data-lucide="tag" class="w-5 h-5 text-blue-600"></i>
|
|
</div>
|
|
<h2>{% trans "Feedback Type" %}</h2>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
<div class="type-card {% if form.complaint_type.value == 'complaint' or not form.complaint_type.value %}active{% endif %}"
|
|
data-value="complaint" id="complaintTypeComplaint">
|
|
<div class="type-card-icon complaint">
|
|
<i data-lucide="alert-triangle" class="w-8 h-8 text-red-600"></i>
|
|
</div>
|
|
<h3 class="font-bold text-navy text-lg mb-2">{% trans "Complaint" %}</h3>
|
|
<p class="text-sm text-slate">{% trans "Report an issue or concern" %}</p>
|
|
</div>
|
|
<div class="type-card {% if form.complaint_type.value == 'appreciation' %}active{% endif %}"
|
|
data-value="appreciation" id="complaintTypeAppreciation">
|
|
<div class="type-card-icon appreciation">
|
|
<i data-lucide="heart" class="w-8 h-8 text-green-600"></i>
|
|
</div>
|
|
<h3 class="font-bold text-navy text-lg mb-2">{% trans "Appreciation" %}</h3>
|
|
<p class="text-sm text-slate">{% trans "Share positive feedback" %}</p>
|
|
</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 animate-in">
|
|
<div class="form-section-header">
|
|
<div class="section-icon">
|
|
<i data-lucide="user" class="w-5 h-5 text-blue-600"></i>
|
|
</div>
|
|
<h2>{% trans "Patient Information" %}</h2>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-5">
|
|
<div>
|
|
<label for="{{ form.relation_to_patient.id_for_label }}" class="form-label">
|
|
{{ form.relation_to_patient.label }} <span class="required-mark">*</span>
|
|
</label>
|
|
{{ form.relation_to_patient }}
|
|
{% if form.relation_to_patient.errors %}
|
|
<p class="form-error">
|
|
<i data-lucide="alert-circle" class="w-4 h-4"></i>
|
|
{% for error in form.relation_to_patient.errors %}{{ error }}{% endfor %}
|
|
</p>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div>
|
|
<label for="{{ form.patient_name.id_for_label }}" class="form-label">
|
|
{{ form.patient_name.label }} <span class="required-mark">*</span>
|
|
</label>
|
|
{{ form.patient_name }}
|
|
{% if form.patient_name.errors %}
|
|
<p class="form-error">
|
|
<i data-lucide="alert-circle" class="w-4 h-4"></i>
|
|
{% for error in form.patient_name.errors %}{{ error }}{% endfor %}
|
|
</p>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div>
|
|
<label for="{{ form.national_id.id_for_label }}" class="form-label">
|
|
{{ form.national_id.label }} <span class="required-mark">*</span>
|
|
</label>
|
|
{{ form.national_id }}
|
|
{% if form.national_id.errors %}
|
|
<p class="form-error">
|
|
<i data-lucide="alert-circle" class="w-4 h-4"></i>
|
|
{% for error in form.national_id.errors %}{{ error }}{% endfor %}
|
|
</p>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div>
|
|
<label for="{{ form.incident_date.id_for_label }}" class="form-label">
|
|
{{ form.incident_date.label }} <span class="required-mark">*</span>
|
|
</label>
|
|
{{ form.incident_date }}
|
|
{% if form.incident_date.errors %}
|
|
<p class="form-error">
|
|
<i data-lucide="alert-circle" class="w-4 h-4"></i>
|
|
{% for error in form.incident_date.errors %}{{ error }}{% endfor %}
|
|
</p>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div>
|
|
<label for="{{ form.encounter_id.id_for_label }}" class="form-label">
|
|
{{ form.encounter_id.label }}
|
|
</label>
|
|
{{ form.encounter_id }}
|
|
{% if form.encounter_id.errors %}
|
|
<p class="form-error">
|
|
<i data-lucide="alert-circle" class="w-4 h-4"></i>
|
|
{% for error in form.encounter_id.errors %}{{ error }}{% endfor %}
|
|
</p>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Organization Information -->
|
|
<div class="form-section animate-in">
|
|
<div class="form-section-header">
|
|
<div class="section-icon">
|
|
<i data-lucide="building" class="w-5 h-5 text-blue-600"></i>
|
|
</div>
|
|
<h2>{% trans "Organization & Location" %}</h2>
|
|
</div>
|
|
|
|
<div class="space-y-5">
|
|
<div>
|
|
<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 %}
|
|
<p class="form-error">
|
|
<i data-lucide="alert-circle" class="w-4 h-4"></i>
|
|
{% for error in form.complaint_source_type.errors %}{{ error }}{% endfor %}
|
|
</p>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-5">
|
|
<div>
|
|
<label for="{{ form.hospital.id_for_label }}" class="form-label">
|
|
{{ form.hospital.label }} <span class="required-mark">*</span>
|
|
</label>
|
|
{{ form.hospital }}
|
|
{% if form.hospital.errors %}
|
|
<p class="form-error">
|
|
<i data-lucide="alert-circle" class="w-4 h-4"></i>
|
|
{% for error in form.hospital.errors %}{{ error }}{% endfor %}
|
|
</p>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div>
|
|
<label for="{{ form.department.id_for_label }}" class="form-label">
|
|
{{ form.department.label }}
|
|
</label>
|
|
{{ form.department }}
|
|
{% if form.department.errors %}
|
|
<p class="form-error">
|
|
<i data-lucide="alert-circle" class="w-4 h-4"></i>
|
|
{% for error in form.department.errors %}{{ error }}{% endfor %}
|
|
</p>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Location Hierarchy -->
|
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-5">
|
|
<div>
|
|
<label for="{{ form.location.id_for_label }}" class="form-label">
|
|
{{ form.location.label }} <span class="required-mark">*</span>
|
|
</label>
|
|
{{ form.location }}
|
|
{% if form.location.errors %}
|
|
<p class="form-error">
|
|
<i data-lucide="alert-circle" class="w-4 h-4"></i>
|
|
{% for error in form.location.errors %}{{ error }}{% endfor %}
|
|
</p>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div>
|
|
<label for="{{ form.main_section.id_for_label }}" class="form-label">
|
|
{{ form.main_section.label }} <span class="required-mark">*</span>
|
|
</label>
|
|
{{ form.main_section }}
|
|
{% if form.main_section.errors %}
|
|
<p class="form-error">
|
|
<i data-lucide="alert-circle" class="w-4 h-4"></i>
|
|
{% for error in form.main_section.errors %}{{ error }}{% endfor %}
|
|
</p>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div>
|
|
<label for="{{ form.subsection.id_for_label }}" class="form-label">
|
|
{{ form.subsection.label }} <span class="required-mark">*</span>
|
|
</label>
|
|
{{ form.subsection }}
|
|
{% if form.subsection.errors %}
|
|
<p class="form-error">
|
|
<i data-lucide="alert-circle" class="w-4 h-4"></i>
|
|
{% for error in form.subsection.errors %}{{ error }}{% endfor %}
|
|
</p>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-5">
|
|
<div>
|
|
<label for="{{ form.staff.id_for_label }}" class="form-label">
|
|
{{ form.staff.label }}
|
|
</label>
|
|
{{ form.staff }}
|
|
{% if form.staff.errors %}
|
|
<p class="form-error">
|
|
<i data-lucide="alert-circle" class="w-4 h-4"></i>
|
|
{% for error in form.staff.errors %}{{ error }}{% endfor %}
|
|
</p>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div>
|
|
<label for="{{ form.staff_name.id_for_label }}" class="form-label">
|
|
{{ form.staff_name.label }}
|
|
</label>
|
|
{{ form.staff_name }}
|
|
{% if form.staff_name.errors %}
|
|
<p class="form-error">
|
|
<i data-lucide="alert-circle" class="w-4 h-4"></i>
|
|
{% for error in form.staff_name.errors %}{{ error }}{% endfor %}
|
|
</p>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Complaint Details -->
|
|
<div class="form-section animate-in">
|
|
<div class="form-section-header">
|
|
<div class="section-icon">
|
|
<i data-lucide="file-text" class="w-5 h-5 text-blue-600"></i>
|
|
</div>
|
|
<h2>{% trans "Complaint Details" %}</h2>
|
|
</div>
|
|
|
|
<div class="space-y-5">
|
|
<div>
|
|
<label for="{{ form.description.id_for_label }}" class="form-label">
|
|
{{ form.description.label }} <span class="required-mark">*</span>
|
|
</label>
|
|
{{ form.description }}
|
|
{% if form.description.errors %}
|
|
<p class="form-error">
|
|
<i data-lucide="alert-circle" class="w-4 h-4"></i>
|
|
{% for error in form.description.errors %}{{ error }}{% endfor %}
|
|
</p>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div>
|
|
<label for="{{ form.expected_result.id_for_label }}" class="form-label">
|
|
{{ form.expected_result.label }}
|
|
</label>
|
|
{{ form.expected_result }}
|
|
{% if form.expected_result.errors %}
|
|
<p class="form-error">
|
|
<i data-lucide="alert-circle" class="w-4 h-4"></i>
|
|
{% for error in form.expected_result.errors %}{{ error }}{% endfor %}
|
|
</p>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Sidebar -->
|
|
<div class="lg:col-span-1 space-y-6">
|
|
<!-- AI Information -->
|
|
<div class="info-card ai animate-in">
|
|
<div class="info-card-header">
|
|
<div class="info-card-icon">
|
|
<i data-lucide="bot" class="w-5 h-5 text-blue-600"></i>
|
|
</div>
|
|
<h3 class="font-bold text-navy m-0">{% trans "AI Classification" %}</h3>
|
|
</div>
|
|
<p class="text-sm text-slate mb-4">
|
|
{% trans "AI will automatically analyze and classify your feedback:" %}
|
|
</p>
|
|
<ul class="info-list">
|
|
<li>
|
|
<div class="info-list-icon">
|
|
<i data-lucide="check" class="w-3 h-3 text-blue-600"></i>
|
|
</div>
|
|
<div><strong class="text-navy">{% trans "Title" %}:</strong> <span class="text-slate">{% trans "AI-generated title" %}</span></div>
|
|
</li>
|
|
<li>
|
|
<div class="info-list-icon">
|
|
<i data-lucide="check" class="w-3 h-3 text-blue-600"></i>
|
|
</div>
|
|
<div><strong class="text-navy">{% trans "Category" %}:</strong> <span class="text-slate">{% trans "AI-determined category" %}</span></div>
|
|
</li>
|
|
<li>
|
|
<div class="info-list-icon">
|
|
<i data-lucide="check" class="w-3 h-3 text-blue-600"></i>
|
|
</div>
|
|
<div><strong class="text-navy">{% trans "Severity" %}:</strong> <span class="text-slate">{% trans "AI-calculated severity" %}</span></div>
|
|
</li>
|
|
<li>
|
|
<div class="info-list-icon">
|
|
<i data-lucide="check" class="w-3 h-3 text-blue-600"></i>
|
|
</div>
|
|
<div><strong class="text-navy">{% trans "Priority" %}:</strong> <span class="text-slate">{% trans "AI-calculated priority" %}</span></div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<!-- SLA Information -->
|
|
<div class="info-card sla animate-in">
|
|
<div class="info-card-header">
|
|
<div class="info-card-icon">
|
|
<i data-lucide="clock" class="w-5 h-5 text-orange-600"></i>
|
|
</div>
|
|
<h3 class="font-bold text-navy m-0">{% trans "SLA Information" %}</h3>
|
|
</div>
|
|
<p class="text-sm text-slate mb-4">
|
|
{% trans "SLA deadline will be automatically calculated based on severity:" %}
|
|
</p>
|
|
<ul class="info-list">
|
|
<li>
|
|
<span class="inline-flex items-center justify-center w-6 h-6 bg-red-100 text-red-600 rounded-full text-xs font-bold flex-shrink-0">C</span>
|
|
<div><strong class="text-navy">{% trans "Critical" %}:</strong> <span class="text-slate">{% trans "4 hours" %}</span></div>
|
|
</li>
|
|
<li>
|
|
<span class="inline-flex items-center justify-center w-6 h-6 bg-orange-100 text-orange-600 rounded-full text-xs font-bold flex-shrink-0">H</span>
|
|
<div><strong class="text-navy">{% trans "High" %}:</strong> <span class="text-slate">{% trans "24 hours" %}</span></div>
|
|
</li>
|
|
<li>
|
|
<span class="inline-flex items-center justify-center w-6 h-6 bg-yellow-100 text-yellow-600 rounded-full text-xs font-bold flex-shrink-0">M</span>
|
|
<div><strong class="text-navy">{% trans "Medium" %}:</strong> <span class="text-slate">{% trans "72 hours" %}</span></div>
|
|
</li>
|
|
<li>
|
|
<span class="inline-flex items-center justify-center w-6 h-6 bg-green-100 text-green-600 rounded-full text-xs font-bold flex-shrink-0">L</span>
|
|
<div><strong class="text-navy">{% trans "Low" %}:</strong> <span class="text-slate">{% trans "168 hours (7 days)" %}</span></div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<!-- Action Buttons -->
|
|
<div class="space-y-3 animate-in">
|
|
<button type="submit" class="btn-submit">
|
|
<i data-lucide="check-circle" class="w-5 h-5"></i>
|
|
{% trans "Create Complaint" %}
|
|
</button>
|
|
{% if source_user %}
|
|
<a href="{% url 'px_sources:source_user_complaint_list' %}" class="btn-cancel">
|
|
<i data-lucide="x-circle" class="w-5 h-5"></i>
|
|
{% trans "Cancel" %}
|
|
</a>
|
|
{% else %}
|
|
<a href="{% url 'complaints:complaint_list' %}" class="btn-cancel">
|
|
<i data-lucide="x-circle" class="w-5 h-5"></i>
|
|
{% trans "Cancel" %}
|
|
</a>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
lucide.createIcons();
|
|
|
|
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('.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
|
|
if (hospitalSelect) {
|
|
hospitalSelect.addEventListener('change', function() {
|
|
const hospitalId = this.value;
|
|
const form = document.getElementById('complaintForm');
|
|
const actionUrl = form.action;
|
|
const url = new URL(actionUrl, window.location);
|
|
url.searchParams.set('hospital', hospitalId);
|
|
window.location.href = url.toString();
|
|
});
|
|
}
|
|
|
|
// Location change handler
|
|
if (locationSelect) {
|
|
locationSelect.addEventListener('change', function() {
|
|
const locationId = this.value;
|
|
mainSectionSelect.innerHTML = '<option value="">{% trans "Select Section" %}</option>';
|
|
subsectionSelect.innerHTML = '<option value="">{% trans "Select Subsection" %}</option>';
|
|
if (locationId) {
|
|
fetch(`/organizations/ajax/main-sections/?location_id=${locationId}`)
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
mainSectionSelect.innerHTML = '<option value="">{% trans "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
|
|
if (mainSectionSelect) {
|
|
mainSectionSelect.addEventListener('change', function() {
|
|
const sectionId = this.value;
|
|
const locationId = locationSelect.value;
|
|
subsectionSelect.innerHTML = '<option value="">{% trans "Select Subsection" %}</option>';
|
|
if (sectionId && locationId) {
|
|
fetch(`/organizations/ajax/subsections/?location_id=${locationId}&main_section_id=${sectionId}`)
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
subsectionSelect.innerHTML = '<option value="">{% trans "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
|
|
if (departmentSelect) {
|
|
departmentSelect.addEventListener('change', function() {
|
|
const departmentId = this.value;
|
|
staffSelect.innerHTML = '<option value="">{% trans "Select staff" %}</option>';
|
|
if (departmentId) {
|
|
fetch(`/complaints/ajax/physicians/?department_id=${departmentId}`)
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
staffSelect.innerHTML = '<option value="">{% trans "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));
|
|
}
|
|
});
|
|
}
|
|
});
|
|
</script>
|
|
{% endblock %}
|