diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..560d4b3 Binary files /dev/null and b/.DS_Store differ diff --git a/.gitignore b/.gitignore index 82f9275..6e23736 100644 --- a/.gitignore +++ b/.gitignore @@ -160,3 +160,4 @@ cython_debug/ # and can be added to the global gitignore or merged into this file. For a more nuclear # option (not recommended) you can uncomment the following to ignore the entire idea folder. #.idea/ +media diff --git a/HospitalSystem/.DS_Store b/HospitalSystem/.DS_Store new file mode 100644 index 0000000..a3484f9 Binary files /dev/null and b/HospitalSystem/.DS_Store differ diff --git a/HospitalSystem/HospitalSystem/__init__.py b/HospitalSystem/HospitalSystem/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/HospitalSystem/HospitalSystem/asgi.py b/HospitalSystem/HospitalSystem/asgi.py new file mode 100644 index 0000000..62e90f2 --- /dev/null +++ b/HospitalSystem/HospitalSystem/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for HospitalSystem project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/4.2/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'HospitalSystem.settings') + +application = get_asgi_application() diff --git a/HospitalSystem/HospitalSystem/settings.py b/HospitalSystem/HospitalSystem/settings.py new file mode 100644 index 0000000..4333a7b --- /dev/null +++ b/HospitalSystem/HospitalSystem/settings.py @@ -0,0 +1,158 @@ +""" +Django settings for HospitalSystem project. + +Generated by 'django-admin startproject' using Django 4.2.14. + +For more information on this file, see +https://docs.djangoproject.com/en/4.2/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/4.2/ref/settings/ +""" + +from pathlib import Path +import os +from dotenv import load_dotenv # to import env file +load_dotenv() + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = os.environ.get("SECRET_KEY") + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = [] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + "django_browser_reload", + 'main', + 'account', + 'clinic', + 'doctor', + 'appointment', + 'patientSummary', + + +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', + "django_browser_reload.middleware.BrowserReloadMiddleware", +] + +ROOT_URLCONF = 'HospitalSystem.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'HospitalSystem.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/4.2/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.postgresql', + 'NAME': 'hospital_db',# write the name of the DB you created + 'USER': 'postgres', + 'PASSWORD': '', + 'HOST': 'localhost' + + } +} +# 'default': { +# 'ENGINE': 'django.db.backends.sqlite3', +# 'NAME': BASE_DIR / 'db.sqlite3', +# } +# } + + + +# Password validation +# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/4.2/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/4.2/howto/static-files/ + +STATIC_URL = 'static/' + + +# Default primary key field type +# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + + +MEDIA_URL = '/media/' +MEDIA_ROOT = os.path.join(BASE_DIR, 'media') + +EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' +EMAIL_HOST = 'smtp.gmail.com' +EMAIL_PORT =587 +EMAIL_USE_TLS =True +EMAIL_HOST_USER = os.environ.get("EMAIL_HOST_USER") +EMAIL_HOST_PASSWORD = os.environ.get("EMAIL_HOST_PASSWORD") diff --git a/HospitalSystem/HospitalSystem/urls.py b/HospitalSystem/HospitalSystem/urls.py new file mode 100644 index 0000000..9c13d43 --- /dev/null +++ b/HospitalSystem/HospitalSystem/urls.py @@ -0,0 +1,31 @@ +""" +URL configuration for HospitalSystem project. + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/4.2/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +from django.urls import path, include +from django.conf.urls.static import static +from . import settings + +urlpatterns = [ + path('admin/', admin.site.urls), + path("__reload__/", include("django_browser_reload.urls")), + path("", include("main.urls")), + path("account/", include("account.urls")), + path("clinic/", include("clinic.urls")), + path("doctor/", include("doctor.urls")), + path("patientSummary/", include("patientSummary.urls")), + path("appointment/", include("appointment.urls")), +] + static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT) diff --git a/HospitalSystem/HospitalSystem/wsgi.py b/HospitalSystem/HospitalSystem/wsgi.py new file mode 100644 index 0000000..fa09618 --- /dev/null +++ b/HospitalSystem/HospitalSystem/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for HospitalSystem project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/4.2/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'HospitalSystem.settings') + +application = get_wsgi_application() diff --git a/HospitalSystem/account/__init__.py b/HospitalSystem/account/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/HospitalSystem/account/admin.py b/HospitalSystem/account/admin.py new file mode 100644 index 0000000..4fb6afd --- /dev/null +++ b/HospitalSystem/account/admin.py @@ -0,0 +1,9 @@ +from django.contrib import admin +from .models import Profile + + +class ProfileAdmin(admin.ModelAdmin): + list_display=("user","phone","avatar") + + +admin.site.register(Profile,ProfileAdmin) \ No newline at end of file diff --git a/HospitalSystem/account/apps.py b/HospitalSystem/account/apps.py new file mode 100644 index 0000000..2b08f1a --- /dev/null +++ b/HospitalSystem/account/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class AccountConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'account' diff --git a/HospitalSystem/account/migrations/0001_initial.py b/HospitalSystem/account/migrations/0001_initial.py new file mode 100644 index 0000000..21a1098 --- /dev/null +++ b/HospitalSystem/account/migrations/0001_initial.py @@ -0,0 +1,31 @@ +# Generated by Django 4.2.14 on 2024-08-06 14:49 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Profile', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('first_name', models.CharField(max_length=50)), + ('last_name', models.CharField(max_length=50)), + ('age', models.IntegerField()), + ('hight', models.DecimalField(decimal_places=2, max_digits=5)), + ('wight', models.DecimalField(decimal_places=2, max_digits=5)), + ('phone', models.CharField(blank=True)), + ('avatar', models.ImageField(default='images/defaultAvatar.png', upload_to='images/avatars/')), + ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + ] diff --git a/HospitalSystem/account/migrations/__init__.py b/HospitalSystem/account/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/HospitalSystem/account/models.py b/HospitalSystem/account/models.py new file mode 100644 index 0000000..d427b9f --- /dev/null +++ b/HospitalSystem/account/models.py @@ -0,0 +1,16 @@ +from django.db import models +from django.contrib.auth.models import User + +class Profile(models.Model): + user = models.OneToOneField(User, on_delete=models.CASCADE) + first_name = models.CharField(max_length=50) + last_name = models.CharField(max_length=50) + age = models.IntegerField() + hight = models.DecimalField(max_digits=5, decimal_places=2) + wight = models.DecimalField(max_digits=5, decimal_places=2) + phone = models.CharField(blank=True) + avatar = models.ImageField(upload_to="images/avatars/", default="images/defaultAvatar.png") + + + def __str__(self) -> str: + return self.first_name \ No newline at end of file diff --git a/HospitalSystem/account/templates/addProfile.html b/HospitalSystem/account/templates/addProfile.html new file mode 100644 index 0000000..bf19f80 --- /dev/null +++ b/HospitalSystem/account/templates/addProfile.html @@ -0,0 +1,140 @@ +{% extends 'base.html' %} + +{% block title %} Profile {% endblock %} + +{% block content %} +{% if request.user.is_authenticated %} +
+
+{% csrf_token %} +
+
+
+

Complete Your Profile

+

Add your Personal Data For Better Experience

+
+
+
+

Personal Details

+
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + + +
+
+
+
+ +
+ +
+ +
+
+
+
+ +{%endif%} +{% if messages %} +{% for message in messages %} + + {% endfor %} + {% endif %} +{% endblock %} \ No newline at end of file diff --git a/HospitalSystem/account/templates/logIn.html b/HospitalSystem/account/templates/logIn.html new file mode 100644 index 0000000..2a5329a --- /dev/null +++ b/HospitalSystem/account/templates/logIn.html @@ -0,0 +1,89 @@ +{% extends 'base.html' %} + +{% block title %} Log In {% endblock %} + +{% block content %} +
+ {% csrf_token %} +
+ + +
+
+ + +
+
+
+ +
+
+ +
+{% if messages %} +{% for message in messages %} + +{% endfor %} {% endif %} +{% endblock%} + + + + + + diff --git a/HospitalSystem/account/templates/mail/welcoming.html b/HospitalSystem/account/templates/mail/welcoming.html new file mode 100644 index 0000000..eace5c8 --- /dev/null +++ b/HospitalSystem/account/templates/mail/welcoming.html @@ -0,0 +1,11 @@ + + + + + + Document + + +

Welcome {{userName.username}} you have been registered successfully.

+ + \ No newline at end of file diff --git a/HospitalSystem/account/templates/profile.html b/HospitalSystem/account/templates/profile.html new file mode 100644 index 0000000..cd7bab9 --- /dev/null +++ b/HospitalSystem/account/templates/profile.html @@ -0,0 +1,133 @@ +{% extends 'base.html' %} + +{% block title %} Profile {% endblock %} + +{% block content %} +{% if request.user.is_authenticated %} +
+ cover-image +
+
+ {% if profile.avatar %} + user-avatar-image + {% else %} + user-avatar-image + {% endif %} +
+
+
    + + +
+
+ +
+
+

{{request.user.username}}

+

{{profile.first_name}} {{profile.last_name}}

+ +
+
+
+
+

Profile Details

+
+
+ +

{{profile.first_name}}

+
+
+ +

{{profile.last_name}}

+
+
+
+
+ +

{{user.username}}

+
+
+ +

{{user.email}}

+
+
+
+
+ +

{{profile.phone}}

+
+
+ +

{{profile.age}}

+
+
+
+
+ +

{{profile.hight}} cm

+
+
+ +

{{profile.wight}} kg

+
+
+
+
+
+
+
+ + +{%endif%} +{% if messages %} +{% for message in messages %} + + {% endfor %} + {% endif %} +{% endblock %} \ No newline at end of file diff --git a/HospitalSystem/account/templates/signUp.html b/HospitalSystem/account/templates/signUp.html new file mode 100644 index 0000000..a5f674f --- /dev/null +++ b/HospitalSystem/account/templates/signUp.html @@ -0,0 +1,152 @@ +{% extends 'base.html' %} {% block title %} Log In {% endblock %} +{% block content %} +
+
+ {% csrf_token %} +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ +
+
+ +
+
+ + +{% if messages %} +{% for message in messages %} + +{% endfor %} {% endif %}{% endblock%} diff --git a/HospitalSystem/account/tests.py b/HospitalSystem/account/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/HospitalSystem/account/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/HospitalSystem/account/urls.py b/HospitalSystem/account/urls.py new file mode 100644 index 0000000..b3ad3be --- /dev/null +++ b/HospitalSystem/account/urls.py @@ -0,0 +1,11 @@ +from django.urls import path +from . import views + +app_name = "account" +urlpatterns = [ + path('signup/', views.sign_up, name="sign_up"), + path('login/', views.log_in, name="log_in"), + path('logout/', views.log_out, name="log_out"), + path('profile//',views.profile_view, name="profile_view"), + path('addProfile//',views.create_profile_view, name="create_profile_view") +] \ No newline at end of file diff --git a/HospitalSystem/account/views.py b/HospitalSystem/account/views.py new file mode 100644 index 0000000..0fa2f0b --- /dev/null +++ b/HospitalSystem/account/views.py @@ -0,0 +1,116 @@ +from django.shortcuts import render, redirect, get_object_or_404 +from django.http import HttpRequest +from django.contrib.auth.models import User +from django.contrib.auth import authenticate, login, logout +from django.contrib import messages +from django.core.mail import EmailMessage +from django.conf import settings +from django.template.loader import render_to_string +from django.contrib.auth.decorators import login_required +from django.db import IntegrityError +from .models import Profile + +def sign_up (request: HttpRequest): + + if request.method == "POST": + + username = request.POST["username"] + email = request.POST["email"] + password = request.POST.get('password') + repeat_password = request.POST.get('repeat_password') + + if password != repeat_password: + messages.error(request, 'Passwords do not match!') + return render(request, 'signUp.html') + # Check if user already exists + if User.objects.filter(username=username).exists(): + messages.error(request, "A user with that username already exists.", "alert-danger") + return render(request, "signUp.html") + + if User.objects.filter(email=email).exists(): + messages.error(request, "A user with that email already exists.", "alert-danger") + return render(request, "signUp.html") + + if request.method == "POST": + try: + new_user = User.objects.create_user(username = request.POST["username"], password=request.POST["password"], email=request.POST["email"]) + new_user.save() + messages.success(request, "You have been Registered Successfully", "alert-success") + #send confirmation email + content_html = render_to_string("mail/welcoming.html",{"userName":new_user}) #set email + send_to = new_user.email + email_message = EmailMessage("welcoming", content_html, settings.EMAIL_HOST_USER, [send_to]) + email_message.content_subtype = "html" + #email_message.connection = email_message.get_connection(True) + email_message.send() + return redirect("account:log_in") + except IntegrityError: + messages.error(request, "An error occurred during registration.", "alert-danger") + except Exception as e: + messages.error(request, f"An unexpected error occurred: {str(e)}", "alert-danger") + return render(request, "signUp.html") + + + +def log_in(request: HttpRequest): + + if request.method == "POST": + #checking user credentials + user = authenticate(request, username=request.POST["username"], password=request.POST["password"]) + print(user) + if user: + #login the user + login(request, user) + messages.success(request, "You are Logged in successfully", "alert-success") + return redirect(request.GET.get("next", "/")) + else: + messages.error(request, "Please try again. You credentials are wrong", "alert-danger") + return render(request, 'logIn.html') + + +def log_out(request:HttpRequest): + logout(request) + messages.success(request, "You are logged out successfully", "alert-warning") + + return redirect(request.GET.get("next", "/")) + +@login_required(login_url="account:log_in") +def profile_view(request:HttpRequest, user_name): + try: + user = User.objects.get(username=user_name) + profile = Profile.objects.filter(user=user).first() + + if not profile: + # Redirect to create_profile_view if profile doesn't exist + return redirect('account:create_profile_view', user_name=user_name) + + except Exception as e: + print(f"An error occurred: {e}") + return render(request, "404.html") + return render(request, "profile.html", {'profile': profile}) + +@login_required(login_url="account:log_in") +def create_profile_view(request:HttpRequest, user_name): + user = get_object_or_404(User, username=user_name) + + if request.method == "POST": + try: + new_profile = Profile( + user=user, # Associate the profile with the user + first_name=request.POST["first_name"], + last_name=request.POST["last_name"], + age=request.POST["age"], + hight=request.POST["hight"], + wight=request.POST["wight"], + phone=request.POST["phone"] + ) + if 'avatar' in request.FILES: + new_profile.avatar = request.FILES["avatar"] + new_profile.save() + messages.success(request, "Profile Created Successfully") + return redirect('account:profile_view', user_name=user_name) + except IntegrityError: + messages.error(request, "An error occurred during Creating profile.", "alert-danger") + except Exception as e: + messages.error(request, f"An unexpected error occurred: {str(e)}", "alert-danger") + return render(request,"addProfile.html", {'user': user}) \ No newline at end of file diff --git a/HospitalSystem/appointment/__init__.py b/HospitalSystem/appointment/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/HospitalSystem/appointment/admin.py b/HospitalSystem/appointment/admin.py new file mode 100644 index 0000000..6e7e291 --- /dev/null +++ b/HospitalSystem/appointment/admin.py @@ -0,0 +1,10 @@ +from django.contrib import admin +from .models import Appointment + + +class AppointmentAdmin(admin.ModelAdmin): + + list_display = ("user", "doctor", "clinic","date","time_slot","created_at") + + +admin.site.register(Appointment,AppointmentAdmin) \ No newline at end of file diff --git a/HospitalSystem/appointment/apps.py b/HospitalSystem/appointment/apps.py new file mode 100644 index 0000000..7b5e362 --- /dev/null +++ b/HospitalSystem/appointment/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class AppointmentConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'appointment' diff --git a/HospitalSystem/appointment/migrations/0001_initial.py b/HospitalSystem/appointment/migrations/0001_initial.py new file mode 100644 index 0000000..ee13c2c --- /dev/null +++ b/HospitalSystem/appointment/migrations/0001_initial.py @@ -0,0 +1,30 @@ +# Generated by Django 4.2.14 on 2024-08-06 14:49 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('doctor', '0001_initial'), + ('clinic', '0001_initial'), + ('account', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='Appointment', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('date', models.DateField()), + ('time_slot', models.TimeField()), + ('created_at', models.DateField(auto_now_add=True)), + ('clinic', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='appointment', to='clinic.clinic')), + ('doctor', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='appointment', to='doctor.doctor')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='appointment', to='account.profile')), + ], + ), + ] diff --git a/HospitalSystem/appointment/migrations/__init__.py b/HospitalSystem/appointment/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/HospitalSystem/appointment/models.py b/HospitalSystem/appointment/models.py new file mode 100644 index 0000000..c1fbaf5 --- /dev/null +++ b/HospitalSystem/appointment/models.py @@ -0,0 +1,17 @@ +from django.db import models +from account.models import Profile +from doctor.models import Doctor +from clinic.models import Clinic + + +class Appointment(models.Model): + + user= models.ForeignKey(Profile, on_delete=models.CASCADE ,related_name='appointment') + doctor= models.ForeignKey(Doctor, on_delete=models.CASCADE ,related_name='appointment') + clinic= models.ForeignKey(Clinic, on_delete=models.CASCADE ,related_name='appointment') + date= models.DateField(auto_now_add=False) + time_slot= models.TimeField() + created_at= models.DateField(auto_now_add=True) + + def __str__ (self): + return f"{self.user.first_name} in Clinic ({self.clinic.name}) with Doctor {self.doctor.name} date{self.date} " \ No newline at end of file diff --git a/HospitalSystem/appointment/templates/addAppointment.html b/HospitalSystem/appointment/templates/addAppointment.html new file mode 100644 index 0000000..96ea425 --- /dev/null +++ b/HospitalSystem/appointment/templates/addAppointment.html @@ -0,0 +1,129 @@ +{% extends 'dashBase.html' %} + +{% block title %} Add Appointment {% endblock %} + +{% block content %} +
+
+{% csrf_token %} +
+
+
+

Add New Appointment

+
+
+

Fill The Appointment Details

+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+
+ +
+
+ +
+ +
+
+
+ + +
+
+
+ +
+
+
+
+ +
+
+{% if messages %} +{% for message in messages %} + + {% endfor %} + {% endif %} +{% endblock%} diff --git a/HospitalSystem/appointment/templates/allAppointment.html b/HospitalSystem/appointment/templates/allAppointment.html new file mode 100644 index 0000000..fdf1ba4 --- /dev/null +++ b/HospitalSystem/appointment/templates/allAppointment.html @@ -0,0 +1,251 @@ +{% extends 'dashBase.html' %} + +{% block title %} Appointments {% endblock %} + +{% block content %} +
+
+
+
+
+
+ +
+
+ +
+ +
+
+
+
+ + + Add appointment + +
+ + +
+
+
+
+ + + + + + + + + + + + + + {%for appointment in appointments%} + + + + + + + + + + + + + + {%endfor%} + +
Patient NameClinicDoctorDateTimeDateCreated + Actions
{{appointment.user.first_name}} {{appointment.user.last_name}}{{appointment.clinic}}{{appointment.doctor}}{{appointment.date}}{{appointment.time_slot}}{{appointment.created_at}} + + +
+
+ +
+
+
+ {% if messages %} +{% for message in messages %} + + {% endfor %} + {% endif %} +{% endblock%} \ No newline at end of file diff --git a/HospitalSystem/appointment/templates/mail/confirmation.html b/HospitalSystem/appointment/templates/mail/confirmation.html new file mode 100644 index 0000000..ba71d62 --- /dev/null +++ b/HospitalSystem/appointment/templates/mail/confirmation.html @@ -0,0 +1,12 @@ + + + + + + Document + + +

Thank you for choosing our Services 👍🏻

+

You reserver appointment with Doctor {{appointment.doctor}} in {{appointment.clinic}} clinic, at {{appointment.date}} time {{appointment.time_slot}}.

+ + \ No newline at end of file diff --git a/HospitalSystem/appointment/templates/myAppointment.html b/HospitalSystem/appointment/templates/myAppointment.html new file mode 100644 index 0000000..e6b52e8 --- /dev/null +++ b/HospitalSystem/appointment/templates/myAppointment.html @@ -0,0 +1,104 @@ +{% extends 'dashBase.html' %} + +{% block title %} Appointment Details {% endblock %} + +{% block content %} +
+
+
+
+
+
+ + + + + + + + + + + + + + {%for appointment in appointments%} + + + + + + + + + + {%endfor%} + +
Patient NameClinicDoctorDateTimeDateCreated + Actions
{{appointment.user.first_name}} {{appointment.user.last_name}}{{appointment.clinic}}{{appointment.doctor}}{{appointment.date}}{{appointment.time_slot}}{{appointment.created_at}} + + +
+
+ +
+
+
+{% endblock%} \ No newline at end of file diff --git a/HospitalSystem/appointment/tests.py b/HospitalSystem/appointment/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/HospitalSystem/appointment/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/HospitalSystem/appointment/urls.py b/HospitalSystem/appointment/urls.py new file mode 100644 index 0000000..a235fd4 --- /dev/null +++ b/HospitalSystem/appointment/urls.py @@ -0,0 +1,10 @@ +from django.urls import path +from . import views + +app_name = "appointment" +urlpatterns = [ + path("allAppointment/", views.all_appointment_view, name="all_appointment_view"), + path("addAppointment/", views.add_appointment_view, name="add_appointment_view"), + path("myAppointment/", views.my_appointment_view, name="my_appointment_view"), + path("deleteAppointment/", views.delete_appointment_view, name="delete_appointment_view"), +] \ No newline at end of file diff --git a/HospitalSystem/appointment/views.py b/HospitalSystem/appointment/views.py new file mode 100644 index 0000000..53bea42 --- /dev/null +++ b/HospitalSystem/appointment/views.py @@ -0,0 +1,95 @@ +from django.shortcuts import render, redirect, get_object_or_404 +from django.http import HttpRequest +from django.contrib.auth import authenticate +from django.contrib import messages +from django.core.mail import EmailMessage +from django.conf import settings +from django.template.loader import render_to_string +from django.contrib.auth.decorators import login_required +from clinic.models import Clinic +from doctor.models import Doctor +from appointment.models import Appointment +from account.models import Profile +from patientSummary.models import PatientSummary +from django.contrib.auth.models import User +from datetime import datetime + + + + +@login_required(login_url="account:log_in") +def all_appointment_view(request: HttpRequest): + if not request.user.is_staff: + messages.error(request,"Only registered users can access") + return redirect("account:log_in") + else: + appointment = Appointment.objects.all() + + return render(request, "allAppointment.html", {"appointments":appointment}) +@login_required(login_url="account:log_in") + +def my_appointment_view(request: HttpRequest, user_username): + user = get_object_or_404(User, username=user_username) + profile = get_object_or_404(Profile, user=user) + appointments = Appointment.objects.filter(user=profile).prefetch_related('appointment') + context = { + "appointments": appointments, + } + return render(request, "myAppointment.html", context) + +@login_required(login_url="account:log_in") +def add_appointment_view(request: HttpRequest): + doctors = Doctor.objects.all() + clinics = Clinic.objects.all() + users = Profile.objects.all() + if not request.user.is_staff: + messages.error(request,"Only registered users can access") + return redirect("account:log_in") + if request.method == "POST": + try: + user = Profile.objects.get(id=request.POST['user']) + doctor = Doctor.objects.get(id=request.POST['doctor']) + clinic = Clinic.objects.get(id=request.POST['clinic']) + date = datetime.strptime(request.POST['date'], '%Y-%m-%d' ).date() + time_slot = datetime.strptime(request.POST['time_slot'], '%H:%M').time() + + new_appointment = Appointment( + user=user, + doctor=doctor, + clinic=clinic, + date=date, + time_slot=time_slot, + ) + new_appointment.save() + content_html = render_to_string("mail/confirmation.html",{"appointment":new_appointment}) + send_to = new_appointment.user.user.email + email_message = EmailMessage("Appointment Confirmation", content_html, settings.EMAIL_HOST_USER, [send_to]) + email_message.content_subtype = "html" + email_message.send() + + messages.success(request, "Appointment has been Added Successfully") + return redirect("appointment:all_appointment_view") + except Exception as e: + messages.error(request, f"An unexpected error occurred: {str(e)}") + + context = { + 'doctors': doctors, + 'clinics': clinics, + 'users': users, + } + return render(request, "addAppointment.html", context) + +@login_required(login_url="account:log_in") +def delete_appointment_view(request:HttpRequest, appointment_id): + if not request.user.is_staff: + messages.error(request,"Only registered users can delete") + return redirect("account:log_in") + try: + appointment = Appointment.objects.get(id=appointment_id) # implement feedback messages + appointment.delete() + messages.success(request, "Appointment has been Deleted successfully", "alert-success") + except Exception as e: + print(e) + messages.error(request, "Couldn't Delete Appointment", "alert-danger") + + return redirect("appointment:all_appointment_view") diff --git a/HospitalSystem/clinic/__init__.py b/HospitalSystem/clinic/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/HospitalSystem/clinic/admin.py b/HospitalSystem/clinic/admin.py new file mode 100644 index 0000000..35bfc0d --- /dev/null +++ b/HospitalSystem/clinic/admin.py @@ -0,0 +1,4 @@ +from django.contrib import admin +from .models import Clinic + +admin.site.register(Clinic) diff --git a/HospitalSystem/clinic/apps.py b/HospitalSystem/clinic/apps.py new file mode 100644 index 0000000..bc7ab8a --- /dev/null +++ b/HospitalSystem/clinic/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class ClinicConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'clinic' diff --git a/HospitalSystem/clinic/migrations/0001_initial.py b/HospitalSystem/clinic/migrations/0001_initial.py new file mode 100644 index 0000000..4213b70 --- /dev/null +++ b/HospitalSystem/clinic/migrations/0001_initial.py @@ -0,0 +1,26 @@ +# Generated by Django 4.2.14 on 2024-08-06 14:49 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('doctor', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='Clinic', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255)), + ('description', models.TextField()), + ('working_hours', models.CharField(choices=[('SunThu', 'Sunday - Thursday'), ('All', 'All Week'), ('MonFri', 'Monday - Friday')], default='SunThu', max_length=50)), + ('feature_image', models.ImageField(default='images/default.jpg', upload_to='images/')), + ('doctors_id', models.ManyToManyField(related_name='products', to='doctor.doctor')), + ], + ), + ] diff --git a/HospitalSystem/clinic/migrations/__init__.py b/HospitalSystem/clinic/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/HospitalSystem/clinic/models.py b/HospitalSystem/clinic/models.py new file mode 100644 index 0000000..c2358fa --- /dev/null +++ b/HospitalSystem/clinic/models.py @@ -0,0 +1,18 @@ +from django.db import models +from doctor.models import Doctor + + +class Clinic(models.Model): + class WorkingHours(models.TextChoices): + SunThu = 'SunThu', "Sunday - Thursday" + All = "All", "All Week" + MonFri = "MonFri", "Monday - Friday" + + name= models.CharField(max_length=255) + description= models.TextField() + working_hours= models.CharField(max_length=50, choices=WorkingHours.choices, default=WorkingHours.SunThu) + feature_image=models.ImageField(upload_to="images/", default="images/default.jpg") + doctors_id = models.ManyToManyField(Doctor, related_name='doctor') + + def __str__(self) -> str: + return self.name \ No newline at end of file diff --git a/HospitalSystem/clinic/templates/addClinic.html b/HospitalSystem/clinic/templates/addClinic.html new file mode 100644 index 0000000..eb1625f --- /dev/null +++ b/HospitalSystem/clinic/templates/addClinic.html @@ -0,0 +1,131 @@ +{% extends 'dashBase.html' %} + +{% block title %} Add Clinic {% endblock %} + +{% block content %} +{% if request.user.is_authenticated %} +
+
+{% csrf_token %} +
+
+
+

Add New Clinic

+
+
+
+

Clinic Details

+
+
+ + +
+ +
+
+
+ + +
+
+
+
+ + +
+
+ + +
+
+
+
+
+ +
+ +
+
+
+
+ +{%endif%} +{% if messages %} +{% for message in messages %} + + {% endfor %} + {% endif %} +{% endblock%} \ No newline at end of file diff --git a/HospitalSystem/clinic/templates/allClinic.html b/HospitalSystem/clinic/templates/allClinic.html new file mode 100644 index 0000000..aa6cc4c --- /dev/null +++ b/HospitalSystem/clinic/templates/allClinic.html @@ -0,0 +1,27 @@ +{% extends 'dashBase.html' %} + +{% block title %} Available Clinics {% endblock %} + +{% block content %} +
+
+

Our latest blog

+
+ {% for clinic in clinics %} +
+
+ {{clinic.name}} +
+
+ {{clinic.get_working_hours_display}} +

{{clinic.name}}

+

{{clinic.description}}

+ More Details.. +
+
+ {% endfor %} +
+
+
+ +{% endblock%} diff --git a/HospitalSystem/clinic/templates/clinicDetails.html b/HospitalSystem/clinic/templates/clinicDetails.html new file mode 100644 index 0000000..f1bd143 --- /dev/null +++ b/HospitalSystem/clinic/templates/clinicDetails.html @@ -0,0 +1,94 @@ +{% extends 'dashBase.html' %} + +{% block title %} Available Clinics {% endblock %} + +{% block content %} +
+
+
+
+ +
+
+

+ {{clinic.name}} +

+
+
+

+ Work Day: {{clinic.get_working_hours_display}} +

+ +
+
+ + + +
+ About Clinic +

+ {{clinic.description}} +

+
+ Doctors +

+ {% for doctor in clinic.doctors_id.all %} + {{ doctor.get_full_name }} {% if doctor.specialization %} {{ doctor.specialization }}{% endif %} + {% endfor %} +

+
+
+
+
+ +{% endblock%} diff --git a/HospitalSystem/clinic/tests.py b/HospitalSystem/clinic/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/HospitalSystem/clinic/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/HospitalSystem/clinic/urls.py b/HospitalSystem/clinic/urls.py new file mode 100644 index 0000000..a080811 --- /dev/null +++ b/HospitalSystem/clinic/urls.py @@ -0,0 +1,10 @@ +from django.urls import path +from . import views + +app_name = "clinic" + +urlpatterns = [ + path("allClinics/", views.all_clinics_view, name="all_clinics_view"), + path("addClinics/", views.add_clinics_view, name="add_clinics_view"), + path("clinicDetail/", views.details_clinics_view, name="details_clinics_view"), +] \ No newline at end of file diff --git a/HospitalSystem/clinic/views.py b/HospitalSystem/clinic/views.py new file mode 100644 index 0000000..884b2fd --- /dev/null +++ b/HospitalSystem/clinic/views.py @@ -0,0 +1,73 @@ +from django.shortcuts import render, redirect +from django.http import HttpRequest +from django.contrib.auth import authenticate +from django.contrib import messages +from django.contrib.auth.decorators import login_required +from clinic.models import Clinic +from doctor.models import Doctor + + + +@login_required(login_url="account:log_in") +def all_clinics_view(request: HttpRequest): + clinic = Clinic.objects.prefetch_related('doctors_id').all() + + return render(request, "allClinic.html", {"clinics":clinic}) +@login_required(login_url="account:log_in") +def details_clinics_view(request: HttpRequest, clinic_id): + # clini_details = Clinic.objects.get(id=clinic_id) + clinic = Clinic.objects.get(id=clinic_id) + + return render(request, "clinicDetails.html", {"clinic":clinic}) + +@login_required(login_url="account:log_in") +def add_clinics_view(request:HttpRequest): + doctors = Doctor.objects.all() + working_hours_choices = Clinic.WorkingHours.choices + if request.method == "POST": + name = request.POST["name"] + if Clinic.objects.filter(name=name).exists(): + messages.error(request, "A Clinic with this name already exists.", "alert-danger") + else: + try: + new_clinic = Clinic( + name=request.POST['name'], + description=request.POST['description'], + working_hours=request.POST['working_hours'], + feature_image=request.FILES['feature_image'] + ) + new_clinic.save() + + # Add selected doctors to the clinic + doctor_ids = request.POST.getlist('doctors') + new_clinic.doctors_id.set(doctor_ids) + messages.success(request, "Clinic has been Added Successfully", "alert-success") + except Exception as e: + messages.error(request, f"An unexpected error occurred: {str(e)}", "alert-danger") + context = { + 'doctors': doctors, + 'working_hours_choices': working_hours_choices, + } + return render(request, "addClinic.html", context) + +# def add_products_view(request: HttpRequest): + if not request.user.is_authenticated: + messages.error(request,"Only registered users can access") + return redirect("account:sign_in") + products = Product.objects.all() + category = Category.objects.all() + allSuppliers = Supplier.objects.all() + if request.method == "POST": + category_id = request.POST['category'] + category_instance = Category.objects.get(id=category_id) + new_product = Product(name=request.POST['name'], + description=request.POST['description'], + price=request.POST['price'], + category= category_instance, + image= request.FILES['image']) + new_product.save() + supplier_ids = request.POST.getlist('suppliers') + suppliers = Supplier.objects.filter(id__in=supplier_ids) + new_product.suppliers.add(*suppliers) + + return render(request, "addProducts.html", {"products": products,"categories":category,"suppliers": allSuppliers}) \ No newline at end of file diff --git a/HospitalSystem/doctor/__init__.py b/HospitalSystem/doctor/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/HospitalSystem/doctor/admin.py b/HospitalSystem/doctor/admin.py new file mode 100644 index 0000000..64df5a5 --- /dev/null +++ b/HospitalSystem/doctor/admin.py @@ -0,0 +1,4 @@ +from django.contrib import admin +from .models import Doctor + +admin.site.register(Doctor) diff --git a/HospitalSystem/doctor/apps.py b/HospitalSystem/doctor/apps.py new file mode 100644 index 0000000..3449810 --- /dev/null +++ b/HospitalSystem/doctor/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class DoctorConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'doctor' diff --git a/HospitalSystem/doctor/migrations/0001_initial.py b/HospitalSystem/doctor/migrations/0001_initial.py new file mode 100644 index 0000000..fca9a67 --- /dev/null +++ b/HospitalSystem/doctor/migrations/0001_initial.py @@ -0,0 +1,26 @@ +# Generated by Django 4.2.14 on 2024-08-06 14:49 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Doctor', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255)), + ('specialization', models.CharField(max_length=255)), + ('about', models.TextField(blank=True)), + ('email', models.EmailField(blank=True, max_length=100)), + ('phone', models.CharField(blank=True, max_length=100)), + ('image', models.ImageField(default='images/defaultAvatar.png', upload_to='images/avatars/')), + ], + ), + ] diff --git a/HospitalSystem/doctor/migrations/__init__.py b/HospitalSystem/doctor/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/HospitalSystem/doctor/models.py b/HospitalSystem/doctor/models.py new file mode 100644 index 0000000..5cc2b7a --- /dev/null +++ b/HospitalSystem/doctor/models.py @@ -0,0 +1,13 @@ +from django.db import models + + +class Doctor(models.Model): + name= models.CharField(max_length=255) + specialization =models.CharField(max_length=255) + about = models.TextField(blank=True) + email = models.EmailField(max_length=100,blank=True) + phone = models.CharField(max_length=100,blank=True ) + image = models.ImageField(upload_to="images/avatars/", default="images/defaultAvatar.png") + + def __str__(self) -> str: + return self.name \ No newline at end of file diff --git a/HospitalSystem/doctor/templates/addDoctors.html b/HospitalSystem/doctor/templates/addDoctors.html new file mode 100644 index 0000000..40e8704 --- /dev/null +++ b/HospitalSystem/doctor/templates/addDoctors.html @@ -0,0 +1,127 @@ +{% extends 'dashBase.html' %} + +{% block title %} Add Doctors {% endblock %} + +{% block content %} +
+{% csrf_token %} +
+
+
+
+

Add New Doctor Form

+
+
+

Doctor Details

+
+
+
+ + +
+
+
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+
+
+
+ +
+ +
+
+
+
+ {% if messages %} +{% for message in messages %} + + {% endfor %} + {% endif %} + +{% endblock%} \ No newline at end of file diff --git a/HospitalSystem/doctor/templates/allDoctors.html b/HospitalSystem/doctor/templates/allDoctors.html new file mode 100644 index 0000000..ad3b910 --- /dev/null +++ b/HospitalSystem/doctor/templates/allDoctors.html @@ -0,0 +1,45 @@ +{% extends 'dashBase.html' %} + +{% block title %} Available Doctors {% endblock %} + +{% block content %} + +
+
+
+

Our Team

+

The Best Doctors

+
+
+ {% for doctor in doctors %} +
+ + {{doctor.name}} Avatar + +
+

+ {{doctor.name}} +

+ {{doctor.specialization}} +

{{doctor.about}}

+

{{doctor.email}}

+

{{doctor.phone}}

+ +
+
+ {% endfor %} +
+
+
+{% endblock%} \ No newline at end of file diff --git a/HospitalSystem/doctor/tests.py b/HospitalSystem/doctor/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/HospitalSystem/doctor/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/HospitalSystem/doctor/urls.py b/HospitalSystem/doctor/urls.py new file mode 100644 index 0000000..07df7fe --- /dev/null +++ b/HospitalSystem/doctor/urls.py @@ -0,0 +1,9 @@ +from django.urls import path +from . import views + +app_name = "doctor" + +urlpatterns = [ + path("allDoctors/", views.all_doctors_view, name="all_doctors_view"), + path("addDoctors/", views.add_doctors_view, name="add_doctors_view"), +] \ No newline at end of file diff --git a/HospitalSystem/doctor/views.py b/HospitalSystem/doctor/views.py new file mode 100644 index 0000000..f5a1d8f --- /dev/null +++ b/HospitalSystem/doctor/views.py @@ -0,0 +1,45 @@ +from django.shortcuts import render, redirect, get_object_or_404 +from django.http import HttpRequest +from django.contrib.auth import authenticate, login, logout +from django.contrib import messages +from django.core.mail import EmailMessage +from django.conf import settings +from django.template.loader import render_to_string +from django.contrib.auth.decorators import login_required +from django.db import IntegrityError +from doctor.models import Doctor + + + +@login_required(login_url="account:log_in") +def all_doctors_view(request: HttpRequest): + doctor = Doctor.objects.all() + + return render(request, "allDoctors.html", {"doctors":doctor}) + +@login_required(login_url="account:log_in") +def add_doctors_view(request:HttpRequest): + if request.method == "POST": + + name = request.POST["name"] + email = request.POST["email"] + # Check if user already exists + if Doctor.objects.filter(name=name).exists(): + messages.error(request, "A user with that username already exists.", "alert-danger") + return render(request, "addDoctors.html") + + if Doctor.objects.filter(email=email).exists(): + messages.error(request, "A user with that email already exists.", "alert-danger") + + if request.method == "POST": + try: + new_doctor = Doctor.objects.create(name = request.POST["name"], specialization=request.POST["specialization"], about=request.POST["about"],email=request.POST["email"],phone=request.POST["phone"],image=request.FILES["image"]) + new_doctor.save() + messages.success(request, "Doctor has been Added Successfully", "alert-success") + except IntegrityError: + messages.error(request, "An error occurred during Creating Doctor.", "alert-danger") + except Exception as e: + messages.error(request, f"An unexpected error occurred: {str(e)}", "alert-danger") + + + return render(request, "addDoctors.html") \ No newline at end of file diff --git a/HospitalSystem/main/__init__.py b/HospitalSystem/main/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/HospitalSystem/main/admin.py b/HospitalSystem/main/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/HospitalSystem/main/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/HospitalSystem/main/apps.py b/HospitalSystem/main/apps.py new file mode 100644 index 0000000..167f044 --- /dev/null +++ b/HospitalSystem/main/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class MainConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'main' diff --git a/HospitalSystem/main/migrations/__init__.py b/HospitalSystem/main/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/HospitalSystem/main/models.py b/HospitalSystem/main/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/HospitalSystem/main/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/HospitalSystem/main/static/js/script.js b/HospitalSystem/main/static/js/script.js new file mode 100644 index 0000000..9c028b8 --- /dev/null +++ b/HospitalSystem/main/static/js/script.js @@ -0,0 +1,82 @@ +const options = { + chart: { + height: "100%", + maxWidth: "100%", + type: "area", + fontFamily: "Inter, sans-serif", + dropShadow: { + enabled: false, + }, + toolbar: { + show: false, + }, + }, + tooltip: { + enabled: true, + x: { + show: false, + }, + }, + fill: { + type: "gradient", + gradient: { + opacityFrom: 0.55, + opacityTo: 0, + shade: "#1C64F2", + gradientToColors: ["#1C64F2"], + }, + }, + dataLabels: { + enabled: false, + }, + stroke: { + width: 6, + }, + grid: { + show: false, + strokeDashArray: 4, + padding: { + left: 2, + right: 2, + top: 0, + }, + }, + series: [ + { + name: "New users", + data: [6500, 6418, 6456, 6526, 6356, 6456], + color: "#1A56DB", + }, + ], + xaxis: { + categories: [ + "01 February", + "02 February", + "03 February", + "04 February", + "05 February", + "06 February", + "07 February", + ], + labels: { + show: false, + }, + axisBorder: { + show: false, + }, + axisTicks: { + show: false, + }, + }, + yaxis: { + show: false, + }, +}; + +if ( + document.getElementById("area-chart") && + typeof ApexCharts !== "undefined" +) { + const chart = new ApexCharts(document.getElementById("area-chart"), options); + chart.render(); +} diff --git a/HospitalSystem/main/templates/404.html b/HospitalSystem/main/templates/404.html new file mode 100644 index 0000000..95c881c --- /dev/null +++ b/HospitalSystem/main/templates/404.html @@ -0,0 +1,29 @@ +{% extends 'base.html' %} {% block title %} Not found 404 {% endblock %} +{%block content %} +
+
+
+

+ 404 +

+

+ Something's missing. +

+

+ Sorry, we can't find that page. You'll find lots to explore on the home + page. +

+ Back to Homepage +
+
+
+ +{% endblock%} diff --git a/HospitalSystem/main/templates/base.html b/HospitalSystem/main/templates/base.html new file mode 100644 index 0000000..99972c4 --- /dev/null +++ b/HospitalSystem/main/templates/base.html @@ -0,0 +1,208 @@ +{% load static%} + + + + + + + + + {% block title %} {% endblock %} + + +
+ +
+ {% block content %} + {% endblock%} + + + + + + + diff --git a/HospitalSystem/main/templates/clinic_details.html b/HospitalSystem/main/templates/clinic_details.html new file mode 100644 index 0000000..7ee0025 --- /dev/null +++ b/HospitalSystem/main/templates/clinic_details.html @@ -0,0 +1,99 @@ +{% extends 'base.html' %} + +{% block title %} Clinic Details {% endblock %} + +{% block content %} +
+
+
+
+ +
+
+

+ {{clinic.name}} +

+
+
+

+ Work Day: {{clinic.get_working_hours_display}} +

+ +
+
+ +
+ {% if request.user.is_authenticated %} + + + Make Appointment + + {%else%} + + + Make Appointment + + {% endif %} +
+ +
+ About Clinic +

+ {{clinic.description}} +

+
+ Doctors +

+ {% for doctor in clinic.doctors_id.all %} + {{ doctor.name }} +

Specialization

+ {% if doctor.specialization %} {{ doctor.specialization }}{% endif %} + {% endfor %} +

+
+
+
+
+{% endblock%} \ No newline at end of file diff --git a/HospitalSystem/main/templates/dashBase.html b/HospitalSystem/main/templates/dashBase.html new file mode 100644 index 0000000..6594ed3 --- /dev/null +++ b/HospitalSystem/main/templates/dashBase.html @@ -0,0 +1,501 @@ +{% load static%} + + + + + + {% block title %}{% endblock %} + + + + + + + +
+ + + + + + +
+ {% block content %} + {%endblock%} +
+
+ + + + diff --git a/HospitalSystem/main/templates/dashboard.html b/HospitalSystem/main/templates/dashboard.html new file mode 100644 index 0000000..c11fcd2 --- /dev/null +++ b/HospitalSystem/main/templates/dashboard.html @@ -0,0 +1,118 @@ +{% extends 'dashBase.html' %} + +{% block title %} Dashboard {% endblock %} + +{% block content %} + +
+
+
+
+
+
+
+
+
+
+
+
32.4k
+

Users this week

+
+
+ 12% + +
+
+
+
+
+ + + + + + Users Report + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + {%endblock%} \ No newline at end of file diff --git a/HospitalSystem/main/templates/index.html b/HospitalSystem/main/templates/index.html new file mode 100644 index 0000000..2ff9ff3 --- /dev/null +++ b/HospitalSystem/main/templates/index.html @@ -0,0 +1,210 @@ +{% extends 'base.html' %} + +{% block title %} Home {% endblock %} + +{% block content %} +
+
+ +

+ Control your Health with our + Efficient Doctors +

+

+ Invest intelligently and discover a better way to manage your + Health. +

+ {% if request.user.is_authenticated %} + + Make Appointment + + + + + + {%else%} + + Create an account + + + + + {%endif%} +
+ Dashboard image +
+
+
+ +{% if messages %} +{% for message in messages %} + +{% endfor %} {% endif %} + +
+ +
+ + +
+

Clinics And Departments

+
+ {% for clinic in clinics %} +
+
+ {{clinic.name}} +
+
+

{{clinic.name}}

+

{{clinic.description}}

+
+ {{clinic.get_working_hours_display}} + More Details.. +
+
+
+ {% endfor %} +
+ +
+ +{% endblock %} diff --git a/HospitalSystem/main/templates/makeAppointment.html b/HospitalSystem/main/templates/makeAppointment.html new file mode 100644 index 0000000..c948056 --- /dev/null +++ b/HospitalSystem/main/templates/makeAppointment.html @@ -0,0 +1,144 @@ +{% extends 'base.html' %} + +{% block title %} Make Appointment {% endblock %} + +{% block content %} +
+
+{% csrf_token %} +
+
+
+

Add New Appointment

+
+
+

Fill The Appointment Details

+
+
+
+ +

{{profile.first_name}} {{profile.last_name}}

+
+
+
+
+ +

{{clinic.name}}

+
+
+
+
+ + + +

{{doctor.name}}

+
+
+
+
+
+ +
+
+ +
+ +
+
+
+ + +
+
+
+ +
+
+
+
+ +
+
+{% if messages %} +{% for message in messages %} + + {% endfor %} + {% endif %} + +{% endblock %} + +
+{% csrf_token %} +
+

Add New Appointment

+

Fill The Appointment Details

+ +

{{profiles.first_name}} {{profiles.last_name}}

+ +

{{clinic.name}}

+ +

{{doctor.name}}

+
+ + +
+ + +
+ +
\ No newline at end of file diff --git a/HospitalSystem/main/tests.py b/HospitalSystem/main/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/HospitalSystem/main/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/HospitalSystem/main/urls.py b/HospitalSystem/main/urls.py new file mode 100644 index 0000000..f285027 --- /dev/null +++ b/HospitalSystem/main/urls.py @@ -0,0 +1,11 @@ +from django.urls import path +from . import views + +app_name = "main" + +urlpatterns = [ + path("", views.home_view, name="home_view"), + path("dashboard/", views.dashboard_view, name="dashboard_view"), + path("clinic_details/", views.details_clinics, name="details_clinics"), + path("make/appointment///", views.make_appointment, name="make_appointment"), +] \ No newline at end of file diff --git a/HospitalSystem/main/views.py b/HospitalSystem/main/views.py new file mode 100644 index 0000000..5e2a68a --- /dev/null +++ b/HospitalSystem/main/views.py @@ -0,0 +1,68 @@ +from django.shortcuts import render, redirect +from django.http import HttpRequest, HttpResponse +from django.contrib import messages +from django.contrib.auth.decorators import login_required +from clinic.models import Clinic +from doctor.models import Doctor +from django.conf import settings +from django.template.loader import render_to_string +from django.core.mail import EmailMessage +from django.contrib.auth.models import User +from account.models import Profile +from appointment.models import Appointment +from datetime import datetime + +def home_view(request:HttpRequest): + clinic = Clinic.objects.prefetch_related('doctors_id').all() + doctor = Doctor.objects.all() + + return render(request, "index.html",{"clinics":clinic, "doctors":doctor}) + +def details_clinics(request: HttpRequest, clinic_id): + clinic = Clinic.objects.get(id=clinic_id) + + return render(request, "clinic_details.html", {"clinic":clinic}) + +def make_appointment(request: HttpRequest, clinic_id, profile_id): + clinic = Clinic.objects.get(id=clinic_id) + doctor = Doctor.objects.all() + user = User.objects.get(id=profile_id) + profile = Profile.objects.get(user=user) + context ={ + "clinic": clinic, + "profile": profile, + "doctor": doctor, + } + if not request.user.is_authenticated: + messages.error(request,"Only registered users can access") + return redirect("account:log_in") + if request.method == "POST": + try: + doctor = Doctor.objects.get(id=request.POST['doctor']) + date = datetime.strptime(request.POST['date'], '%Y-%m-%d').date() + time_slot = datetime.strptime(request.POST['time_slot'], '%H:%M').time() + + new_appointment = Appointment( + user=profile, + doctor=doctor, + clinic=clinic, + date=date, + time_slot=time_slot, + ) + new_appointment.save() + content_html = render_to_string("appointment/templates/mail/confirmation.html",{"appointment":new_appointment}) + send_to = new_appointment.user.user.email + email_message = EmailMessage("Appointment Confirmation", content_html, settings.EMAIL_HOST_USER, [send_to]) + email_message.content_subtype = "html" + email_message.send() + messages.success(request, "Appointment has been Added Successfully") + return redirect("appointment:all_appointment_view") + except Exception as e: + messages.error(request, f"An unexpected error occurred: {str(e)}") + + return render(request, "makeAppointment.html",context) + +@login_required(login_url="account:log_in") +def dashboard_view(request:HttpRequest): + + return render(request, "dashboard.html") \ No newline at end of file diff --git a/HospitalSystem/manage.py b/HospitalSystem/manage.py new file mode 100755 index 0000000..abf1fc0 --- /dev/null +++ b/HospitalSystem/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'HospitalSystem.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/HospitalSystem/media/.DS_Store b/HospitalSystem/media/.DS_Store new file mode 100644 index 0000000..13771c8 Binary files /dev/null and b/HospitalSystem/media/.DS_Store differ diff --git a/HospitalSystem/media/images/.DS_Store b/HospitalSystem/media/images/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/HospitalSystem/media/images/.DS_Store differ diff --git a/HospitalSystem/media/images/HeroImg.avif b/HospitalSystem/media/images/HeroImg.avif new file mode 100644 index 0000000..1eb1c21 Binary files /dev/null and b/HospitalSystem/media/images/HeroImg.avif differ diff --git a/HospitalSystem/media/images/avatars/aljouf.jpeg b/HospitalSystem/media/images/avatars/aljouf.jpeg new file mode 100644 index 0000000..ae3993b Binary files /dev/null and b/HospitalSystem/media/images/avatars/aljouf.jpeg differ diff --git a/HospitalSystem/media/images/avatars/aljouf_9xCik2Z.jpeg b/HospitalSystem/media/images/avatars/aljouf_9xCik2Z.jpeg new file mode 100644 index 0000000..ae3993b Binary files /dev/null and b/HospitalSystem/media/images/avatars/aljouf_9xCik2Z.jpeg differ diff --git a/HospitalSystem/media/images/avatars/aljouf_nheTS0k.jpeg b/HospitalSystem/media/images/avatars/aljouf_nheTS0k.jpeg new file mode 100644 index 0000000..ae3993b Binary files /dev/null and b/HospitalSystem/media/images/avatars/aljouf_nheTS0k.jpeg differ diff --git a/HospitalSystem/media/images/avatars/aljouf_tlooAqr.jpeg b/HospitalSystem/media/images/avatars/aljouf_tlooAqr.jpeg new file mode 100644 index 0000000..ae3993b Binary files /dev/null and b/HospitalSystem/media/images/avatars/aljouf_tlooAqr.jpeg differ diff --git a/HospitalSystem/media/images/defaultAvatar.png b/HospitalSystem/media/images/defaultAvatar.png new file mode 100644 index 0000000..077038b Binary files /dev/null and b/HospitalSystem/media/images/defaultAvatar.png differ diff --git a/HospitalSystem/media/images/defualt.png b/HospitalSystem/media/images/defualt.png new file mode 100644 index 0000000..b146667 Binary files /dev/null and b/HospitalSystem/media/images/defualt.png differ diff --git a/HospitalSystem/media/images/hospitalLogo.png b/HospitalSystem/media/images/hospitalLogo.png new file mode 100644 index 0000000..5f4db9d Binary files /dev/null and b/HospitalSystem/media/images/hospitalLogo.png differ diff --git a/HospitalSystem/patientSummary/__init__.py b/HospitalSystem/patientSummary/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/HospitalSystem/patientSummary/admin.py b/HospitalSystem/patientSummary/admin.py new file mode 100644 index 0000000..e2224f2 --- /dev/null +++ b/HospitalSystem/patientSummary/admin.py @@ -0,0 +1,9 @@ +from django.contrib import admin +from .models import PatientSummary + +class PatientAdmin(admin.ModelAdmin): + + list_display = ("appointment", "diagnosis", "prescription_name","created_at") + + +admin.site.register(PatientSummary,PatientAdmin) \ No newline at end of file diff --git a/HospitalSystem/patientSummary/apps.py b/HospitalSystem/patientSummary/apps.py new file mode 100644 index 0000000..61efdc6 --- /dev/null +++ b/HospitalSystem/patientSummary/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class PatientsummaryConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'patientSummary' diff --git a/HospitalSystem/patientSummary/migrations/0001_initial.py b/HospitalSystem/patientSummary/migrations/0001_initial.py new file mode 100644 index 0000000..a5bf9d6 --- /dev/null +++ b/HospitalSystem/patientSummary/migrations/0001_initial.py @@ -0,0 +1,26 @@ +# Generated by Django 4.2.14 on 2024-08-06 14:49 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('appointment', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='PatientSummary', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('diagnosis', models.TextField()), + ('prescription_name', models.TextField()), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('appointment', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='appointment', to='appointment.appointment')), + ], + ), + ] diff --git a/HospitalSystem/patientSummary/migrations/__init__.py b/HospitalSystem/patientSummary/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/HospitalSystem/patientSummary/models.py b/HospitalSystem/patientSummary/models.py new file mode 100644 index 0000000..6c56c5d --- /dev/null +++ b/HospitalSystem/patientSummary/models.py @@ -0,0 +1,12 @@ +from django.db import models +from appointment.models import Appointment + + +class PatientSummary(models.Model): + appointment= models.ForeignKey(Appointment, on_delete=models.CASCADE ,related_name='appointment') + diagnosis= models.TextField() + prescription_name= models.TextField() + created_at= models.DateTimeField(auto_now_add=True) + + def __str__ (self): + return f"{self.appointment.user} in Clinic ({self.diagnosis}) with Doctor {self.prescription_name} date{self.created_at} " \ No newline at end of file diff --git a/HospitalSystem/patientSummary/templates/addSummery.html b/HospitalSystem/patientSummary/templates/addSummery.html new file mode 100644 index 0000000..eb1625f --- /dev/null +++ b/HospitalSystem/patientSummary/templates/addSummery.html @@ -0,0 +1,131 @@ +{% extends 'dashBase.html' %} + +{% block title %} Add Clinic {% endblock %} + +{% block content %} +{% if request.user.is_authenticated %} +
+
+{% csrf_token %} +
+
+
+

Add New Clinic

+
+
+
+

Clinic Details

+
+
+ + +
+ +
+
+
+ + +
+
+
+
+ + +
+
+ + +
+
+
+
+
+ +
+ +
+
+
+
+ +{%endif%} +{% if messages %} +{% for message in messages %} + + {% endfor %} + {% endif %} +{% endblock%} \ No newline at end of file diff --git a/HospitalSystem/patientSummary/templates/allPatientRecords.html b/HospitalSystem/patientSummary/templates/allPatientRecords.html new file mode 100644 index 0000000..f944e84 --- /dev/null +++ b/HospitalSystem/patientSummary/templates/allPatientRecords.html @@ -0,0 +1,219 @@ +{% extends 'dashBase.html' %} + +{% block title %} Patients Records {% endblock %} + +{% block content %} +
+
+

Patients Reports

+
+
+
+
+
+
+ +
+
+ +
+ +
+
+
+
+
+ + +
+
+
+
+ + + + + + + + + + + + + + {%for patientSummary in patientSummaries%} + + + + + + + + + + + + + {%endfor%} + +
Patient NameClinicDoctorDiagnosisPrescriptionDateCreated + Actions
{{patientSummary.appointment.user.first_name}} {{patientSummary.appointment.user.last_name}}{{patientSummary.appointment.clinic}}{{patientSummary.appointment.doctor}}{{patientSummary.diagnosis}}{{patientSummary.prescription_name}}{{patientSummary.created_at}} + + +
+
+ +
+
+
+ {% if messages %} +{% for message in messages %} + + {% endfor %} + {% endif %} +{% endblock%} diff --git a/HospitalSystem/patientSummary/templates/patientSummery.html b/HospitalSystem/patientSummary/templates/patientSummery.html new file mode 100644 index 0000000..af50fa2 --- /dev/null +++ b/HospitalSystem/patientSummary/templates/patientSummery.html @@ -0,0 +1,182 @@ +{% extends 'base.html' %} + +{% block title %} Patient Record {% endblock %} + +{% block content %} +
+
+

Patient Report

+
+
+
+
+
+
+ +
+
+ +
+ +
+
+
+
+
+ + +
+
+
+
+ + + + + + + + + + + + + + {%for patientSummary in patientSummaries%} + + + + + + + + + + + + + {%endfor%} + +
Patient NameClinicDoctorDiagnosisPrescriptionDateCreated + Actions
{{patientSummary.appointment.user.first_name}} {{patientSummary.appointment.user.last_name}}{{patientSummary.appointment.clinic}}{{patientSummary.appointment.doctor}}{{patientSummary.diagnosis}}{{patientSummary.prescription_name}}{{patientSummary.created_at}} + + +
+
+ +
+
+
\ No newline at end of file diff --git a/HospitalSystem/patientSummary/tests.py b/HospitalSystem/patientSummary/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/HospitalSystem/patientSummary/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/HospitalSystem/patientSummary/urls.py b/HospitalSystem/patientSummary/urls.py new file mode 100644 index 0000000..d187aa2 --- /dev/null +++ b/HospitalSystem/patientSummary/urls.py @@ -0,0 +1,9 @@ +from django.urls import path +from . import views + +app_name = "patientSummary" +urlpatterns = [ + path("add/patient/summary/" ,views.add_patient_summary, name="add_patient_summary"), + path("patient/summary/" ,views.display_patient_summary, name="display_patient_summary"), + path("all/patient/summary/" ,views.all_patient_summary, name="all_patient_summary"), +] \ No newline at end of file diff --git a/HospitalSystem/patientSummary/views.py b/HospitalSystem/patientSummary/views.py new file mode 100644 index 0000000..8c180e8 --- /dev/null +++ b/HospitalSystem/patientSummary/views.py @@ -0,0 +1,62 @@ +from django.shortcuts import render, redirect, get_object_or_404 +from django.http import HttpRequest +from django.contrib.auth import authenticate +from django.contrib.auth.decorators import login_required +from django.contrib import messages +from appointment.models import Appointment +from patientSummary.models import PatientSummary + + + + +@login_required(login_url="account:log_in") +def display_patient_summary(request:HttpRequest,patient_id): + patientSummary = PatientSummary.objects.get(id=patient_id) + return redirect(request, "patientSummery.html",{"patientSummary":patientSummary}) + +@login_required(login_url="account:log_in") +def add_patient_summary(request: HttpRequest, appointment_id): + appointment = get_object_or_404(Appointment, id=appointment_id) + + if request.method == "POST": + try: + new_summary = PatientSummary( + appointment=appointment, + diagnosis=request.POST['diagnosis'], + prescription_name=request.POST['prescription_name'] + ) + new_summary.save() + messages.success(request, "Patient summary added successfully.") + return redirect("patientSummary:all_patient_summary") + except Exception as e: + messages.error(request, f"An error occurred: {str(e)}") + + context = { + 'appointment': appointment, + } + return render(request, "add_patient_summary.html", context) + +@login_required(login_url="account:log_in") +def all_patient_summary(request:HttpRequest): + if not request.user.is_staff: + messages.error(request,"Only registered users can access") + return redirect("account:log_in") + else: + patientSummary = PatientSummary.objects.all() + + return render(request,"allPatientRecords.html",{"patientSummaries":patientSummary}) + +@login_required(login_url="account:log_in") +def delete_patient_summary(request:HttpRequest, record_id): + if not request.user.is_staff: + messages.error(request,"Only registered users can delete") + return redirect("account:log_in") + try: + patientSummary = PatientSummary.objects.get(id=record_id) # implement feedback messages + patientSummary.delete() + messages.success(request, "Patient Record has been Deleted successfully", "alert-success") + except Exception as e: + print(e) + messages.error(request, "Couldn't Delete Patient Record", "alert-danger") + + return redirect("patientSummary:all_patient_summary") \ No newline at end of file diff --git a/Hospital_UML.png b/Hospital_UML.png new file mode 100644 index 0000000..1633eaf Binary files /dev/null and b/Hospital_UML.png differ diff --git a/README.md b/README.md index 0a3504b..c1ac690 100644 --- a/README.md +++ b/README.md @@ -2,19 +2,26 @@ ### Project Overview: Hospital Website -In this project you are going to build a web application for a hospital. The website will allow users to view clinic details, see information about doctors, make reservations, and manage their reservations. +In this project you are going to build a web application for a hospital. The website will allow users to view clinic details, see information about doctors, make reservations, and manage their reservations. + +### UML Design + +![alt text](Hospital_UML.png) ### Requirements 1. **User Registration and Authentication**: + - Users must be able to sign up and log in to the system. - Only authenticated users can make reservations and view their reservation history. 2. **Clinic Management**: + - Users can view a list of clinics. - Users can view detailed information about each clinic, including its working hours and the doctors assigned to it. 3. **Doctor Management**: + - Users can view a list of doctors. - Users can view detailed information about each doctor, including their specialization and the clinic(s) they are associated with. @@ -26,9 +33,11 @@ In this project you are going to build a web application for a hospital. The we #### Models and Their Relationships 1. **User (Django's default User model)** + - Extended with a `Profile` model with additional fields (like phone number, address) are required. 2. **Profile** + - **Fields**: - `user` (OneToOneField to User) - `phone_number` (CharField) @@ -36,16 +45,16 @@ In this project you are going to build a web application for a hospital. The we - **Relationships**: - One-to-One with `User`. - 3. **Doctor** + - **Fields**: - `full_name` (CharField) - `specialization` (CharField with appropriate choices) - `bio` (TextField) - `photo` (ImageField) - - + 4. **Clinic** + - **Fields**: - `name` (CharField) - `description` (TextField) @@ -55,10 +64,10 @@ In this project you are going to build a web application for a hospital. The we - **Relationships**: - Many-to-Many with `Doctor`. - - 5. **Reservation** + - **Fields**: + - `user` (ForeignKey to User) - `clinic` (ForeignKey to Clinic) - `doctor` (ForeignKey to Doctor) @@ -74,38 +83,44 @@ In this project you are going to build a web application for a hospital. The we ### Key Features to Implement 1. **Required Pages** - - Home page: In home page user can view informatino about the hospital , view clinics (limited with view more) , doctors (limited with view more) in the hospital, etc. + + - Home page: In home page user can view informatino about the hospital , view clinics (limited with view more) , doctors (limited with view more) in the hospital, etc. - Clinics Page: view all clinics with pagination. - Doctors page: View all doctors with pagination. - Clinic Detail page: view clinic details, doctors working in that clinic, working hours, and the form for making a reservation for registered users. - Doctor Detail Page: View doctor details. - - User Profile page: (private), where he/she can view or update his/her info. + - User Profile page: (private), where he/she can view or update his/her info. - User reservations page: (private) , where he/she can view or cancel reservations. 2. **Registration and Login**: + - Use Django's built-in authentication system. - Extend the `User` model if necessary using a `Profile` model. 3. **Clinic Listing and Details**: + - A page to list all clinics. - A detail page for each clinic showing its information and assigned doctors. 4. **Doctor Listing and Details**: + - A page to list all doctors. - A detail page for each doctor showing their information and associated clinics. 5. **Reservation System**: + - A form for authenticated users to make a reservation by choosing a clinic, doctor, and date time slot. 6. **User Dashboard**: + - A profile page where users can view and update their information. - A reservations page where users can manage their bookings. - -7. **Staff Dashboard**: - - implement update, add, delete for clinics, doctors. (only staff can access this page and use the features in it. +7. **Staff Dashboard**: + +- implement update, add, delete for clinics, doctors. (only staff can access this page and use the features in it. -### Bonus +### Bonus - Implement a search feature for clinics and doctors. - When making a reservation on a clinic, check first that there is no prior reservation by another patient on the same clinic and same doctor. diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..dfafc21 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,7 @@ +asgiref==3.8.1 +Django==4.2.14 +django-browser-reload==1.13.0 +pillow==10.4.0 +psycopg2-binary==2.9.9 +sqlparse==0.5.1 +typing_extensions==4.12.2