HH/templates/organizations/patient_detail.html
2026-02-22 08:35:53 +03:00

342 lines
15 KiB
HTML

{% extends 'layouts/base.html' %}
{% load i18n %}
{% load static %}
{% block title %}{{ patient.get_full_name }} - {% trans "Patient Details" %}{% endblock %}
{% block extra_css %}
<style>
.info-card {
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.info-card:hover {
transform: translateY(-4px);
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
}
.field-label {
font-size: 10px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.05em;
color: #64748b;
}
.field-value {
font-size: 14px;
font-weight: 600;
color: #1e293b;
line-height: 1.5;
}
.field-value-secondary {
font-size: 13px;
color: #64748b;
}
.survey-item {
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
border-left: 3px solid transparent;
}
.survey-item:hover {
border-left-color: #007bbd;
background: linear-gradient(135deg, #eef6fb 0%, #f0f9ff 100%);
transform: translateX(4px);
}
.metric-card {
background: linear-gradient(135deg, #007bbd 0%, #005696 100%);
}
.avatar-circle {
background: linear-gradient(135deg, #007bbd 0%, #005696 100%);
box-shadow: 0 4px 6px -1px rgba(0, 123, 189, 0.4);
}
.status-badge {
box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.1);
}
.action-btn {
transition: all 0.2s ease;
}
.action-btn:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px -1px rgba(0, 0, 0, 0.15);
}
.icon-wrapper {
box-shadow: 0 2px 8px -2px rgba(0, 0, 0, 0.1);
}
</style>
{% endblock %}
{% block content %}
<div class="p-8">
<!-- Header -->
<header class="mb-8">
<!-- Breadcrumb -->
<nav class="flex items-center gap-2 text-sm text-slate mb-6">
<a href="{% url 'organizations:patient_list' %}"
class="hover:text-navy transition flex items-center gap-1 group">
<i data-lucide="arrow-left" class="w-4 h-4 group-hover:-translate-x-1 transition-transform"></i>
{% trans "Patients" %}
</a>
<i data-lucide="chevron-right" class="w-4 h-4 text-slate-300"></i>
<span class="font-bold text-navy">{{ patient.get_full_name }}</span>
<span class="ml-2 px-2.5 py-1 rounded-full text-[10px] font-bold uppercase tracking-wider status-badge
{% if patient.status == 'active' %}bg-gradient-to-r from-green-100 to-emerald-100 text-green-700 border border-green-200
{% else %}bg-gradient-to-r from-slate-100 to-gray-100 text-slate-700 border border-slate-200{% endif %}">
{{ patient.get_status_display }}
</span>
</nav>
<!-- Patient Info -->
<div class="flex items-start justify-between gap-6">
<div class="flex items-center gap-5">
<!-- Avatar -->
<div class="avatar-circle w-20 h-20 rounded-2xl flex items-center justify-center text-white font-bold text-2xl flex-shrink-0">
{{ patient.first_name|first }}{{ patient.last_name|first }}
</div>
<!-- Name & Identifiers -->
<div>
<h1 class="text-3xl font-bold text-navy mb-2 flex items-center gap-3">
{{ patient.get_full_name }}
{% if patient.first_name_ar or patient.last_name_ar %}
<span class="text-lg text-slate font-normal" dir="rtl">
{{ patient.first_name_ar|default:'' }} {{ patient.last_name_ar|default:'' }}
</span>
{% endif %}
</h1>
<div class="flex items-center gap-5 text-sm">
<span class="flex items-center gap-2 bg-slate-50 px-3 py-1.5 rounded-lg border border-slate-200">
<i data-lucide="hash" class="w-4 h-4 text-blue"></i>
<span class="text-slate text-xs font-semibold uppercase">{% trans "MRN" %}:</span>
<span class="font-mono font-bold text-navy">{{ patient.mrn }}</span>
</span>
{% if patient.national_id %}
<span class="flex items-center gap-2 bg-slate-50 px-3 py-1.5 rounded-lg border border-slate-200">
<i data-lucide="credit-card" class="w-4 h-4 text-blue"></i>
<span class="text-slate text-xs font-semibold uppercase">{% trans "National ID" %}:</span>
<span class="font-mono font-bold text-navy">{{ patient.national_id }}</span>
</span>
{% endif %}
{% if patient.date_of_birth %}
<span class="flex items-center gap-2 bg-slate-50 px-3 py-1.5 rounded-lg border border-slate-200">
<i data-lucide="calendar" class="w-4 h-4 text-blue"></i>
<span class="text-slate text-xs font-semibold uppercase">{% trans "DOB" %}:</span>
<span class="font-bold text-navy">{{ patient.date_of_birth }}</span>
</span>
{% endif %}
</div>
</div>
</div>
<!-- Action Buttons -->
<div class="flex gap-3 flex-shrink-0">
<a href="{% url 'organizations:patient_update' patient.pk %}"
class="action-btn px-5 py-2.5 border border-slate-200 text-slate rounded-xl font-semibold hover:bg-slate-50 hover:border-slate-300 transition flex items-center gap-2 bg-white">
<i data-lucide="edit-2" class="w-4 h-4"></i>
{% trans "Edit Patient" %}
</a>
{% if request.user.is_px_admin %}
<a href="{% url 'organizations:patient_delete' patient.pk %}"
class="action-btn px-5 py-2.5 border border-red-200 bg-red-50 text-red-600 rounded-xl font-semibold hover:bg-red-100 transition flex items-center gap-2 hover:shadow-md">
<i data-lucide="trash-2" class="w-4 h-4"></i>
{% trans "Delete" %}
</a>
{% endif %}
</div>
</div>
</header>
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
<!-- Main Content -->
<div class="lg:col-span-2 space-y-6">
<!-- Basic Information Card -->
<section class="bg-white rounded-2xl p-6 shadow-sm border border-slate-100 info-card">
<h2 class="text-lg font-bold text-navy mb-6 flex items-center gap-2">
<div class="icon-wrapper w-9 h-9 bg-gradient-to-br from-blue-100 to-blue-50 rounded-xl flex items-center justify-center">
<i data-lucide="user-circle" class="w-5 h-5 text-blue"></i>
</div>
{% trans "Basic Information" %}
</h2>
<div class="grid grid-cols-2 gap-x-8 gap-y-6">
<div class="space-y-2">
<p class="field-label">{% trans "First Name" %}</p>
<p class="field-value">{{ patient.first_name|default:"-" }}</p>
{% if patient.first_name_ar %}
<p class="field-value-secondary" dir="rtl">{{ patient.first_name_ar }}</p>
{% endif %}
</div>
<div class="space-y-2">
<p class="field-label">{% trans "Last Name" %}</p>
<p class="field-value">{{ patient.last_name|default:"-" }}</p>
{% if patient.last_name_ar %}
<p class="field-value-secondary" dir="rtl">{{ patient.last_name_ar }}</p>
{% endif %}
</div>
<div class="space-y-2">
<p class="field-label">{% trans "Date of Birth" %}</p>
<p class="field-value">{{ patient.date_of_birth|default:"-" }}</p>
</div>
<div class="space-y-2">
<p class="field-label">{% trans "Gender" %}</p>
<p class="field-value">{{ patient.get_gender_display|default:"-" }}</p>
</div>
<div class="space-y-2">
<p class="field-label">{% trans "National ID" %}</p>
<p class="field-value font-mono">{{ patient.national_id|default:"-" }}</p>
</div>
<div class="space-y-2">
<p class="field-label">{% trans "Status" %}</p>
<span class="inline-flex px-3 py-1.5 rounded-full text-xs font-bold uppercase tracking-wider status-badge
{% if patient.status == 'active' %}bg-gradient-to-r from-green-100 to-emerald-100 text-green-700 border border-green-200
{% else %}bg-gradient-to-r from-slate-100 to-gray-100 text-slate-700 border border-slate-200{% endif %}">
{{ patient.get_status_display }}
</span>
</div>
</div>
</section>
<!-- Contact Information Card -->
<section class="bg-white rounded-2xl p-6 shadow-sm border border-slate-100 info-card">
<h2 class="text-lg font-bold text-navy mb-6 flex items-center gap-2">
<div class="icon-wrapper w-9 h-9 bg-gradient-to-br from-green-100 to-green-50 rounded-xl flex items-center justify-center">
<i data-lucide="phone" class="w-5 h-5 text-green-600"></i>
</div>
{% trans "Contact Information" %}
</h2>
<div class="grid grid-cols-2 gap-x-8 gap-y-6">
<div class="space-y-2">
<p class="field-label">{% trans "Phone" %}</p>
<p class="field-value font-mono">{{ patient.phone|default:"-" }}</p>
</div>
<div class="space-y-2">
<p class="field-label">{% trans "Email" %}</p>
<p class="field-value">{{ patient.email|default:"-" }}</p>
</div>
<div class="col-span-2 space-y-2">
<p class="field-label">{% trans "Address" %}</p>
<p class="field-value">{{ patient.address|default:"-" }}</p>
</div>
<div class="space-y-2">
<p class="field-label">{% trans "City" %}</p>
<p class="field-value">{{ patient.city|default:"-" }}</p>
</div>
</div>
</section>
<!-- Survey History Card -->
{% if surveys %}
<section class="bg-white rounded-2xl p-6 shadow-sm border border-slate-100 info-card">
<h2 class="text-lg font-bold text-navy mb-6 flex items-center gap-2">
<div class="icon-wrapper w-9 h-9 bg-gradient-to-br from-purple-100 to-purple-50 rounded-xl flex items-center justify-center">
<i data-lucide="clipboard-list" class="w-5 h-5 text-purple-600"></i>
</div>
{% trans "Recent Surveys" %}
<span class="ml-auto text-xs font-bold text-purple-600 bg-purple-50 px-2.5 py-1 rounded-lg">{{ surveys.count }}</span>
</h2>
<div class="space-y-3">
{% for survey in surveys %}
<div class="survey-item flex justify-between items-start p-4 bg-slate-50 rounded-xl border border-slate-100">
<div class="flex-1 min-w-0">
<p class="font-semibold text-navy text-sm mb-1 truncate">{{ survey.survey_template.name }}</p>
<div class="flex items-center gap-3 text-xs text-slate">
<span class="flex items-center gap-1">
<i data-lucide="calendar" class="w-3 h-3"></i>
{{ survey.created_at|date:"d M Y" }}
</span>
<span class="flex items-center gap-1">
<i data-lucide="clock" class="w-3 h-3"></i>
{{ survey.created_at|date:"H:i" }}
</span>
</div>
</div>
<div class="flex items-center gap-2 ml-4 flex-shrink-0">
{% if survey.total_score %}
<div class="flex flex-col items-end">
<span class="px-2.5 py-1 rounded-lg text-xs font-bold
{% if survey.is_negative %}bg-gradient-to-r from-red-100 to-red-50 text-red-700 border border-red-200
{% else %}bg-gradient-to-r from-green-100 to-emerald-50 text-green-700 border border-green-200{% endif %}">
{{ survey.total_score }}
</span>
<span class="text-[10px] text-slate mt-0.5">{% trans "Score" %}</span>
</div>
{% endif %}
<span class="px-2.5 py-1 rounded-lg text-[10px] font-bold uppercase tracking-wider
{% if survey.status == 'completed' %}bg-gradient-to-r from-green-100 to-emerald-100 text-green-700 border border-green-200
{% elif survey.status == 'sent' %}bg-gradient-to-r from-blue-100 to-sky-100 text-blue-700 border border-blue-200
{% else %}bg-gradient-to-r from-slate-100 to-gray-100 text-slate-700 border border-slate-200{% endif %}">
{{ survey.get_status_display }}
</span>
</div>
</div>
{% endfor %}
</div>
<div class="mt-6 text-center pt-4 border-t border-slate-100">
<a href="{% url 'surveys:instance_list' %}?search={{ patient.mrn }}"
class="inline-flex items-center gap-2 text-blue font-semibold hover:text-navy text-sm transition group">
{% trans "View all surveys" %}
<i data-lucide="arrow-right" class="w-4 h-4 group-hover:translate-x-1 transition-transform"></i>
</a>
</div>
</section>
{% endif %}
</div>
<!-- Sidebar -->
<div class="space-y-6">
<!-- Hospital Information Card -->
<section class="metric-card rounded-2xl p-6 shadow-lg text-white info-card relative overflow-hidden">
<div class="absolute top-0 right-0 w-32 h-32 bg-white/5 rounded-full -translate-y-1/2 translate-x-1/2"></div>
<div class="absolute bottom-0 left-0 w-24 h-24 bg-white/5 rounded-full translate-y-1/2 -translate-x-1/2"></div>
<div class="relative z-10">
<div class="flex items-center gap-3 mb-4">
<div class="w-10 h-10 bg-white/10 rounded-xl flex items-center justify-center backdrop-blur-sm">
<i data-lucide="building-2" class="w-5 h-5 text-blue"></i>
</div>
<h3 class="text-sm font-bold">{% trans "Hospital" %}</h3>
</div>
<p class="font-bold text-lg mb-1">{{ patient.primary_hospital.name|default:"-" }}</p>
{% if patient.primary_hospital.name_ar %}
<p class="text-sm text-blue/80" dir="rtl">{{ patient.primary_hospital.name_ar }}</p>
{% endif %}
</div>
</section>
<!-- Metadata Card -->
<section class="bg-white rounded-2xl p-6 shadow-sm border border-slate-100 info-card">
<div class="flex items-center gap-3 mb-5">
<div class="icon-wrapper w-9 h-9 bg-gradient-to-br from-slate-100 to-slate-50 rounded-xl flex items-center justify-center">
<i data-lucide="info" class="w-5 h-5 text-slate"></i>
</div>
<h3 class="text-sm font-bold text-navy">{% trans "Metadata" %}</h3>
</div>
<div class="space-y-4">
<div class="flex justify-between items-center pb-4 border-b border-slate-100">
<div class="flex items-center gap-2">
<i data-lucide="plus-circle" class="w-3.5 h-3.5 text-slate"></i>
<span class="text-xs font-semibold text-slate uppercase">{% trans "Created" %}</span>
</div>
<span class="text-sm font-medium text-navy">{{ patient.created_at|date:"d M Y" }}</span>
</div>
<div class="flex justify-between items-center">
<div class="flex items-center gap-2">
<i data-lucide="refresh-cw" class="w-3.5 h-3.5 text-slate"></i>
<span class="text-xs font-semibold text-slate uppercase">{% trans "Updated" %}</span>
</div>
<span class="text-sm font-medium text-navy">{{ patient.updated_at|date:"d M Y" }}</span>
</div>
</div>
</section>
</div>
</div>
</div>
{% endblock %}
{% block extra_js %}
<script>
lucide.createIcons();
</script>
{% endblock %}