From 8ebb22de88993b6d2406901b0b2a145f79e87422 Mon Sep 17 00:00:00 2001
From: James2Tulloch <146088090+James2Tulloch@users.noreply.github.com>
Date: Fri, 28 Mar 2025 13:59:50 +0000
Subject: [PATCH] Work in progress

---
 .../myapp/templates/myapp/base.html           |  1 -
 .../myapp/templates/myapp/group_detail.html   | 10 ++
 .../myapp/templates/myapp/login.html          | 94 +++++++++++++++----
 django_project/myapp/views/groupviews.py      | 35 ++++---
 rust_crud_api/src/db/groups.rs                | 24 +++--
 rust_crud_api/src/db/init.rs                  |  2 +-
 6 files changed, 119 insertions(+), 47 deletions(-)

diff --git a/django_project/myapp/templates/myapp/base.html b/django_project/myapp/templates/myapp/base.html
index 3a284d8..e5e7945 100644
--- a/django_project/myapp/templates/myapp/base.html
+++ b/django_project/myapp/templates/myapp/base.html
@@ -7,7 +7,6 @@
     <style>
         nav {
             background-image: linear-gradient(to right, #00bfff, #00ffd5); 
-            /*background-color: #344cff;*/
             overflow: hidden;
         }
         nav ul {
diff --git a/django_project/myapp/templates/myapp/group_detail.html b/django_project/myapp/templates/myapp/group_detail.html
index faba797..d349063 100644
--- a/django_project/myapp/templates/myapp/group_detail.html
+++ b/django_project/myapp/templates/myapp/group_detail.html
@@ -9,6 +9,16 @@
     {% else %}
         <p><strong>Group Name:</strong> {{ group.name }}</p>
         <p><strong>Group ID:</strong> {{ group.id }}</p>
+        <p><strong>Member Count:</strong> {{ group.member_count }}</p>
+        {% if request.user in group.members.all %}
+        <p>You’re already a member of this group.</p>
+        {% else %}
+        <form method="post">
+            {% csrf_token %}
+            <input type="hidden" name="user_id" value="{{ request.user.id }}">
+            <button type="submit">Join Group</button>
+        </form>
+    {% endif %}
     {% endif %}
     <p><a href="{% url 'group_list' %}">Back to Groups</a></p>
 </body>
diff --git a/django_project/myapp/templates/myapp/login.html b/django_project/myapp/templates/myapp/login.html
index 235de7b..dd14de3 100644
--- a/django_project/myapp/templates/myapp/login.html
+++ b/django_project/myapp/templates/myapp/login.html
@@ -4,29 +4,83 @@
     <meta charset="UTF-8">
     <title>Login</title>
     <style>
-        body { font-family: Arial, sans-serif; margin: 2em; }
-        .error { color: red; }
+        body {
+            font-family: Arial, sans-serif;
+            margin: 0;
+            display: flex;
+            height: 100vh;
+        }
+        .container {
+            display: flex;
+            width: 100%;
+        }
+        .left, .right {
+            width: 50%;
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            padding: 2em;
+        }
+        .left {
+            background-color: #f8f9fa;
+        }
+        .right {
+            background-image: linear-gradient(to right, #00bfff, #00ffd5); 
+            text-align: center;
+        }
+        .error {
+            color: red;
+        }
+        form {
+            width: 100%;
+            max-width: 300px;
+        }
+        input, button {
+            width: 100%;
+            padding: 0.5em;
+            margin-top: 0.5em;
+        }
+        button {
+            background-color: #007bff;
+            color: white;
+            border: none;
+            cursor: pointer;
+        }
+        button:hover {
+            background-color: #0056b3;
+        }
     </style>
 </head>
 <body>
-    <h1>Login</h1>
-    {% if error %}
-      <p class="error">{{ error }}</p>
-    {% endif %}
-    <form method="post">
-        {% csrf_token %}
-        <label for="id_email">Email:</label>
-        <input type="email" name="email" id="id_email" required><br><br>
-        
-        <label for="id_password">Password:</label>
-        <input type="password" name="password" id="id_password" required><br><br>
-        
-        <button type="submit">Login</button>
-    </form>
-    <p>
-        Don't have an account?
-        <a href="{% url 'register' %}">Register here</a>.
-    </p>
+    <div class="container">
+        <div class="left">
+            <div>
+                <h1>Login</h1>
+                {% if error %}
+                  <p class="error">{{ error }}</p>
+                {% endif %}
+                <form method="post">
+                    {% csrf_token %}
+                    <label for="id_email">Email:</label>
+                    <input type="email" name="email" id="id_email" required><br>
+                    
+                    <label for="id_password">Password:</label>
+                    <input type="password" name="password" id="id_password" required><br>
+                    
+                    <button type="submit">Login</button>
+                </form>
+                <p>
+                    Don't have an account?
+                    <a href="{% url 'register' %}">Register here</a>.
+                </p>
+            </div>
+        </div>
+        <div class="right">
+            <h1>UniHub</h1>
+            <p>Where university happens.</p>
+        </div>
+    </div>
 </body>
 </html>
 
+
diff --git a/django_project/myapp/views/groupviews.py b/django_project/myapp/views/groupviews.py
index f73ac8a..a4f28c9 100644
--- a/django_project/myapp/views/groupviews.py
+++ b/django_project/myapp/views/groupviews.py
@@ -95,38 +95,36 @@ def group_delete_view(request, group_id):
     return render(request, 'myapp/group_delete.html', context)
 
 def group_detail_view(request, group_id):
-    """
-    Fetch a single group's details using the Rust extension and display them.
-    """
     db_url = settings.DATABASE_URL
     context = {}
 
-    try:
-        # Fetch group details
-        group = rust_crud_api.get_group(db_url, group_id)
-        if group is None:
-            return HttpResponseNotFound("Group not found.")
-
-        # Fetch group members and member count
-        members, member_count = rust_crud_api.get_group_members(db_url, group_id)
+    if request.method == 'POST':
+        user_id = request.POST.get('user_id')  # might be None or 'None'
 
-        # Populate context with group details
-        context['group'] = group
-        context['members'] = members
-        context['member_count'] = member_count
+        # Check for None *before* calling Rust
+        if not user_id or user_id == 'None':
+            context['error'] = "Invalid user_id: None"
+            return render(request, 'myapp/group_detail.html', context)
 
-    except Exception as e:
-        context['error'] = f"An error occurred: {e}"
+        try:
+            # Now we safely do int(user_id) because we checked it's not None
+            result = rust_crud_api.add_user_to_group(db_url, int(group_id), int(user_id))
+        except Exception as e:
+            context['error'] = f"An error occurred: {e}"
+            return render(request, 'myapp/group_detail.html', context)
 
+    # Normal GET behavior...
     return render(request, 'myapp/group_detail.html', context)
 
 
+
+
 def group_search_view(request):
     """
     Handles searching for groups using Rust.
     """
     db_url = settings.DATABASE_URL  
-    query = request.GET.get("q", "").strip()  
+    query = request .GET.get("q", "").strip()  
     groups = [] 
     if query:
         try:
@@ -135,4 +133,3 @@ def group_search_view(request):
             return render(request, "group_search.html", {"error": str(e), "query": query})
 
     return render(request, "group_search.html", {"groups": groups, "query": query})
-
diff --git a/rust_crud_api/src/db/groups.rs b/rust_crud_api/src/db/groups.rs
index fa9e5a9..27f6d68 100644
--- a/rust_crud_api/src/db/groups.rs
+++ b/rust_crud_api/src/db/groups.rs
@@ -60,17 +60,19 @@ pub fn get_all_groups(db_url: &str) -> PyResult<Vec<Group>> {
 #[pyfunction]
 pub fn add_user_to_group(db_url: &str, group_id: i32, user_id: i32) -> PyResult<()> {
     let mut client = Client::connect(db_url, NoTls).map_err(pg_err)?;
+    
+    // Insert a row to show membership
     client.execute(
-        "INSERT INTO group_members (group_id, user_id) VALUES ($1, $2)",
-        &[&group_id, &user_id]
-    ).map_err(pg_err)?;
-    client.execute(
-        "UPDATE groups SET member_count = member_count + 1 WHERE id = $1",
-        &[&group_id]
+        "INSERT INTO group_members (group_id, user_id)
+         VALUES ($1, $2)
+         ON CONFLICT DO NOTHING",
+        &[&group_id, &user_id],
     ).map_err(pg_err)?;
+
     Ok(())
 }
 
+
 /// Get all members of a group.
 #[pyfunction]
 pub fn get_group_members(db_url: &str, group_id: i32) -> PyResult<(Vec<User>, i32)> {
@@ -134,3 +136,13 @@ pub fn search_groups(db_url: &str, query: &str) -> PyResult<Vec<Group>> {
 
     Ok(groups)
 }
+
+#[pyfunction]
+pub fn get_group_member_count(db_url: &str, group_id: i32) -> PyResult<i64> {
+    let mut client = Client::connect(db_url, NoTls).map_err(pg_err)?;
+    let row = client.query_one(
+        "SELECT COUNT(*) FROM group_members WHERE group_id = $1",
+        &[&group_id]
+    ).map_err(pg_err)?;
+    Ok(row.get(0)) // returns i64
+}
\ No newline at end of file
diff --git a/rust_crud_api/src/db/init.rs b/rust_crud_api/src/db/init.rs
index 9e090ac..031b6d9 100644
--- a/rust_crud_api/src/db/init.rs
+++ b/rust_crud_api/src/db/init.rs
@@ -26,7 +26,7 @@ pub fn init_db(db_url: &str) -> PyResult<()> {
         CREATE TABLE IF NOT EXISTS groups (
             id SERIAL PRIMARY KEY,
             name VARCHAR NOT NULL,
-            member_count INTEGER DEFAULT 0
+            member_count INTEGER NOT NULL DEFAULT 0
         );
         CREATE TABLE IF NOT EXISTS group_members (
             group_id INTEGER REFERENCES groups(id),
-- 
GitLab