HH/templates/feedback/feedback_detail.html
2025-12-29 11:52:54 +03:00

657 lines
29 KiB
HTML

{% extends "layouts/base.html" %}
{% load i18n %}
{% load static %}
{% block title %}Feedback Detail - PX360{% endblock %}
{% block extra_css %}
<style>
.detail-card {
border: 1px solid #dee2e6;
border-radius: 8px;
margin-bottom: 20px;
}
.detail-card-header {
background: #f8f9fa;
border-bottom: 1px solid #dee2e6;
padding: 15px 20px;
font-weight: 600;
}
.detail-card-body {
padding: 20px;
}
.info-row {
display: flex;
padding: 10px 0;
border-bottom: 1px solid #f0f0f0;
}
.info-row:last-child {
border-bottom: none;
}
.info-label {
font-weight: 600;
color: #666;
min-width: 150px;
}
.info-value {
flex: 1;
color: #333;
}
.status-badge {
padding: 6px 16px;
border-radius: 12px;
font-size: 0.9rem;
font-weight: 500;
}
.status-submitted { background: #e3f2fd; color: #1976d2; }
.status-reviewed { background: #fff3e0; color: #f57c00; }
.status-acknowledged { background: #e8f5e9; color: #388e3c; }
.status-closed { background: #f5f5f5; color: #616161; }
.type-badge {
padding: 6px 16px;
border-radius: 12px;
font-size: 0.9rem;
font-weight: 500;
}
.type-compliment { background: #e8f5e9; color: #2e7d32; }
.type-suggestion { background: #e3f2fd; color: #1565c0; }
.type-general { background: #f5f5f5; color: #616161; }
.type-inquiry { background: #fff3e0; color: #ef6c00; }
.sentiment-badge {
padding: 6px 16px;
border-radius: 12px;
font-size: 0.9rem;
font-weight: 500;
}
.sentiment-positive { background: #e8f5e9; color: #2e7d32; }
.sentiment-neutral { background: #f5f5f5; color: #616161; }
.sentiment-negative { background: #ffebee; color: #c62828; }
.rating-stars {
color: #ffc107;
font-size: 1.5rem;
}
.timeline {
position: relative;
padding-left: 30px;
}
.timeline::before {
content: '';
position: absolute;
left: 8px;
top: 0;
bottom: 0;
width: 2px;
background: #dee2e6;
}
.timeline-item {
position: relative;
padding-bottom: 30px;
}
.timeline-item::before {
content: '';
position: absolute;
left: -26px;
top: 5px;
width: 12px;
height: 12px;
border-radius: 50%;
background: #fff;
border: 2px solid #0d6efd;
}
.timeline-content {
background: #f8f9fa;
border: 1px solid #dee2e6;
border-radius: 8px;
padding: 15px;
}
.timeline-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
.timeline-user {
font-weight: 600;
color: #0d6efd;
}
.timeline-date {
font-size: 0.85rem;
color: #666;
}
.timeline-message {
color: #333;
white-space: pre-wrap;
}
.action-buttons {
display: flex;
gap: 10px;
flex-wrap: wrap;
}
.featured-badge {
background: #ffd700;
color: #000;
padding: 4px 12px;
border-radius: 12px;
font-size: 0.85rem;
font-weight: 600;
}
</style>
{% endblock %}
{% block content %}
<div class="container-fluid">
<!-- Page Header -->
<div class="d-flex justify-content-between align-items-center mb-4">
<div>
<nav aria-label="breadcrumb">
<ol class="breadcrumb mb-2">
<li class="breadcrumb-item"><a href="{% url 'feedback:feedback_list' %}">{% trans "Feedback" %}</a></li>
<li class="breadcrumb-item active">Detail</li>
</ol>
</nav>
<h2 class="mb-0">
<i class="bi bi-chat-heart-fill text-primary me-2"></i>
Feedback Detail
</h2>
</div>
<div class="action-buttons">
{% if can_edit %}
<a href="{% url 'feedback:feedback_update' feedback.id %}" class="btn btn-outline-primary">
<i class="bi bi-pencil me-1"></i> Edit
</a>
<a href="{% url 'feedback:feedback_delete' feedback.id %}" class="btn btn-outline-danger">
<i class="bi bi-trash me-1"></i> Delete
</a>
{% endif %}
<a href="{% url 'feedback:feedback_list' %}" class="btn btn-outline-secondary">
<i class="bi bi-arrow-left me-1"></i> Back to List
</a>
</div>
</div>
<div class="row">
<!-- Main Content -->
<div class="col-lg-8">
<!-- Feedback Details -->
<div class="detail-card">
<div class="detail-card-header">
<div class="d-flex justify-content-between align-items-center">
<span>Feedback Information</span>
<div class="d-flex gap-2">
<span class="type-badge type-{{ feedback.feedback_type }}">
{{ feedback.get_feedback_type_display }}
</span>
<span class="status-badge status-{{ feedback.status }}">
{{ feedback.get_status_display }}
</span>
{% if feedback.is_featured %}
<span class="featured-badge">★ FEATURED</span>
{% endif %}
</div>
</div>
</div>
<div class="detail-card-body">
<div class="info-row">
<div class="info-label">ID:</div>
<div class="info-value">
<code>{{ feedback.id }}</code>
</div>
</div>
<div class="info-row">
<div class="info-label">Title:</div>
<div class="info-value">
<strong>{{ feedback.title }}</strong>
</div>
</div>
<div class="info-row">
<div class="info-label">Message:</div>
<div class="info-value">
<p class="mb-0" style="white-space: pre-wrap;">{{ feedback.message }}</p>
</div>
</div>
<div class="info-row">
<div class="info-label">Category:</div>
<div class="info-value">
<span class="badge bg-secondary">{{ feedback.get_category_display }}</span>
{% if feedback.subcategory %}
<span class="text-muted ms-2">/ {{ feedback.subcategory }}</span>
{% endif %}
</div>
</div>
{% if feedback.rating %}
<div class="info-row">
<div class="info-label">Rating:</div>
<div class="info-value">
<span class="rating-stars">
{% for i in "12345" %}
{% if forloop.counter <= feedback.rating %}
<i class="bi bi-star-fill"></i>
{% else %}
<i class="bi bi-star"></i>
{% endif %}
{% endfor %}
</span>
<span class="ms-2">({{ feedback.rating }}/5)</span>
</div>
</div>
{% endif %}
<div class="info-row">
<div class="info-label">Sentiment:</div>
<div class="info-value">
<span class="sentiment-badge sentiment-{{ feedback.sentiment }}">
{{ feedback.get_sentiment_display }}
</span>
{% if feedback.sentiment_score %}
<span class="text-muted ms-2">(Score: {{ feedback.sentiment_score|floatformat:2 }})</span>
{% endif %}
</div>
</div>
<div class="info-row">
<div class="info-label">Priority:</div>
<div class="info-value">
<span class="badge bg-info">{{ feedback.get_priority_display }}</span>
</div>
</div>
<div class="info-row">
<div class="info-label">Created:</div>
<div class="info-value">
{{ feedback.created_at|date:"F d, Y H:i" }}
</div>
</div>
</div>
</div>
<!-- Patient/Contact Information -->
<div class="detail-card">
<div class="detail-card-header">Patient/Contact Information</div>
<div class="detail-card-body">
{% if feedback.patient %}
<div class="info-row">
<div class="info-label">Patient:</div>
<div class="info-value">
<strong>{{ feedback.patient.get_full_name }}</strong>
</div>
</div>
<div class="info-row">
<div class="info-label">MRN:</div>
<div class="info-value">{{ feedback.patient.mrn }}</div>
</div>
{% if feedback.patient.phone %}
<div class="info-row">
<div class="info-label">Phone:</div>
<div class="info-value">{{ feedback.patient.phone }}</div>
</div>
{% endif %}
{% if feedback.patient.email %}
<div class="info-row">
<div class="info-label">Email:</div>
<div class="info-value">{{ feedback.patient.email }}</div>
</div>
{% endif %}
{% else %}
<div class="info-row">
<div class="info-label">Type:</div>
<div class="info-value">
<span class="badge bg-secondary">Anonymous Feedback</span>
</div>
</div>
{% if feedback.contact_name %}
<div class="info-row">
<div class="info-label">Contact Name:</div>
<div class="info-value">{{ feedback.contact_name }}</div>
</div>
{% endif %}
{% if feedback.contact_email %}
<div class="info-row">
<div class="info-label">Email:</div>
<div class="info-value">{{ feedback.contact_email }}</div>
</div>
{% endif %}
{% if feedback.contact_phone %}
<div class="info-row">
<div class="info-label">Phone:</div>
<div class="info-value">{{ feedback.contact_phone }}</div>
</div>
{% endif %}
{% endif %}
</div>
</div>
<!-- Organization Information -->
<div class="detail-card">
<div class="detail-card-header">Organization Information</div>
<div class="detail-card-body">
<div class="info-row">
<div class="info-label">Hospital:</div>
<div class="info-value">{{ feedback.hospital.name }}</div>
</div>
{% if feedback.department %}
<div class="info-row">
<div class="info-label">Department:</div>
<div class="info-value">{{ feedback.department.name }}</div>
</div>
{% endif %}
{% if feedback.physician %}
<div class="info-row">
<div class="info-label">Physician:</div>
<div class="info-value">{{ feedback.physician.get_full_name }}</div>
</div>
{% endif %}
{% if feedback.encounter_id %}
<div class="info-row">
<div class="info-label">Encounter ID:</div>
<div class="info-value"><code>{{ feedback.encounter_id }}</code></div>
</div>
{% endif %}
</div>
</div>
<!-- Related Survey (if satisfaction check) -->
{% if feedback.related_survey %}
<div class="detail-card border-info">
<div class="detail-card-header bg-info text-white">
<i class="bi bi-link-45deg me-2"></i>Related Survey
</div>
<div class="detail-card-body">
<div class="alert alert-info mb-3">
<i class="bi bi-info-circle me-2"></i>
This is a <strong>satisfaction check</strong> feedback following a negative survey response.
</div>
<div class="info-row">
<div class="info-label">Survey:</div>
<div class="info-value">
<strong>{{ feedback.related_survey.survey_template.name }}</strong>
</div>
</div>
<div class="info-row">
<div class="info-label">Original Score:</div>
<div class="info-value">
<span class="badge bg-danger">{{ feedback.related_survey.total_score|floatformat:1 }}/5.0</span>
<span class="text-muted ms-2">(Negative)</span>
</div>
</div>
<div class="info-row">
<div class="info-label">Survey Date:</div>
<div class="info-value">
{{ feedback.related_survey.completed_at|date:"M d, Y H:i" }}
</div>
</div>
{% if feedback.related_survey.patient_contacted %}
<div class="info-row">
<div class="info-label">Patient Contacted:</div>
<div class="info-value">
<i class="bi bi-check-circle-fill text-success"></i>
{{ feedback.related_survey.patient_contacted_at|date:"M d, Y H:i" }}
<br>
<small class="text-muted">By {{ feedback.related_survey.patient_contacted_by.get_full_name }}</small>
</div>
</div>
{% endif %}
<div class="mt-3">
<a href="{% url 'surveys:instance_detail' feedback.related_survey.id %}"
class="btn btn-info btn-sm w-100">
<i class="bi bi-box-arrow-up-right me-1"></i>View Original Survey
</a>
</div>
</div>
</div>
{% endif %}
<!-- Timeline -->
<div class="detail-card">
<div class="detail-card-header">Timeline & Responses</div>
<div class="detail-card-body">
{% if timeline %}
<div class="timeline">
{% for response in timeline %}
<div class="timeline-item">
<div class="timeline-content">
<div class="timeline-header">
<div>
<span class="timeline-user">
{% if response.created_by %}
{{ response.created_by.get_full_name }}
{% else %}
System
{% endif %}
</span>
<span class="badge bg-secondary ms-2">{{ response.get_response_type_display }}</span>
{% if response.is_internal %}
<span class="badge bg-warning ms-1">Internal</span>
{% endif %}
</div>
<span class="timeline-date">
{{ response.created_at|date:"M d, Y H:i" }}
</span>
</div>
<div class="timeline-message">{{ response.message }}</div>
</div>
</div>
{% endfor %}
</div>
{% else %}
<p class="text-muted text-center py-3">No responses yet</p>
{% endif %}
</div>
</div>
</div>
<!-- Sidebar -->
<div class="col-lg-4">
<!-- Actions -->
{% if can_edit %}
<div class="detail-card">
<div class="detail-card-header">Actions</div>
<div class="detail-card-body">
<!-- Change Status -->
<form method="post" action="{% url 'feedback:feedback_change_status' feedback.id %}" class="mb-3">
{% csrf_token %}
<label class="form-label fw-bold">{% trans "Change Status" %}</label>
<select name="status" class="form-select mb-2">
{% for value, label in status_choices %}
<option value="{{ value }}" {% if feedback.status == value %}selected{% endif %}>
{{ label }}
</option>
{% endfor %}
</select>
<textarea name="note" class="form-control mb-2" rows="2"
placeholder="{% trans 'Add a note (optional)...' %}"></textarea>
<button type="submit" class="btn btn-primary btn-sm w-100">
<i class="bi bi-arrow-repeat me-1"></i> Update Status
</button>
</form>
<hr>
<!-- Assign -->
<form method="post" action="{% url 'feedback:feedback_assign' feedback.id %}" class="mb-3">
{% csrf_token %}
<label class="form-label fw-bold">{% trans "Assign To" %}</label>
<select name="user_id" class="form-select mb-2">
<option value="">Select user...</option>
{% for user in assignable_users %}
<option value="{{ user.id }}" {% if feedback.assigned_to.id == user.id %}selected{% endif %}>
{{ user.get_full_name }}
</option>
{% endfor %}
</select>
<button type="submit" class="btn btn-primary btn-sm w-100">
<i class="bi bi-person-check me-1"></i> Assign
</button>
</form>
<hr>
<!-- Add Response -->
<form method="post" action="{% url 'feedback:feedback_add_response' feedback.id %}">
{% csrf_token %}
<label class="form-label fw-bold">{% trans "Add Response" %}</label>
<select name="response_type" class="form-select mb-2">
<option value="response">Response to Patient</option>
<option value="note">Internal Note</option>
<option value="acknowledgment">Acknowledgment</option>
</select>
<textarea name="message" class="form-control mb-2" rows="3"
placeholder="{% trans 'Enter your response...' %}" required></textarea>
<div class="form-check mb-2">
<input type="checkbox" class="form-check-input" name="is_internal" id="is_internal">
<label class="form-check-label" for="is_internal">
Internal only (not visible to patient)
</label>
</div>
<button type="submit" class="btn btn-success btn-sm w-100">
<i class="bi bi-chat-left-text me-1"></i> Add Response
</button>
</form>
<hr>
<!-- Toggle Actions -->
<div class="d-grid gap-2">
<form method="post" action="{% url 'feedback:feedback_toggle_featured' feedback.id %}" class="d-inline">
{% csrf_token %}
<button type="submit" class="btn btn-outline-warning btn-sm w-100">
<i class="bi bi-star me-1"></i>
{% if feedback.is_featured %}Unfeature{% else %}Feature{% endif %}
</button>
</form>
<form method="post" action="{% url 'feedback:feedback_toggle_follow_up' feedback.id %}" class="d-inline">
{% csrf_token %}
<button type="submit" class="btn btn-outline-info btn-sm w-100">
<i class="bi bi-flag me-1"></i>
{% if feedback.requires_follow_up %}Remove Follow-up{% else %}Mark for Follow-up{% endif %}
</button>
</form>
</div>
</div>
</div>
{% endif %}
<!-- Assignment Info -->
<div class="detail-card">
<div class="detail-card-header">Assignment & Tracking</div>
<div class="detail-card-body">
<div class="info-row">
<div class="info-label">Assigned To:</div>
<div class="info-value">
{% if feedback.assigned_to %}
{{ feedback.assigned_to.get_full_name }}
<br><small class="text-muted">{{ feedback.assigned_at|date:"M d, Y H:i" }}</small>
{% else %}
<span class="text-muted">Unassigned</span>
{% endif %}
</div>
</div>
{% if feedback.reviewed_by %}
<div class="info-row">
<div class="info-label">Reviewed By:</div>
<div class="info-value">
{{ feedback.reviewed_by.get_full_name }}
<br><small class="text-muted">{{ feedback.reviewed_at|date:"M d, Y H:i" }}</small>
</div>
</div>
{% endif %}
{% if feedback.acknowledged_by %}
<div class="info-row">
<div class="info-label">Acknowledged By:</div>
<div class="info-value">
{{ feedback.acknowledged_by.get_full_name }}
<br><small class="text-muted">{{ feedback.acknowledged_at|date:"M d, Y H:i" }}</small>
</div>
</div>
{% endif %}
{% if feedback.closed_by %}
<div class="info-row">
<div class="info-label">Closed By:</div>
<div class="info-value">
{{ feedback.closed_by.get_full_name }}
<br><small class="text-muted">{{ feedback.closed_at|date:"M d, Y H:i" }}</small>
</div>
</div>
{% endif %}
</div>
</div>
<!-- Flags -->
<div class="detail-card">
<div class="detail-card-header">Flags & Settings</div>
<div class="detail-card-body">
<div class="info-row">
<div class="info-label">Featured:</div>
<div class="info-value">
{% if feedback.is_featured %}
<i class="bi bi-check-circle-fill text-success"></i> Yes
{% else %}
<i class="bi bi-x-circle text-muted"></i> No
{% endif %}
</div>
</div>
<div class="info-row">
<div class="info-label">Public:</div>
<div class="info-value">
{% if feedback.is_public %}
<i class="bi bi-check-circle-fill text-success"></i> Yes
{% else %}
<i class="bi bi-x-circle text-muted"></i> No
{% endif %}
</div>
</div>
<div class="info-row">
<div class="info-label">Follow-up Required:</div>
<div class="info-value">
{% if feedback.requires_follow_up %}
<i class="bi bi-check-circle-fill text-warning"></i> Yes
{% else %}
<i class="bi bi-x-circle text-muted"></i> No
{% endif %}
</div>
</div>
<div class="info-row">
<div class="info-label">Source:</div>
<div class="info-value">
<span class="badge bg-info">{{ feedback.source }}</span>
</div>
</div>
</div>
</div>
<!-- Attachments -->
{% if attachments %}
<div class="detail-card">
<div class="detail-card-header">Attachments ({{ attachments.count }})</div>
<div class="detail-card-body">
<div class="list-group list-group-flush">
{% for attachment in attachments %}
<div class="list-group-item px-0">
<div class="d-flex justify-content-between align-items-center">
<div>
<i class="bi bi-paperclip me-2"></i>
<strong>{{ attachment.filename }}</strong>
<br>
<small class="text-muted">
{{ attachment.file_size|filesizeformat }} •
{{ attachment.created_at|date:"M d, Y" }}
</small>
</div>
<a href="{{ attachment.file.url }}" class="btn btn-sm btn-outline-primary"
target="_blank" download>
<i class="bi bi-download"></i>
</a>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
{% endif %}
</div>
</div>
</div>
{% endblock %}