diff --git a/core/__pycache__/forms.cpython-311.pyc b/core/__pycache__/forms.cpython-311.pyc index 6c37854..73d549c 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 2abb700..84a28fd 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 5f0037b..34e9e1c 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 5fbdbe9..d8c8071 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 7f0ecea..82282c5 100644 --- a/core/forms.py +++ b/core/forms.py @@ -15,14 +15,10 @@ class UserRegisterForm(UserCreationForm): fields = ['username', 'email'] class UserUpdateForm(forms.ModelForm): - email = forms.EmailField() - class Meta: model = User - fields = ['username', 'email', 'first_name', 'last_name'] + fields = ['first_name', 'last_name'] widgets = { - 'username': forms.TextInput(attrs={'class': 'form-control'}), - 'email': forms.EmailInput(attrs={'class': 'form-control'}), 'first_name': forms.TextInput(attrs={'class': 'form-control'}), 'last_name': forms.TextInput(attrs={'class': 'form-control'}), } @@ -30,11 +26,12 @@ class UserUpdateForm(forms.ModelForm): class ProfileUpdateForm(forms.ModelForm): class Meta: model = UserProfile - fields = ['bio', 'location', 'phone', 'blood_group', 'profile_pic'] + fields = ['bio', 'location', 'phone', 'birth_date', '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'}), + 'birth_date': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}), 'blood_group': forms.Select(attrs={'class': 'form-control'}, choices=BLOOD_GROUPS), 'profile_pic': forms.FileInput(attrs={'class': 'form-control'}), } diff --git a/core/migrations/0015_userprofile_last_location_update_and_more.py b/core/migrations/0015_userprofile_last_location_update_and_more.py new file mode 100644 index 0000000..3de02e8 --- /dev/null +++ b/core/migrations/0015_userprofile_last_location_update_and_more.py @@ -0,0 +1,28 @@ +# Generated by Django 5.2.7 on 2026-02-18 13:55 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0014_message'), + ] + + operations = [ + migrations.AddField( + model_name='userprofile', + name='last_location_update', + field=models.DateTimeField(blank=True, null=True), + ), + migrations.AddField( + model_name='userprofile', + name='latitude', + field=models.DecimalField(blank=True, decimal_places=6, max_digits=9, null=True), + ), + migrations.AddField( + model_name='userprofile', + name='longitude', + field=models.DecimalField(blank=True, decimal_places=6, max_digits=9, null=True), + ), + ] diff --git a/core/migrations/0016_badge_userprofile_badges.py b/core/migrations/0016_badge_userprofile_badges.py new file mode 100644 index 0000000..fc3cb71 --- /dev/null +++ b/core/migrations/0016_badge_userprofile_badges.py @@ -0,0 +1,27 @@ +# Generated by Django 5.2.7 on 2026-02-18 14:17 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0015_userprofile_last_location_update_and_more'), + ] + + operations = [ + migrations.CreateModel( + name='Badge', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=50)), + ('description', models.CharField(max_length=255)), + ('icon_class', models.CharField(default='fas fa-medal', max_length=50)), + ], + ), + migrations.AddField( + model_name='userprofile', + name='badges', + field=models.ManyToManyField(blank=True, related_name='users', to='core.badge'), + ), + ] diff --git a/core/migrations/0017_message_attachment_message_message_type_and_more.py b/core/migrations/0017_message_attachment_message_message_type_and_more.py new file mode 100644 index 0000000..4489cab --- /dev/null +++ b/core/migrations/0017_message_attachment_message_message_type_and_more.py @@ -0,0 +1,33 @@ +# Generated by Django 5.2.7 on 2026-02-18 15:03 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0016_badge_userprofile_badges'), + ] + + operations = [ + migrations.AddField( + model_name='message', + name='attachment', + field=models.FileField(blank=True, null=True, upload_to='chat_attachments/'), + ), + migrations.AddField( + model_name='message', + name='message_type', + field=models.CharField(choices=[('text', 'Text'), ('image', 'Image'), ('video', 'Video'), ('file', 'File'), ('sticker', 'Sticker')], default='text', max_length=10), + ), + migrations.AddField( + model_name='message', + name='sticker_id', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='message', + name='content', + field=models.TextField(blank=True, null=True), + ), + ] diff --git a/core/migrations/0018_bloodrequest_image.py b/core/migrations/0018_bloodrequest_image.py new file mode 100644 index 0000000..deb4e44 --- /dev/null +++ b/core/migrations/0018_bloodrequest_image.py @@ -0,0 +1,18 @@ +# Generated by Django 5.2.7 on 2026-02-19 04:30 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0017_message_attachment_message_message_type_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='bloodrequest', + name='image', + field=models.ImageField(blank=True, null=True, upload_to='blood_requests/'), + ), + ] diff --git a/core/migrations/0019_healthreport.py b/core/migrations/0019_healthreport.py new file mode 100644 index 0000000..7ec9bd0 --- /dev/null +++ b/core/migrations/0019_healthreport.py @@ -0,0 +1,32 @@ +# Generated by Django 5.2.7 on 2026-02-19 04:45 + +import django.db.models.deletion +import django.utils.timezone +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0018_bloodrequest_image'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='HealthReport', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=200)), + ('hospital_name', models.CharField(blank=True, max_length=255, null=True)), + ('report_file', models.FileField(upload_to='health_reports/')), + ('description', models.TextField(blank=True, null=True)), + ('report_date', models.DateField(default=django.utils.timezone.now)), + ('next_test_date', models.DateField(blank=True, null=True)), + ('allow_notifications', models.BooleanField(default=False)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='health_reports', to=settings.AUTH_USER_MODEL)), + ], + ), + ] diff --git a/core/migrations/__pycache__/0015_userprofile_last_location_update_and_more.cpython-311.pyc b/core/migrations/__pycache__/0015_userprofile_last_location_update_and_more.cpython-311.pyc new file mode 100644 index 0000000..09409a5 Binary files /dev/null and b/core/migrations/__pycache__/0015_userprofile_last_location_update_and_more.cpython-311.pyc differ diff --git a/core/migrations/__pycache__/0016_badge_userprofile_badges.cpython-311.pyc b/core/migrations/__pycache__/0016_badge_userprofile_badges.cpython-311.pyc new file mode 100644 index 0000000..83b2863 Binary files /dev/null and b/core/migrations/__pycache__/0016_badge_userprofile_badges.cpython-311.pyc differ diff --git a/core/migrations/__pycache__/0017_message_attachment_message_message_type_and_more.cpython-311.pyc b/core/migrations/__pycache__/0017_message_attachment_message_message_type_and_more.cpython-311.pyc new file mode 100644 index 0000000..1c00a37 Binary files /dev/null and b/core/migrations/__pycache__/0017_message_attachment_message_message_type_and_more.cpython-311.pyc differ diff --git a/core/migrations/__pycache__/0018_bloodrequest_image.cpython-311.pyc b/core/migrations/__pycache__/0018_bloodrequest_image.cpython-311.pyc new file mode 100644 index 0000000..89cd3cb Binary files /dev/null and b/core/migrations/__pycache__/0018_bloodrequest_image.cpython-311.pyc differ diff --git a/core/migrations/__pycache__/0019_healthreport.cpython-311.pyc b/core/migrations/__pycache__/0019_healthreport.cpython-311.pyc new file mode 100644 index 0000000..b85f3ca Binary files /dev/null and b/core/migrations/__pycache__/0019_healthreport.cpython-311.pyc differ diff --git a/core/models.py b/core/models.py index 2b82091..e6f9f77 100644 --- a/core/models.py +++ b/core/models.py @@ -11,14 +11,26 @@ BLOOD_GROUPS = [ ('AB+', 'AB+'), ('AB-', 'AB-'), ] +class Badge(models.Model): + name = models.CharField(max_length=50) + description = models.CharField(max_length=255) + icon_class = models.CharField(max_length=50, default='fas fa-medal') # FontAwesome class + + def __str__(self): + return self.name + class UserProfile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile') bio = models.TextField(max_length=500, blank=True) location = models.CharField(max_length=100, blank=True) + 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) + last_location_update = models.DateTimeField(null=True, blank=True) 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) + badges = models.ManyToManyField(Badge, blank=True, related_name='users') def __str__(self): return self.user.username @@ -40,6 +52,8 @@ def sync_donor_profile(sender, instance, **kwargs): 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.latitude = instance.latitude + donor.longitude = instance.longitude donor.phone = instance.phone donor.save() @@ -103,6 +117,7 @@ class BloodRequest(models.Model): 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) contact_number = models.CharField(max_length=20) + image = models.ImageField(upload_to='blood_requests/', null=True, blank=True) required_date = models.DateField(default=timezone.now) status = models.CharField(max_length=20, default='Active') created_at = models.DateTimeField(auto_now_add=True) @@ -150,11 +165,35 @@ class Notification(models.Model): return f"Notification for {self.user.username}: {self.message[:20]}..." class Message(models.Model): + MESSAGE_TYPES = [ + ('text', 'Text'), + ('image', 'Image'), + ('video', 'Video'), + ('file', 'File'), + ('sticker', 'Sticker'), + ] sender = models.ForeignKey(User, on_delete=models.CASCADE, related_name='sent_messages') receiver = models.ForeignKey(User, on_delete=models.CASCADE, related_name='received_messages') - content = models.TextField() + content = models.TextField(blank=True, null=True) + attachment = models.FileField(upload_to='chat_attachments/', blank=True, null=True) + message_type = models.CharField(max_length=10, choices=MESSAGE_TYPES, default='text') + sticker_id = models.CharField(max_length=50, blank=True, null=True) timestamp = models.DateTimeField(auto_now_add=True) is_read = models.BooleanField(default=False) def __str__(self): return f"From {self.sender.username} to {self.receiver.username} at {self.timestamp}" + +class HealthReport(models.Model): + user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='health_reports') + title = models.CharField(max_length=200) + hospital_name = models.CharField(max_length=255, blank=True, null=True) + report_file = models.FileField(upload_to='health_reports/') + description = models.TextField(blank=True, null=True) + report_date = models.DateField(default=timezone.now) + next_test_date = models.DateField(blank=True, null=True) + allow_notifications = models.BooleanField(default=False) + created_at = models.DateTimeField(auto_now_add=True) + + def __str__(self): + return f"Report: {self.title} for {self.user.username}" diff --git a/core/templates/base.html b/core/templates/base.html index 9d11911..b485bca 100644 --- a/core/templates/base.html +++ b/core/templates/base.html @@ -281,6 +281,7 @@
  • {% trans "Vaccination" %}
  • {% if user.is_authenticated %}
  • {% trans "My Records" %}
  • +
  • {% trans "Health Reports" %}
  • {% endif %}
  • {% trans "Settings" %}
  • @@ -511,5 +512,46 @@ {% block scripts %}{% endblock %} + + {% if user.is_authenticated %} + + {% endif %} diff --git a/core/templates/core/blood_request_list.html b/core/templates/core/blood_request_list.html index 8d716ff..5c0aaaa 100644 --- a/core/templates/core/blood_request_list.html +++ b/core/templates/core/blood_request_list.html @@ -47,7 +47,14 @@
    {{ req.patient_name }}
    -

    {{ req.hospital }}

    +

    {{ req.hospital }}

    + + {% if req.image %} +
    + Patient/Prescription +
    + {% endif %} +
    {{ req.created_at|timesince }} ago diff --git a/core/templates/core/chat.html b/core/templates/core/chat.html index 7126ade..d6b7d29 100644 --- a/core/templates/core/chat.html +++ b/core/templates/core/chat.html @@ -128,7 +128,28 @@
    {% for msg in chat_messages %}
    - {{ msg.content }} + {% if msg.message_type == 'text' %} + {{ msg.content }} + {% elif msg.message_type == 'image' %} + + {% if msg.content %}

    {{ msg.content }}

    {% endif %} + {% elif msg.message_type == 'video' %} + + {% if msg.content %}

    {{ msg.content }}

    {% endif %} + {% elif msg.message_type == 'file' %} +
    + +
    + + {{ msg.attachment.name|cut:"chat_attachments/" }} + + {{ msg.attachment.size|filesizeformat }} +
    +
    + {% if msg.content %}

    {{ msg.content }}

    {% endif %} + {% elif msg.message_type == 'sticker' %} +
    {{ msg.sticker_id }}
    + {% endif %} {{ msg.timestamp|date:"g:i a" }} @@ -140,16 +161,86 @@ {% endfor %}
    -
    + {% csrf_token %} - - +
    +
    + +
    + +
    + + + + + + + + + + +
    + + +