HH/templates/surveys/instance_detail.html
2026-01-24 15:27:30 +03:00

471 lines
24 KiB
HTML

{% extends "layouts/base.html" %}
{% load i18n %}
{% load static %}
{% load survey_filters %}
{% block title %}{{ _("Survey") }} #{{ survey.id|slice:":8" }} - PX360{% endblock %}
{% block extra_css %}
<style>
.response-card {
transition: all 0.2s ease;
}
.response-card:hover {
box-shadow: var(--hh-shadow);
}
.rating-stars {
color: #ffd700;
}
.choice-option-bar {
transition: width 0.3s ease;
}
</style>
{% endblock %}
{% block content %}
<div class="container-fluid">
<!-- Back Button -->
<div class="mb-3">
<a href="{% url 'surveys:instance_list' %}" class="btn btn-outline-secondary btn-sm">
<i class="bi bi-arrow-left me-1"></i> {{ _("Back to Surveys")}}
</a>
</div>
<!-- Page Header -->
<div class="mb-4">
<h2 class="mb-1">
<i class="bi bi-clipboard-data text-info me-2"></i>
{{ survey.survey_template.name }}
</h2>
<p class="text-muted mb-0">
{{ _("Survey") }} #{{ survey.id|slice:":8" }} •
<span class="badge badge-soft-primary">{{ survey.survey_template.get_survey_type_display }}</span>
</p>
</div>
<!-- Score Comparison Banner (if completed) -->
{% if survey.status == 'completed' and survey.total_score %}
<div class="card mb-4 border-0 bg-gradient-teal">
<div class="card-body text-white">
<div class="row align-items-center">
<div class="col-md-6 text-center">
<div class="mb-2">{{ _("Patient Score") }}</div>
<h1 class="display-4 mb-0">{{ survey.total_score|floatformat:1 }}</h1>
<div class="fs-4 opacity-75">/ 5.0</div>
</div>
<div class="col-md-6 text-center border-start border-light border-opacity-25">
<div class="mb-2">{{ _("Template Average") }}</div>
<h1 class="display-4 mb-0">{{ template_average|floatformat:1 }}</h1>
<div class="fs-4 opacity-75">/ 5.0</div>
</div>
</div>
<div class="text-center mt-3">
{% if survey.total_score >= template_average %}
<span class="badge bg-success fs-6">
<i class="bi bi-arrow-up me-1"></i>
{% trans "Above average" %}
</span>
{% else %}
<span class="badge bg-warning fs-6">
<i class="bi bi-arrow-down me-1"></i>
{% trans "Below average" %}
</span>
{% endif %}
{% if survey.is_negative %}
<span class="badge bg-danger fs-6 ms-2">
<i class="bi bi-exclamation-triangle me-1"></i>
{% trans "Negative feedback" %}
</span>
{% endif %}
</div>
</div>
</div>
{% endif %}
<div class="row">
<!-- Main Content: Survey Responses -->
<div class="col-lg-8">
<div class="card">
<div class="card-header">
<h6 class="card-title mb-0">
<i class="bi bi-question-circle text-info me-2"></i>
{% trans "Survey Responses" %}
</h6>
</div>
<div class="card-body">
{% for response in responses %}
<div class="response-card card mb-3 border">
<div class="card-body">
<div class="d-flex justify-content-between align-items-start mb-3">
<div class="flex-grow-1">
<span class="badge badge-soft-primary me-2">Q{{ forloop.counter }}</span>
<strong>{{ response.question.text }}</strong>
<div class="text-muted small mt-1">
{% trans "Question type" %}: {{ response.question.get_question_type_display }}
</div>
</div>
{% if response.numeric_value %}
<div class="text-end">
<div class="display-6 fw-bold {% if response.numeric_value >= 4 %}text-success{% elif response.numeric_value >= 3 %}text-warning{% else %}text-danger{% endif %}">
{{ response.numeric_value }}
</div>
<div class="text-muted small">{% trans "out of" %} 5</div>
</div>
{% endif %}
</div>
<!-- Rating Visualization -->
{% if response.question.question_type == 'rating' %}
<div class="mb-3">
<div class="d-flex align-items-center mb-2">
<span class="me-3">{% trans "Your rating" %}:</span>
{% for i in "12345" %}
{% if forloop.counter <= response.numeric_value|floatformat:0 %}
<i class="bi bi-star-fill rating-stars fs-4"></i>
{% else %}
<i class="bi bi-star rating-stars text-muted fs-4"></i>
{% endif %}
{% endfor %}
</div>
{% if response.question.id in question_stats %}
{% with question_stat=question_stats|get_item:response.question.id %}
<div class="bg-light rounded p-2">
<div class="d-flex justify-content-between">
<span class="text-muted">{% trans "Average" %}: <strong>{{ question_stat.average }}</strong></span>
<span class="text-muted">{{ question_stat.total_responses }} {% trans "responses" %}</span>
</div>
<div class="progress mt-2" style="height: 8px;">
<div class="progress-bar {% if response.numeric_value >= question_stat.average %}bg-success{% else %}bg-warning{% endif %}"
style="width: {{ response.numeric_value|mul:20 }}%"
title="{% trans "Your rating" %}">
</div>
<div class="progress-bar bg-secondary"
style="width: {{ question_stat.average|mul:20 }}%"
title="{% trans "Average" %}">
</div>
</div>
</div>
{% endwith %}
{% endif %}
</div>
{% endif %}
<!-- Choice Visualization -->
{% if response.question.question_type in 'multiple_choice,single_choice' %}
<div class="mb-3">
<div class="alert alert-light mb-2">
<strong>{% trans "Your response" %}:</strong> {{ response.choice_value }}
</div>
{% if response.question.id in question_stats and question_stats|get_item:response.question.id.type == 'choice' %}
<div class="mt-3">
<strong class="d-block mb-2">{% trans "Response Distribution" %}:</strong>
{% for option in question_stats|get_item:response.question.id.options %}
<div class="mb-2">
<div class="d-flex justify-content-between mb-1">
<small>{{ option.value }}</small>
<small>{{ option.count }} ({{ option.percentage }}%)</small>
</div>
<div class="progress" style="height: 6px;">
<div class="progress-bar choice-option-bar {% if option.value == response.choice_value %}bg-primary{% else %}bg-light{% endif %}"
style="width: {{ option.percentage }}%">
</div>
</div>
</div>
{% endfor %}
</div>
{% endif %}
</div>
{% endif %}
<!-- Text Response -->
{% if response.text_value %}
<div class="bg-light rounded p-3 mb-0">
<div class="d-flex justify-content-between mb-2">
<strong>{% trans "Comment" %}</strong>
<small class="text-muted">{{ response.text_value|length }} {% trans "characters" %}</small>
</div>
<p class="mb-0">{{ response.text_value|linebreaks }}</p>
</div>
{% endif %}
</div>
</div>
{% empty %}
<div class="text-center py-5">
<i class="bi bi-clipboard" style="font-size: 3rem; color: #ccc;"></i>
<p class="text-muted mt-3">{{ _("No responses yet")}}</p>
</div>
{% endfor %}
</div>
</div>
<!-- Related Surveys -->
{% if related_surveys %}
<div class="card mt-4">
<div class="card-header">
<h6 class="card-title mb-0">
<i class="bi bi-collection text-primary me-2"></i>
{% trans "Related Surveys from Patient" %}
</h6>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-sm">
<thead>
<tr>
<th>{% trans "Survey" %}</th>
<th>{% trans "Type" %}</th>
<th>{% trans "Score" %}</th>
<th>{% trans "Date" %}</th>
<th>{% trans "Actions" %}</th>
</tr>
</thead>
<tbody>
{% for related in related_surveys %}
<tr>
<td>{{ related.survey_template.name }}</td>
<td><span class="badge badge-soft-primary">{{ related.survey_template.get_survey_type_display }}</span></td>
<td>
<span class="{% if related.total_score < 3 %}text-danger{% elif related.total_score < 4 %}text-warning{% else %}text-success{% endif %} fw-bold">
{{ related.total_score|floatformat:1 }}
</span>
</td>
<td>{{ related.completed_at|date:"M d, Y" }}</td>
<td>
<a href="{% url 'surveys:instance_detail' related.id %}" class="btn btn-sm btn-outline-primary">
<i class="bi bi-eye"></i>
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endif %}
</div>
<!-- Sidebar: Survey Info & Actions -->
<div class="col-lg-4">
<!-- Survey Information -->
<div class="card mb-3">
<div class="card-header">
<h6 class="card-title mb-0">
<i class="bi bi-info-circle text-info me-2"></i>
{% trans "Survey Information" %}
</h6>
</div>
<div class="card-body">
<div class="mb-3">
<strong>{% trans "Status" %}:</strong><br>
{% if survey.status == 'completed' %}
<span class="badge bg-success">{{ survey.get_status_display }}</span>
{% elif survey.status == 'sent' %}
<span class="badge bg-warning">{{ survey.get_status_display }}</span>
{% elif survey.status == 'active' %}
<span class="badge bg-info">{{ survey.get_status_display }}</span>
{% elif survey.status == 'cancelled' %}
<span class="badge bg-danger">{{ survey.get_status_display }}</span>
{% else %}
<span class="badge bg-secondary">{{ survey.get_status_display }}</span>
{% endif %}
</div>
{% if survey.total_score %}
<div class="mb-3">
<strong>{% trans "Total Score" %}:</strong><br>
<h3 class="mb-0 {% if survey.is_negative %}text-danger{% else %}text-success{% endif %}">
{{ survey.total_score|floatformat:1 }}/5.0
</h3>
{% if survey.is_negative %}
<span class="badge bg-danger mt-2">{% trans "Negative Feedback" %}</span>
{% endif %}
</div>
{% endif %}
{% if survey.sent_at %}
<div class="mb-3">
<strong>{% trans "Sent" %}:</strong><br>
<small>{{ survey.sent_at|date:"M d, Y H:i" }}</small>
</div>
{% endif %}
{% if survey.completed_at %}
<div class="mb-3">
<strong>{% trans "Completed" %}:</strong><br>
<small>{{ survey.completed_at|date:"M d, Y H:i" }}</small>
</div>
{% endif %}
<div class="mb-3">
<strong>{% trans "Survey Type" %}:</strong><br>
<span class="badge badge-soft-primary">{{ survey.survey_template.get_survey_type_display }}</span>
</div>
{% if survey.survey_template.hospital %}
<div class="mb-0">
<strong>{% trans "Hospital" %}:</strong><br>
<small>{{ survey.survey_template.hospital.name }}</small>
</div>
{% endif %}
</div>
</div>
<!-- Patient Information -->
<div class="card mb-3">
<div class="card-header">
<h6 class="card-title mb-0">
<i class="bi bi-person text-primary me-2"></i>
{% trans "Patient Information" %}
</h6>
</div>
<div class="card-body">
<div class="mb-2">
<strong>{% trans "Name" %}:</strong><br>
{{ survey.patient.get_full_name }}
</div>
<div class="mb-2">
<strong>{% trans "Phone" %}:</strong><br>
{{ survey.patient.phone }}
</div>
<div class="mb-2">
<strong>{% trans "MRN" %}:</strong><br>
{{ survey.patient.mrn }}
</div>
{% if survey.patient.email %}
<div class="mb-0">
<strong>{% trans "Email" %}:</strong><br>
<small>{{ survey.patient.email }}</small>
</div>
{% endif %}
</div>
</div>
<!-- Journey Information (if applicable) -->
{% if survey.journey_instance %}
<div class="card mb-3">
<div class="card-header">
<h6 class="card-title mb-0">
<i class="bi bi-diagram-3 text-success me-2"></i>
{% trans "Journey Information" %}
</h6>
</div>
<div class="card-body">
<div class="mb-2">
<strong>{% trans "Journey" %}:</strong><br>
<small>{{ survey.journey_instance.journey_template.name }}</small>
</div>
{% if survey.journey_stage_instance %}
<div class="mb-2">
<strong>{% trans "Stage" %}:</strong><br>
<small>{{ survey.journey_stage_instance.stage_template.name }}</small>
</div>
{% endif %}
<div class="mb-0">
<a href="{% url 'journeys:instance_detail' survey.journey_instance.id %}" class="btn btn-sm btn-outline-success">
<i class="bi bi-diagram-3 me-1"></i>
{% trans "View Journey" %}
</a>
</div>
</div>
</div>
{% endif %}
<!-- Follow-up Actions (for negative surveys) -->
{% if survey.is_negative %}
<div class="card border-warning mb-3">
<div class="card-header bg-warning text-dark">
<h6 class="card-title mb-0">
<i class="bi bi-exclamation-triangle me-2"></i>
{% trans "Follow-up Actions" %}
</h6>
</div>
<div class="card-body">
{% if not survey.patient_contacted %}
<div class="alert alert-warning mb-3">
<i class="bi bi-info-circle me-2"></i>
<strong>{% trans "Action Required" %}:</strong> {% trans "Contact patient to discuss negative feedback" %}.
</div>
<form method="post" action="{% url 'surveys:log_patient_contact' survey.id %}">
{% csrf_token %}
<div class="mb-3">
<label for="contact_notes" class="form-label">{% trans "Contact Notes *" %}</label>
<textarea class="form-control" id="contact_notes" name="contact_notes" rows="4" required
placeholder="{% trans 'Document your conversation with patient...' %}"></textarea>
</div>
<div class="form-check mb-3">
<input class="form-check-input" type="checkbox" id="issue_resolved" name="issue_resolved">
<label class="form-check-label" for="issue_resolved">
{% trans "Issue resolved or explained to patient" %}
</label>
</div>
<button type="submit" class="btn btn-warning w-100">
<i class="bi bi-telephone me-2"></i>{% trans "Log Patient Contact" %}
</button>
</form>
{% else %}
<div class="alert alert-success mb-3">
<i class="bi bi-check-circle me-2"></i>
<strong>{% trans "Patient Contacted" %}</strong><br>
<small>{% trans "By" %} {{ survey.patient_contacted_by.get_full_name }} {% trans "on" %} {{ survey.patient_contacted_at|date:"M d, Y H:i" }}</small>
</div>
<div class="mb-3">
<strong>{% trans "Contact Notes" %}:</strong>
<p class="mb-0 mt-2">{{ survey.contact_notes }}</p>
</div>
<div class="mb-3">
<strong>{% trans "Status" %}:</strong><br>
{% if survey.issue_resolved %}
<span class="badge bg-success">{% trans "Issue Resolved" %}</span>
{% else %}
<span class="badge bg-warning">{% trans "Issue Discussed" %}</span>
{% endif %}
</div>
{% if not survey.satisfaction_feedback_sent %}
<hr>
<h6 class="mb-3">{% trans "Send Satisfaction Feedback" %}</h6>
<p class="text-muted small mb-3">
{% trans "Send a feedback form to patient to assess their satisfaction with how their concerns were addressed" %}.
</p>
<form method="post" action="{% url 'surveys:send_satisfaction_feedback' survey.id %}">
{% csrf_token %}
<button type="submit" class="btn btn-primary w-100">
<i class="bi bi-send me-2"></i>{% trans "Send Satisfaction Feedback" %}
</button>
</form>
{% else %}
<hr>
<div class="alert alert-info mb-0">
<i class="bi bi-check-circle me-2"></i>
<strong>{% trans "Satisfaction Feedback Sent" %}</strong><br>
<small>{{ survey.satisfaction_feedback_sent_at|date:"M d, Y H:i" }}</small>
</div>
{% if survey.follow_up_feedbacks.exists %}
<div class="mt-3">
<strong>{% trans "Related Feedback" %}:</strong>
{% for feedback in survey.follow_up_feedbacks.all %}
<div class="mt-2">
<a href="{% url 'feedback:feedback_detail' feedback.id %}" class="btn btn-sm btn-outline-primary">
<i class="bi bi-chat-left-text me-1"></i>{% trans "View Feedback" %} #{{ feedback.id|slice:":8" }}
</a>
</div>
{% endfor %}
</div>
{% endif %}
{% endif %}
{% endif %}
</div>
</div>
{% endif %}
</div>
</div>
</div>
{% endblock %}