Autosave: 20260219-080818
This commit is contained in:
parent
fd84fa729b
commit
924c47dea2
Binary file not shown.
Binary file not shown.
Binary file not shown.
18
core/migrations/0020_vaccinerecord_photo.py
Normal file
18
core/migrations/0020_vaccinerecord_photo.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.2.7 on 2026-02-19 05:04
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0019_healthreport'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='vaccinerecord',
|
||||
name='photo',
|
||||
field=models.ImageField(blank=True, null=True, upload_to='vaccine_photos/'),
|
||||
),
|
||||
]
|
||||
Binary file not shown.
@ -65,6 +65,7 @@ class VaccineRecord(models.Model):
|
||||
location = models.CharField(max_length=255)
|
||||
center_name = models.CharField(max_length=255, null=True, blank=True)
|
||||
notes = models.TextField(blank=True, null=True)
|
||||
photo = models.ImageField(upload_to='vaccine_photos/', null=True, blank=True)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
def __str__(self):
|
||||
|
||||
@ -281,9 +281,10 @@
|
||||
<li class="{% if request.resolver_match.url_name == 'vaccination_info' %}active{% endif %}"><a href="{% url 'vaccination_info' %}"><i class="bi bi-shield-check"></i> {% trans "Vaccination" %}</a></li>
|
||||
{% if user.is_authenticated %}
|
||||
<li class="{% if 'vaccination_dashboard' in request.resolver_match.url_name or 'add_vaccination' in request.resolver_match.url_name %}active{% endif %}"><a href="{% url 'vaccination_dashboard' %}"><i class="bi bi-journal-check"></i> {% trans "My Records" %}</a></li>
|
||||
<li class="{% if 'health_report' in request.resolver_match.url_name %}active{% endif %}"><a href="{% url 'health_report_list' %}"><i class="bi bi-file-medical-fill text-danger"></i> {% trans "Health Reports" %}</a></li>
|
||||
{% endif %}
|
||||
{% if user.is_superuser %}
|
||||
<li><a href="/admin/"><i class="bi bi-gear-fill"></i> {% trans "Settings" %}</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
@ -295,10 +296,12 @@
|
||||
<button type="button" id="sidebarCollapse" class="btn btn-link text-danger me-3 p-0">
|
||||
<i class="bi bi-list fs-3"></i>
|
||||
</button>
|
||||
<div class="search-box d-none d-lg-flex">
|
||||
<i class="bi bi-search text-secondary"></i>
|
||||
<input type="text" placeholder="Search anything...">
|
||||
</div>
|
||||
<form action="{% url 'donor_list' %}" method="GET" class="search-box d-none d-lg-flex">
|
||||
<button type="submit" class="btn btn-link p-0 text-secondary border-0">
|
||||
<i class="bi bi-search"></i>
|
||||
</button>
|
||||
<input type="text" name="q" placeholder="Search anything..." value="{{ request.GET.q }}">
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="d-flex align-items-center gap-2 gap-md-4">
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
<p class="text-secondary">Keep your immunization data accurate and up to date.</p>
|
||||
</div>
|
||||
|
||||
<form method="POST">
|
||||
<form method="POST" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
|
||||
<div class="mb-3">
|
||||
@ -57,6 +57,11 @@
|
||||
<input type="text" name="center_name" class="form-control bg-light border-secondary text-dark" placeholder="e.g. Teaching Hospital">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label text-dark fw-bold">Certificate Photo (Optional)</label>
|
||||
<input type="file" name="photo" class="form-control bg-light border-secondary text-dark" accept="image/*">
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<label class="form-label text-dark fw-bold">Notes (Optional)</label>
|
||||
<textarea name="notes" class="form-control bg-light border-secondary text-dark" rows="3" placeholder="Any side effects or remarks..."></textarea>
|
||||
|
||||
@ -49,6 +49,17 @@
|
||||
<h5 class="mb-1 fw-bold text-dark">{{ req.patient_name }}</h5>
|
||||
<p class="text-secondary small mb-2"><i class="bi bi-hospital me-1"></i> {{ req.hospital }}</p>
|
||||
|
||||
{% with acceptance=req.donations.first %}
|
||||
{% if acceptance %}
|
||||
<div class="mb-2 p-2 rounded bg-success bg-opacity-10 border border-success border-opacity-25">
|
||||
<p class="mb-0 small text-success">
|
||||
<i class="bi bi-person-check-fill me-1"></i>
|
||||
Accepted by: <strong>{{ acceptance.donor.name }}</strong>
|
||||
</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
|
||||
{% if req.image %}
|
||||
<div class="mb-3">
|
||||
<img src="{{ req.image.url }}" class="img-fluid rounded border shadow-sm" alt="Patient/Prescription" style="max-height: 150px; width: 100%; object-fit: cover; cursor: pointer;" onclick="window.open(this.src)">
|
||||
@ -64,7 +75,9 @@
|
||||
<i class="bi bi-chat-dots-fill"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if user.is_authenticated and user.donor_profile and req.user != user %}
|
||||
<a href="{% url 'volunteer_for_request' req.id %}" class="btn btn-sm btn-outline-danger px-3 rounded-pill">Volunteer</a>
|
||||
{% endif %}
|
||||
<a href="tel:{{ req.contact_number }}" class="btn btn-sm btn-danger px-3 rounded-pill">Call</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -15,6 +15,10 @@
|
||||
<div class="glass-card mb-4">
|
||||
<form method="GET" id="donorFilterForm" class="row g-3 mb-4">
|
||||
<div class="col-md-3">
|
||||
<input type="text" name="q" class="form-control bg-light border-secondary text-dark"
|
||||
placeholder="Search name or location..." value="{{ request.GET.q }}">
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<select name="blood_group" class="form-select bg-light border-secondary text-dark">
|
||||
<option value="">All Blood Groups</option>
|
||||
{% for group in blood_groups %}
|
||||
@ -22,9 +26,9 @@
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="col-md-2">
|
||||
<input type="text" name="district" class="form-control bg-light border-secondary text-dark"
|
||||
placeholder="Search district (e.g. Kathmandu)..." value="{{ request.GET.district }}">
|
||||
placeholder="District..." value="{{ request.GET.district }}">
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<button type="submit" class="btn btn-danger w-100 shadow-sm">Filter</button>
|
||||
@ -34,8 +38,8 @@
|
||||
<i class="bi bi-geo-alt-fill me-1"></i> Nearest
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<a href="{% url 'donor_list' %}" class="btn btn-outline-secondary w-100">Reset</a>
|
||||
<div class="col-md-1">
|
||||
<a href="{% url 'donor_list' %}" class="btn btn-outline-secondary w-100 px-0" title="Reset">Reset</a>
|
||||
</div>
|
||||
<input type="hidden" name="lat" id="latInput" value="{{ request.GET.lat }}">
|
||||
<input type="hidden" name="lng" id="lngInput" value="{{ request.GET.lng }}">
|
||||
|
||||
@ -1,80 +0,0 @@
|
||||
{% extends "base.html" %}
|
||||
{% load static %}
|
||||
|
||||
{% block title %}My Health Records - RaktaPulse{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container py-5">
|
||||
<div class="d-flex justify-content-between align-items-center mb-5">
|
||||
<div>
|
||||
<h1 style="font-weight: 800; color: var(--text-primary);">My Health Records</h1>
|
||||
<p class="text-muted">Manage your hospital reports and medical history.</p>
|
||||
</div>
|
||||
<a href="{% url 'upload_health_report' %}" class="btn btn-primary px-4 py-2" style="border-radius: 10px; font-weight: 700; background-color: var(--pulse-red); border: none;">
|
||||
<i class="fas fa-plus me-2"></i> Add New Report
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{% if reports %}
|
||||
<div class="row">
|
||||
{% for report in reports %}
|
||||
<div class="col-md-6 col-lg-4 mb-4">
|
||||
<div class="card h-100 shadow-sm border-0" style="border-radius: 15px; overflow: hidden; transition: all 0.3s ease;">
|
||||
<div class="card-body p-4">
|
||||
<div class="d-flex justify-content-between align-items-start mb-3">
|
||||
<div class="icon-box" style="width: 50px; height: 50px; background: rgba(230, 57, 70, 0.1); border-radius: 12px; display: flex; align-items: center; justify-content: center; color: var(--pulse-red);">
|
||||
<i class="fas fa-file-medical fa-lg"></i>
|
||||
</div>
|
||||
{% if report.allow_notifications %}
|
||||
<span class="badge bg-success" style="border-radius: 6px;">
|
||||
<i class="fas fa-bell me-1"></i> Notifications On
|
||||
</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<h5 style="font-weight: 700; margin-bottom: 5px;">{{ report.title }}</h5>
|
||||
<p class="text-muted small mb-3">
|
||||
<i class="fas fa-hospital me-1"></i> {{ report.hospital_name|default:"Not Specified" }}
|
||||
</p>
|
||||
|
||||
<div class="mb-3">
|
||||
<div class="d-flex justify-content-between small text-muted mb-1">
|
||||
<span>Test Date:</span>
|
||||
<span class="fw-bold">{{ report.report_date }}</span>
|
||||
</div>
|
||||
{% if report.next_test_date %}
|
||||
<div class="d-flex justify-content-between small text-muted">
|
||||
<span>Next Test:</span>
|
||||
<span class="text-primary fw-bold">{{ report.next_test_date }}</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if report.description %}
|
||||
<p class="small text-secondary mb-4">{{ report.description|truncatechars:80 }}</p>
|
||||
{% endif %}
|
||||
|
||||
<div class="d-grid">
|
||||
<a href="{{ report.report_file.url }}" class="btn btn-outline-dark" target="_blank" style="border-radius: 8px; font-weight: 600;">
|
||||
<i class="fas fa-eye me-2"></i> View Report
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="text-center py-5">
|
||||
<div class="mb-4">
|
||||
<i class="fas fa-folder-open fa-5x text-muted opacity-50"></i>
|
||||
</div>
|
||||
<h3>No health records found</h3>
|
||||
<p class="text-muted">Start by uploading your first medical report today.</p>
|
||||
<a href="{% url 'upload_health_report' %}" class="btn btn-primary mt-3 px-5 py-2" style="border-radius: 10px; font-weight: 700; background-color: var(--pulse-red); border: none;">
|
||||
Upload Now
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
@ -121,7 +121,7 @@
|
||||
<div class="col-md-5 text-md-end mt-3 mt-md-0">
|
||||
<div class="d-flex flex-wrap gap-2 justify-content-md-end">
|
||||
{% for badge in user_badges %}
|
||||
<div class="badge-item d-flex align-items-center gap-2 px-3 py-2 bg-white rounded-pill border shadow-sm" title="{{ badge.description }}">
|
||||
<div class="badge-item d-flex align-items-center gap-2 px-3 py-2 bg-white rounded-pill border shadow-sm {% if badge.name == 'First-Time Donor' %}d-md-none{% endif %}" title="{{ badge.description }}">
|
||||
<i class="{{ badge.icon_class }} text-warning"></i>
|
||||
<span class="small fw-bold text-dark">{{ badge.name }}</span>
|
||||
</div>
|
||||
@ -344,6 +344,17 @@
|
||||
</div>
|
||||
<h6 class="mb-1 text-dark">{{ req.patient_name }}</h6>
|
||||
<p class="text-secondary extra-small mb-2"><i class="bi bi-hospital me-1"></i> {{ req.hospital }}</p>
|
||||
|
||||
{% with acceptance=req.donations.first %}
|
||||
{% if acceptance %}
|
||||
<div class="mb-2 p-1 px-2 rounded bg-success bg-opacity-10">
|
||||
<p class="mb-0 extra-small text-success">
|
||||
<i class="bi bi-person-check-fill me-1"></i>
|
||||
Accepted by: <strong>{{ acceptance.donor.name }}</strong>
|
||||
</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<small class="text-muted" style="font-size: 0.7rem;">{{ req.created_at|timesince }} ago</small>
|
||||
<div class="d-flex gap-2 align-items-center">
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
<th>Blood Group</th>
|
||||
<th>Hospital</th>
|
||||
<th>Urgency</th>
|
||||
<th>Status / Accepted By</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -48,6 +49,17 @@
|
||||
<span class="badge bg-info">NORMAL</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% with acceptance=req.donations.first %}
|
||||
{% if acceptance %}
|
||||
<span class="badge bg-success bg-opacity-10 text-success">
|
||||
<i class="bi bi-person-check-fill"></i> {{ acceptance.donor.name }}
|
||||
</span>
|
||||
{% else %}
|
||||
<span class="badge bg-light text-secondary">Awaiting Help</span>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
</td>
|
||||
<td>
|
||||
<button class="btn btn-sm btn-outline-danger" onclick="focusOnMarker({{ req.latitude }}, {{ req.longitude }})">
|
||||
<i class="bi bi-eye"></i> View on Map
|
||||
@ -114,6 +126,11 @@
|
||||
Blood Group: <span class="badge bg-danger">{{ req.blood_group }}</span><br>
|
||||
Hospital: {{ req.hospital }}<br>
|
||||
Urgency: {{ req.urgency }}<br>
|
||||
{% with acceptance=req.donations.first %}
|
||||
{% if acceptance %}
|
||||
<div class="mt-1 text-success small"><i class="bi bi-person-check-fill"></i> Accepted by: {{ acceptance.donor.name }}</div>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
<a href="tel:{{ req.contact_number }}" class="btn btn-sm btn-primary mt-2">Contact</a>
|
||||
`);
|
||||
|
||||
|
||||
@ -61,7 +61,7 @@
|
||||
<button type="submit" class="btn btn-primary py-3" style="border-radius: 10px; font-weight: 700; background-color: var(--pulse-red); border: none;">
|
||||
<i class="fas fa-upload me-2"></i> Save Report
|
||||
</button>
|
||||
<a href="{% url 'health_report_list' %}" class="btn btn-light py-3" style="border-radius: 10px; font-weight: 600;">Cancel</a>
|
||||
<a href="{% url 'vaccination_dashboard' %}" class="btn btn-light py-3" style="border-radius: 10px; font-weight: 600;">Cancel</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
{% extends "base.html" %}
|
||||
{% load static %}
|
||||
|
||||
{% block title %}My Vaccination Records - {{ project_name }}{% endblock %}
|
||||
{% block title %}My Records - {{ project_name }}{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
<style>
|
||||
.vaccine-card {
|
||||
.record-card {
|
||||
background: #ffffff;
|
||||
border-radius: 15px;
|
||||
padding: 20px;
|
||||
@ -13,11 +13,11 @@
|
||||
transition: transform 0.2s, box-shadow 0.2s;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.vaccine-card:hover {
|
||||
.record-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 10px 20px rgba(0,0,0,0.05);
|
||||
}
|
||||
.dose-badge {
|
||||
.status-badge {
|
||||
background: var(--pulse-red-light);
|
||||
color: var(--pulse-red);
|
||||
font-weight: 700;
|
||||
@ -35,6 +35,27 @@
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
}
|
||||
.nav-tabs-custom .nav-link {
|
||||
border: none;
|
||||
color: #6c757d;
|
||||
font-weight: 600;
|
||||
padding: 1rem 1.5rem;
|
||||
position: relative;
|
||||
}
|
||||
.nav-tabs-custom .nav-link.active {
|
||||
color: var(--pulse-red);
|
||||
background: transparent;
|
||||
}
|
||||
.nav-tabs-custom .nav-link.active::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 3px;
|
||||
background: var(--pulse-red);
|
||||
border-radius: 3px 3px 0 0;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
@ -42,12 +63,17 @@
|
||||
<div class="container py-4">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<div>
|
||||
<h2 class="brand-font mb-1 text-dark">Vaccination Journey</h2>
|
||||
<p class="text-secondary">Track and manage your immunization history safely.</p>
|
||||
<h2 class="brand-font mb-1 text-dark">Health & Records</h2>
|
||||
<p class="text-secondary">Manage your vaccinations and hospital reports in one place.</p>
|
||||
</div>
|
||||
<div id="action-buttons">
|
||||
<a href="{% url 'add_vaccination' %}" class="btn btn-outline-danger rounded-pill px-4 shadow-sm me-2" id="btn-add-vaccination">
|
||||
<i class="bi bi-shield-plus me-2"></i>Add Vaccination
|
||||
</a>
|
||||
<a href="{% url 'upload_health_report' %}" class="btn btn-danger rounded-pill px-4 shadow-sm d-none" id="btn-upload-report">
|
||||
<i class="bi bi-file-earmark-medical me-2"></i>Upload Report
|
||||
</a>
|
||||
</div>
|
||||
<a href="{% url 'add_vaccination' %}" class="btn btn-danger rounded-pill px-4 shadow-sm">
|
||||
<i class="bi bi-plus-lg me-2"></i>Add New Record
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{% if messages %}
|
||||
@ -62,42 +88,141 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="row">
|
||||
{% for record in records %}
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<div class="vaccine-card shadow-sm">
|
||||
<div class="d-flex justify-content-between align-items-start mb-3">
|
||||
<h5 class="fw-bold mb-0 text-dark">{{ record.vaccine_name }}</h5>
|
||||
<span class="dose-badge">Dose {{ record.dose_number }}</span>
|
||||
</div>
|
||||
|
||||
<div class="d-flex flex-wrap gap-2 mb-3">
|
||||
<span class="date-badge"><i class="bi bi-calendar-event"></i> {{ record.date_taken|date:"M d, Y" }}</span>
|
||||
<span class="date-badge"><i class="bi bi-geo-alt"></i> {{ record.center_name|default:record.location }}</span>
|
||||
</div>
|
||||
<ul class="nav nav-tabs nav-tabs-custom mb-4" id="recordTabs" role="tablist">
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link active" id="vaccinations-tab" data-bs-toggle="tab" data-bs-target="#vaccinations" type="button" role="tab" aria-controls="vaccinations" aria-selected="true">
|
||||
<i class="bi bi-shield-check me-2"></i>Vaccinations
|
||||
</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="reports-tab" data-bs-toggle="tab" data-bs-target="#reports" type="button" role="tab" aria-controls="reports" aria-selected="false">
|
||||
<i class="bi bi-file-earmark-text me-2"></i>Hospital Reports
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="mt-2 border-top pt-2">
|
||||
<p class="text-secondary small mb-0">
|
||||
<strong>Location:</strong> {{ record.location }}
|
||||
</p>
|
||||
{% if record.notes %}
|
||||
<p class="text-secondary small mt-2 mb-0">
|
||||
<i class="bi bi-sticky me-1"></i> {{ record.notes|truncatechars:100 }}
|
||||
</p>
|
||||
{% endif %}
|
||||
<div class="tab-content" id="recordTabsContent">
|
||||
<!-- Vaccinations Tab -->
|
||||
<div class="tab-pane fade show active" id="vaccinations" role="tabpanel" aria-labelledby="vaccinations-tab">
|
||||
<div class="row">
|
||||
{% for record in records %}
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<div class="record-card shadow-sm">
|
||||
<div class="d-flex justify-content-between align-items-start mb-3">
|
||||
<h5 class="fw-bold mb-0 text-dark">{{ record.vaccine_name }}</h5>
|
||||
<span class="status-badge">Dose {{ record.dose_number }}</span>
|
||||
</div>
|
||||
|
||||
<div class="d-flex flex-wrap gap-2 mb-3">
|
||||
<span class="date-badge"><i class="bi bi-calendar-event"></i> {{ record.date_taken|date:"M d, Y" }}</span>
|
||||
<span class="date-badge"><i class="bi bi-geo-alt"></i> {{ record.center_name|default:record.location }}</span>
|
||||
</div>
|
||||
|
||||
{% if record.photo %}
|
||||
<div class="mb-3">
|
||||
<a href="{{ record.photo.url }}" target="_blank" class="btn btn-sm btn-light w-100 rounded-pill border-secondary">
|
||||
<i class="bi bi-image me-1"></i> View Certificate
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="mt-2 border-top pt-2">
|
||||
<p class="text-secondary small mb-0">
|
||||
<strong>Location:</strong> {{ record.location }}
|
||||
</p>
|
||||
{% if record.notes %}
|
||||
<p class="text-secondary small mt-2 mb-0">
|
||||
<i class="bi bi-sticky me-1"></i> {{ record.notes|truncatechars:100 }}
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% empty %}
|
||||
<div class="col-12 text-center py-5">
|
||||
<div class="glass-card py-5">
|
||||
<i class="bi bi-shield-slash fs-1 text-secondary opacity-25"></i>
|
||||
<h4 class="mt-3 text-dark">No vaccination records</h4>
|
||||
<p class="text-secondary">Keep track of your immunizations.</p>
|
||||
<a href="{% url 'add_vaccination' %}" class="btn btn-outline-danger mt-2 rounded-pill px-4">Add Record</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% empty %}
|
||||
<div class="col-12 text-center py-5">
|
||||
<div class="glass-card py-5">
|
||||
<i class="bi bi-shield-slash fs-1 text-secondary opacity-25"></i>
|
||||
<h4 class="mt-3 text-dark">No records found</h4>
|
||||
<p class="text-secondary">Start tracking your vaccinations today to keep your community safe.</p>
|
||||
<a href="{% url 'add_vaccination' %}" class="btn btn-outline-danger mt-2 rounded-pill px-4">Add Your First Record</a>
|
||||
|
||||
<!-- Health Reports Tab -->
|
||||
<div class="tab-pane fade" id="reports" role="tabpanel" aria-labelledby="reports-tab">
|
||||
<div class="row">
|
||||
{% for report in reports %}
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<div class="record-card shadow-sm">
|
||||
<div class="d-flex justify-content-between align-items-start mb-3">
|
||||
<h5 class="fw-bold mb-0 text-dark">{{ report.title }}</h5>
|
||||
<a href="{{ report.report_file.url }}" target="_blank" class="btn btn-sm btn-outline-danger rounded-circle">
|
||||
<i class="bi bi-download"></i>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<p class="text-muted small mb-3"><i class="bi bi-hospital me-1"></i> {{ report.hospital_name }}</p>
|
||||
|
||||
<div class="d-flex flex-wrap gap-2 mb-3">
|
||||
<span class="date-badge"><i class="bi bi-calendar-check"></i> {{ report.report_date|date:"M d, Y" }}</span>
|
||||
{% if report.next_test_date %}
|
||||
<span class="date-badge text-danger fw-bold"><i class="bi bi-bell"></i> Next: {{ report.next_test_date|date:"M d, Y" }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if report.description %}
|
||||
<p class="text-secondary small mb-3">{{ report.description|truncatechars:120 }}</p>
|
||||
{% endif %}
|
||||
|
||||
<div class="mt-2 border-top pt-2 d-flex justify-content-between align-items-center">
|
||||
<span class="small {% if report.allow_notifications %}text-success{% else %}text-muted{% endif %}">
|
||||
<i class="bi {% if report.allow_notifications %}bi-bell-fill{% else %}bi-bell-slash{% endif %}"></i>
|
||||
{% if report.allow_notifications %}Notifications On{% else %}Notifications Off{% endif %}
|
||||
</span>
|
||||
<span class="text-secondary smaller">{{ report.created_at|timesince }} ago</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% empty %}
|
||||
<div class="col-12 text-center py-5">
|
||||
<div class="glass-card py-5">
|
||||
<i class="bi bi-file-earmark-medical fs-1 text-secondary opacity-25"></i>
|
||||
<h4 class="mt-3 text-dark">No hospital reports</h4>
|
||||
<p class="text-secondary">Upload your medical reports for safekeeping and reminders.</p>
|
||||
<a href="{% url 'upload_health_report' %}" class="btn btn-outline-danger mt-2 rounded-pill px-4">Upload First Report</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const vaccinationsTab = document.getElementById('vaccinations-tab');
|
||||
const reportsTab = document.getElementById('reports-tab');
|
||||
const btnAddVaccination = document.getElementById('btn-add-vaccination');
|
||||
const btnUploadReport = document.getElementById('btn-upload-report');
|
||||
|
||||
vaccinationsTab.addEventListener('shown.bs.tab', function() {
|
||||
btnAddVaccination.classList.remove('d-none');
|
||||
btnUploadReport.classList.add('d-none');
|
||||
});
|
||||
|
||||
reportsTab.addEventListener('shown.bs.tab', function() {
|
||||
btnAddVaccination.classList.add('d-none');
|
||||
btnUploadReport.classList.remove('d-none');
|
||||
});
|
||||
|
||||
// Handle initial state if needed
|
||||
if (window.location.hash === '#reports') {
|
||||
const tab = new bootstrap.Tab(reportsTab);
|
||||
tab.show();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
@ -8,7 +8,7 @@ from .views import (
|
||||
complete_donation, notifications_view,
|
||||
register_donor, hospital_list, public_profile, inbox, chat,
|
||||
update_location, emergency_sms, delete_personal_info,
|
||||
health_report_list, upload_health_report
|
||||
upload_health_report
|
||||
)
|
||||
|
||||
urlpatterns = [
|
||||
@ -27,7 +27,6 @@ urlpatterns = [
|
||||
path("vaccination/", vaccination_info, name="vaccination_info"),
|
||||
path("vaccination/dashboard/", vaccination_dashboard, name="vaccination_dashboard"),
|
||||
path("vaccination/add/", add_vaccination, name="add_vaccination"),
|
||||
path("reports/", health_report_list, name="health_report_list"),
|
||||
path("reports/upload/", upload_health_report, name="upload_health_report"),
|
||||
path("live-map/", live_map, name="live_map"),
|
||||
path("request-blood/", request_blood, name="request_blood"),
|
||||
|
||||
@ -314,12 +314,15 @@ def home(request):
|
||||
return render(request, "core/index.html", context)
|
||||
|
||||
def donor_list(request):
|
||||
query = request.GET.get('q', '')
|
||||
blood_group = request.GET.get('blood_group', '')
|
||||
district = request.GET.get('district', '')
|
||||
user_lat = request.GET.get('lat')
|
||||
user_lng = request.GET.get('lng')
|
||||
|
||||
donors = Donor.objects.all()
|
||||
if query:
|
||||
donors = donors.filter(Q(name__icontains=query) | Q(location__icontains=query))
|
||||
if blood_group:
|
||||
donors = donors.filter(blood_group=blood_group)
|
||||
if district:
|
||||
@ -448,11 +451,14 @@ def request_blood(request):
|
||||
}
|
||||
return render(request, 'core/request_blood.html', context)
|
||||
|
||||
@login_required
|
||||
@login_required
|
||||
def vaccination_dashboard(request):
|
||||
records = VaccineRecord.objects.filter(user=request.user).order_by('-date_taken')
|
||||
reports = HealthReport.objects.filter(user=request.user).order_by('-report_date')
|
||||
context = {
|
||||
'records': records,
|
||||
'reports': reports,
|
||||
'project_name': "RaktaPulse",
|
||||
}
|
||||
return render(request, 'core/vaccination_dashboard.html', context)
|
||||
@ -466,6 +472,7 @@ def add_vaccination(request):
|
||||
location = request.POST.get('location')
|
||||
center_name = request.POST.get('center_name')
|
||||
notes = request.POST.get('notes')
|
||||
photo = request.FILES.get('photo')
|
||||
|
||||
if vaccine_name and dose_number and date_taken:
|
||||
VaccineRecord.objects.create(
|
||||
@ -475,7 +482,8 @@ def add_vaccination(request):
|
||||
date_taken=date_taken,
|
||||
location=location,
|
||||
center_name=center_name,
|
||||
notes=notes
|
||||
notes=notes,
|
||||
photo=photo
|
||||
)
|
||||
messages.success(request, "Vaccination record added successfully!")
|
||||
return redirect('vaccination_dashboard')
|
||||
@ -493,6 +501,11 @@ def volunteer_for_request(request, request_id):
|
||||
messages.error(request, "You need to be registered as a donor to volunteer.")
|
||||
return redirect('donor_list')
|
||||
|
||||
# Prevent requester from volunteering for their own request
|
||||
if blood_request.user == request.user:
|
||||
messages.error(request, "You cannot volunteer for your own blood request.")
|
||||
return redirect('blood_request_list')
|
||||
|
||||
# Check if already volunteered
|
||||
if DonationEvent.objects.filter(donor=donor_profile, request=blood_request).exists():
|
||||
messages.warning(request, "You have already volunteered for this request.")
|
||||
@ -669,11 +682,6 @@ def chat(request, username):
|
||||
|
||||
return render(request, 'core/chat.html', {'other_user': other_user, 'chat_messages': messages})
|
||||
|
||||
@login_required
|
||||
def health_report_list(request):
|
||||
reports = HealthReport.objects.filter(user=request.user).order_by('-report_date')
|
||||
return render(request, 'core/health_report_list.html', {'reports': reports})
|
||||
|
||||
@login_required
|
||||
def upload_health_report(request):
|
||||
if request.method == "POST":
|
||||
@ -697,7 +705,7 @@ def upload_health_report(request):
|
||||
allow_notifications=allow_notifications
|
||||
)
|
||||
messages.success(request, "Health report uploaded successfully!")
|
||||
return redirect('health_report_list')
|
||||
return redirect('vaccination_dashboard')
|
||||
else:
|
||||
messages.error(request, "Please fill in all required fields.")
|
||||
|
||||
|
||||
BIN
media/blood_requests/Garden_City.jpg
Normal file
BIN
media/blood_requests/Garden_City.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.0 MiB |
Loading…
x
Reference in New Issue
Block a user