From 95b3430240bfdd97e5c545ef821f20a8a554b96e Mon Sep 17 00:00:00 2001
From: DavePk04 <Dave.Pikop.Pokam@ulb.be>
Date: Thu, 30 Jan 2025 09:16:38 +0100
Subject: [PATCH 1/6] ui: add the user status logic

---
 .../src/routes/sessions/[id]/Message.svelte   | 49 ++++++++++++++++---
 1 file changed, 42 insertions(+), 7 deletions(-)

diff --git a/frontend/src/routes/sessions/[id]/Message.svelte b/frontend/src/routes/sessions/[id]/Message.svelte
index 943515d2..9908f0b2 100644
--- a/frontend/src/routes/sessions/[id]/Message.svelte
+++ b/frontend/src/routes/sessions/[id]/Message.svelte
@@ -185,6 +185,32 @@
 
 		await message.deleteFeedback(feedback);
 	}
+
+	function getUserStatus(user: User, isInConversation: boolean): string {
+		console.log("status", user.is_active);
+    if (!user.is_active) {
+        return 'red'; 
+    }
+    if (isInConversation) {
+        return 'green'; 
+    }
+    return 'orange'; 
+}
+
+function getUserStatusTooltip(status: string): string {
+    switch (status) {
+        case 'green':
+            return 'User is in this conversation';
+        case 'orange':
+            return 'User is connected but not in this conversation';
+        case 'red':
+            return 'User is not connected to LL';
+        default:
+            return '';
+    }
+}
+
+
 </script>
 
 <div
@@ -193,13 +219,22 @@
 	class:chat-start={!isSender}
 	class:chat-end={isSender}
 >
-	<div class="rounded-full mx-2 chat-image size-12" title={message.user.nickname}>
-		<img
-			src={`https://gravatar.com/avatar/${message.user.emailHash}?d=identicon`}
-			alt={user.nickname}
-			class="rounded-full border border-neutral-400 text-sm"
-		/>
-	</div>
+<div class="relative rounded-full mx-2 chat-image size-12" title={message.user.nickname}>
+	<img
+		src={`https://gravatar.com/avatar/${message.user.emailHash}?d=identicon`}
+		alt={user.nickname}
+		class="rounded-full border border-neutral-400 text-sm"
+	/>
+	<div
+	class={`absolute bottom-0 right-0 w-3 h-3 rounded-full border-2 border-white ${
+	  getUserStatus(message.user, true) === 'green' ? 'bg-green-500' :
+	  getUserStatus(message.user, false) === 'orange' ? 'bg-orange-500' :
+	  getUserStatus(message.user, false) === 'red' ? 'bg-red-500' : ''
+	}`}
+	></div>
+</div>
+
+
 
 	<div class="chat-bubble text-black" class:bg-blue-50={isSender} class:bg-gray-300={!isSender}>
 		{#if replyToMessage}
-- 
GitLab


From c6153a350c2b692406cfac30b7795c0a284e951f Mon Sep 17 00:00:00 2001
From: DavePk04 <Dave.Pikop.Pokam@ulb.be>
Date: Thu, 30 Jan 2025 09:19:46 +0100
Subject: [PATCH 2/6] fix linting

---
 .../src/routes/sessions/[id]/Message.svelte   | 78 +++++++++----------
 1 file changed, 39 insertions(+), 39 deletions(-)

diff --git a/frontend/src/routes/sessions/[id]/Message.svelte b/frontend/src/routes/sessions/[id]/Message.svelte
index 9908f0b2..aa19c714 100644
--- a/frontend/src/routes/sessions/[id]/Message.svelte
+++ b/frontend/src/routes/sessions/[id]/Message.svelte
@@ -187,30 +187,28 @@
 	}
 
 	function getUserStatus(user: User, isInConversation: boolean): string {
-		console.log("status", user.is_active);
-    if (!user.is_active) {
-        return 'red'; 
-    }
-    if (isInConversation) {
-        return 'green'; 
-    }
-    return 'orange'; 
-}
-
-function getUserStatusTooltip(status: string): string {
-    switch (status) {
-        case 'green':
-            return 'User is in this conversation';
-        case 'orange':
-            return 'User is connected but not in this conversation';
-        case 'red':
-            return 'User is not connected to LL';
-        default:
-            return '';
-    }
-}
-
+		console.log('status', user.is_active);
+		if (!user.is_active) {
+			return 'red';
+		}
+		if (isInConversation) {
+			return 'green';
+		}
+		return 'orange';
+	}
 
+	function getUserStatusTooltip(status: string): string {
+		switch (status) {
+			case 'green':
+				return 'User is in this conversation';
+			case 'orange':
+				return 'User is connected but not in this conversation';
+			case 'red':
+				return 'User is not connected to LL';
+			default:
+				return '';
+		}
+	}
 </script>
 
 <div
@@ -219,22 +217,24 @@ function getUserStatusTooltip(status: string): string {
 	class:chat-start={!isSender}
 	class:chat-end={isSender}
 >
-<div class="relative rounded-full mx-2 chat-image size-12" title={message.user.nickname}>
-	<img
-		src={`https://gravatar.com/avatar/${message.user.emailHash}?d=identicon`}
-		alt={user.nickname}
-		class="rounded-full border border-neutral-400 text-sm"
-	/>
-	<div
-	class={`absolute bottom-0 right-0 w-3 h-3 rounded-full border-2 border-white ${
-	  getUserStatus(message.user, true) === 'green' ? 'bg-green-500' :
-	  getUserStatus(message.user, false) === 'orange' ? 'bg-orange-500' :
-	  getUserStatus(message.user, false) === 'red' ? 'bg-red-500' : ''
-	}`}
-	></div>
-</div>
-
-
+	<div class="relative rounded-full mx-2 chat-image size-12" title={message.user.nickname}>
+		<img
+			src={`https://gravatar.com/avatar/${message.user.emailHash}?d=identicon`}
+			alt={user.nickname}
+			class="rounded-full border border-neutral-400 text-sm"
+		/>
+		<div
+			class={`absolute bottom-0 right-0 w-3 h-3 rounded-full border-2 border-white ${
+				getUserStatus(message.user, true) === 'green'
+					? 'bg-green-500'
+					: getUserStatus(message.user, false) === 'orange'
+						? 'bg-orange-500'
+						: getUserStatus(message.user, false) === 'red'
+							? 'bg-red-500'
+							: ''
+			}`}
+		></div>
+	</div>
 
 	<div class="chat-bubble text-black" class:bg-blue-50={isSender} class:bg-gray-300={!isSender}>
 		{#if replyToMessage}
-- 
GitLab


From ea5bc2c2524366c7920a3d921a60f21c175ee80f Mon Sep 17 00:00:00 2001
From: DavePk04 <Dave.Pikop.Pokam@ulb.be>
Date: Thu, 30 Jan 2025 10:29:28 +0100
Subject: [PATCH 3/6] feat: Update user active status on login/logout and
 improve chat UI

---
 frontend/src/routes/+layout.server.ts         | 12 +++++++--
 frontend/src/routes/logout/+page.server.ts    | 18 +++++++++++--
 .../src/routes/sessions/[id]/Message.svelte   | 26 ++++++-------------
 3 files changed, 34 insertions(+), 22 deletions(-)

diff --git a/frontend/src/routes/+layout.server.ts b/frontend/src/routes/+layout.server.ts
index b3aecd87..c403b2a7 100644
--- a/frontend/src/routes/+layout.server.ts
+++ b/frontend/src/routes/+layout.server.ts
@@ -1,4 +1,5 @@
 import { type ServerLoad, redirect } from '@sveltejs/kit';
+import { patchUserAPI } from '$lib/api/users';
 
 const publicly_allowed = ['/login', '/register', '/tests', '/surveys', '/tutor/register'];
 
@@ -11,10 +12,17 @@ const isPublic = (path: string) => {
 	return false;
 };
 
-export const load: ServerLoad = async ({ locals, url }) => {
+export const load: ServerLoad = async ({ locals, url, fetch }) => {
+
 	if (locals.user == null || locals.user == undefined) {
 		if (!isPublic(url.pathname)) {
-			redirect(303, `/login`);
+			throw redirect(303, `/login`);
+		}
+	} else {
+		try {
+			await patchUserAPI(fetch, locals.user.id, { is_active: true });
+		} catch (error) {
+			console.error('Failed to update user status:', error);
 		}
 	}
 
diff --git a/frontend/src/routes/logout/+page.server.ts b/frontend/src/routes/logout/+page.server.ts
index 7790fb9c..7cd9bda3 100644
--- a/frontend/src/routes/logout/+page.server.ts
+++ b/frontend/src/routes/logout/+page.server.ts
@@ -1,8 +1,22 @@
 import { type ServerLoad, redirect } from '@sveltejs/kit';
+import { patchUserAPI } from '$lib/api/users';
+
+export const load: ServerLoad = async ({ cookies, locals, fetch }) => {
+	if (locals.user) {
+		try {
+			const success = await patchUserAPI(fetch, locals.user.id, { is_active: false });
+			if (!success) {
+				console.error('Failed to update user status.');
+			}
+		} catch (error) {
+			console.error('Error updating user status:', error);
+		}
+	}
 
-export const load: ServerLoad = async ({ cookies }) => {
 	cookies.set('access_token_cookie', '', { maxAge: -1, path: '/' });
 	cookies.set('refresh_token_cookie', '', { maxAge: -1, path: '/' });
 
-	redirect(303, '/login');
+	locals.user = null;
+
+	throw redirect(303, '/login');
 };
diff --git a/frontend/src/routes/sessions/[id]/Message.svelte b/frontend/src/routes/sessions/[id]/Message.svelte
index aa19c714..796beded 100644
--- a/frontend/src/routes/sessions/[id]/Message.svelte
+++ b/frontend/src/routes/sessions/[id]/Message.svelte
@@ -186,28 +186,20 @@
 		await message.deleteFeedback(feedback);
 	}
 
-	function getUserStatus(user: User, isInConversation: boolean): string {
-		console.log('status', user.is_active);
+	function getUserStatus(user: User | null, isInConversation: boolean): string {
+		if (!user) {
+			return 'red';
+		}
+
 		if (!user.is_active) {
 			return 'red';
 		}
+
 		if (isInConversation) {
 			return 'green';
 		}
-		return 'orange';
-	}
 
-	function getUserStatusTooltip(status: string): string {
-		switch (status) {
-			case 'green':
-				return 'User is in this conversation';
-			case 'orange':
-				return 'User is connected but not in this conversation';
-			case 'red':
-				return 'User is not connected to LL';
-			default:
-				return '';
-		}
+		return 'orange';
 	}
 </script>
 
@@ -229,9 +221,7 @@
 					? 'bg-green-500'
 					: getUserStatus(message.user, false) === 'orange'
 						? 'bg-orange-500'
-						: getUserStatus(message.user, false) === 'red'
-							? 'bg-red-500'
-							: ''
+						: 'bg-red-500'
 			}`}
 		></div>
 	</div>
-- 
GitLab


From ebcec9ac040de36ff347a2874eede43e963799c6 Mon Sep 17 00:00:00 2001
From: DavePk04 <Dave.Pikop.Pokam@ulb.be>
Date: Thu, 30 Jan 2025 10:30:14 +0100
Subject: [PATCH 4/6] fix linting

---
 frontend/src/routes/+layout.server.ts | 1 -
 1 file changed, 1 deletion(-)

diff --git a/frontend/src/routes/+layout.server.ts b/frontend/src/routes/+layout.server.ts
index c403b2a7..52b690c6 100644
--- a/frontend/src/routes/+layout.server.ts
+++ b/frontend/src/routes/+layout.server.ts
@@ -13,7 +13,6 @@ const isPublic = (path: string) => {
 };
 
 export const load: ServerLoad = async ({ locals, url, fetch }) => {
-
 	if (locals.user == null || locals.user == undefined) {
 		if (!isPublic(url.pathname)) {
 			throw redirect(303, `/login`);
-- 
GitLab


From 1b6e1e3f29850a02259223000423e0dbb8761416 Mon Sep 17 00:00:00 2001
From: DavePk04 <Dave.Pikop.Pokam@ulb.be>
Date: Thu, 30 Jan 2025 19:28:45 +0100
Subject: [PATCH 5/6] --wip--

---
 frontend/src/routes/Header.svelte             | 42 +++++++++++++++----
 .../src/routes/sessions/[id]/+page.svelte     | 38 +++++++++++++----
 2 files changed, 65 insertions(+), 15 deletions(-)

diff --git a/frontend/src/routes/Header.svelte b/frontend/src/routes/Header.svelte
index 876faf2f..99cf2da8 100644
--- a/frontend/src/routes/Header.svelte
+++ b/frontend/src/routes/Header.svelte
@@ -14,6 +14,22 @@
 			displayMetadataWarning = true;
 		}
 	}
+
+	function getUserStatus(user: User | null, isIn: boolean): string {
+		if (!user) {
+			return 'red';
+		}
+
+		if (!user.is_active) {
+			return 'red';
+		}
+
+		if (isIn) {
+			return 'green';
+		}
+
+		return 'orange';
+	}
 </script>
 
 <header class="navbar shadow bg-gray-200">
@@ -54,14 +70,26 @@
 			{#if user}
 				<li>
 					<details>
-						<summary class="px-3">
-							<img
-								src={`https://gravatar.com/avatar/${user.emailHash}?d=identicon`}
-								alt={''}
-								class="rounded-full border text-sm size-8 border-neutral-400"
-							/>
-							{user.nickname}
+						<summary class="px-3 flex items-center space-x-2">
+							<div class="relative">
+								<img
+									src={`https://gravatar.com/avatar/${user.emailHash}?d=identicon`}
+									alt={''}
+									class="rounded-full border text-sm size-8 border-neutral-400"
+								/>
+								<div
+									class={`absolute bottom-0 right-0 w-3 h-3 rounded-full border-2 border-white ${
+										getUserStatus(user, true) === 'green'
+											? 'bg-green-500'
+											: getUserStatus(user, false) === 'orange'
+												? 'bg-orange-500'
+												: 'bg-red-500'
+									}`}
+								></div>
+							</div>
+							<span>{user.nickname}</span>
 						</summary>
+
 						<ul class="menu menu-sm dropdown-content absolute right-0">
 							<li>
 								<a data-sveltekit-reload href="/logout" class="whitespace-nowrap">
diff --git a/frontend/src/routes/sessions/[id]/+page.svelte b/frontend/src/routes/sessions/[id]/+page.svelte
index 6f53193a..a217ed93 100644
--- a/frontend/src/routes/sessions/[id]/+page.svelte
+++ b/frontend/src/routes/sessions/[id]/+page.svelte
@@ -3,12 +3,28 @@
 	import type { PageData } from './$types.js';
 	import WeeklySurvey from './WeeklySurvey.svelte';
 	import Chatbox from './Chatbox.svelte';
+	import type User from '$lib/types/user';
 
 	let { data }: { data: PageData } = $props();
 	let user = data.user!;
 
 	let { session, jwt } = data;
-	let { onlineUsers } = session;
+
+	function getUserStatus(user: User | null, isIn: boolean): string {
+		if (!user) {
+			return 'red';
+		}
+
+		if (!user.is_active) {
+			return 'red';
+		}
+
+		if (isIn) {
+			return 'green';
+		}
+
+		return 'orange';
+	}
 </script>
 
 <div class="h-full flex lg:flex-row flex-col pt-2 lg:pt-0">
@@ -18,22 +34,28 @@
 		<h2 class="text-center font-bold">{$t('utils.words.participants')}</h2>
 		<div class="pb-2 space-y-2">
 			{#each session.users as sessionUser (sessionUser.id)}
-				<div class="flex space-x-2">
-					<div class="rounded-full mx-2 chat-image size-6" title={sessionUser.nickname}>
+				<div class="flex space-x-2 items-center">
+					<div class="relative mx-2 chat-image size-6" title={sessionUser.nickname}>
 						<img
 							src={`https://gravatar.com/avatar/${sessionUser.emailHash}?d=identicon`}
 							alt={sessionUser.nickname}
-							class="rounded-full border-2 text-sm {sessionUser.id == user?.id ||
-							$onlineUsers.has(sessionUser.id)
-								? 'border-green-500'
-								: 'border-red-500'}"
+							class="rounded-full border-2 text-sm size-6"
 						/>
+						<div
+							class={`absolute bottom-0 right-0 w-3 h-3 rounded-full border-2 border-white ${
+								getUserStatus(sessionUser, true) === 'green'
+									? 'bg-green-500'
+									: getUserStatus(sessionUser, false) === 'orange'
+										? 'bg-orange-500'
+										: 'bg-red-500'
+							}`}
+						></div>
 					</div>
-
 					<span class:font-bold={sessionUser === user}>{sessionUser.nickname}</span>
 				</div>
 			{/each}
 		</div>
+
 		<h2 class="text-center font-bold border-t pt-2">{$t('utils.words.topics')}</h2>
 		<p class="text-center text-sm text-neutral-500 italic">{$t('session.noTopic')}</p>
 	</div>
-- 
GitLab


From 517f4172ce62f5f09d67ed3f11b865493b92ce77 Mon Sep 17 00:00:00 2001
From: DavePk04 <Dave.Pikop.Pokam@ulb.be>
Date: Tue, 4 Feb 2025 13:01:40 +0100
Subject: [PATCH 6/6] revert to previous version

---
 .../src/routes/sessions/[id]/+page.svelte     | 38 ++++---------------
 1 file changed, 8 insertions(+), 30 deletions(-)

diff --git a/frontend/src/routes/sessions/[id]/+page.svelte b/frontend/src/routes/sessions/[id]/+page.svelte
index a217ed93..6f53193a 100644
--- a/frontend/src/routes/sessions/[id]/+page.svelte
+++ b/frontend/src/routes/sessions/[id]/+page.svelte
@@ -3,28 +3,12 @@
 	import type { PageData } from './$types.js';
 	import WeeklySurvey from './WeeklySurvey.svelte';
 	import Chatbox from './Chatbox.svelte';
-	import type User from '$lib/types/user';
 
 	let { data }: { data: PageData } = $props();
 	let user = data.user!;
 
 	let { session, jwt } = data;
-
-	function getUserStatus(user: User | null, isIn: boolean): string {
-		if (!user) {
-			return 'red';
-		}
-
-		if (!user.is_active) {
-			return 'red';
-		}
-
-		if (isIn) {
-			return 'green';
-		}
-
-		return 'orange';
-	}
+	let { onlineUsers } = session;
 </script>
 
 <div class="h-full flex lg:flex-row flex-col pt-2 lg:pt-0">
@@ -34,28 +18,22 @@
 		<h2 class="text-center font-bold">{$t('utils.words.participants')}</h2>
 		<div class="pb-2 space-y-2">
 			{#each session.users as sessionUser (sessionUser.id)}
-				<div class="flex space-x-2 items-center">
-					<div class="relative mx-2 chat-image size-6" title={sessionUser.nickname}>
+				<div class="flex space-x-2">
+					<div class="rounded-full mx-2 chat-image size-6" title={sessionUser.nickname}>
 						<img
 							src={`https://gravatar.com/avatar/${sessionUser.emailHash}?d=identicon`}
 							alt={sessionUser.nickname}
-							class="rounded-full border-2 text-sm size-6"
+							class="rounded-full border-2 text-sm {sessionUser.id == user?.id ||
+							$onlineUsers.has(sessionUser.id)
+								? 'border-green-500'
+								: 'border-red-500'}"
 						/>
-						<div
-							class={`absolute bottom-0 right-0 w-3 h-3 rounded-full border-2 border-white ${
-								getUserStatus(sessionUser, true) === 'green'
-									? 'bg-green-500'
-									: getUserStatus(sessionUser, false) === 'orange'
-										? 'bg-orange-500'
-										: 'bg-red-500'
-							}`}
-						></div>
 					</div>
+
 					<span class:font-bold={sessionUser === user}>{sessionUser.nickname}</span>
 				</div>
 			{/each}
 		</div>
-
 		<h2 class="text-center font-bold border-t pt-2">{$t('utils.words.topics')}</h2>
 		<p class="text-center text-sm text-neutral-500 italic">{$t('session.noTopic')}</p>
 	</div>
-- 
GitLab