diff --git a/config/__pycache__/settings.cpython-311.pyc b/config/__pycache__/settings.cpython-311.pyc index 50ad71d..404de93 100644 Binary files a/config/__pycache__/settings.cpython-311.pyc and b/config/__pycache__/settings.cpython-311.pyc differ diff --git a/config/__pycache__/urls.cpython-311.pyc b/config/__pycache__/urls.cpython-311.pyc index 8cde51e..3c20f11 100644 Binary files a/config/__pycache__/urls.cpython-311.pyc and b/config/__pycache__/urls.cpython-311.pyc differ diff --git a/config/settings.py b/config/settings.py index 103f1eb..cd49a45 100644 --- a/config/settings.py +++ b/config/settings.py @@ -193,3 +193,6 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' LOGIN_URL = '/login/' LOGIN_REDIRECT_URL = '/' + +MEDIA_URL = '/media/' +MEDIA_ROOT = BASE_DIR / 'media' diff --git a/config/urls.py b/config/urls.py index baccfac..701370b 100644 --- a/config/urls.py +++ b/config/urls.py @@ -28,3 +28,4 @@ urlpatterns = [ if settings.DEBUG: urlpatterns += static("/assets/", document_root=settings.BASE_DIR / "assets") urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) + urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/core/__pycache__/forms.cpython-311.pyc b/core/__pycache__/forms.cpython-311.pyc index 684052f..6c37854 100644 Binary files a/core/__pycache__/forms.cpython-311.pyc and b/core/__pycache__/forms.cpython-311.pyc differ diff --git a/core/__pycache__/models.cpython-311.pyc b/core/__pycache__/models.cpython-311.pyc index ffaadc6..3d8eb68 100644 Binary files a/core/__pycache__/models.cpython-311.pyc and b/core/__pycache__/models.cpython-311.pyc differ diff --git a/core/__pycache__/urls.cpython-311.pyc b/core/__pycache__/urls.cpython-311.pyc index 77f725c..116ac38 100644 Binary files a/core/__pycache__/urls.cpython-311.pyc and b/core/__pycache__/urls.cpython-311.pyc differ diff --git a/core/__pycache__/views.cpython-311.pyc b/core/__pycache__/views.cpython-311.pyc index c9d8df3..2dedc28 100644 Binary files a/core/__pycache__/views.cpython-311.pyc and b/core/__pycache__/views.cpython-311.pyc differ diff --git a/core/forms.py b/core/forms.py index 114e4ff..7f0ecea 100644 --- a/core/forms.py +++ b/core/forms.py @@ -2,6 +2,18 @@ from django import forms from django.contrib.auth.models import User from .models import UserProfile, BLOOD_GROUPS +from django.contrib.auth.forms import UserCreationForm + +class UserRegisterForm(UserCreationForm): + email = forms.EmailField(required=True) + blood_group = forms.ChoiceField(choices=BLOOD_GROUPS, required=True) + location = forms.CharField(max_length=255, required=True) + phone = forms.CharField(max_length=20, required=True) + + class Meta: + model = User + fields = ['username', 'email'] + class UserUpdateForm(forms.ModelForm): email = forms.EmailField() @@ -18,10 +30,11 @@ class UserUpdateForm(forms.ModelForm): class ProfileUpdateForm(forms.ModelForm): class Meta: model = UserProfile - fields = ['bio', 'location', 'phone', 'blood_group'] + fields = ['bio', 'location', 'phone', 'blood_group', 'profile_pic'] widgets = { 'bio': forms.Textarea(attrs={'class': 'form-control', 'rows': 3}), 'location': forms.TextInput(attrs={'class': 'form-control'}), 'phone': forms.TextInput(attrs={'class': 'form-control'}), 'blood_group': forms.Select(attrs={'class': 'form-control'}, choices=BLOOD_GROUPS), + 'profile_pic': forms.FileInput(attrs={'class': 'form-control'}), } diff --git a/core/management/__init__.py b/core/management/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/core/management/__pycache__/__init__.cpython-311.pyc b/core/management/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..80f2921 Binary files /dev/null and b/core/management/__pycache__/__init__.cpython-311.pyc differ diff --git a/core/management/commands/__init__.py b/core/management/commands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/core/management/commands/__pycache__/__init__.cpython-311.pyc b/core/management/commands/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..822ff85 Binary files /dev/null and b/core/management/commands/__pycache__/__init__.cpython-311.pyc differ diff --git a/core/management/commands/__pycache__/cleanup_requests.cpython-311.pyc b/core/management/commands/__pycache__/cleanup_requests.cpython-311.pyc new file mode 100644 index 0000000..f75a249 Binary files /dev/null and b/core/management/commands/__pycache__/cleanup_requests.cpython-311.pyc differ diff --git a/core/management/commands/__pycache__/seed_hospitals.cpython-311.pyc b/core/management/commands/__pycache__/seed_hospitals.cpython-311.pyc new file mode 100644 index 0000000..b243ce4 Binary files /dev/null and b/core/management/commands/__pycache__/seed_hospitals.cpython-311.pyc differ diff --git a/core/management/commands/cleanup_requests.py b/core/management/commands/cleanup_requests.py new file mode 100644 index 0000000..b307ced --- /dev/null +++ b/core/management/commands/cleanup_requests.py @@ -0,0 +1,46 @@ +from django.core.management.base import BaseCommand +from django.utils import timezone +from core.models import BloodRequest +from datetime import timedelta + +class Command(BaseCommand): + help = 'Deletes old blood requests based on urgency and status' + + def handle(self, *args, **options): + now = timezone.now() + + # Define thresholds (days) + thresholds = { + 'CRITICAL': 3, + 'URGENT': 7, + 'NORMAL': 15, + } + + deleted_count = 0 + + # 1. Delete by Urgency + for urgency, days in thresholds.items(): + cutoff = now - timedelta(days=days) + old_requests = BloodRequest.objects.filter( + urgency=urgency, + created_at__lt=cutoff + ) + count = old_requests.count() + if count > 0: + old_requests.delete() + self.stdout.write(self.style.SUCCESS(f'Deleted {count} {urgency} requests older than {days} days.')) + deleted_count += count + + # 2. Delete non-Active requests older than 7 days + cutoff_inactive = now - timedelta(days=7) + inactive_requests = BloodRequest.objects.exclude(status='Active').filter(created_at__lt=cutoff_inactive) + count_inactive = inactive_requests.count() + if count_inactive > 0: + inactive_requests.delete() + self.stdout.write(self.style.SUCCESS(f'Deleted {count_inactive} non-active requests older than 7 days.')) + deleted_count += count_inactive + + if deleted_count == 0: + self.stdout.write(self.style.SUCCESS('No old requests to delete.')) + else: + self.stdout.write(self.style.SUCCESS(f'Cleanup complete. Total deleted: {deleted_count}')) diff --git a/core/management/commands/seed_hospitals.py b/core/management/commands/seed_hospitals.py new file mode 100644 index 0000000..5600d30 --- /dev/null +++ b/core/management/commands/seed_hospitals.py @@ -0,0 +1,47 @@ +from django.core.management.base import BaseCommand +from core.models import Hospital + +class Command(BaseCommand): + help = 'Seed the database with Kathmandu hospitals and coordinates' + + def handle(self, *args, **kwargs): + hospitals = [ + {"name": "Bir Hospital", "location": "Kanti Path, Kathmandu", "phone": "01-4221988", "lat": 27.7058, "lng": 85.3135}, + {"name": "Kathmandu Valley Hospital", "location": "Bagh darbar marg, Kathmandu", "phone": "01-4255330", "lat": 27.7015, "lng": 85.3115}, + {"name": "Civil Service Hospital of Nepal", "location": "Minbhawan marg, Kathmandu", "phone": "01-4793000", "website": "https://csh.gov.np/ne", "lat": 27.6841, "lng": 85.3385}, + {"name": "Venus Hospital", "location": "Devkota Sadak, Kathmandu", "phone": "01-4475120", "lat": 27.6945, "lng": 85.3415}, + {"name": "Vayodha Hospital", "location": "Balkhu, Kathmandu", "phone": "01-4281666", "website": "https://www.vayodhahospitals.com/", "lat": 27.6855, "lng": 85.2935}, + {"name": "Grande City Hospital", "location": "Kanti path, Kathmandu", "phone": "01-4163500", "website": "http://grandecityhospital.com/", "lat": 27.7065, "lng": 85.3135}, + {"name": "Teaching Hospital", "location": "Maharajgunj, Kathmandu", "phone": "01-4412303", "website": "http://iom.edu.np/", "lat": 27.7351, "lng": 85.3315}, + {"name": "Kathmandu Hospital", "location": "Tripureshwor marg, Kathmandu", "phone": "01-4229656", "lat": 27.6935, "lng": 85.3145}, + {"name": "Kathmandu Neuro & General Hospital", "location": "Bagh Durbar marg, Kathmandu", "phone": "01-5327735", "lat": 27.7018, "lng": 85.3118}, + {"name": "Teku Hospital", "location": "Teku, Kathmandu", "phone": "01-4253396", "website": "http://www.stidh.gov.np/", "lat": 27.6961, "lng": 85.3025}, + {"name": "Nepal Eye Hospital", "location": "Tripureswor, Kathmandu", "phone": "01-4260813", "website": "https://www.nepaleyehospital.org/", "lat": 27.6940, "lng": 85.3140}, + {"name": "Everest Hospital Pvt. Ltd.", "location": "Kathmandu", "phone": "01-4793024", "website": "http://everesthospital.org.np/", "lat": 27.6925, "lng": 85.3345}, + {"name": "Om Hospital & Research Center", "location": "Chabil, Kathmandu", "phone": "01-4476225", "website": "https://omhospitalnepal.com/", "lat": 27.7175, "lng": 85.3485}, + {"name": "Annapurna Neuro Hospital", "location": "Maitighar mandala", "phone": "01-4256656", "website": "https://www.annapurnahospitals.com", "lat": 27.6945, "lng": 85.3215}, + {"name": "Norvic International Hospital", "location": "Kathmandu", "phone": "01-5970032", "website": "https://www.norvichospital.com/", "lat": 27.6897, "lng": 85.3235}, + {"name": "Blue Cross Hospital", "location": "Tripura marga, Kathmandu", "phone": "01-4262027", "lat": 27.6948, "lng": 85.3148}, + {"name": "Paropakar Maternity and Womens’ Hospital", "location": "Thapathali, Kathmandu", "phone": "01-4261363", "lat": 27.6915, "lng": 85.3215}, + {"name": "ERA INTERNATIONAL HOSPITAL Pvt. Ltd.", "location": "Kathmandu", "phone": "01-4352447", "website": "https://www.era-hospital.com/", "lat": 27.7215, "lng": 85.3015}, + {"name": "Birendra Military Hospital", "location": "Kathmandu", "phone": "01-4271941", "website": "https://birendrahospital.nepalarmy.mil.np/", "lat": 27.7085, "lng": 85.2815}, + {"name": "Capital Hospital", "location": "Kathmandu", "phone": "01-4168222", "lat": 27.7045, "lng": 85.3215}, + {"name": "Valley Maternity Nursing Home", "location": "Kathmandu", "phone": "01-4420224", "lat": 27.7125, "lng": 85.3245}, + {"name": "Medicare National Hospital & Research Center", "location": "Ring road, kathmandu", "phone": "01-4467067", "website": "http://medicarehosp.com/", "lat": 27.7145, "lng": 85.3415}, + {"name": "CIWEC Hospital Pvt. Ltd.", "location": "Kathmandu", "phone": "01-4435232", "lat": 27.7165, "lng": 85.3215}, + {"name": "Nepal-Bharat Maitri Hospital", "location": "Dakshinha murti marga, Kathmandu", "phone": "01-5241288", "lat": 27.7185, "lng": 85.3515}, + {"name": "Kantipur Hospital", "location": "Shriganesh Marg, Tripureshwor", "phone": "01-4111", "lat": 27.6938, "lng": 85.3142}, + ] + + for h_data in hospitals: + Hospital.objects.update_or_create( + name=h_data['name'], + defaults={ + 'location': h_data['location'], + 'phone': h_data['phone'], + 'website': h_data.get('website', ''), + 'latitude': h_data.get('lat'), + 'longitude': h_data.get('lng'), + } + ) + self.stdout.write(self.style.SUCCESS(f'Successfully updated {len(hospitals)} hospitals with coordinates.')) diff --git a/core/migrations/0010_delete_feedback.py b/core/migrations/0010_delete_feedback.py new file mode 100644 index 0000000..3756f65 --- /dev/null +++ b/core/migrations/0010_delete_feedback.py @@ -0,0 +1,16 @@ +# Generated by Django 5.2.7 on 2026-02-18 05:57 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0009_bloodrequest_user_donor_user_donationevent_feedback_and_more'), + ] + + operations = [ + migrations.DeleteModel( + name='Feedback', + ), + ] diff --git a/core/migrations/0011_hospital.py b/core/migrations/0011_hospital.py new file mode 100644 index 0000000..be6635e --- /dev/null +++ b/core/migrations/0011_hospital.py @@ -0,0 +1,23 @@ +# Generated by Django 5.2.7 on 2026-02-18 06:05 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0010_delete_feedback'), + ] + + operations = [ + migrations.CreateModel( + name='Hospital', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255)), + ('location', models.CharField(max_length=255)), + ('phone', models.CharField(blank=True, max_length=100, null=True)), + ('website', models.URLField(blank=True, null=True)), + ], + ), + ] diff --git a/core/migrations/0012_hospital_latitude_hospital_longitude.py b/core/migrations/0012_hospital_latitude_hospital_longitude.py new file mode 100644 index 0000000..ba98870 --- /dev/null +++ b/core/migrations/0012_hospital_latitude_hospital_longitude.py @@ -0,0 +1,23 @@ +# Generated by Django 5.2.7 on 2026-02-18 06:19 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0011_hospital'), + ] + + operations = [ + migrations.AddField( + model_name='hospital', + name='latitude', + field=models.DecimalField(blank=True, decimal_places=6, max_digits=9, null=True), + ), + migrations.AddField( + model_name='hospital', + name='longitude', + field=models.DecimalField(blank=True, decimal_places=6, max_digits=9, null=True), + ), + ] diff --git a/core/migrations/0013_userprofile_profile_pic.py b/core/migrations/0013_userprofile_profile_pic.py new file mode 100644 index 0000000..095f467 --- /dev/null +++ b/core/migrations/0013_userprofile_profile_pic.py @@ -0,0 +1,18 @@ +# Generated by Django 5.2.7 on 2026-02-18 07:10 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0012_hospital_latitude_hospital_longitude'), + ] + + operations = [ + migrations.AddField( + model_name='userprofile', + name='profile_pic', + field=models.ImageField(blank=True, null=True, upload_to='profile_pics'), + ), + ] diff --git a/core/migrations/__pycache__/0010_delete_feedback.cpython-311.pyc b/core/migrations/__pycache__/0010_delete_feedback.cpython-311.pyc new file mode 100644 index 0000000..adbdc32 Binary files /dev/null and b/core/migrations/__pycache__/0010_delete_feedback.cpython-311.pyc differ diff --git a/core/migrations/__pycache__/0011_hospital.cpython-311.pyc b/core/migrations/__pycache__/0011_hospital.cpython-311.pyc new file mode 100644 index 0000000..bab95c1 Binary files /dev/null and b/core/migrations/__pycache__/0011_hospital.cpython-311.pyc differ diff --git a/core/migrations/__pycache__/0012_hospital_latitude_hospital_longitude.cpython-311.pyc b/core/migrations/__pycache__/0012_hospital_latitude_hospital_longitude.cpython-311.pyc new file mode 100644 index 0000000..6039d83 Binary files /dev/null and b/core/migrations/__pycache__/0012_hospital_latitude_hospital_longitude.cpython-311.pyc differ diff --git a/core/migrations/__pycache__/0013_userprofile_profile_pic.cpython-311.pyc b/core/migrations/__pycache__/0013_userprofile_profile_pic.cpython-311.pyc new file mode 100644 index 0000000..6041900 Binary files /dev/null and b/core/migrations/__pycache__/0013_userprofile_profile_pic.cpython-311.pyc differ diff --git a/core/models.py b/core/models.py index 00c3cec..60feb33 100644 --- a/core/models.py +++ b/core/models.py @@ -18,6 +18,7 @@ class UserProfile(models.Model): birth_date = models.DateField(null=True, blank=True) phone = models.CharField(max_length=20, blank=True) blood_group = models.CharField(max_length=5, choices=BLOOD_GROUPS, blank=True) + profile_pic = models.ImageField(upload_to='profile_pics', blank=True, null=True) def __str__(self): return self.user.username @@ -32,6 +33,16 @@ def create_or_save_user_profile(sender, instance, created, **kwargs): UserProfile.objects.create(user=instance) instance.profile.save() +@receiver(post_save, sender=UserProfile) +def sync_donor_profile(sender, instance, **kwargs): + if instance.blood_group: + donor, created = Donor.objects.get_or_create(user=instance.user) + donor.name = f"{instance.user.first_name} {instance.user.last_name}".strip() or instance.user.username + donor.blood_group = instance.blood_group + donor.location = instance.location + donor.phone = instance.phone + donor.save() + class VaccineRecord(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='vaccine_records') vaccine_name = models.CharField(max_length=100) @@ -66,6 +77,17 @@ class Donor(models.Model): def __str__(self): return f"{self.name} ({self.blood_group}) - {'Verified' if self.is_verified else 'Unverified'}" +class Hospital(models.Model): + name = models.CharField(max_length=255) + location = models.CharField(max_length=255) + latitude = models.DecimalField(max_digits=9, decimal_places=6, null=True, blank=True) + longitude = models.DecimalField(max_digits=9, decimal_places=6, null=True, blank=True) + phone = models.CharField(max_length=100, null=True, blank=True) + website = models.URLField(null=True, blank=True) + + def __str__(self): + return self.name + class BloodRequest(models.Model): URGENCY_LEVELS = [ ('CRITICAL', 'Critical'), @@ -126,12 +148,3 @@ class Notification(models.Model): def __str__(self): return f"Notification for {self.user.username}: {self.message[:20]}..." - -class Feedback(models.Model): - user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='feedbacks') - content = models.TextField() - rating = models.PositiveIntegerField(default=5) - created_at = models.DateTimeField(auto_now_add=True) - - def __str__(self): - return f"Feedback from {self.user.username} - {self.rating} stars" diff --git a/core/templates/base.html b/core/templates/base.html index 6f5d13f..70f3723 100644 --- a/core/templates/base.html +++ b/core/templates/base.html @@ -218,6 +218,10 @@ z-index: -1; } + .dropdown-toggle.no-caret::after { + display: none; + } + .sos-content { display: flex; flex-direction: column; @@ -272,11 +276,10 @@
  • {% trans "Donors" %}
  • {% trans "Blood Requests" %}
  • {% trans "Blood Banks" %}
  • +
  • {% trans "Hospitals" %}
  • {% trans "Live Alerts" %}
  • {% trans "Vaccination" %}
  • -
  • {% trans "Feedback" %}
  • {% if user.is_authenticated %} -
  • {% trans "My Profile" %}
  • {% trans "My Records" %}
  • {% endif %}
  • {% trans "Settings" %}
  • @@ -340,13 +343,43 @@ {{ user.notifications.count }} - -
    - -
    - {{ user.username }} -
    - Logout + + + {% else %}
    diff --git a/core/templates/core/donor_list.html b/core/templates/core/donor_list.html index 1818a0c..48e66c0 100644 --- a/core/templates/core/donor_list.html +++ b/core/templates/core/donor_list.html @@ -45,8 +45,17 @@ {% for donor in donors %}
    -
    - {{ donor.blood_group }} +
    + {% if donor.user and donor.user.profile.profile_pic %} + {{ donor.name }} + + {{ donor.blood_group }} + + {% else %} +
    + {{ donor.blood_group }} +
    + {% endif %}
    diff --git a/core/templates/core/feedback.html b/core/templates/core/feedback.html deleted file mode 100644 index 6451f56..0000000 --- a/core/templates/core/feedback.html +++ /dev/null @@ -1,34 +0,0 @@ -{% extends 'core/base.html' %} -{% load i18n %} - -{% block content %} -
    -
    -
    -
    -

    {% trans "Share Your Feedback" %}

    -

    {% trans "We value your experience. Please let us know how we can improve." %}

    - -
    - {% csrf_token %} -
    - - -
    -
    - - -
    - -
    -
    -
    -
    -
    -{% endblock %} diff --git a/core/templates/core/hospital_list.html b/core/templates/core/hospital_list.html new file mode 100644 index 0000000..8e01635 --- /dev/null +++ b/core/templates/core/hospital_list.html @@ -0,0 +1,92 @@ +{% extends "base.html" %} +{% load static %} + +{% block title %}Hospitals - RaktaPulse{% endblock %} + +{% block content %} +
    +
    +
    +

    Hospitals in Kathmandu

    +

    A comprehensive list of public and private hospitals for blood requests and emergency care.

    +
    +
    + +
    +
    + +
    + {% for hospital in hospitals %} +
    +
    +
    +
    +

    {{ hospital.name }}

    + {% if hospital.distance %} + + {{ hospital.distance|floatformat:1 }} km away + + {% endif %} +
    +

    {{ hospital.location }}

    +
    + +
    + {% if hospital.phone %} +

    + + {{ hospital.phone }} + +

    + {% endif %} + + {% if hospital.website %} +

    + + Visit Website + +

    + {% endif %} + + Request Blood Here +
    +
    +
    + {% empty %} +
    + +

    No hospitals registered in the system.

    +
    + {% endfor %} +
    +
    + + +{% endblock %} diff --git a/core/templates/core/index.html b/core/templates/core/index.html index 34766e4..378a591 100644 --- a/core/templates/core/index.html +++ b/core/templates/core/index.html @@ -224,8 +224,18 @@ {% for donor in donors %}
    -
    {{ donor.blood_group }}
    +
    + {% if donor.user and donor.user.profile.profile_pic %} + {{ donor.name }} + + {{ donor.blood_group }} + + {% else %} +
    {{ donor.blood_group }}
    + {% endif %} +
    +
    {{ donor.name }} {% if donor.is_verified %} diff --git a/core/templates/core/notifications.html b/core/templates/core/notifications.html index 14fa0fd..e5c80c5 100644 --- a/core/templates/core/notifications.html +++ b/core/templates/core/notifications.html @@ -1,4 +1,4 @@ -{% extends 'core/base.html' %} +{% extends 'base.html' %} {% load i18n %} {% block content %} diff --git a/core/templates/core/profile.html b/core/templates/core/profile.html index 4ecf840..d69206f 100644 --- a/core/templates/core/profile.html +++ b/core/templates/core/profile.html @@ -9,16 +9,20 @@
    -
    - -
    + {% if user.profile.profile_pic %} + {{ user.username }} + {% else %} +
    + +
    + {% endif %}

    {{ user.username }}

    Member since {{ user.date_joined|date:"M d, Y" }}

    -
    + {% csrf_token %}
    Account Information
    @@ -59,6 +63,10 @@ {{ p_form.location }}
    +
    + + {{ p_form.profile_pic }} +
    diff --git a/core/templates/core/register_donor.html b/core/templates/core/register_donor.html index dd78090..375f8d2 100644 --- a/core/templates/core/register_donor.html +++ b/core/templates/core/register_donor.html @@ -1,4 +1,4 @@ -{% extends 'core/base.html' %} +{% extends 'base.html' %} {% load i18n %} {% block content %} diff --git a/core/templates/core/request_blood.html b/core/templates/core/request_blood.html index 71627d6..8d91805 100644 --- a/core/templates/core/request_blood.html +++ b/core/templates/core/request_blood.html @@ -34,7 +34,7 @@
    - +
    diff --git a/core/urls.py b/core/urls.py index 1feb659..9d3763d 100644 --- a/core/urls.py +++ b/core/urls.py @@ -5,8 +5,8 @@ from .views import ( blood_request_list, blood_bank_list, vaccination_info, vaccination_dashboard, add_vaccination, live_map, request_blood, profile, volunteer_for_request, - complete_donation, submit_feedback, notifications_view, - register_donor + complete_donation, notifications_view, + register_donor, hospital_list ) urlpatterns = [ @@ -25,7 +25,7 @@ urlpatterns = [ path("request-blood/", request_blood, name="request_blood"), path("volunteer//", volunteer_for_request, name="volunteer_for_request"), path("complete-donation//", complete_donation, name="complete_donation"), - path("feedback/", submit_feedback, name="submit_feedback"), path("notifications/", notifications_view, name="notifications"), path("register-donor/", register_donor, name="register_donor"), + path("hospitals/", hospital_list, name="hospital_list"), ] diff --git a/core/views.py b/core/views.py index 39bd9ef..de394c0 100644 --- a/core/views.py +++ b/core/views.py @@ -1,5 +1,6 @@ import os import platform +import math from django.db import models from django.shortcuts import render, redirect from django.contrib.auth import login, logout, authenticate @@ -7,9 +8,32 @@ from django.contrib.auth.forms import UserCreationForm, AuthenticationForm from django.contrib.auth.decorators import login_required from django.contrib import messages from django.utils import timezone -from .models import Donor, BloodRequest, BloodBank, VaccineRecord, UserProfile, BLOOD_GROUPS, DonationEvent, Notification, Feedback -from .forms import UserUpdateForm, ProfileUpdateForm -import math +from .models import Donor, BloodRequest, BloodBank, VaccineRecord, UserProfile, BLOOD_GROUPS, DonationEvent, Notification, Hospital +from .forms import UserUpdateForm, ProfileUpdateForm, UserRegisterForm + +def hospital_list(request): + user_lat = request.GET.get('lat') + user_lng = request.GET.get('lng') + + hospitals = Hospital.objects.all() + hospital_list_data = list(hospitals) + + if user_lat and user_lng: + try: + u_lat = float(user_lat) + u_lng = float(user_lng) + for h in hospital_list_data: + if h.latitude and h.longitude: + h.distance = haversine(u_lat, u_lng, float(h.latitude), float(h.longitude)) + else: + h.distance = 999999 + hospital_list_data.sort(key=lambda x: x.distance) + except ValueError: + hospital_list_data.sort(key=lambda x: x.name) + else: + hospital_list_data.sort(key=lambda x: x.name) + + return render(request, 'core/hospital_list.html', {'hospitals': hospital_list_data}) @login_required def profile(request): @@ -18,7 +42,7 @@ def profile(request): if request.method == 'POST': u_form = UserUpdateForm(request.POST, instance=request.user) - p_form = ProfileUpdateForm(request.POST, instance=profile) + p_form = ProfileUpdateForm(request.POST, request.FILES, instance=profile) if u_form.is_valid() and p_form.is_valid(): u_form.save() p_form.save() @@ -67,13 +91,20 @@ def logout_view(request): def register_view(request): if request.method == "POST": - form = UserCreationForm(request.POST) + form = UserRegisterForm(request.POST) if form.is_valid(): user = form.save() + profile = user.profile + profile.blood_group = form.cleaned_data.get('blood_group') + profile.location = form.cleaned_data.get('location') + profile.phone = form.cleaned_data.get('phone') + profile.save() + login(request, user) + messages.success(request, f"Welcome to RaktaPulse, {user.username}! You are now a registered donor.") return redirect("home") else: - form = UserCreationForm() + form = UserRegisterForm() return render(request, "core/register.html", {"form": form}) def home(request): @@ -276,6 +307,7 @@ def request_blood(request): context = { 'blood_groups': [g[0] for g in BLOOD_GROUPS], 'urgency_levels': BloodRequest.URGENCY_LEVELS, + 'selected_hospital': request.GET.get('hospital', ''), } return render(request, 'core/request_blood.html', context) @@ -355,12 +387,12 @@ def complete_donation(request, event_id): # Notify both Notification.objects.create( user=event.donor_user, - message=f"Thank you for your donation to {event.request.patient_name}! Your feedback is valuable to us." + message=f"Thank you for your donation to {event.request.patient_name}!" ) if event.request.user: Notification.objects.create( user=event.request.user, - message=f"We hope the donation for {event.request.patient_name} went well. Please share your feedback!" + message=f"We hope the donation for {event.request.patient_name} went well." ) messages.success(request, "Donation marked as completed. Thank you!") @@ -369,21 +401,6 @@ def complete_donation(request, event_id): return redirect('home') -@login_required -def submit_feedback(request): - if request.method == "POST": - content = request.POST.get('content') - rating = request.POST.get('rating') - if content: - Feedback.objects.create( - user=request.user, - content=content, - rating=rating if rating else 5 - ) - messages.success(request, "Thank you for your feedback!") - return redirect('home') - return render(request, 'core/feedback.html') - @login_required def notifications_view(request): notifications = Notification.objects.filter(user=request.user).order_by('-created_at')