From b3d1c676f50d8a7df2ae9879c39bf7324bec399e Mon Sep 17 00:00:00 2001
From: y2-youssef <youssef2.youssef@live.uwe.ac.uk>
Date: Fri, 28 Mar 2025 19:06:41 +0000
Subject: [PATCH] Update 82 files

- /accounts/admin.py
- /accounts/apps.py
- /accounts/decorators.py
- /accounts/forms.py
- /accounts/models.py
- /accounts/tests.py
- /accounts/urls.py
- /accounts/views.py
- /accounts/__init__.py
- /accounts/migrations/0001_initial.py
- /accounts/migrations/__init__.py
- /accounts/migrations/__pycache__/0001_initial.cpython-39.pyc
- /accounts/migrations/__pycache__/__init__.cpython-39.pyc
- /accounts/templates/accounts/login.html
- /accounts/templates/accounts/signup.html
- /accounts/__pycache__/admin.cpython-313.pyc
- /accounts/__pycache__/admin.cpython-39.pyc
- /accounts/__pycache__/apps.cpython-313.pyc
- /accounts/__pycache__/apps.cpython-39.pyc
- /accounts/__pycache__/auth_forms.cpython-39.pyc
- /accounts/__pycache__/forms.cpython-313.pyc
- /accounts/__pycache__/forms.cpython-39.pyc
- /accounts/__pycache__/models.cpython-313.pyc
- /accounts/__pycache__/models.cpython-39.pyc
- /accounts/__pycache__/urls.cpython-313.pyc
- /accounts/__pycache__/urls.cpython-39.pyc
- /accounts/__pycache__/views.cpython-313.pyc
- /accounts/__pycache__/views.cpython-39.pyc
- /accounts/__pycache__/__init__.cpython-313.pyc
- /accounts/__pycache__/__init__.cpython-39.pyc
- /events/admin.py
- /events/apps.py
- /events/forms.py
- /events/models.py
- /events/tests.py
- /events/urls.py
- /events/views.py
- /events/__init__.py
- /events/migrations/0001_initial.py
- /events/migrations/__init__.py
- /events/migrations/__pycache__/0001_initial.cpython-39.pyc
- /events/migrations/__pycache__/__init__.cpython-39.pyc
- /events/templates/home.html
- /events/templates/events/event_detail.html
- /events/templates/events/event_form.html
- /events/templates/events/event_list.html
- /events/__pycache__/admin.cpython-313.pyc
- /events/__pycache__/admin.cpython-39.pyc
- /events/__pycache__/apps.cpython-313.pyc
- /events/__pycache__/apps.cpython-39.pyc
- /events/__pycache__/forms.cpython-313.pyc
- /events/__pycache__/forms.cpython-39.pyc
- /events/__pycache__/models.cpython-313.pyc
- /events/__pycache__/models.cpython-39.pyc
- /events/__pycache__/urls.cpython-313.pyc
- /events/__pycache__/urls.cpython-39.pyc
- /events/__pycache__/views.cpython-313.pyc
- /events/__pycache__/views.cpython-39.pyc
- /events/__pycache__/__init__.cpython-313.pyc
- /events/__pycache__/__init__.cpython-39.pyc
- /unihub_project/asgi.py
- /unihub_project/settings.py
- /unihub_project/urls.py
- /unihub_project/views.py
- /unihub_project/wsgi.py
- /unihub_project/__init__.py
- /unihub_project/__pycache__/settings.cpython-313.pyc
- /unihub_project/__pycache__/settings.cpython-39.pyc
- /unihub_project/__pycache__/urls.cpython-313.pyc
- /unihub_project/__pycache__/urls.cpython-39.pyc
- /unihub_project/__pycache__/views.cpython-313.pyc
- /unihub_project/__pycache__/views.cpython-39.pyc
- /unihub_project/__pycache__/wsgi.cpython-39.pyc
- /unihub_project/__pycache__/__init__.cpython-313.pyc
- /unihub_project/__pycache__/__init__.cpython-39.pyc
- /Dockerfile
- /manage.py
- /Pipfile
- /Pipfile.lock
- /requirements.txt
- /docker-compose.yml
- /README.md
---
 Dockerfile                                    |  22 ++
 Pipfile                                       |  16 ++
 Pipfile.lock                                  | 210 ++++++++++++++++++
 README.md                                     |  10 +-
 accounts/__init__.py                          |   0
 accounts/__pycache__/__init__.cpython-313.pyc | Bin 0 -> 170 bytes
 accounts/__pycache__/__init__.cpython-39.pyc  | Bin 0 -> 117 bytes
 accounts/__pycache__/admin.cpython-313.pyc    | Bin 0 -> 214 bytes
 accounts/__pycache__/admin.cpython-39.pyc     | Bin 0 -> 158 bytes
 accounts/__pycache__/apps.cpython-313.pyc     | Bin 0 -> 538 bytes
 accounts/__pycache__/apps.cpython-39.pyc      | Bin 0 -> 398 bytes
 .../__pycache__/auth_forms.cpython-39.pyc     | Bin 0 -> 756 bytes
 accounts/__pycache__/forms.cpython-313.pyc    | Bin 0 -> 917 bytes
 accounts/__pycache__/forms.cpython-39.pyc     | Bin 0 -> 711 bytes
 accounts/__pycache__/models.cpython-313.pyc   | Bin 0 -> 1088 bytes
 accounts/__pycache__/models.cpython-39.pyc    | Bin 0 -> 803 bytes
 accounts/__pycache__/urls.cpython-313.pyc     | Bin 0 -> 560 bytes
 accounts/__pycache__/urls.cpython-39.pyc      | Bin 0 -> 428 bytes
 accounts/__pycache__/views.cpython-313.pyc    | Bin 0 -> 1531 bytes
 accounts/__pycache__/views.cpython-39.pyc     | Bin 0 -> 966 bytes
 accounts/admin.py                             |   3 +
 accounts/apps.py                              |   6 +
 accounts/decorators.py                        |  11 +
 accounts/forms.py                             |  18 ++
 accounts/migrations/0001_initial.py           |  45 ++++
 accounts/migrations/__init__.py               |   0
 .../__pycache__/0001_initial.cpython-39.pyc   | Bin 0 -> 2280 bytes
 .../__pycache__/__init__.cpython-39.pyc       | Bin 0 -> 128 bytes
 accounts/models.py                            |  31 +++
 accounts/templates/accounts/login.html        |  16 ++
 accounts/templates/accounts/signup.html       |  16 ++
 accounts/tests.py                             |   3 +
 accounts/urls.py                              |  10 +
 accounts/views.py                             |  32 +++
 docker-compose.yml                            |  27 +++
 events/__init__.py                            |   0
 events/__pycache__/__init__.cpython-313.pyc   | Bin 0 -> 168 bytes
 events/__pycache__/__init__.cpython-39.pyc    | Bin 0 -> 115 bytes
 events/__pycache__/admin.cpython-313.pyc      | Bin 0 -> 212 bytes
 events/__pycache__/admin.cpython-39.pyc       | Bin 0 -> 156 bytes
 events/__pycache__/apps.cpython-313.pyc       | Bin 0 -> 532 bytes
 events/__pycache__/apps.cpython-39.pyc        | Bin 0 -> 392 bytes
 events/__pycache__/forms.cpython-313.pyc      | Bin 0 -> 788 bytes
 events/__pycache__/forms.cpython-39.pyc       | Bin 0 -> 577 bytes
 events/__pycache__/models.cpython-313.pyc     | Bin 0 -> 1314 bytes
 events/__pycache__/models.cpython-39.pyc      | Bin 0 -> 828 bytes
 events/__pycache__/urls.cpython-313.pyc       | Bin 0 -> 458 bytes
 events/__pycache__/urls.cpython-39.pyc        | Bin 0 -> 354 bytes
 events/__pycache__/views.cpython-313.pyc      | Bin 0 -> 1821 bytes
 events/__pycache__/views.cpython-39.pyc       | Bin 0 -> 1154 bytes
 events/admin.py                               |   3 +
 events/apps.py                                |   6 +
 events/forms.py                               |   7 +
 events/migrations/0001_initial.py             |  30 +++
 events/migrations/__init__.py                 |   0
 .../__pycache__/0001_initial.cpython-39.pyc   | Bin 0 -> 1075 bytes
 .../__pycache__/__init__.cpython-39.pyc       | Bin 0 -> 126 bytes
 events/models.py                              |  18 ++
 events/templates/events/event_detail.html     |   7 +
 events/templates/events/event_form.html       |   9 +
 events/templates/events/event_list.html       |  16 ++
 events/templates/home.html                    |   2 +
 events/tests.py                               |   3 +
 events/urls.py                                |  11 +
 events/views.py                               |  32 +++
 manage.py                                     |  22 ++
 requirements.txt                              |   5 +
 unihub_project/__init__.py                    |   0
 .../__pycache__/__init__.cpython-313.pyc      | Bin 0 -> 176 bytes
 .../__pycache__/__init__.cpython-39.pyc       | Bin 0 -> 123 bytes
 .../__pycache__/settings.cpython-313.pyc      | Bin 0 -> 2792 bytes
 .../__pycache__/settings.cpython-39.pyc       | Bin 0 -> 2449 bytes
 .../__pycache__/urls.cpython-313.pyc          | Bin 0 -> 1289 bytes
 .../__pycache__/urls.cpython-39.pyc           | Bin 0 -> 1089 bytes
 .../__pycache__/views.cpython-313.pyc         | Bin 0 -> 377 bytes
 .../__pycache__/views.cpython-39.pyc          | Bin 0 -> 294 bytes
 .../__pycache__/wsgi.cpython-39.pyc           | Bin 0 -> 540 bytes
 unihub_project/asgi.py                        |  16 ++
 unihub_project/settings.py                    | 137 ++++++++++++
 unihub_project/urls.py                        |  26 +++
 unihub_project/views.py                       |   4 +
 unihub_project/wsgi.py                        |  16 ++
 82 files changed, 841 insertions(+), 5 deletions(-)
 create mode 100644 Dockerfile
 create mode 100644 Pipfile
 create mode 100644 Pipfile.lock
 create mode 100644 accounts/__init__.py
 create mode 100644 accounts/__pycache__/__init__.cpython-313.pyc
 create mode 100644 accounts/__pycache__/__init__.cpython-39.pyc
 create mode 100644 accounts/__pycache__/admin.cpython-313.pyc
 create mode 100644 accounts/__pycache__/admin.cpython-39.pyc
 create mode 100644 accounts/__pycache__/apps.cpython-313.pyc
 create mode 100644 accounts/__pycache__/apps.cpython-39.pyc
 create mode 100644 accounts/__pycache__/auth_forms.cpython-39.pyc
 create mode 100644 accounts/__pycache__/forms.cpython-313.pyc
 create mode 100644 accounts/__pycache__/forms.cpython-39.pyc
 create mode 100644 accounts/__pycache__/models.cpython-313.pyc
 create mode 100644 accounts/__pycache__/models.cpython-39.pyc
 create mode 100644 accounts/__pycache__/urls.cpython-313.pyc
 create mode 100644 accounts/__pycache__/urls.cpython-39.pyc
 create mode 100644 accounts/__pycache__/views.cpython-313.pyc
 create mode 100644 accounts/__pycache__/views.cpython-39.pyc
 create mode 100644 accounts/admin.py
 create mode 100644 accounts/apps.py
 create mode 100644 accounts/decorators.py
 create mode 100644 accounts/forms.py
 create mode 100644 accounts/migrations/0001_initial.py
 create mode 100644 accounts/migrations/__init__.py
 create mode 100644 accounts/migrations/__pycache__/0001_initial.cpython-39.pyc
 create mode 100644 accounts/migrations/__pycache__/__init__.cpython-39.pyc
 create mode 100644 accounts/models.py
 create mode 100644 accounts/templates/accounts/login.html
 create mode 100644 accounts/templates/accounts/signup.html
 create mode 100644 accounts/tests.py
 create mode 100644 accounts/urls.py
 create mode 100644 accounts/views.py
 create mode 100644 docker-compose.yml
 create mode 100644 events/__init__.py
 create mode 100644 events/__pycache__/__init__.cpython-313.pyc
 create mode 100644 events/__pycache__/__init__.cpython-39.pyc
 create mode 100644 events/__pycache__/admin.cpython-313.pyc
 create mode 100644 events/__pycache__/admin.cpython-39.pyc
 create mode 100644 events/__pycache__/apps.cpython-313.pyc
 create mode 100644 events/__pycache__/apps.cpython-39.pyc
 create mode 100644 events/__pycache__/forms.cpython-313.pyc
 create mode 100644 events/__pycache__/forms.cpython-39.pyc
 create mode 100644 events/__pycache__/models.cpython-313.pyc
 create mode 100644 events/__pycache__/models.cpython-39.pyc
 create mode 100644 events/__pycache__/urls.cpython-313.pyc
 create mode 100644 events/__pycache__/urls.cpython-39.pyc
 create mode 100644 events/__pycache__/views.cpython-313.pyc
 create mode 100644 events/__pycache__/views.cpython-39.pyc
 create mode 100644 events/admin.py
 create mode 100644 events/apps.py
 create mode 100644 events/forms.py
 create mode 100644 events/migrations/0001_initial.py
 create mode 100644 events/migrations/__init__.py
 create mode 100644 events/migrations/__pycache__/0001_initial.cpython-39.pyc
 create mode 100644 events/migrations/__pycache__/__init__.cpython-39.pyc
 create mode 100644 events/models.py
 create mode 100644 events/templates/events/event_detail.html
 create mode 100644 events/templates/events/event_form.html
 create mode 100644 events/templates/events/event_list.html
 create mode 100644 events/templates/home.html
 create mode 100644 events/tests.py
 create mode 100644 events/urls.py
 create mode 100644 events/views.py
 create mode 100644 manage.py
 create mode 100644 requirements.txt
 create mode 100644 unihub_project/__init__.py
 create mode 100644 unihub_project/__pycache__/__init__.cpython-313.pyc
 create mode 100644 unihub_project/__pycache__/__init__.cpython-39.pyc
 create mode 100644 unihub_project/__pycache__/settings.cpython-313.pyc
 create mode 100644 unihub_project/__pycache__/settings.cpython-39.pyc
 create mode 100644 unihub_project/__pycache__/urls.cpython-313.pyc
 create mode 100644 unihub_project/__pycache__/urls.cpython-39.pyc
 create mode 100644 unihub_project/__pycache__/views.cpython-313.pyc
 create mode 100644 unihub_project/__pycache__/views.cpython-39.pyc
 create mode 100644 unihub_project/__pycache__/wsgi.cpython-39.pyc
 create mode 100644 unihub_project/asgi.py
 create mode 100644 unihub_project/settings.py
 create mode 100644 unihub_project/urls.py
 create mode 100644 unihub_project/views.py
 create mode 100644 unihub_project/wsgi.py

diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..cedc68d
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,22 @@
+# Use the official Python image
+FROM python:3.9-slimcd
+
+# Set the working directory
+WORKDIR /code
+
+# Install system dependencies required for mysqlclient
+RUN apt-get update && apt-get install -y \
+    gcc \
+    libmariadb-dev \
+    pkg-config \
+    && rm -rf /var/lib/apt/lists/*
+
+# Copy and install dependencies
+COPY requirements.txt /code/
+RUN pip install --upgrade pip && pip install -r requirements.txt
+
+# Copy the project files
+COPY . /code/
+
+# Command to run the application
+CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
diff --git a/Pipfile b/Pipfile
new file mode 100644
index 0000000..aee7311
--- /dev/null
+++ b/Pipfile
@@ -0,0 +1,16 @@
+[[source]]
+url = "https://pypi.org/simple"
+verify_ssl = true
+name = "pypi"
+
+[packages]
+django = ">=4.0"
+mysqlclient = "*"
+djangorestframework = "*"
+pymysql = "*"
+cryptography = "*"
+
+[dev-packages]
+
+[requires]
+python_version = "3.13"
diff --git a/Pipfile.lock b/Pipfile.lock
new file mode 100644
index 0000000..5ac1f0f
--- /dev/null
+++ b/Pipfile.lock
@@ -0,0 +1,210 @@
+{
+    "_meta": {
+        "hash": {
+            "sha256": "2945d5ab87cd0426818793fb4ba82a8e6f0ecac5546e04c1fbb52e092c8cea36"
+        },
+        "pipfile-spec": 6,
+        "requires": {
+            "python_version": "3.13"
+        },
+        "sources": [
+            {
+                "name": "pypi",
+                "url": "https://pypi.org/simple",
+                "verify_ssl": true
+            }
+        ]
+    },
+    "default": {
+        "asgiref": {
+            "hashes": [
+                "sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47",
+                "sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590"
+            ],
+            "markers": "python_version >= '3.8'",
+            "version": "==3.8.1"
+        },
+        "cffi": {
+            "hashes": [
+                "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8",
+                "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2",
+                "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1",
+                "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15",
+                "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36",
+                "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824",
+                "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8",
+                "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36",
+                "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17",
+                "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf",
+                "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc",
+                "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3",
+                "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed",
+                "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702",
+                "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1",
+                "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8",
+                "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903",
+                "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6",
+                "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d",
+                "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b",
+                "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e",
+                "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be",
+                "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c",
+                "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683",
+                "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9",
+                "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c",
+                "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8",
+                "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1",
+                "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4",
+                "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655",
+                "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67",
+                "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595",
+                "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0",
+                "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65",
+                "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41",
+                "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6",
+                "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401",
+                "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6",
+                "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3",
+                "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16",
+                "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93",
+                "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e",
+                "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4",
+                "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964",
+                "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c",
+                "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576",
+                "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0",
+                "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3",
+                "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662",
+                "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3",
+                "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff",
+                "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5",
+                "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd",
+                "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f",
+                "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5",
+                "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14",
+                "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d",
+                "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9",
+                "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7",
+                "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382",
+                "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a",
+                "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e",
+                "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a",
+                "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4",
+                "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99",
+                "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87",
+                "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"
+            ],
+            "markers": "python_version >= '3.8'",
+            "version": "==1.17.1"
+        },
+        "cryptography": {
+            "hashes": [
+                "sha256:04abd71114848aa25edb28e225ab5f268096f44cf0127f3d36975bdf1bdf3390",
+                "sha256:0529b1d5a0105dd3731fa65680b45ce49da4d8115ea76e9da77a875396727b41",
+                "sha256:1bc312dfb7a6e5d66082c87c34c8a62176e684b6fe3d90fcfe1568de675e6688",
+                "sha256:268e4e9b177c76d569e8a145a6939eca9a5fec658c932348598818acf31ae9a5",
+                "sha256:29ecec49f3ba3f3849362854b7253a9f59799e3763b0c9d0826259a88efa02f1",
+                "sha256:2bf7bf75f7df9715f810d1b038870309342bff3069c5bd8c6b96128cb158668d",
+                "sha256:3b721b8b4d948b218c88cb8c45a01793483821e709afe5f622861fc6182b20a7",
+                "sha256:3c00b6b757b32ce0f62c574b78b939afab9eecaf597c4d624caca4f9e71e7843",
+                "sha256:3dc62975e31617badc19a906481deacdeb80b4bb454394b4098e3f2525a488c5",
+                "sha256:4973da6ca3db4405c54cd0b26d328be54c7747e89e284fcff166132eb7bccc9c",
+                "sha256:4e389622b6927d8133f314949a9812972711a111d577a5d1f4bee5e58736b80a",
+                "sha256:51e4de3af4ec3899d6d178a8c005226491c27c4ba84101bfb59c901e10ca9f79",
+                "sha256:5f6f90b72d8ccadb9c6e311c775c8305381db88374c65fa1a68250aa8a9cb3a6",
+                "sha256:6210c05941994290f3f7f175a4a57dbbb2afd9273657614c506d5976db061181",
+                "sha256:6f101b1f780f7fc613d040ca4bdf835c6ef3b00e9bd7125a4255ec574c7916e4",
+                "sha256:7bdcd82189759aba3816d1f729ce42ffded1ac304c151d0a8e89b9996ab863d5",
+                "sha256:7ca25849404be2f8e4b3c59483d9d3c51298a22c1c61a0e84415104dacaf5562",
+                "sha256:81276f0ea79a208d961c433a947029e1a15948966658cf6710bbabb60fcc2639",
+                "sha256:8cadc6e3b5a1f144a039ea08a0bdb03a2a92e19c46be3285123d32029f40a922",
+                "sha256:8e0ddd63e6bf1161800592c71ac794d3fb8001f2caebe0966e77c5234fa9efc3",
+                "sha256:909c97ab43a9c0c0b0ada7a1281430e4e5ec0458e6d9244c0e821bbf152f061d",
+                "sha256:96e7a5e9d6e71f9f4fca8eebfd603f8e86c5225bb18eb621b2c1e50b290a9471",
+                "sha256:9a1e657c0f4ea2a23304ee3f964db058c9e9e635cc7019c4aa21c330755ef6fd",
+                "sha256:9eb9d22b0a5d8fd9925a7764a054dca914000607dff201a24c791ff5c799e1fa",
+                "sha256:af4ff3e388f2fa7bff9f7f2b31b87d5651c45731d3e8cfa0944be43dff5cfbdb",
+                "sha256:b042d2a275c8cee83a4b7ae30c45a15e6a4baa65a179a0ec2d78ebb90e4f6699",
+                "sha256:bc821e161ae88bfe8088d11bb39caf2916562e0a2dc7b6d56714a48b784ef0bb",
+                "sha256:c505d61b6176aaf982c5717ce04e87da5abc9a36a5b39ac03905c4aafe8de7aa",
+                "sha256:c63454aa261a0cf0c5b4718349629793e9e634993538db841165b3df74f37ec0",
+                "sha256:c7362add18b416b69d58c910caa217f980c5ef39b23a38a0880dfd87bdf8cd23",
+                "sha256:d03806036b4f89e3b13b6218fefea8d5312e450935b1a2d55f0524e2ed7c59d9",
+                "sha256:d1b3031093a366ac767b3feb8bcddb596671b3aaff82d4050f984da0c248b615",
+                "sha256:d1c3572526997b36f245a96a2b1713bf79ce99b271bbcf084beb6b9b075f29ea",
+                "sha256:efcfe97d1b3c79e486554efddeb8f6f53a4cdd4cf6086642784fa31fc384e1d7",
+                "sha256:f514ef4cd14bb6fb484b4a60203e912cfcb64f2ab139e88c2274511514bf7308"
+            ],
+            "index": "pypi",
+            "markers": "python_version >= '3.7' and python_full_version not in '3.9.0, 3.9.1'",
+            "version": "==44.0.2"
+        },
+        "django": {
+            "hashes": [
+                "sha256:1323617cb624add820cb9611cdcc788312d250824f92ca6048fda8625514af2b",
+                "sha256:30de4ee43a98e5d3da36a9002f287ff400b43ca51791920bfb35f6917bfe041c"
+            ],
+            "index": "pypi",
+            "markers": "python_version >= '3.10'",
+            "version": "==5.1.7"
+        },
+        "djangorestframework": {
+            "hashes": [
+                "sha256:bea7e9f6b96a8584c5224bfb2e4348dfb3f8b5e34edbecb98da258e892089361",
+                "sha256:f022ff46613584de994c0c6a4aebbace5fd700555fbe9d33b865ebf173eba6c9"
+            ],
+            "index": "pypi",
+            "markers": "python_version >= '3.9'",
+            "version": "==3.16.0"
+        },
+        "mysqlclient": {
+            "hashes": [
+                "sha256:199dab53a224357dd0cb4d78ca0e54018f9cee9bf9ec68d72db50e0a23569076",
+                "sha256:201a6faa301011dd07bca6b651fe5aaa546d7c9a5426835a06c3172e1056a3c5",
+                "sha256:24ae22b59416d5fcce7e99c9d37548350b4565baac82f95e149cac6ce4163845",
+                "sha256:2e3c11f7625029d7276ca506f8960a7fd3c5a0a0122c9e7404e6a8fe961b3d22",
+                "sha256:4b4c0200890837fc64014cc938ef2273252ab544c1b12a6c1d674c23943f3f2e",
+                "sha256:92af368ed9c9144737af569c86d3b6c74a012a6f6b792eb868384787b52bb585",
+                "sha256:977e35244fe6ef44124e9a1c2d1554728a7b76695598e4b92b37dc2130503069",
+                "sha256:a22d99d26baf4af68ebef430e3131bb5a9b722b79a9fcfac6d9bbf8a88800687"
+            ],
+            "index": "pypi",
+            "markers": "python_version >= '3.8'",
+            "version": "==2.2.7"
+        },
+        "pycparser": {
+            "hashes": [
+                "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6",
+                "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"
+            ],
+            "markers": "python_version >= '3.8'",
+            "version": "==2.22"
+        },
+        "pymysql": {
+            "hashes": [
+                "sha256:4de15da4c61dc132f4fb9ab763063e693d521a80fd0e87943b9a453dd4c19d6c",
+                "sha256:e127611aaf2b417403c60bf4dc570124aeb4a57f5f37b8e95ae399a42f904cd0"
+            ],
+            "index": "pypi",
+            "markers": "python_version >= '3.7'",
+            "version": "==1.1.1"
+        },
+        "sqlparse": {
+            "hashes": [
+                "sha256:09f67787f56a0b16ecdbde1bfc7f5d9c3371ca683cfeaa8e6ff60b4807ec9272",
+                "sha256:cf2196ed3418f3ba5de6af7e82c694a9fbdbfecccdfc72e281548517081f16ca"
+            ],
+            "markers": "python_version >= '3.8'",
+            "version": "==0.5.3"
+        },
+        "tzdata": {
+            "hashes": [
+                "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8",
+                "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9"
+            ],
+            "markers": "python_version >= '2'",
+            "version": "==2025.2"
+        }
+    },
+    "develop": {}
+}
diff --git a/README.md b/README.md
index a4a019c..fef23e3 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# Uni Hub - DSD Project
+# GROUP_PROJECT_UWE
 
 
 
@@ -11,18 +11,18 @@ Already a pro? Just edit this README.md and make it your own. Want to make it ea
 ## Add your files
 
 - [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
-- [ ] [Add files using the command line](https://docs.gitlab.com/topics/git/add_files/#add-files-to-a-git-repository) or push an existing Git repository with the following command:
+- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command:
 
 ```
 cd existing_repo
-git remote add origin https://gitlab.uwe.ac.uk/y2-youssef/uni-hub-dsd-project.git
+git remote add origin https://gitlab.uwe.ac.uk/m2-sefari/group_project_uwe.git
 git branch -M main
 git push -uf origin main
 ```
 
 ## Integrate with your tools
 
-- [ ] [Set up project integrations](https://gitlab.uwe.ac.uk/y2-youssef/uni-hub-dsd-project/-/settings/integrations)
+- [ ] [Set up project integrations](https://gitlab.uwe.ac.uk/m2-sefari/group_project_uwe/-/settings/integrations)
 
 ## Collaborate with your team
 
@@ -30,7 +30,7 @@ git push -uf origin main
 - [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
 - [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
 - [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
-- [ ] [Set auto-merge](https://docs.gitlab.com/user/project/merge_requests/auto_merge/)
+- [ ] [Set auto-merge](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html)
 
 ## Test and Deploy
 
diff --git a/accounts/__init__.py b/accounts/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/accounts/__pycache__/__init__.cpython-313.pyc b/accounts/__pycache__/__init__.cpython-313.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..63ab691557bfd2616aeb18a6be3cf1feab5f7234
GIT binary patch
literal 170
zcmey&%ge>Uz`)=bb|oD|KL!yn%m`(CW?^7pn97jOpvmaBlA(x+fq~&ONa~iSvsFxJ
zacWU<jBjdsqC#*<eo<<SOMZD?PJUuaaZGwqerZ8`K~a8IYH~?@X?dz{ZenI$Ok#3!
zeraAwaZG%CW?p7Ve7s&k<t+}I-29Z%oK(9aRt5$Jkj=#)#z$sGM#ds$1_lNIfqg7r

literal 0
HcmV?d00001

diff --git a/accounts/__pycache__/__init__.cpython-39.pyc b/accounts/__pycache__/__init__.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..0bc38790f85d990d9ad61ddc79c2ee330f977ba1
GIT binary patch
literal 117
zcmYe~<>g{vU|^{4Kba1qAA<;F%*epN;K0DZP|U)>z>vZa%%I8Wx00a<B#a<_N$Dr&
rr=;p9CMV~Y=9Lud$H!;pWtPOp>lIYq;;_lhPbtkwwFBw-3^E%4Gwc^h

literal 0
HcmV?d00001

diff --git a/accounts/__pycache__/admin.cpython-313.pyc b/accounts/__pycache__/admin.cpython-313.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..81ef455e5599562790f2d46bee1fa32b66089b14
GIT binary patch
literal 214
zcmey&%ge>Uz`)=bb|u}Ofq~&Mhy%k+P{wBg1_p+y48aV+jNS}hj75wJ4Czdo%r8OG
znvAzt6H{_C^ZYcKZt<mLCFZ5)>m}#sl@w(r6)`g~Fsx+w3{rQ?&Dkm@v^ce>IL0?M
zJy9XJB)=#%#wEWzFDE}Sr8p+ND8IBIzMv>SD>b<!zO+15H#adeFD5ZLIlnZoq&Nm_
rhh9PDEe@O9{FKt1RJ$S$1_lO31_p*=5aR<gBO~KI28ALv1_lNIfa*B>

literal 0
HcmV?d00001

diff --git a/accounts/__pycache__/admin.cpython-39.pyc b/accounts/__pycache__/admin.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..f588d68e1308cf3485b01f620556527c1fc08e69
GIT binary patch
literal 158
zcmYe~<>g{vU|^{4KbdaNz`*br#6iYP3=9ko3=9m#0t^fcDGVu$ISjdsQH+cXDNMl(
zn#?ajYBd>eu_mVEX6E^6GDY#FWF_XM=j$cs=am#?CKZ7USjkYt%)kI4eu?WR=clCV
kCnhK7m*$le>w|Ub6;$5hu*uC&Da}c>V`N}p_zW@_0L@S$lK=n!

literal 0
HcmV?d00001

diff --git a/accounts/__pycache__/apps.cpython-313.pyc b/accounts/__pycache__/apps.cpython-313.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..c738dfa96d77fa16bb801c08988f041f288b900d
GIT binary patch
literal 538
zcmey&%ge>Uz`)=bb|rlZ0|Ucj5C?`?p^VRJ3=9lY8G;#t8NC_27>gJc7$g{!7=oFk
z7=oE&7)_ZW>WY}sSu|N+f;gItw>TXO3Y_!v(lXPNK_W2B2xWYh0h<}aP{bI_P{b6>
zSi~I6RKya@T*Mm8QpA?ds>ybX&oMbUzcjC;7-G&#76t}}D%q5*#Ju!;y_6)q-29Z(
zoMJtv%yh@nl6<$!)SQ%C9EngpD;fMW*>7>g$LA&HrpCwL;);*Y%}*)K0kL`F;|og@
zbD%Q(@$qSyMa3mKnR%&s`SJ0$gi=z|5=(PR;uA|t^5fIM=CXhk-x7_FFD^+e$xMz<
zEGa3<Oe!r&Esl>b;$UE4_zd#cEmvo&n9$<XqT(3e)bvD!;FA2J)EJli^1Ph<#FXNg
z^rHOIg7|`>{H)aElK9f{RNdUf%)A(wn`06S3X1g#DvLlN4<<lfF6L!mU}$5wA!%`e
zMeGK*XtPU^00RR9Sl&;Q`4%@cL_nI0Kyd+<0Xqt!P>_Lv;TDGt#QSzd!VC-yplB!-
eVPIhRz|6?Vc$Y!(3mX%o*o4Th3`~q-U|j%@C6L1a

literal 0
HcmV?d00001

diff --git a/accounts/__pycache__/apps.cpython-39.pyc b/accounts/__pycache__/apps.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..d1fed5bf79691aeedf50c4e89bdb54f0097d347e
GIT binary patch
literal 398
zcmYe~<>g{vU|^{4Kbby-fq~&Mh=Yt-7#J8F7#J9e6&M&8QW#Pga~N_NqZk<(+!<1s
zQkYv9QkYX2o0+4SQdoi+G+AGQ^lCER;&d!1aL&(5%S=xOi6CP}n290`3=F9ZQH&`J
zQA{a}QOqe!Q7kFU!3>%#xA+{Blk-dSN{S(7RLQ1fCFZ5)>!l>=<>sfP<`nBWWu`lp
zmgKu-rskyF;z)!l_tRv(#StH$mzbLxAAgH0K0Y@;r8Eb`=82ClEKSUT$_S;TrX`l<
zl*A{NmgL8$fem2+$*p840)+>d_$8*FoS%}a4>Mdpv7n$>ub{GsnSp@;6fVUef`gHT
t5iH`T$$X0&>Q0c#A|?g~2Cxj+G$ewXfq~%`hYiGScA)Sm2C3y?1^|?AUqJu>

literal 0
HcmV?d00001

diff --git a/accounts/__pycache__/auth_forms.cpython-39.pyc b/accounts/__pycache__/auth_forms.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..bab1fa326ecd5cb46eb917ffeaf73d9c11a7edb7
GIT binary patch
literal 756
zcmYe~<>g{vU|`^yb~3$-k%8ech=Yt-7#J8F7#J9eEf^RWQW#Pga~N_NqZk=MY^EHh
zT;?cdFq=7tC6_gdm65@nA%!J{wS^&tHI=!UIf^ZXEto-*{UyjuO~zZSY57ID#hQ$_
z1VW2bi=2y66H7Al^W5@_ay1!mv4F&qK`N0k+yxp83=F9ZQH&`JQB0}KSu81xDNHHM
zy-ZQ82s@jZU^d?33eHT=3oQVd{qi3J14ETYP-<amW>IR2o<cxTepzNpszRbdSz=CR
zib85`VrGs)VoFL;YH_iiCetmh+{B9boYcJZl8jrN8L2r1@g=DhB^YjFgoTa>irb=C
zQW&FHQ<#DoG?}aT5$@3QO)W{(WVyvrTAW&xmzbM+ixq71EzW|(;^OlBq7*{})5uSg
z?G{ITJV;%9{4K8d_}u)I(wx-z_**>j@r9*{IS`p5PypRx&CO3q&AG*vmYJH9QoNF(
zNQi*}Lj01^PtH$C)lW=L&M(a?Db`OcEy;)n$Aex$<t-MFn>ax+3^Ip<k%h4c<QYFr
z_99-85quzmA4D)QFfiQWas>sI8_1R-P|5)-Mpy=634@fgGB7Z(A<X4tDguf4X|ms9
zOUX*iOV2L?8z>3k=q2apl@w(r>499Q2X<W%Gsr?IZ1P~w7K42bHWgwm+{;BE2i)SY
TfdrTx$ev=5Q+OD87<rfgo@ch*

literal 0
HcmV?d00001

diff --git a/accounts/__pycache__/forms.cpython-313.pyc b/accounts/__pycache__/forms.cpython-313.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..24d3ee5ecbd76875656389e502afb456b82b9170
GIT binary patch
literal 917
zcmey&%ge>Uz`)=bb|t-%k%8echy%l{P{!v71_p+y48aV+jNS}hj75wJAU2aXlNWOl
zGnmcn&Emyc#0qA!c(Zx27qKfa#IP$dm_m&xVwGS}VhCoHVhCo7VK!xk2p4grvukp^
z1aUMOZ?UH37v&afGTsshElw?RE=o--$;{7l%P-2+WW2=!64PY7#h0F15?@-JS`?p~
zpOTuB4AKk3EKtU04X}G-7>XE!8H$*K8H<>~wlhgF1T&j5K~xp71hW*ern73Y-Qo()
zOwS7~0NM1ClYxN&#ZahnhR+HZhQ_cIvFbAfGX*jhu>~_1v8S_WvfkoH7^df&T9Wt@
z6uz1)w>UtK&P&Wqy~UcEo0yq%i?blHxVSvOD8&%LG+N2vr^#`PBR(FaGCuwmS3Jm{
zr8%kb@wa&5;|og@bD%Q(@$qSyMa3mKnR%&s`SI~ZpxC;_3J#T9Y-yRPIVr`rMC0R&
zOA<>mlj9RhN{TX*N=s6U<Kv4285kHogM#6fo3m96C}fLcd{fgC6@p9hi&A4;^2_sb
z@)J{vW73QAOAF!)it@8klS|@D%Tsl86EpK-5|fkjOY=&KW56+{S5SG21?1HtZUzPh
zkavrD7#JAZ7;XrNbg<qMbm(R)l4M|DD3S&dAiMoE*@}cf9AOY40wP2~1XzIthy_vw
z(If@pa=-{s^c3@fP5;is#OlcSg#koDl!8?GX>#6TOUX*iOV2L?rLtR+5RP7QejX?U
z^b$);GW5XiE&`>OTT<BM!J$|T2~uG!3X0fZ4g!ZI#CniRZ*kb<=BJeAq}mmM(hDO4
z14A(=HGW`bWMq8GAaR$$>@I`$T?V~}?4p<1#T!_@urM<^GF}i={K^1gfK37b4PWD0

literal 0
HcmV?d00001

diff --git a/accounts/__pycache__/forms.cpython-39.pyc b/accounts/__pycache__/forms.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..8842586f3b933eb434500ad686c325b13c977a36
GIT binary patch
literal 711
zcmYe~<>g{vU|{&JaW1`^k%8ech=Yt-7#J8F7#J9ey%-o6QW#Pga~N_NqZk=MY^EHh
zT;?cdFq=7tC6_gd70hPIVasKYVrOJXWp8GPVs&RoVNGFcVMt+1Wo~AU;z(f+X3*q#
z39?0#@fK@Zeo=0*CgUxE(Bjl0=c3falFa-(xBQ}9O~zX+ATdqGTYTxMCGn-jsYUU*
z`6;P6$soPRm>K3uDFz0HRE8+V6ox1!cZL+k6s8u26sBgTDCQLAU<OT=TU^1J>3N|A
zAoDRyVS<?=fn-W5a}-NDLki;}#wgYlreFq5<|=-K8G62{C5f6Ww>UtK%S+5ny~UcE
zo0yq%i?blHxVSvOD8&%LH1gAAyTuV74^kH&e~T*~<eSo*)cE*YJn`{`rHMHZnIcf2
z-(m%O^%h%NW@=7K@k)jw0R{#L@k?AkIX@*;KQTEuzcjC;SRWjOdIgoYSU}DJMQAa|
z2o6RT#v&mG1_nP(mLhJDZXOW93nD<m2ooVJL68I+0|NsmD8fOZ!NFJr;`?cG-eOD1
zO3X{oF9HeQl7w*dlJoOQiZYY*5=%=m^uVqt0!76wDQxm!{}e+!CyYfw5i87oh;!in
eEdn|07Kcr4eoARhsvXD$#UM}eFoGcy8xsH*T&3Uu

literal 0
HcmV?d00001

diff --git a/accounts/__pycache__/models.cpython-313.pyc b/accounts/__pycache__/models.cpython-313.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..ba8f239623aa2c93a88e0d9e92951fd5d256a5e9
GIT binary patch
literal 1088
zcmey&%ge>Uz`)=bb|qb&nStRkhy%l{P{wB?1_p+y48aV+jNS}hj75wJAU2aXlNWOl
zvjT$zgAzk9vlK%xOAMnaGel1jOFFA2+e;8flkpahV^VQRQDSmQXmM(hCgUx(-29Z(
zoZ@7VGz_yr8J`z{EsJ3&Vhm;|VhUy~Vh(01VhLt0Vhv^~VvAu3W;J1oVGU+8VTxf3
zW;bEdXD(uo;Rq6f>PMoK7=k%s*kf3NIW3usxMDbh#E>MROeKb3u3+w9o?u=}<{}=P
zYWRZrp=x-81&a961vQ0kv4DK@l7)eR;TC&wNoh)IUdb(i<ow*+(!9))%J`hr#FW&c
zTdavGxtV#l*n=S|ssx;2DinO6DjY#7UWza<FlaL0;>t~|h|fvQOE1Z|#h#pzpP8Im
ze2YCLH7&6;r=*H2v9u&Z&%G$WwBVLda%pi%er|keacWU~I!LHEM3d<jPf==4Vo7RB
zd|qO1>Mho!oW#8BDt@rOfYhSg%;MtA{JdM@$eIh_;>9Z&{51J*am0gl$H(8|ijU9D
zPbtkwjgP;@6CYn#nwSGJH$MIre|&seW>IlTPG(+eUVeQ1E%xA$P#0IfkXr)I{=UAU
zex4zb@jkAOF0MhhSRGw_J^gO+1o`{8#yflXdpf%Y7lA{L(>Wut$SpH9C*>APQGQP9
zEq>p`yvmS#5D5`xgLv(h0N9^MPQ4`>A75OOSdy6>pIA~-l$lgol3E-eUnI)F!0;Iq
zy|>(*tztltR2<`*nx3c-T#{du8sm~*o|luKm{J@AHaNbZC_gJTxg@@{JXJS0F*7eF
zF*!NEG_RyM29iqk3Mz|0i4#nK++5tqz`)SPaDz|0!TpA~<^>j!8$7}dt{>PKxCAF?
zUf__q!6|t`TK58n-VIK^3G5d*BtEdSh_E&IeBfc=5xUMTeTiFoLD2@A6XF-S0~=gE
zurct7T<2B3#H)ORL*$02<_$ifkL)abYz=N7xELhlu8Zql64$-KA$dbo4<aSOc9}(_
zNQHrc0qiC}P1ajdDOrhm>G^ue`FWs_&;v&|#QjB}EP0C)svso^9PVI^;E;ltqY6sJ
x95#@swky(LU|?WmU|=W~XJBCXz|6?Vc$dNWE`!V$7I8+l4x6tG;*4xyjQ}AaGJF64

literal 0
HcmV?d00001

diff --git a/accounts/__pycache__/models.cpython-39.pyc b/accounts/__pycache__/models.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..06b64117f518bc5c816e0a6d6b766ae4ae82c94d
GIT binary patch
literal 803
zcmYe~<>g{vU|=|^dMaI>nStRkh=Yt-7#J8F7#J9ebr={JQW#Pga~N_NqZk=MY^EHh
zT;?cdMh16=6y_9`7KRj-RK{lJD3%n~U<OULmmqUA8E^48CKZ<yB_@}I7N-_zGTvg#
z%}+_qDNY7SBV$&WRdEaq45<uJj42FJOeu^}%qdJ!EGf)Utf|Z?ENM)sEGevMOsT9X
zY-vpC%u#Hq>{%Qs?5S+2%qbkb%u$@F>{(nXoGDx>+$lW0%u(E6K5q&il+TmGAIzXB
zaEk@xnke?-lG2paypkw^<ow*+(!9))%J`hr#FW&cTdavGxtV!U?7<KfRRYd16$(CJ
z6;Z5?AQdk~7#J8dnQw9BCRW7fq~@iUWZYs;&dAS9PA$I0o|2lDSejE(#g$lElA-5b
zlwVp9C6ruRT#}y~Us{}66rT<fDh|<Py2VqJnv+<Pni8Lvn45ZwH7O@CFT08#tS=z7
zC^xgXI5R&lN*q~p0bIP;Pm}i+M?6?>eEco0`1suXl+v8k`1o5q@$rSFi8&xs<Kv^)
zgF`}HT>V0#1f2bSeM9{`Ln7mSTpe9pgKn`py7+qfMezjr`?$tCd-!`gy9O6AGcYjR
z;&jePEON_C%}Ke%Qk0*QdW+vTF|RTtA4Ecg*&zP7B>?smlDk$i6p1o0K!{%w`pNkz
zsrre@$@!&uCB^!Xl%Q8oSp-UFAY81%z`(%4$O3}QY>aG-Y=2qU1ejSEnLzL_8!L<j
z*5RkgdP^!LD={xUUoSa7ucRn5Ne>)g5QB@Dz>bG1NJ#>F2CNa`CJ0Lmq>#e~5@vRc
Npac(c4G$v^697LK+!Fu*

literal 0
HcmV?d00001

diff --git a/accounts/__pycache__/urls.cpython-313.pyc b/accounts/__pycache__/urls.cpython-313.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..f4dc712c771852614779519229b64f286d80a267
GIT binary patch
literal 560
zcmey&%ge>Uz`)=bb|u}Dk%8echy%l%P{!vn1_p+y48aV+jNS}hj75wJ48csn%-&31
z%tg#zEJZ8|AUPIqRxh?9HU)+lMkR(|))?kswqSNkW-yN<h9#I2&f|(<3*v*CjYKIi
z1ak&+TQUaofK=);7jdNXYVy4VsnBG+#Zr)1lJSy}fq_Aj=@xf!W_n&}L3~+eYWXd$
zoc#36JTP06@fMd)etLdsNmyoTc@;ZEnf@&{2m@qHUSe))6&qNK{w-E8UB#XQ)}yb<
zc#AVHwW1`xATd4l7D!QkX^EdE=PmA(ti-(Ze7(}5oZ=#81_p*(tRSn4i&z;L7>d|H
z0+LWA$@zIDMVU!@iKQhOdJskIAbIx0Vz3i$ahDe56eO0Eq!#5BuVnZP^4=|1XRDad
z;?$zz7~j<NM1|mz{G!wtm;Ca)oczR;;+XWJ{L+H>f};Ga)Z~)*((+W@+{Dbhn8f7d
z{L;LV;uw&#^a?6(aoFVMr<CTT+7*d1Fff3^s@RQzf#Cx)BO~Ke2ATT|T6Y-?KC&^e
za&|~g@LrH{kwyO|3rB~<1giz^7g=;bY{>~;*G1GWiKuN5zbImPfa4;I=LdEcex^q5
JB4Gvw1^{l^o<INq

literal 0
HcmV?d00001

diff --git a/accounts/__pycache__/urls.cpython-39.pyc b/accounts/__pycache__/urls.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..a26d0697866c0255bed01d4e1c00de3c3e9f0057
GIT binary patch
literal 428
zcmYe~<>g{vU|?82?PPi|BLl-@5C<8vGcYhXFfcF_$1pH3q%fo~<}l<kMlmunq%fs0
z=P>0mM=|HJM6ob}<XCc8bJ?QU7#UI-Q&>}(Q`l12dzn)iQ#evtQaGV(u2i-x_7u((
z?q0?e9*|f%a}-AkZ!m)<-%F6anvAzt3KB~)UNSN;FlaK};x5ii&nqp6FUw3Vzr~f4
zpPrcqW@|Fu;_}H)&o3<r%S<h=VuvWxk79!`K*r=H=B8G$fwk!0Vg=Jx>^WdP`kIVU
zoO!7gCGiD`>8ZCsit<ZK{4_alai?S@=B4NBl@{d`7cns~Fx+AVSzTPj!oa{##0nCS
zgepnS&nqd)Owvm%Ey>V>C}IQ2vnLjVop_78v?!+_v7{umD6e=WLlHm71Q78{Og}k4
yB~?E$IXS;HucTNXWSL$;<t+}I-29Z%oK!oI#l<`f3=BMs0*pM&Jd8YyB7Xs3eRZq=

literal 0
HcmV?d00001

diff --git a/accounts/__pycache__/views.cpython-313.pyc b/accounts/__pycache__/views.cpython-313.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..490bec89c11f8102d00fdb854915497507a1cd68
GIT binary patch
literal 1531
zcmey&%ge>Uz`)=bb|u}Og@NHQhy%k+P{!vF1_p+y48aV+jNS}hj75wJAT|?(?Zs5Y
z1m-h)GkdWVv3Ri-v4Z(5-fUj%MeGU;!K}e--W*<>MVtx@!R%5DMO?ugQVd1h>71He
zFF{slGTve<O3h12Ez)EvVrF1qxW!SFnvz+Rnp~pEbc;17KRq+=7EfYnNk(d3NoI0l
zNvbB}Eg?q)KQlkiEx#!DB_jg^gC^rGuHek{ywC!WP%=meWCsYdF)%QIjQ{)%?4MAE
zAdn~;4ra89U|>iLWMGH}sRhf1G6b=J87PD))a*RQP{ts36e%#r6ihNOXh7*iH3o)I
z#vo287m0$Y%wvk?h6zV7nL@)~fgzd~CK}8HvsHz`p9|qaxCxBW{4lkl48hF7ETN1B
zjHXbZs4!@<`rTp)@DC2T#gdVqn_4B3n4FwnnpaY+U!0kqS6ZN#QIeZ;izO|;C|8r?
z7F%v=Nk)E35y;6!AeY_Z$SjU8OU%hkxy4ePSe9DE%D})-1PU8)ysc!u#a@(JSejZ~
zQUr4HEtb;a)S_aL?FtGCx7?hqVnRUzF}|tki3-6b`9-NQF8SqoIr)hx#WCqc`K1N%
z1x5K;smUerrRAx*xrv#1F)$a#lx3!t7wZ*N-r|P1H6A2TB+9_R0CHb(Is*ek1H%n=
zzV^Dtx*1}Z+2!x>OU_WAuQOBUGQWBU%MEV+e%nsle)~@Q8^Yq#Ehkz|w(fAb!y`CB
z{R)r59bxGiZkL6XFYqXTU}xZw{=&r|Ak|&d!E%RNaDw^;X~PX}J6tx{UFLSWz~b~7
z6vWt*)+fSA%O5#uMPN-@!AzD+bWK*wBqb}BU{<tb#pVZ2ADWD}SW*&85{q~k7#OOA
zVNs_K&cfid1x^>597TMfgagVnV0}fPM0<-PJ+&krlw#15RgoYA0|P7-6^Vcf2rjUR
zkQ5-rz`y_!EY84^0u&dhZ|B*_bCKT`BL&z_w4H2^KLsdV=2wO%0fP-@J4`m{UFLSY
zz~WdW#=yYfr^$0mASEj?FFjwcI3vHPB)PPt7@QNpdE%BZR4zF`ucRn5Ne@(nLHq_P
zif&0_k=6rcz2YKJ$lPLuutBLCoXm?rK3&NGwi*%)95%W6DWy57c0~#d3=E+1s2Iff
nz|6?Vc$Y!>IfL$f2IIR77Ec*uKe2E!Ix~J2<79MV1e*W=bHX-|

literal 0
HcmV?d00001

diff --git a/accounts/__pycache__/views.cpython-39.pyc b/accounts/__pycache__/views.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..da3d75a994d4308aaad2c1e9133b117843171491
GIT binary patch
literal 966
zcmYe~<>g{vU|?w1IG1kE!octt#6iYP3=9ko3=9m#5ey6rDGVu$ISjdsQH+crHWP%M
z%M`@~<}>Fo=dwhx<g!Mwg83{tY`N@F?2HU4tSM|c9J!oPoQw=9>?s^A3{hMuoGDx_
z3{l)E+`$Z*JTF0ZYBJtpD@x5vNiEW3Dgs%2i=!wtC9^0sxkQuc7Hdv^dS>1&p2X6U
zjMTi6%;dz9R87WPLXHT2W`3Sqeo^jAMg|53O~zYX!I|lKp#>nJWRMWZ4iIK$U|?Wn
zU|?_t`OA-ifuV*Wiy?(Eo2kg6gt3Mpi>aBhma&F$0rNtJBD)&K1uP30YMDw{YZz*n
znwc0GO4w4Eni+!`^4Llkn;B{uOW11|QkYX%Y8W#ao0)?dG+F&_u>|-BhumVx$j?o!
z5=l%>&M(a?Db_E}OwTJV(90;v&AG*rmS2>s$#IJ<H?<@qKc$F+fq|ijlYxQZ7Dr}r
zd|6^nX38y=;>5DlA{LMg$j#s|S;>5hy(qP?G_|;-h#RDwrL;J;XeC3D5Ca3lFLC|k
z{FGFExQ%6*spZ9b1(mnBA$G@u1VFYF3xGm`k&BUwk%N%~L^H857Kt!0FyIcVAmpI3
z0R<H(uu_<Mnc%_Ygf+OBF@lRFg%uuLY<^&WYck$qNl7e8ECMCSDq*-6z|js4Gq8U(
zIf{5d0m23%Kt3tr1%(1fdTL2LC?wE=tB4<@4iq-v04fp&Ddqy32@VU8kKtj#ha48-
z3=9l@nmkbgDOrhm>G^ua8Tmye$)zR5;AkiUMaV5-s9bV>UP)1Ak{&2+LL2}}U$-Q&
zNb7;(y|@VE{9CLLHaO}*4k-fJ32`Tyi#cp^^HWN5Qtd$LxEK@wJWK+N0*pLNJWL$i
E0KL-MWdHyG

literal 0
HcmV?d00001

diff --git a/accounts/admin.py b/accounts/admin.py
new file mode 100644
index 0000000..8c38f3f
--- /dev/null
+++ b/accounts/admin.py
@@ -0,0 +1,3 @@
+from django.contrib import admin
+
+# Register your models here.
diff --git a/accounts/apps.py b/accounts/apps.py
new file mode 100644
index 0000000..3e3c765
--- /dev/null
+++ b/accounts/apps.py
@@ -0,0 +1,6 @@
+from django.apps import AppConfig
+
+
+class AccountsConfig(AppConfig):
+    default_auto_field = 'django.db.models.BigAutoField'
+    name = 'accounts'
diff --git a/accounts/decorators.py b/accounts/decorators.py
new file mode 100644
index 0000000..1b30439
--- /dev/null
+++ b/accounts/decorators.py
@@ -0,0 +1,11 @@
+from django.core.exceptions import PermissionDenied
+
+def role_required(allowed_roles):
+    """ Restrict access to views based on user roles. """
+    def decorator(view_func):
+        def wrapper(request, *args, **kwargs):
+            if not request.user.is_authenticated or request.user.role not in allowed_roles:
+                raise PermissionDenied  # 403 Forbidden
+            return view_func(request, *args, **kwargs)
+        return wrapper
+    return decorator
diff --git a/accounts/forms.py b/accounts/forms.py
new file mode 100644
index 0000000..637109d
--- /dev/null
+++ b/accounts/forms.py
@@ -0,0 +1,18 @@
+# accounts/forms.py
+from django import forms
+from django.contrib.auth.forms import UserCreationForm
+from django.contrib.auth.models import User
+from django.contrib.auth import get_user_model  
+
+User = get_user_model()  
+
+class SignUpForm(UserCreationForm):
+    class Meta:
+        model = User  
+        fields = ["username", "email", "password1", "password2"]
+
+
+
+# forms.py
+
+
diff --git a/accounts/migrations/0001_initial.py b/accounts/migrations/0001_initial.py
new file mode 100644
index 0000000..34b418a
--- /dev/null
+++ b/accounts/migrations/0001_initial.py
@@ -0,0 +1,45 @@
+# Generated by Django 4.2.19 on 2025-03-06 22:56
+
+import django.contrib.auth.models
+import django.contrib.auth.validators
+from django.db import migrations, models
+import django.utils.timezone
+
+
+class Migration(migrations.Migration):
+
+    initial = True
+
+    dependencies = [
+        ('auth', '0012_alter_user_first_name_max_length'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='User',
+            fields=[
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('password', models.CharField(max_length=128, verbose_name='password')),
+                ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
+                ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
+                ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
+                ('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')),
+                ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
+                ('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')),
+                ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
+                ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
+                ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
+                ('role', models.CharField(choices=[('student', 'Student'), ('community_leader', 'Community Leader'), ('admin', 'Admin')], default='student', max_length=20)),
+                ('groups', models.ManyToManyField(blank=True, related_name='custom_user_groups', to='auth.group')),
+                ('user_permissions', models.ManyToManyField(blank=True, related_name='custom_user_permissions', to='auth.permission')),
+            ],
+            options={
+                'verbose_name': 'user',
+                'verbose_name_plural': 'users',
+                'abstract': False,
+            },
+            managers=[
+                ('objects', django.contrib.auth.models.UserManager()),
+            ],
+        ),
+    ]
diff --git a/accounts/migrations/__init__.py b/accounts/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/accounts/migrations/__pycache__/0001_initial.cpython-39.pyc b/accounts/migrations/__pycache__/0001_initial.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..41c6efb56fee2663616aff7ded2853aac90f243d
GIT binary patch
literal 2280
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
Spy({-0QrlNgHeEygBbv!#MX-d

literal 0
HcmV?d00001

diff --git a/accounts/migrations/__pycache__/__init__.cpython-39.pyc b/accounts/migrations/__pycache__/__init__.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..ef155c26c26564f4d41fbb44fd05016f668ac3cf
GIT binary patch
literal 128
zcmYe~<>g{vU|^{4Kba1qAA<;F%*epN;K0DZP|U)>z>vZa%%I8Wx00a<B#a<_sp==^
zr=;p9CMV~Y=9Lud=VqoCC6;97=N0S6$7kkcmc+;F6;$5hu*uC&Da}c>18M&ZvIYQh
Cc^kk0

literal 0
HcmV?d00001

diff --git a/accounts/models.py b/accounts/models.py
new file mode 100644
index 0000000..78c42db
--- /dev/null
+++ b/accounts/models.py
@@ -0,0 +1,31 @@
+from django.contrib.auth.models import AbstractUser
+from django.db import models
+
+class User(AbstractUser):
+    STUDENT = 'student'
+    COMMUNITY_LEADER = 'community_leader'
+    ADMIN = 'admin'
+
+    ROLE_CHOICES = [
+        (STUDENT, 'Student'),
+        (COMMUNITY_LEADER, 'Community Leader'),
+        (ADMIN, 'Admin'),
+    ]
+
+    role = models.CharField(max_length=20, choices=ROLE_CHOICES, default=STUDENT)
+
+    # Fix for SystemCheckError: Add `related_name` to prevent clashes with auth.User
+    groups = models.ManyToManyField(
+        "auth.Group",
+        related_name="custom_user_groups",
+        blank=True
+    )
+    user_permissions = models.ManyToManyField(
+        "auth.Permission",
+        related_name="custom_user_permissions",
+        blank=True
+    )
+
+
+
+# Create your models here.
diff --git a/accounts/templates/accounts/login.html b/accounts/templates/accounts/login.html
new file mode 100644
index 0000000..96f3d18
--- /dev/null
+++ b/accounts/templates/accounts/login.html
@@ -0,0 +1,16 @@
+<!-- templates/accounts/signup.html -->
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Login</title>
+</head>
+<body>
+    <h2>Login</h2>
+    <form method="post">
+        {% csrf_token %}
+        {{ form.as_p }}
+        <button type="submit">Login</button>
+    </form>
+    <p>Don't have an account? <a href="{% url 'signup' %}">Register here</a>.</p>
+</body>
+</html>
diff --git a/accounts/templates/accounts/signup.html b/accounts/templates/accounts/signup.html
new file mode 100644
index 0000000..d0f7a9c
--- /dev/null
+++ b/accounts/templates/accounts/signup.html
@@ -0,0 +1,16 @@
+<!-- templates/accounts/login.html -->
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Sign Up</title>
+</head>
+<body>
+    <h2>Sign Up</h2>
+    <form method="post">
+        {% csrf_token %}
+        {{ form.as_p }}
+        <button type="submit">Sign Up</button>
+    </form>
+    <p>Already have an account?<a href="{% url 'login' %}">Login here</a>.</p>
+</body>
+</html>
diff --git a/accounts/tests.py b/accounts/tests.py
new file mode 100644
index 0000000..7ce503c
--- /dev/null
+++ b/accounts/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/accounts/urls.py b/accounts/urls.py
new file mode 100644
index 0000000..301858a
--- /dev/null
+++ b/accounts/urls.py
@@ -0,0 +1,10 @@
+# accounts/urls.py
+from django.urls import path
+from .views import signup_view, login_view
+from django.contrib.auth.views import LogoutView
+
+urlpatterns = [
+    path("signup/", signup_view, name="signup"),
+    path("login/", login_view, name="login"),
+    path("logout/", LogoutView.as_view(next_page="login"), name="logout"),
+]
diff --git a/accounts/views.py b/accounts/views.py
new file mode 100644
index 0000000..3680ccd
--- /dev/null
+++ b/accounts/views.py
@@ -0,0 +1,32 @@
+from django.shortcuts import render
+# accounts/views.py
+from django.shortcuts import render, redirect
+from django.contrib.auth import login, authenticate
+from django.contrib.auth.forms import AuthenticationForm
+
+from .forms import SignUpForm
+
+def signup_view(request):
+    if request.method == "POST":
+        form = SignUpForm(request.POST)
+        if form.is_valid():
+            user = form.save()
+            login(request, user)  # Automatically log in the user after signup
+            return redirect("home")  # Redirect to homepage after signup
+    else:
+        form = SignUpForm()
+    return render(request, "accounts/signup.html", {"form": form})
+
+def login_view(request):
+    if request.method == "POST":
+        form = AuthenticationForm(request, data=request.POST)
+        if form.is_valid():
+            user = form.get_user()
+            login(request, user)
+            return redirect("home")  # Redirect to homepage after login
+    else:
+        form = AuthenticationForm()
+    return render(request, "accounts/login.html", {"form": form})
+
+
+# Create your views here.
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..294c75f
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,27 @@
+
+services:
+  web:
+    build: .
+    command: python manage.py runserver 0.0.0.0:8000
+    volumes:
+      - .:/code
+    ports:
+      - "8000:8000"
+    depends_on:
+      - db
+
+  db:
+    image: mysql:8.0
+    restart: always
+    environment:
+      MYSQL_DATABASE: unihub_db
+      MYSQL_USER: unihub_user
+      MYSQL_PASSWORD: Thescotts111
+      MYSQL_ROOT_PASSWORD: Constantine.25
+    ports:
+      - "3307:3306"
+    volumes:
+      - db_data:/var/lib/mysql
+
+volumes:
+  db_data:
diff --git a/events/__init__.py b/events/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/events/__pycache__/__init__.cpython-313.pyc b/events/__pycache__/__init__.cpython-313.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..81fd327f1a1854dd82d2e08cec1ea1d8efa9c99b
GIT binary patch
literal 168
zcmey&%ge>Uz`)=bb|oD|KL!yn%m`(CW?^7pn97jOpvmaBlA(x+fq~&ONa~imvsFxJ
zacWU<jBjdsqC#*<eo<<SOMZD?PJUuaaZGwqerZ8`K~a8IYH~?@X?dz{ZenI$Olnzb
xUP*CGe0*kJW=VX!UP0w84x8Nkl+v73yCPNw1_qG5#URE<W=2NFB4!2#1^^l*E0O>J

literal 0
HcmV?d00001

diff --git a/events/__pycache__/__init__.cpython-39.pyc b/events/__pycache__/__init__.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..07c93c299966525bb0dc622df306925289af718a
GIT binary patch
literal 115
zcmYe~<>g{vU|?XeJCzQiAA<;F%*epN;K0DZP|U)>z>vZa%%I8Wx00a<B#a<_N$4l%
pr=;qqmZj#E6zj*wXXa&=#K-FuRNmsS$<0qG%}KQb>G%vX833zZ6|n#S

literal 0
HcmV?d00001

diff --git a/events/__pycache__/admin.cpython-313.pyc b/events/__pycache__/admin.cpython-313.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..85bc0c386dbe0456b22170ca5b7fa2e5481a1ed3
GIT binary patch
literal 212
zcmey&%ge>Uz`)=bb|u}Ofq~&Mhy%k+P{wBg1_p+y48aV+jNS}hj75wJ4Czdo%r8OG
znvAzt6H{_C^ZYcKZt<mLCFZ5)>m}#sl@w(r6)`g~Fsx+w3{rQ?#n~z*v^ce>IL0?M
zJy9XJB)=#%#wEWzFDE}Sr8p+ND8IBIzMv>SD>b<!zO+15H#adeFDA7tHLs*N25f^~
pLFFwDo80`A(wtPgA`S)y21W)3hGG!o12ZEd<2?q2A~psF1^@sSI4=MI

literal 0
HcmV?d00001

diff --git a/events/__pycache__/admin.cpython-39.pyc b/events/__pycache__/admin.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..7c49eeed3100ad2cdafa4c41ca39dbccdb6af90a
GIT binary patch
literal 156
zcmYe~<>g{vU|?XeJC$zFz`*br#6iYP3=9ko3=9m#0t^fcDGVu$ISjdsQH+cXDNMl(
zn#?ajYBd>eu_mVEX6E^6GDY#FWF_XM=j$cs=am#?CKZ7USjkYt%)kI4eu?TQ=clCV
ir<SGWl@#lP_30H<-r}&y%}*)KNws5SU|{$RG8O<0(;)i*

literal 0
HcmV?d00001

diff --git a/events/__pycache__/apps.cpython-313.pyc b/events/__pycache__/apps.cpython-313.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..2f869b4099b269e211c70696a8cff4d216864919
GIT binary patch
literal 532
zcmey&%ge>Uz`)=bb|rlR0|Ucj5C?`?p^VRJ3=9lY8G;#t8NC_27>gJc7$g{!7=oFk
z7=oE&7)_ZW>WY}sSu|N+f;gItw>TXO3Y_!v(lXPNK_W2B2xWYh0h<}aP{bI_P{b6>
zSi~I6RKya@T*Mm8QpA?ds>ybX$F(dqucR1a%1ago28Jrxl&r+O^nAUPB)#1Hl+>JJ
zJ*Uic$I_B~x6IU>lv`}6U>z$N{508bam2^xCFZ8a$KT?LkI&6dDa`?~dE(;>OA~XT
zGW_xJX_-aEB{`XSsd@SF@wbFhQqvMkb4ub9OH1<O)4-;(fE3>njgK!bNi4}sj!!Hp
zDauSLElDkok1yh2U|{$R^3*M7XRDad;?$zz7~j<NM1|mz{G!wtm;Ca)oczR;;+XWJ
z{L+H>f};Ga)Z~)*((+W@+{Dbh7>J8w5(^57^$IGBKw%ChK;A9pWnf@vW4Iw{ae+nb
z2DfmtOOXHr0|QvzPm}o;H#9Urnu|cO0G0te38GMtfq~%`hYiH@c16Mr3=E(MC>CL0
cVEDky$jEq?LGcS46Qjrk%dZSfj3QuN0Cc~OG5`Po

literal 0
HcmV?d00001

diff --git a/events/__pycache__/apps.cpython-39.pyc b/events/__pycache__/apps.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..37181a8abb832d49b5a6c91ac678d152b2f0b3f3
GIT binary patch
literal 392
zcmYe~<>g{vU|?XeJC#0xfq~&Mh=Yt-7#J8F7#J9e6&M&8QW#Pga~N_NqZk<(+!<1s
zQkYv9QkYX2o0+4SQdoi+G+AGQ^lCER;&d!1aL&(5%S=xOi6CP}n290`3=F9ZQH&`J
zQA{a}QOqe!Q7kFU!3>%#w|HF3Qu9iRAtqGGrer1NrRVFVB<bbmr=;c->p5knJC>H@
zyJe>4q}*al1uOQ`WWB`^AD@?)n;IW~iz_}pH$SB`2gK%yk1s4u%z?@XrKF}Mmgbbi
zCzh7v$ESgfU;)XkWGDiK1(^6HqMw|flBy3eT0gO%pjfY<vWOWJRG`oR1q%lw3nN&>
qPm}o;H`I+Fl|@Vp3=Ciyuvth1Hv<F1Ee;!q%j`fQQ4CVc!wdkI{agzG

literal 0
HcmV?d00001

diff --git a/events/__pycache__/forms.cpython-313.pyc b/events/__pycache__/forms.cpython-313.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..edcd646bdc553765cd6c930a26c2cc72dc1d859b
GIT binary patch
literal 788
zcmey&%ge>Uz`)=bb|w7~0|Ucj5C?`?p^VRN3=9lY8G;#t8NC_27>gJc7=oFCnZ233
zn2VSd7$g{!7=l@(7=l@27=t*VdXOknW(cQ<HJwe9{UwN_$#{!3Ex#zY_$4C)0|SWX
zT9%quk_?iAVHPOkvj*7q7=|LoV1^>5V8$Y5u#HSo48hE%Ob}H?EWs>Atm&+pY_~YU
zM!Dq|<-P<Nfnp|9HN$5G3^QX`idgj-f|&vti`ashi`dgyG+A%)!Ohb1O)W`$2?`NS
z)?2J4nI$=?x42VMi<65o3raHc^KP-EB$lM!VkybYO})jDlb@Uj5?#sQr^#`PBR)Pa
zF*h|n{uWn!d~SY9X%2|Z6CYn#nwSHX;g63`%PcA`$;r%1&C8FEF9KP0i#0btB{k<3
zTUusnPD=4D(fIh{lEjkC<oLvrlA_F{(vsBT`1m401_p-Dpm4b5;%pTYTAW%`9OIjs
zo~RI9l3$b><C0&Vmy@5EQXG?BlwVp9Ur>~vm6}`<Us|53o12)K7n2GK`{EdIgy<Di
z-eLjywFs0hK#nNpVPIfrW4Iw8+QE8D(6yVbNRokpp-37;fNb{DWGfN^afCsH2#62`
z5nu%pAQng!M3WSV%MK$z(NoL^HvKyj6RR8J7X}asQ3_J!r^$AUEhQ^4FFn5ql!$Jz
zfy1L15;&Z`puhn|bP-4~I2a&$LDt;juz>`%U6DKk0|O|X70WU(FnnNUWMsU{AaR#L
X@(T+yqZ{J{*6I8c`M)xN*kJ7d>_N8B

literal 0
HcmV?d00001

diff --git a/events/__pycache__/forms.cpython-39.pyc b/events/__pycache__/forms.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..9aabdf07b080c83280a5d08b175275127a7f4139
GIT binary patch
literal 577
zcmYe~<>g{vU|<N?b0PgC0|Ucj5C<8vFfcGUFfcF_>oG7eq%fo~<}l<kMlmunq%fs0
z=P>0mM=>)pxHF`%q_DOyq_CzkX0bFgN3o``1v6-}zXX}2$#{!3Ex#zY_$4C)0|SWX
zT9%quk_?hV#>_CAq!<_&QW>HcQy8L{+!<0BQ<z#9Qka^VqL@>dgBdhgZgGMQaLX^s
z#V~{kW{3omA*sw!Ea?m>jEfkfSW}pS88n%z_~1t9`KFd6YO>y9Ey*m&Nxj9Ll3JWx
zlvz-cnV)xyB_**W^%hG>W^U>&j-34DM3AVTCfhBJ`1riU+|>B^TU_z+x%nxjIUqJq
ze0*VPVh%*62o!R+Sab7JQgd#xrDdk(q!h1YC=y^`fDpe#^^@~cQuR|ofl;gv4k5jQ
z%3CZT_ppLO9Ap3oBMW1Z5Ca2)pC(HYH%KoJh~NbgAYp`g5SAcF0;C(Hxfm209E?RE
zKFHN<DOrhm>G?$<;ahBAmlZ>t$>|GnCMZO~iXmpfomvDk^%jQ>#G`hgXe<Vq&%?;W
F1OO-#d~g5&

literal 0
HcmV?d00001

diff --git a/events/__pycache__/models.cpython-313.pyc b/events/__pycache__/models.cpython-313.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..1bf1f0ac9993b8700854969bde01d7e201101eed
GIT binary patch
literal 1314
zcmey&%ge>Uz`)=bb|qbfiGkrUhy%l{P{wCB1_p+y48aV+jNS}hj75wJAU2aXlNWOl
zvjT$zgAzk9vlK%xOAKQW2UHIdWy%cU6tSkWYO=iqaWolkvE}Bcq~;WBGT!1SPAw_P
z%u6p$21&s%8<g=`hY@6X3_}rPFhdbjFk=yO3`-E$(NGmoN{JzuDVW)kv4|~(C5R6y
zh(swdm_m6)95F0GLQoD8g`|Qjh9yW0NeaqDQo%#O6}&MlK{8NnNR$#o41bUUk^qz$
z!xE$fWg=0*EWxan%tb;mEJ12W!ce9XLoiz~yCq|hNHB*KLy>4OXOUPsmnQcuR@buB
zypoqJ3=9k}|1&T!Xfod7%1x|@&q>WoFUhzikYALZn3q|Vni8K1Qdq3Xbc-`TFFqwT
zC$%K?7Ee)XPGU)FN_<{oZfb}o<1L=V(vtl6y!`U`#FUg|MyTx|3d9D*?q?}*3JGNh
z0*Rtw6$VX4KTXD4tR<NxIjNeAw^)i(bJB`IdKGTDI$Onr7N-^!$M~kECn^M&<QJvJ
zxa61T<>V)(6vw0&<(C%37Zl}Zr6!lemzJmM<|bz5#Xy`L14%-91(mnh<Kv4<isIvM
z@q)ds2j%iJFfbJJFfcGQFx=o5?yu^sy1*g%8RWi|41Sv8w>aX#o{W#b#T6f)o1ape
zlNuj?izhz5urx6T<o)>gTm13yX_-aEB{`XSsd@SF@kJmH-{N%6NGx*8OwCCt0$Fm4
zGbFX51kAt1oswFdT$EW*l9``(i_;~sBo!jgl9E`GdW$n8GZ!XMl9`)&iz6pLIT5Uu
z%PqesH8VZWJGHV16nD4y9YaGr;zNU7gW`StU0i)`u{%2kJ3G3#-r|HsVbLvKkPQe!
zxsr=g!LgTEQUprlw?si<kyw(M9G_THQk0ogT9R5EA73QOz`#%>0wM%K1Sq=|fe4Vr
z#jOks3~dZIc!aL=$Xw!)S;2gfN2kH{hLFT{A*D+~N|%LH8oY0C3ts1zzQiqknOnBO
z1&zlqdYxbX62JTk<BR<I4IVcH#I6e{UJ_8e!69&+L*XKa!V0(bek=Vhct(F@W)fs;
z@ch8WAS7{JQ1z0a>IRdGf))*4Us)Jgr64W@xyw(J?G|TBR$^XyzFtZaBoerx{N((+
zG)RcC`hrRout(5*c#FdZ62W#wIt&a9pww3^&A`C$ftit!@h*eRT?U0OEIf=-9d7+T
NojzX~co-p;0|1U$GVA~V

literal 0
HcmV?d00001

diff --git a/events/__pycache__/models.cpython-39.pyc b/events/__pycache__/models.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..dd7106e098e800bd3a6e197810a8db1f7ca78aba
GIT binary patch
literal 828
zcmYe~<>g{vU|>+&eIZ?iiGkrUh=Yt-7#J8F7#J9e^%xi!QW#Pga~N_NqZk=MY^EHh
zT;?cdMh16=6y_9`7KRj-RK_fpX67i?6xLt{O}3XHlQbD`vE}Bcq~;WBGT!1SPAw_P
z%u6p$21y}fR+vR83=9mZ3{i|J3{gy}%vmfcj44dLj8Uwq%nR5SGDNYbGB4m*$PmSu
z%DjMUAwv{5k{X^=<}BV+zAXM!<}3k_lX{t>1XG!_gi=^j*m@bGgj3j4I9eE@L{d0|
z88o?WvAUL}=9Rqs&%nT-$#{z^H?bl<Cp9m<BqK^7zbHL1FS9B&B|a6TrdX5d7H585
zd`fCgYDwxXo}$#8#FEsM_`Jm2)DTU^TRe%SCHe7r`Q`D6DJjW}NFD>RLD(4-h-?fD
z3^fc{48aVVjDDJow^&OuOL9^*8E>%^r{<)sWGLccU|{$qrk|XjlBy4}SRWF0dIgoY
z*yH1iON!#-`9Vf8f$U(c;stv_4=UrQDSC?|9_*_4_*-1@@wxdar8%kb@wa&5;|og@
zb3pEmk1qmgzQyUBkyzxGnVOSQ1WE(9I73n^O2GVE+$pKW$wiq3C7Jnow>VuAOHv`?
zEGda4skb;oGIL=9C7HRYw>Wb0lM}&ex!m%LQZv)@yi+TSm>C!tZt**YhIqt>2D=8u
z`}(`M`rKl7b_{lQba9R1gavWYEnbifa6_ZGl8aKop_^Dz#K*t@2^DbAKnPxt7${+a
zaIpvj0|N&m4<iQ{@-VV6a{Xsx=3y!V$@*!s-QrBiO3X{o*Gox)_?sKbPtMOvgE*4a
i7nDB18Xz`+q5;AJ*>#J<1`>{TpolC6najh-!vp|*pwpND

literal 0
HcmV?d00001

diff --git a/events/__pycache__/urls.cpython-313.pyc b/events/__pycache__/urls.cpython-313.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..6e92f1c16f9a755e6408ae0499c87a268fe41634
GIT binary patch
literal 458
zcmey&%ge>Uz`)=bb|u}9k%8echy%kMP{!vV1_p+y48aV+jNS}hj75wJ48csn%-&31
z%tg#zEJZ9{tVOH}3^9yK48bfh%)zX|Y?jPm9(xQ+FbAB+8N(XP1>)&57qO*tYx2AV
zS)j>yi=`m3B;zF`0|SF5^DVB_vedki_?*n*l3P3wc1mhVVrI@Qp5&s`#FEr_u;49*
zB36(F##=0TiMgp&{5F|+C01am_{<bL{USC728Jqjh!*`Kb_NCpKTY;q+$mX!dFlCj
zrA0Z#Ma&Eg47XUzGE>Wo!G?kLfR*0jE-lI_NGvHyEy^oi$?zHE&|A*VRxzQ)sYS&x
zzNzVn3c)4$MX50^`Q>>z`H3mTG3iD5r3LW?Mfq8&$tCfn<*B;4iJ5sZU?&yFfGpH2
zsJz8tlbfGXnv-f*B*4JH0P=IO4Fdzi2WCb_#=8tM_ZciNGFX1(U|{9!5bB7Uk#mtn
r`z8y=1x~3MJ}c@jve?~Z;pmW@;Ip9aB8%Avb{2l7M(!d$1_lNIIAVQt

literal 0
HcmV?d00001

diff --git a/events/__pycache__/urls.cpython-39.pyc b/events/__pycache__/urls.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..ee5c8912770e457abb17b6d4f2f1e379b14f02e8
GIT binary patch
literal 354
zcmYe~<>g{vU|{e$bRj*Gk%8ech=YvT85kHG7#J9eeHa)RQW#Pga~N_NqZk<(QkYVh
zbC`0OqnLA9qF8cSqgWXkQW;ZNQkhd&Q`mZ$QyEj(Q(00tplr@m))X!fJDoX-ErmOn
zL6het$R16`TPy{MB^fUn85kHenQw8WmZj#E#OGudm)zokuv1b?5;Jpd@gx_eCYGee
zg9UFf6tRFbFy3OxOUzBJ;<w4nE3pDg#b>72=@+pwFfdfHL$v4@u`w_(_-V4=;!ep*
z%uCPLD=o??E@EO}V7SFvmYG^!3^oj`2dwlKcWF^hL1IZsYEfSCN`@jH1_lW6OGH08
rKP6QkY*Dd3$QZqX%3B;Zx%nxjIjMFaPZWa!l!sA-g@=)ck>@V}XBJpK

literal 0
HcmV?d00001

diff --git a/events/__pycache__/views.cpython-313.pyc b/events/__pycache__/views.cpython-313.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..0637b9595f1cf1bfd3006bdac8d8f2c183d68728
GIT binary patch
literal 1821
zcmey&%ge>Uz`)=bb|rl(3j@Pr5C?{tpp4HE3=9lY8G;#t8NC_27>gLan2MOZn2VSd
zKw?bZEMBZdtO^Xl%)u<)Y+md|>|i#lH-{Hz5vKw}Fq;%Z5mzv~6hjer3~Mll6oV<$
z;3A%MPED?tAf6`kEw-Z6yp+_UTY~ASCGq)5S*gh-@%csZCI%+AIEqqJGK*4^OEej8
z@#W;FXXeEhr52WE7Nw@VWMp7q&}6*D>ROhX2a@LmGu-lva+5()Aj3hJje&uInSp`f
za~0S#(I7D}4uW|T%!3d?tPmQRggH8h9a$8@4rVlk+Lgx`%?S}>U<hRhW(sBwWi((k
z1=-BNz@WmQ$>Mj5B_**WwMr}%<ltg`FcqJZSzMx*QIeZ;iw!JLtjSu$!N9<9iyaaY
z#kZIfb8>ER<QJu+7R4u37J*FEWV*!;3WwC<k|G`k28LpgR}>U(xj0+Jgche37039d
zrY9-{m*f|v#<=8{=jG%lrWD7d7v+~0#1|ChgM+xVJXJS0F*7d)VsA`YW@>q{UP0w8
zF0cUDWko^^3=AND7n?9JFf=gS;T7tS?To$7D|eAs?lP~!bzaSjyqYW2F7p~TxZU9v
zoS=R|+IU080k#XK?w7eeF0gof1_eqo$bBFN2*V@91`;9A0Ayf@hN}u?3}&=s%43R#
zM+Y=Wnb3k%lkpZ)W=fR=*u}6QO-U_D%*=rVDl1q<levh6fq?-Wu#f;`E)oC*G6z^X
zJ~O3A3>1u@uvJh{C=vw8@j&DtrWHvrFff3FS{V`$JhF3AS8!b9F>G*!`rC8|`vK7l
z=1_kZ2{SM-U{8oyjG$Z<$`Aw!4K$1`Q3f+wl`}9Tax*X>!Xuaomhe;<LK%WUVTxu_
zFtb$z14CjO0|Rox3<BqRRHZPJ@)$!IgLqNpKs;Cm&;W557#I?*85lwtgZQCbBr2FC
znAMUoj|scqLYZ<vDI2UllnI-Dm`w^eeCp4I@C!_B9%D2ps3E2@1hWORqh&k}zgq&y
z`MJ5Jd6^}Z@j0o9DXB%^bbX5@z&|*|O_T8!8%RF01TAZ(<rn2bQV|P?smXPVrL;J;
z=oU*+eokr;C~4ke%S|oG$WJK(W&I*)P^#g`ERHWr%*jl-#ZsJDmU@dbzbHL1FS9DO
z2sz;u$%2w2mNb`Kl$uzQ8V^o-MJfyo44|Y~JPn-Y9<cMZ*EH5#XP3ChE^$Fd?=rjI
z9e(i{JeT=ZFL0=WWa}F1W{6#8m%qa=F++U5%uJcf{AwL6H@NxxZ98rI?K|ynh)7KL
zoanhAbb{vv5$z7w8*-}ib7tmrxc2zp;1TTi>h$XIxg#t+!{@TF<^>+j51b4<(qDKO
z1SGqwJ6N8;@^{*flnrs0xm_->xPX(npC<1uft0Moy!3p%;*9*FlH}5oVz751*$y03
za!>`y`FSNpnMrzyr6n19DXGc%MTsT(Ma4y+Bz%i4H$Npcrx=`3Z?S?xy%-X<pmGSD
z2f=}|k^yWlB%gBF<mRW8=A_ycX)!P`fJ&2MGX@5R56p~=jQ1HFE;2aWWw5-<AbFQT
g<`WweqbK7hE)e;Fi-AetBNHE^E8}NoI1_9x0M=Q6iU0rr

literal 0
HcmV?d00001

diff --git a/events/__pycache__/views.cpython-39.pyc b/events/__pycache__/views.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..a3d48a69ccce03e41d2399db0a1989976706d79e
GIT binary patch
literal 1154
zcmYe~<>g{vU|{Ine<6J;3j@Pr5C<7EGcYhXFfcF_M=&rjq%fo~<}l<kMlt3xMKR?v
zM=>*k#F%nea#^ET85vTTQ&@7?a@nKU!EDwXj$F<tPDX|lwiNajhA6HSjug%ohA8e-
z))cN3?iPk-#weZ?o?r$|-j^UdHJNX*6{Y5-q!!&0OiwL|&rixqO)iPgFN!xYFuBE1
zl$w%Rl$u<k$#{z|CqF$iFTN<Xur#wMHRUBE0|SF5<1JR#veZ0~JSUjpmS2>c43YvF
z4#G?f3=FIc3=Ga74=FG(FqAN4F)m<Q$gqGpg>fNcEn^8w4MPf33Udu(CSx;mFoPzG
z-z}Du#FEr1u~d-J#rj|>J}0xdL@%QxH|G``SfE&wwTPX8f#DWA#LdOGm=kkyZgJ!n
zrKA?cCsh`KY}RDD#SU_DYH>*sD9~3j6!9}KF#HnLPtH$Cg_vBdUzV9#UaVJ8d5a5d
zGT17R(ZwtvA213q76~#iFeHNv1POpJD30LXk^y_Ggt3M(g|U~ZmZ^jZ>Ln()moyn~
zF=eJyNq{YYc_}5eBr!7w;we_Jj3#pt$Yij`ARb^Y;$vW7h~fZC$7iM#2{SN2JOTDe
zkpL(Ncp$P6^LRiZ4RJXSW045R<;W2NG9T{p90mr48ip)}EXEYZY~~`75~dWUX2xKU
z7;_49Hd9d;D0;G3n;B~vYZw=>Eo3N)sbS1wPhm-6?PaWG0_m+`isz_dTEM=Lfsp~G
zKaZ`1rJ13Yv4pb*oD$)Y%i(uRAUQubw=^%aq%uAyH8CZ%2pqb%SOWZmL)<hOZ?S>o
zGfU8-KP|r~7ZOq|Af_hQEtb;a)S_D~Mfo|YMIi6qV#`e}$;eMB;sAw^7${sgGK=HO
z5_2+BZm|?6mZjd}%r8n$%*(7wEkX|5A_<TNtl^qml$uzQ8V?R$P#P!(8Oy-L!^pwJ
z#mL3T!N|kN!N|eL#l*%`B+tOW;HSxZOCTjHF)uw|uQ(&Ws3f_xq!?@$BwoSpl!Gcr
z&d)0;%1qKrEG@~<OG!=6FG?)QFDfnq#m+6Z-29Z(oMLcFxWx+caxuhXAZLJM6>K3S
n5rEP(gau9x95%W6DWy57cA$7K2BjYnMjjAk=3wPuWnu&XE>scH

literal 0
HcmV?d00001

diff --git a/events/admin.py b/events/admin.py
new file mode 100644
index 0000000..8c38f3f
--- /dev/null
+++ b/events/admin.py
@@ -0,0 +1,3 @@
+from django.contrib import admin
+
+# Register your models here.
diff --git a/events/apps.py b/events/apps.py
new file mode 100644
index 0000000..20f48f2
--- /dev/null
+++ b/events/apps.py
@@ -0,0 +1,6 @@
+from django.apps import AppConfig
+
+
+class EventsConfig(AppConfig):
+    default_auto_field = 'django.db.models.BigAutoField'
+    name = 'events'
diff --git a/events/forms.py b/events/forms.py
new file mode 100644
index 0000000..d8efb62
--- /dev/null
+++ b/events/forms.py
@@ -0,0 +1,7 @@
+from django import forms
+from .models import Event
+
+class EventForm(forms.ModelForm):
+    class Meta:
+        model = Event
+        fields = ["title", "description", "date", "time", "location"]
diff --git a/events/migrations/0001_initial.py b/events/migrations/0001_initial.py
new file mode 100644
index 0000000..d3ece7d
--- /dev/null
+++ b/events/migrations/0001_initial.py
@@ -0,0 +1,30 @@
+# Generated by Django 4.2.20 on 2025-03-11 22:38
+
+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='Event',
+            fields=[
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('title', models.CharField(max_length=255)),
+                ('description', models.TextField()),
+                ('date', models.DateField()),
+                ('time', models.TimeField()),
+                ('location', models.CharField(max_length=255)),
+                ('created_at', models.DateTimeField(auto_now_add=True)),
+                ('organizer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='organized_events', to=settings.AUTH_USER_MODEL)),
+            ],
+        ),
+    ]
diff --git a/events/migrations/__init__.py b/events/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/events/migrations/__pycache__/0001_initial.cpython-39.pyc b/events/migrations/__pycache__/0001_initial.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..9ff70ed178a0d1e18a7bf8a70edba9b2845be094
GIT binary patch
literal 1075
zcmYe~<>g{vU|{gveIZ?qg@NHQh=Yt-7#J8F7#J9etr!>>QW#Pga~N_NqZk=MY^EHh
zT;?d|T$U&nFrPVxHHyuhA%!J{wS^&tHI+Gwy_q?RJ%u@#L6hwz$W%?nTO7ryB_)}8
z>BX8%x43dM(~A;IGV}9_Z?Wa(r=;c-`z3?aA!B}+3zji3Fr+d>F{Us?F{Lm@F{iRD
zU`=JqVqeIZ&KSj!%96#I!j!_C%9X{P!kEGcazzSTFH0Iz3VSM77EcOC3TH248dC~a
zD%S$ug$!v-Dcq@C3;4h+o>Z;{{9qO@idw!@t}KBR#uR?APJvXeEWuQvEa5D!ERihH
z6hV;fDMG!>X-w%HDZ;%>>5NfgDI&oPnxeNjePLb;xy9;QmYP>`izze3?G}@#izdr0
zp2X6U{P^Ue)Wnk1lv~^dMVYyYMV0Z{sg<`li&Kj-6LT`FQg88;r4}XS7pKPOCFZ8y
zVlBxm$w__rpMilvlkpZ;Zem4zPHJ9yNyaVil+@znqRawNK;B|WNi0dd#Zr=)n|g~Q
zCqEe+ytlZZcEu-_Xfi^r&&w~5PfSU<#hG7}o|u<em0EO50LDy-PX)QTSd;k{XMSFM
zN@`AON$M@0qSPFaiy;nTD#_Pmy2S!^99vpuYEDYApQiXNj(D(ieEco0`1suXl+v8k
z`1o5q@$rSFi8&y}@$t9VGxIV_G81!(m>C!tZiy6^Cl(YWCgr5Yr=%97=B1?OC07<P
zfu#5yLqj~`LxWv|;(h&HTzziwz*S_X7T@A_1_z-pDCrb|lIkrUr_6N6(vo~Pkb7=%
zI%gynL75?`6(vxnOJYeXlo^tl3uW?xL=jvrxBQ~i%=A3()XH0IDOrhm>G`*qQj%_Q
zfWsm)KkpX1vtzKcql@b;uKa>jXfj^OP-Mu!03m*<>nG=@r0PRLQXi4l^$iRR4CA3e
zpjS{?#LB?HzyZo+3Lpj(3p3Y$7FHHUCMFR^K1MDu<YVMxl=;E*kL5pDwI;_cZiu7w
zlJoP@Ac4gR6-h|~hbtsNB;kU3kQ}B5^FWaf$fY2=5pIUCj6gxpVFQUgJ5U@IvoSC*
L@GuH6axen`(oR3T

literal 0
HcmV?d00001

diff --git a/events/migrations/__pycache__/__init__.cpython-39.pyc b/events/migrations/__pycache__/__init__.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..37c89e2a65040891a4a594bcbedc537cf624664d
GIT binary patch
literal 126
zcmYe~<>g{vU|?XeJCzQiAA<;F%*epN;K0DZP|U)>z>vZa%%I8Wx00a<B#a<_DeEWa
zr=;qqmZj#E6zk_^rWYlaWaj4;>&M4u=4F<|$LkeT-r}&y%}*)KNwouM{tU7N0N70$
AC;$Ke

literal 0
HcmV?d00001

diff --git a/events/models.py b/events/models.py
new file mode 100644
index 0000000..5913ad1
--- /dev/null
+++ b/events/models.py
@@ -0,0 +1,18 @@
+from django.db import models
+from django.conf import settings
+
+class Event(models.Model):
+    title = models.CharField(max_length=255)
+    description = models.TextField()
+    date = models.DateField()
+    time = models.TimeField()
+    location = models.CharField(max_length=255)
+    organizer = models.ForeignKey(
+        settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="organized_events"
+    )
+    created_at = models.DateTimeField(auto_now_add=True)
+
+    def __str__(self):
+        return self.title
+
+# Create your models here.
diff --git a/events/templates/events/event_detail.html b/events/templates/events/event_detail.html
new file mode 100644
index 0000000..d11f455
--- /dev/null
+++ b/events/templates/events/event_detail.html
@@ -0,0 +1,7 @@
+{% extends "base.html" %}
+{% block content %}
+<h2>{{ event.title }}</h2>
+<p><strong>Date:</strong> {{ event.date }} at {{ event.time }}</p>
+<p><strong>Location:</strong> {{ event.location }}</p>
+<p>{{ event.description }}</p>
+{% endblock %}
diff --git a/events/templates/events/event_form.html b/events/templates/events/event_form.html
new file mode 100644
index 0000000..cc7b8c9
--- /dev/null
+++ b/events/templates/events/event_form.html
@@ -0,0 +1,9 @@
+{% extends "base.html" %}
+{% block content %}
+<h2>Create an Event</h2>
+<form method="POST">
+    {% csrf_token %}
+    {{ form.as_p }}
+    <button type="submit">Save Event</button>
+</form>
+{% endblock %}
diff --git a/events/templates/events/event_list.html b/events/templates/events/event_list.html
new file mode 100644
index 0000000..509e014
--- /dev/null
+++ b/events/templates/events/event_list.html
@@ -0,0 +1,16 @@
+{% extends "base.html" %}
+
+{% block content %}
+    <h2>Upcoming Events</h2>
+    <ul>
+        {% for event in events %}
+            <li><a href="{% url 'event_detail' event.id %}">{{ event.title }}</a> - {{ event.date }}</li>
+        {% empty %}
+            <li>No events available.</li>
+        {% endfor %}
+    </ul>
+    
+    {% if user.is_authenticated and user.role == "community_leader" %}
+        <a href="{% url 'create_event' %}">Create Event</a>
+    {% endif %}
+{% endblock %}
diff --git a/events/templates/home.html b/events/templates/home.html
new file mode 100644
index 0000000..8e6f219
--- /dev/null
+++ b/events/templates/home.html
@@ -0,0 +1,2 @@
+<h1>Welcome to Uni Hub</h1>
+<p>Go to <a href="/events/">Events</a></p>
diff --git a/events/tests.py b/events/tests.py
new file mode 100644
index 0000000..7ce503c
--- /dev/null
+++ b/events/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/events/urls.py b/events/urls.py
new file mode 100644
index 0000000..7377619
--- /dev/null
+++ b/events/urls.py
@@ -0,0 +1,11 @@
+from django.urls import path
+from .views import event_list, event_detail, create_event
+
+
+urlpatterns = [
+    path("", event_list, name="event_list"),  # Show all events
+    path("<int:event_id>/", event_detail, name="event_detail"),  # View event details
+    path("create/", create_event, name="create_event"),  # Create an event
+]
+
+
diff --git a/events/views.py b/events/views.py
new file mode 100644
index 0000000..eacb72c
--- /dev/null
+++ b/events/views.py
@@ -0,0 +1,32 @@
+from django.shortcuts import render, get_object_or_404, redirect
+from django.contrib.auth.decorators import login_required
+from .models import Event
+from .forms import EventForm
+
+# ✅ View All Events (Homepage)
+def event_list(request):
+    events = Event.objects.all().order_by('date')
+    return render(request, "events/event_list.html", {"events": events})
+
+# ✅ View a Single Event
+def event_detail(request, event_id):
+    event = get_object_or_404(Event, id=event_id)
+    return render(request, "events/event_detail.html", {"event": event})
+
+# ✅ Create an Event (Only for Community Leaders)
+@login_required
+def create_event(request):
+    if request.user.role != "community_leader":  # Restrict access
+        return redirect("event_list")  # Redirect unauthorized users
+    
+    if request.method == "POST":
+        form = EventForm(request.POST)
+        if form.is_valid():
+            event = form.save(commit=False)
+            event.organizer = request.user  # Set the event creator
+            event.save()
+            return redirect("event_list")
+    else:
+        form = EventForm()
+    
+    return render(request, "events/event_form.html", {"form": form})
diff --git a/manage.py b/manage.py
new file mode 100644
index 0000000..497afbc
--- /dev/null
+++ b/manage.py
@@ -0,0 +1,22 @@
+#!/usr/bin/env python
+import os
+import sys
+
+def main():
+    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'unihub_project.settings')
+
+    try:
+        from django.core.management import execute_from_command_line
+    except ImportError:
+        try:
+            import django
+        except ImportError:
+            raise ImportError(
+                "Couldn't import Django. Are you sure it's installed and available on your PYTHONPATH environment variable?"
+            )
+        raise
+
+    execute_from_command_line(sys.argv)
+
+if __name__ == '__main__':
+    main()
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..fabc354
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,5 @@
+Django>=4.0
+mysqlclient
+djangorestframework
+pymysql
+cryptography
diff --git a/unihub_project/__init__.py b/unihub_project/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/unihub_project/__pycache__/__init__.cpython-313.pyc b/unihub_project/__pycache__/__init__.cpython-313.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..77b1621ecfe7f0844cf92f21e92efc123645fae2
GIT binary patch
literal 176
zcmey&%ge>Uz`)=bb|oD|KL!yn%m`(CW?^7pn97jOpvmaBlA(x+fq~&ONa~iqvsFxJ
zacWU<jBjdsqC#*<eo<<SOMZD?PJUuaaZGwqerZ8`K~a8IYH~?@X?dz{ZenI$Ole+b
zMrjgEJSILqGcU6wK3=b&@)n0pZhlH>PO4oID+2=q$o^sw<0CU8BV!RW0|Ns9$-6G*

literal 0
HcmV?d00001

diff --git a/unihub_project/__pycache__/__init__.cpython-39.pyc b/unihub_project/__pycache__/__init__.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..0c893463e52528bb5219b3f6587d4cf85c5371ff
GIT binary patch
literal 123
zcmYe~<>g{vU|=}yb|M`_KL!!Vn2~{j!GVE+p_qk%fgyz<m_d`#ZzV$!NEku<QqWJ%
xPf67;&CARvO^Pol%FjwoF42#V&&<m#iI3MSsJz8tlbfGXnv-e=()k%=0|4Pe8PWg%

literal 0
HcmV?d00001

diff --git a/unihub_project/__pycache__/settings.cpython-313.pyc b/unihub_project/__pycache__/settings.cpython-313.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..cb8c527d375feb8531c6c77abea1dd56c24c28fa
GIT binary patch
literal 2792
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

literal 0
HcmV?d00001

diff --git a/unihub_project/__pycache__/settings.cpython-39.pyc b/unihub_project/__pycache__/settings.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..92d747bfaf1605954944f125db7e4cd20b58e124
GIT binary patch
literal 2449
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
a@GqACEJ7^*nOKnUHx^+QCNN}UVFduE21o}0

literal 0
HcmV?d00001

diff --git a/unihub_project/__pycache__/urls.cpython-313.pyc b/unihub_project/__pycache__/urls.cpython-313.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..c725bca990714f571f369a13026b258e0f8067c8
GIT binary patch
literal 1289
zcmey&%ge>Uz`)=bb|syig@NHQhy%l%P{!v?3=9lY8G;##7=jstnY<ajn2MMbKx}4j
zW-pc^7BAK!Rt1J&mS9$IHZS%fb_IqQ7A1yYwiu=$0jL>BRFDu72g)>Mf-u1P*kf3g
z7=k%W86jdQa-3i}F069gG3>!S!Mv8t`Yc6U>3o{}iLFcw3|yf>J_^bCd1;yHrA3J)
znfZANY57G8rFoedrAhGxMfq8&$t4O<T91n>BqLQJp|mKcAhDz*wJ5JRK_MrzxJ02S
zzqBN^SRpjXr&ysRU!g2BwY*qQ!7aZ?AveD$RUtDkEx#xiVthePYGQG!LUC%U6_<j7
zf<i_~NkOrdzJ5x6a<N`YR$^XyKFqr0{9OIiJbhC=L;aHcg3RP%eUM`P(xRMVeJ<CE
z#N2|M)M6_xx6-_1u*<>Lf(<p)Q*ca4QAo^F$jmLsFDkK8P)IAv&sE5+j87~mfC@sK
z307|eRS)t3$OA||v{FzgNG!?FP*>N1Xwb{Z&rQ`)$V<#kwN(eP)it@Ca}tY-b(0c{
zQ&S*{z^3AIMSe*}Y7xjGdSDmBoa2$7n+n!Pq-#Lx^%9HYL565(qPfU3FFB_)B{MHw
zAu$hZAINK<hz8qWsHflw4j6@!3{dod)TU}^Dx^V!(h3q>km%3@1vt!+nP78Mb-;lF
zHj5b7CgtR(>#OT1Ky_=Vg9O0ls%vU;y#ys?O~zZSi7C06d74bOSU@3uiyf-^B`B$D
zGT!0@1vc2XRcv6D`c<5X$;tVpc_qdARlG1J*w`xe)Us5tI5&g=7QMxAiv?teCgUv@
zQ2hC6a^GT)k59=@j*q{^2lZ`oeqKpYW>OI|0|Ub?Zm1wA2#Q!37#NCJLBgz{FfT4*
z2eDa-GfPr$v4B+E;zmk1D;Yk6{B_IQ*(xTqIJKxa#y2%RQ6ab_zbG}vCBHl`CqFTz
zI3~R)zqA0B)8b3ZQ+0C_GxK6lb6^a}biIPgTO2mI`6;D2sdh!83=9mQfGLh*U|{&b
z%*e?2k%^y?<*Nb%qvCxA)w>KbAK4gKIXfgKm`=BvXf@q_qWxtS<(n)V9nuriXXIZN
s)4R-~58_Hrbf4jSSw!nHi#CWW)Dbx&>>`WG2ToRgrbg}}VFm^U0GH5x=>Px#

literal 0
HcmV?d00001

diff --git a/unihub_project/__pycache__/urls.cpython-39.pyc b/unihub_project/__pycache__/urls.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..476840f2406d3b785ac9d1d402638f6149707e40
GIT binary patch
literal 1089
zcmYe~<>g{vU|`VWxs<NR!octt#6iX!3=9ko3=9m#DGUq@DGX5zDU2yhIgGhXQA~^=
zHggVhE=v?kE^8DkBSQ*H3TqBqE_)O^BSR`n3R@~u7DpCmGgB%{3VSMR3P&>|n9Z5W
zn!*KTbEmSW@TBneGN-ddai#DDGidTBwlXm=aD@i>C?x0SrDdj<7A2Ns=I1G-<rgWG
z=4ED-CdC&N<!7ZPmncAKJua@0j8uh$(xRM##FCQKqP*e+g`CXd5{07t(vs9-h0q|M
zVug}?g|f`l@?t#&xBMc7-29?ch0MIP{Gwcl@dY`liN&c3#i^-QTnY*b3K=CO1;tkS
z`YHLz#d;}OiFxVyFzb@@bM;g6^iA~)^-J;#GLwt-L5lTDi*kzfxm+s}a|?1(i><ia
zO7oJzE(co+Hq=m0!7(L8Au&%OGq)hWsKiP^A+0DsS0T4DKCz$xDhP2VSiKQcJ;(<j
z4<Px_N<pC@u_Qx7U0nyFK`$deH&sU=FEKaORvpAv*W_}}Nh~hbO-d|IO@Sx^n~KX7
z`6U^tMIeXhfn5x9jz@lODp((pt^ujnODv8D8KR+y<|5C$<ebu!%)E4k#5}NlAg_TU
z8f=51o`NShU=&I+K+ywIo2sFykOmD(D@brbqC*c9;4nvKg3V3U0S5}$EMi=nl#`#X
zudbs2)vcip5&)a4uBplO5|k4(8E>&BrsQVkX)@hn0fqQ2cBtx?j0_A6nvAzNL4ghS
zZ510>rG6D>VsdhRX<kXOeibi_2{yKhJ+&+qEY1yKfJJXH++qP4qRDuR1r&dNn%uY8
z<Kt8EljGx~_@KT`&d)0;%1kO^Vqjpn#SIk%1wj!r0|P@53rLt16z0W6Y#=sEab`*C
zEf$c9Tii$qXC*_C07wIf_$8yCoS%}akD9N*DOs<e@)n0pZhlH>PO2Tqr^O%*ECM`?
N0*pM&Jd9xY2LSOTPU`>w

literal 0
HcmV?d00001

diff --git a/unihub_project/__pycache__/views.cpython-313.pyc b/unihub_project/__pycache__/views.cpython-313.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..1e59009d6588ca854fc5532d6fc070549160e1d1
GIT binary patch
literal 377
zcmey&%ge>Uz`)=bb|t-^fq~&Mhy%k+P{wC51_p+y48aV+jNS}hj75wJ48crN3`I=o
z%$h7OL5fx~-eN0C%}YrwN@fJ{p_qk%fq|KUf#I_h*nnubTqr{@qbbyQ6$VWvzbej*
z{M=N%jFQ}(B9IPE##`(~sfDGf#U;fcT?)5+oULL)i&Kk=V|-K76BU9>@{3YqT=L8F
za`F>Xieu7?@=FWi3ySiyQj<&KOUqMra}zW3VoLKeGfI<S;xT2JspZ9b1(mnJ*2ROk
zMI2B^7V|SOFf=gS;TD{rKEwJlxB3MZ_0J%W_-QiV5=hBP%uCPLE6&I-DoHLaDJ}x}
z4Xk%1LlGwf149uz0|Ub?4x8Nkl+v73yCNP21_qGJi+LFs7(OsFGBVy}Q2xxq$fyBU
F4gdjESu+3t

literal 0
HcmV?d00001

diff --git a/unihub_project/__pycache__/views.cpython-39.pyc b/unihub_project/__pycache__/views.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..91529644c8eda20741bd3dd07afca03ab6032b4c
GIT binary patch
literal 294
zcmYe~<>g{vU|`t7eJOo10|Ucj5C<7EF)%PVFfcF_OE54nq%fo~<}l<kMlmunq%fs0
zw=hI8rLY7uXtKTp=~>Bmi>)X%FD11onGwW?Vi22|fq}spWDLl*5{4Rv6vk$zU<OSl
zzbej*{M=N%jFQ}(B9LX8jJMc}QVUB{i%V8A6tOZeF#M9$PtH$C)i2G<%qUHYFDS~-
zN=+`&FUw3VFV-ulyahHO9>fLNQVcSLfw734fq}tKllhiFN>*ZCdcIz9Mt)IAa%o9%
h5l9tS8f-ce!N$PAaErqxH$SB`C)Ez*Y_MTGOaKL;Jn#Sj

literal 0
HcmV?d00001

diff --git a/unihub_project/__pycache__/wsgi.cpython-39.pyc b/unihub_project/__pycache__/wsgi.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..56c909a3d223001ddc5f74ef328b5ad153c132e7
GIT binary patch
literal 540
zcmYe~<>g{vU|=}yb|QT#BLl-@5C<8vFfcGUFfcF_8!#|1q%cG=q%fv1<uFDurZA>3
z=P>0mM=>)pq%vl)EMQGxNnu^c#K@4!+{_TgmckUwpvhKsk1IUb-BTesKQApaT_G*M
zNTD<@Gov&qzMv>SD>b=90ZQv}ae0;~q*fH<7pE30lw_nTK=dW%<Rm8Lq$(s9D<mr9
z=BJeAr0V9RmZjz>lqD8rf~E2jb5m0k5)u*%3UV@&6H7Al^AZyDxVYT%ixhJ6i&7Ob
z^V0H*a={V``FRQ@8JWcjX_+~xIts<9sazQ)B?ZM+`uZvP$;EmpS&4b+`7k#n=jZCD
z=INX28R}=`mzU)0r=%9-<X7gV=9TD|7pG_HbG-zGm7gZ#Es^xpl6a6<Jd!hRiMe<=
z`nmhZ2fK!Zc>1{q$NT!bg!;HviK7OBUU6zkNoHPpu_pU1_W1ae{N(ufTTJ=Iw*(;W
z(M!%RO4S3IUc|(}z;KH_HLonQC_nEOS8-}dN@`kSX->&4ZX}CWG8BQL6-@k+(NE4#
kN!3TS66}7xg34PQHjq%YV+6%A2Ll5G3nvE?4-+2~0A7ly^Z)<=

literal 0
HcmV?d00001

diff --git a/unihub_project/asgi.py b/unihub_project/asgi.py
new file mode 100644
index 0000000..02da321
--- /dev/null
+++ b/unihub_project/asgi.py
@@ -0,0 +1,16 @@
+"""
+ASGI config for unihub_project 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/5.1/howto/deployment/asgi/
+"""
+
+import os
+
+from django.core.asgi import get_asgi_application
+
+os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'unihub_project.settings')
+
+application = get_asgi_application()
diff --git a/unihub_project/settings.py b/unihub_project/settings.py
new file mode 100644
index 0000000..745d403
--- /dev/null
+++ b/unihub_project/settings.py
@@ -0,0 +1,137 @@
+"""
+Django settings for unihub_project project.
+
+Generated by 'django-admin startproject' using Django 5.1.6.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/5.1/topics/settings/
+
+For the full list of settings and their values, see
+https://docs.djangoproject.com/en/5.1/ref/settings/
+"""
+
+from pathlib import Path
+import pymysql
+pymysql.install_as_MySQLdb()
+
+# 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/5.1/howto/deployment/checklist/
+
+# SECURITY WARNING: keep the secret key used in production secret!
+SECRET_KEY = 'django-insecure-9os%w6o3zjgxf-7^=51h4vtl)j)7e4yp--puf!v8_zmh7!#@nc'
+
+# 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',
+    'accounts',
+    'events',
+]
+
+AUTH_USER_MODEL = 'accounts.User'
+
+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',
+]
+
+ROOT_URLCONF = 'unihub_project.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 = 'unihub_project.wsgi.application'
+
+
+# Database
+# https://docs.djangoproject.com/en/5.1/ref/settings/#databases
+
+# unihub_project/settings.py
+
+DATABASES = {
+    'default': {
+        'ENGINE': 'django.db.backends.mysql',
+        'NAME': 'unihub_db',
+        'USER': 'unihub_user',
+        'PASSWORD': 'Thescotts111',
+        'HOST': 'db',  # Refer to the service name in docker-compose.yml
+        'PORT': '3306',
+    }
+}
+
+
+
+# Password validation
+# https://docs.djangoproject.com/en/5.1/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/5.1/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/5.1/howto/static-files/
+
+STATIC_URL = 'static/'
+
+# Default primary key field type
+# https://docs.djangoproject.com/en/5.1/ref/settings/#default-auto-field
+
+DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
diff --git a/unihub_project/urls.py b/unihub_project/urls.py
new file mode 100644
index 0000000..0feeb72
--- /dev/null
+++ b/unihub_project/urls.py
@@ -0,0 +1,26 @@
+"""
+URL configuration for unihub_project project.
+
+The `urlpatterns` list routes URLs to views. For more information please see:
+    https://docs.djangoproject.com/en/5.1/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 .views import home_view  # Import the homepage view
+
+urlpatterns = [
+    path("admin/", admin.site.urls),  
+    path("accounts/", include("accounts.urls")),  # Include accounts URLs
+    path("events/", include("events.urls")),  #  Include events URLs
+    path("", home_view, name="home"),  # Homepage
+]
diff --git a/unihub_project/views.py b/unihub_project/views.py
new file mode 100644
index 0000000..ab86773
--- /dev/null
+++ b/unihub_project/views.py
@@ -0,0 +1,4 @@
+from django.shortcuts import render
+
+def home_view(request):
+    return render(request, "home.html")  # This will look for templates/home.html
diff --git a/unihub_project/wsgi.py b/unihub_project/wsgi.py
new file mode 100644
index 0000000..d8a08ab
--- /dev/null
+++ b/unihub_project/wsgi.py
@@ -0,0 +1,16 @@
+"""
+WSGI config for unihub_project 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/5.1/howto/deployment/wsgi/
+"""
+
+import os
+
+from django.core.wsgi import get_wsgi_application
+
+os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'unihub_project.settings')
+
+application = get_wsgi_application()
-- 
GitLab