From c0bb59aeba378ada66feb5ffcd0a8e5670cd7104 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Wed, 18 Feb 2026 09:21:22 +0000 Subject: [PATCH] RaktaPulse --- config/__pycache__/settings.cpython-311.pyc | Bin 5837 -> 5878 bytes config/settings.py | 1 + .../context_processors.cpython-311.pyc | Bin 763 -> 1263 bytes core/__pycache__/models.cpython-311.pyc | Bin 12014 -> 12941 bytes core/__pycache__/urls.cpython-311.pyc | Bin 2122 -> 2419 bytes core/__pycache__/views.cpython-311.pyc | Bin 26303 -> 29982 bytes core/context_processors.py | 8 + core/migrations/0014_message.py | 27 ++ .../__pycache__/0014_message.cpython-311.pyc | Bin 0 -> 1779 bytes core/models.py | 10 + core/templates/base.html | 14 +- core/templates/core/blood_request_list.html | 5 + core/templates/core/chat.html | 353 ++++++++++++++++++ core/templates/core/donor_list.html | 12 +- core/templates/core/hospital_list.html | 2 +- core/templates/core/inbox.html | 54 +++ core/templates/core/index.html | 18 +- core/templates/core/public_profile.html | 72 ++++ core/urls.py | 5 +- core/views.py | 68 +++- 20 files changed, 639 insertions(+), 10 deletions(-) create mode 100644 core/migrations/0014_message.py create mode 100644 core/migrations/__pycache__/0014_message.cpython-311.pyc create mode 100644 core/templates/core/chat.html create mode 100644 core/templates/core/inbox.html create mode 100644 core/templates/core/public_profile.html diff --git a/config/__pycache__/settings.cpython-311.pyc b/config/__pycache__/settings.cpython-311.pyc index 404de93122d242d1ddaf7e10659a70c6acd600fb..14cf095844b5b3a93419d280508c1401734941d9 100644 GIT binary patch delta 103 zcmX@B`%Ra3IWI340}$NHo|@UTk(ZU5k#({#_x8yPxuy6^^NLavQ{r<|i;EM}Q;RpB x;y%L6xOHo9v delta 83 zcmeySdsdfsIWI340}yOaoto*sk(ZU5k!7+l_x8=7xsNb2ZrQwpe>ICLn=;=A1~|dY dA;R^6lb4n40|SU)=I3Q<;QXMpxkDt62>|ld7cT$+ diff --git a/config/settings.py b/config/settings.py index cd49a45..0e1371a 100644 --- a/config/settings.py +++ b/config/settings.py @@ -86,6 +86,7 @@ TEMPLATES = [ 'django.contrib.messages.context_processors.messages', # IMPORTANT: do not remove – injects PROJECT_DESCRIPTION/PROJECT_IMAGE_URL and cache-busting timestamp 'core.context_processors.project_context', + 'core.context_processors.unread_messages', ], }, }, diff --git a/core/__pycache__/context_processors.cpython-311.pyc b/core/__pycache__/context_processors.cpython-311.pyc index 10556ae831db2cb0f5a23c3a72b9661fea2d4021..db70f1c20f6920edc5c8658a728e54aec70788ae 100644 GIT binary patch delta 709 zcmZWmO=}ZD7=CB=t4W(R7KEZGie2Jf`~gP9Q%@Qx9tyD#*PStL+$1u)D;^5Tp?^R^ z+oL&XrPPc6z=JW+ge>C!1P_H>&!qj7rU2_l;Ahdg4^SY<=BMpFB;S>d5iNj(6%bPn_n+3C2#4YqVUe?8@Lieb5uD zcyvv188>lNip_SH@i0=os`8ck2$WLA`?YizHA%?ti5uu46GfW{xkdSJWooZQRkCt6UHpOuk NWMuomfJuN&1OS;%ElvOc diff --git a/core/__pycache__/models.cpython-311.pyc b/core/__pycache__/models.cpython-311.pyc index 3d8eb6827bc22155101b514a30a14c61c11f0f64..2abb700771b5d689b5b2b2a2fcd7dee8b164f689 100644 GIT binary patch delta 761 zcmZ`#&ui0A9DnKWR`L?Hbk5nDVY@9`DfJ*l&(dnqda%eS?MmBZ(rH_H2|d&w&0$DE zg-Rw&hUjSy?4i0HM44l^2_6y&5_|iahxh&U`Fwak3Qt7%nx=gK zpV?c_s_EcUc!K)o+s9kEp9S}}k2Yhhz5A~i`zs>}xZ)ziQMST>3 zf21hTB62L>$F14BVAQUB<6~Dx|ba;68zm1c(Q8o&aI6d~K5(fmIyRa}3Jp zGwD$0hCzo`<&9?V!QM5E&g*pEpz})7WVlY#V7T@xe?PDl(lRBDDeFwxV9LrR6NWmA z1`O$tGa#p=Og7wg8Em*8*4Tv3CJZ*ATsGk(8JgUPXfUqBxB=rzYTrRQ7pQ%3I9j%e z*$h86@Cr+%y1Fy>j@njh(V*`$u9F9s9&WBg)3%GpJQSfi96O7TZ~q+je*I@+DE1dh Ck<8Zs delta 85 zcmeB8eHY8OoR^o20SGpvPR-1bp2#P`cxj{hMMkz1sbB_8>CGxkJ2aX7G{q*%>+hI+ hM_-cb5Kt{65Eln+{;%)FB*4JV7{K@eOcrSX#Q_d)6{P?G diff --git a/core/__pycache__/urls.cpython-311.pyc b/core/__pycache__/urls.cpython-311.pyc index 116ac3842142db44aca461364847f8c1c3455352..0c55c4376bbf1111b8748e383d08749f94641004 100644 GIT binary patch delta 474 zcmX>l@L5QGIWI340}!NVPtDxH#=!6x#DM`xDC6^#iR$q@xuQ{`xnfabx#Cgc6Wh9( zMNq6A_nr}Cw!fK;lc3QRU&l4KT4(Ey2SrV6EKff(AU!YMjHhOus{ zNQ&MXwq?u=46A_{0@6jJBvSN)88i)Ef&?@fZ?P04mSntS1aU++S20O4O7j(zCgo%% z#}^dkr)B1(-eS$nOUkdf#gd$nIC&y-sFOHULf@viq{ynYIJGD*F*nstzepTtNEI7c zwSJKVh$8~jQ-YyRa`Pi*9Y#jU$^5LvJYZd5)kTt%>sbT1)PNd6&M7`N`6lb*$p&n4 zllQP?SzX{%THtrV((?j~*F_euD=c0&SU4J7IwU5T&M3dYqJEJ@{R)dZSnL9)`~r~` gZWmaLFR~b4VKLsU$S%dmuPw&U)W8jbMJhnk0i%e5$N&HU delta 289 zcmew?bV@*dIWI340}x1uPtE+u%E0g##DM`ZDC4u$MD=(cMg}H^RK^sRROS@c$qJ03 z6E|luvQL&{lw{^e5dsOY3a4_Wh=5t5saz>yV3v3)cZvjv#Vnc1GkF0}HE)UxSVlIL zFGUV4BcCcT`5jP3FhvP0qns*~q5@{ArV6L1fmp`ssUj&FYuJ`CGcc?MVhBhViV{uH z3}(>OdI=KHWW2>vkXVxOk`cra+I)pcl5sK@OYr8!EEkR9HNZ;s>1wC4cs7DqzIG-0D>$!s{jB1 diff --git a/core/__pycache__/views.cpython-311.pyc b/core/__pycache__/views.cpython-311.pyc index 2dedc28399e3445c8f4114dcb2063edaa7e8ebad..51dcfcb02adda23bcc44debaf526274f3d6a060f 100644 GIT binary patch delta 7567 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 CrvWMe delta 4773 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 {% trans "Dashboard" %}
  • {% trans "Donors" %}
  • {% trans "Blood Requests" %}
  • -
  • {% trans "Blood Banks" %}
  • -
  • {% trans "Hospitals" %}
  • +
  • {% trans "Blood Banks" %}
  • +
  • {% trans "Hospitals" %}
  • {% trans "Live Alerts" %}
  • {% trans "Vaccination" %}
  • {% if user.is_authenticated %} @@ -343,6 +343,16 @@ {{ user.notifications.count }} + + + + + {% if unread_messages_count > 0 %} + + {{ unread_messages_count }} + + {% endif %} + {% endfor %} diff --git a/core/templates/core/hospital_list.html b/core/templates/core/hospital_list.html index 8e01635..edf2eb5 100644 --- a/core/templates/core/hospital_list.html +++ b/core/templates/core/hospital_list.html @@ -50,7 +50,7 @@

    {% endif %} - Request Blood Here + Request Blood Here diff --git a/core/templates/core/inbox.html b/core/templates/core/inbox.html new file mode 100644 index 0000000..025d72a --- /dev/null +++ b/core/templates/core/inbox.html @@ -0,0 +1,54 @@ +{% extends "base.html" %} +{% load i18n %} + +{% block title %}Inbox - RaktaPulse{% endblock %} + +{% block content %} + +{% endblock %} diff --git a/core/templates/core/index.html b/core/templates/core/index.html index 378a591..4b4a9c5 100644 --- a/core/templates/core/index.html +++ b/core/templates/core/index.html @@ -257,7 +257,14 @@

    Last Donated: {{ donor.last_donation_date|default:"Never" }}

    - Contact +
    + {% if donor.user %} + + + + {% endif %} + Call +
    {% empty %} @@ -312,7 +319,14 @@

    {{ req.hospital }}

    {{ req.created_at|timesince }} ago - Help Now → +
    + {% if req.user %} + + + + {% endif %} + Help Now → +
    {% empty %} diff --git a/core/templates/core/public_profile.html b/core/templates/core/public_profile.html new file mode 100644 index 0000000..c04758e --- /dev/null +++ b/core/templates/core/public_profile.html @@ -0,0 +1,72 @@ +{% extends "base.html" %} +{% load i18n %} + +{% block title %}{{ profile_user.username }}'s Profile - RaktaPulse{% endblock %} + +{% block content %} +
    +
    +
    +
    +
    +
    + {% if profile.profile_pic %} + {{ profile_user.username }} + {% else %} +
    + +
    + {% endif %} +
    +

    {{ profile_user.first_name }} {{ profile_user.last_name }}

    +

    @{{ profile_user.username }}

    + + {% if donor %} +
    + {{ donor.blood_group }} + {% if donor.is_available %} + Available + {% else %} + Not Available + {% endif %} +
    + {% endif %} +
    + +
    +
    +
    +
    Location
    +

    {{ profile.location|default:"Not specified" }}

    +
    +
    +
    +
    +
    Member Since
    +

    {{ profile_user.date_joined|date:"F Y" }}

    +
    +
    +
    + +
    +
    About
    +
    + {{ profile.bio|default:"No bio provided."|linebreaks }} +
    +
    + +
    + {% if user.is_authenticated and user != profile_user %} + + Send Message + + {% endif %} + + Back to Donors + +
    +
    +
    +
    +
    +{% endblock %} diff --git a/core/urls.py b/core/urls.py index 9d3763d..c1f8813 100644 --- a/core/urls.py +++ b/core/urls.py @@ -6,7 +6,7 @@ from .views import ( vaccination_dashboard, add_vaccination, live_map, request_blood, profile, volunteer_for_request, complete_donation, notifications_view, - register_donor, hospital_list + register_donor, hospital_list, public_profile, inbox, chat ) urlpatterns = [ @@ -15,6 +15,9 @@ urlpatterns = [ path("logout/", logout_view, name="logout"), path("register/", register_view, name="register"), path("profile/", profile, name="profile"), + path("profile//", public_profile, name="public_profile"), + path("inbox/", inbox, name="inbox"), + path("chat//", chat, name="chat"), path("donors/", donor_list, name="donor_list"), path("requests/", blood_request_list, name="blood_request_list"), path("banks/", blood_bank_list, name="blood_bank_list"), diff --git a/core/views.py b/core/views.py index de394c0..f3f8d34 100644 --- a/core/views.py +++ b/core/views.py @@ -1,14 +1,16 @@ import os import platform import math -from django.db import models +from django.db.models import Q from django.shortcuts import render, redirect from django.contrib.auth import login, logout, authenticate 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, Hospital +from django.contrib.auth.models import User +from .models import Donor, BloodRequest, BloodBank, VaccineRecord, UserProfile, BLOOD_GROUPS, DonationEvent, Notification, Hospital, Message + from .forms import UserUpdateForm, ProfileUpdateForm, UserRegisterForm def hospital_list(request): @@ -171,7 +173,7 @@ def home(request): if request.user.is_authenticated: # Get active involvements (where user is donor or requester) involved_events = DonationEvent.objects.filter( - (models.Q(donor_user=request.user) | models.Q(request__user=request.user)), + (Q(donor_user=request.user) | Q(request__user=request.user)), is_completed=False ) context["involved_events"] = involved_events @@ -434,3 +436,63 @@ def register_donor(request): messages.error(request, "Please fill in all required fields.") return render(request, 'core/register_donor.html', {'blood_groups': [g[0] for g in BLOOD_GROUPS]}) + +def public_profile(request, username): + user = User.objects.get(username=username) + profile = user.profile + donor_profile = getattr(user, 'donor_profile', None) + + context = { + 'profile_user': user, + 'profile': profile, + 'donor': donor_profile, + } + return render(request, 'core/public_profile.html', context) + +@login_required +def inbox(request): + # Get all users the current user has messaged or received messages from + sent_to = Message.objects.filter(sender=request.user).values_list('receiver', flat=True) + received_from = Message.objects.filter(receiver=request.user).values_list('sender', flat=True) + user_ids = set(list(sent_to) + list(received_from)) + + users = User.objects.filter(id__in=user_ids) + + # Get last message for each conversation + conversations = [] + for user in users: + last_message = Message.objects.filter( + (Q(sender=request.user) & Q(receiver=user)) | + (Q(sender=user) & Q(receiver=request.user)) + ).order_by('-timestamp').first() + conversations.append({ + 'user': user, + 'last_message': last_message + }) + + conversations.sort(key=lambda x: x['last_message'].timestamp, reverse=True) + + return render(request, 'core/inbox.html', {'conversations': conversations}) + +@login_required +def chat(request, username): + other_user = User.objects.get(username=username) + if request.method == "POST": + content = request.POST.get('content') + if content: + Message.objects.create( + sender=request.user, + receiver=other_user, + content=content + ) + return redirect('chat', username=username) + + messages = Message.objects.filter( + (Q(sender=request.user) & Q(receiver=other_user)) | + (Q(sender=other_user) & Q(receiver=request.user)) + ).order_by('timestamp') + + # Mark as read + Message.objects.filter(sender=other_user, receiver=request.user, is_read=False).update(is_read=True) + + return render(request, 'core/chat.html', {'other_user': other_user, 'chat_messages': messages})