diff --git a/backend/app/crud.py b/backend/app/crud.py
index 3736f8043f9802fb4569c52526237137853cfc2b..a750cb73cfd54ef68d88be33e8a839634d3480b9 100644
--- a/backend/app/crud.py
+++ b/backend/app/crud.py
@@ -77,12 +77,20 @@ def create_user_survey_weekly(db: Session, user_id: int, survey: schemas.SurveyC
 
 
 def get_contact_sessions(db: Session, user_id: int, contact_id: int):
-    return (
+    sessions = (
         db.query(models.Session)
         .filter(models.Session.users.any(models.User.id == user_id))
         .filter(models.Session.users.any(models.User.id == contact_id))
         .all()
     )
+    for session in sessions:
+        session.length = (
+            db.query(models.Message)
+            .filter(models.Message.session_id == session.id)
+            .count()
+        )
+
+    return sessions
 
 
 def create_session(db: Session, user: schemas.User):
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 85e434b8ea32a3a4449243cecec13c93e086bde2..0fe6f39df8bdd4a91ed38b8bafd7e1de92fc0ff7 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -8,6 +8,7 @@
 			"name": "frontend",
 			"version": "0.0.1",
 			"dependencies": {
+				"@sveltekit-i18n/parser-icu": "^1.0.8",
 				"dayjs": "^1.11.13",
 				"emoji-picker-element": "^1.23.0",
 				"linkify-html": "^4.1.3",
@@ -655,7 +656,6 @@
 			"version": "2.0.0",
 			"resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-2.0.0.tgz",
 			"integrity": "sha512-rRqXOqdFmk7RYvj4khklyqzcfQl9vEL/usogncBHRZfZBDOwMGuSRNFl02fu5KGHXdbinju+YXyuR+Nk8xlr/g==",
-			"dev": true,
 			"license": "MIT",
 			"dependencies": {
 				"@formatjs/intl-localematcher": "0.5.4",
@@ -666,7 +666,6 @@
 			"version": "2.2.0",
 			"resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-2.2.0.tgz",
 			"integrity": "sha512-hnk/nY8FyrL5YxwP9e4r9dqeM6cAbo8PeU9UjyXojZMNvVad2Z06FAVHyR3Ecw6fza+0GH7vdJgiKIVXTMbSBA==",
-			"dev": true,
 			"license": "MIT",
 			"dependencies": {
 				"tslib": "^2.4.0"
@@ -676,7 +675,6 @@
 			"version": "2.7.8",
 			"resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.7.8.tgz",
 			"integrity": "sha512-nBZJYmhpcSX0WeJ5SDYUkZ42AgR3xiyhNCsQweFx3cz/ULJjym8bHAzWKvG5e2+1XO98dBYC0fWeeAECAVSwLA==",
-			"dev": true,
 			"license": "MIT",
 			"dependencies": {
 				"@formatjs/ecma402-abstract": "2.0.0",
@@ -688,7 +686,6 @@
 			"version": "1.8.2",
 			"resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.2.tgz",
 			"integrity": "sha512-k4ERKgw7aKGWJZgTarIcNEmvyTVD9FYh0mTrrBMHZ1b8hUu6iOJ4SzsZlo3UNAvHYa+PnvntIwRPt1/vy4nA9Q==",
-			"dev": true,
 			"license": "MIT",
 			"dependencies": {
 				"@formatjs/ecma402-abstract": "2.0.0",
@@ -699,7 +696,6 @@
 			"version": "0.5.4",
 			"resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.5.4.tgz",
 			"integrity": "sha512-zTwEpWOzZ2CiKcB93BLngUX59hQkuZjT2+SAQEscSm52peDW/getsawMcWF1rGRpMCX6D7nSJA3CzJ8gn13N/g==",
-			"dev": true,
 			"license": "MIT",
 			"dependencies": {
 				"tslib": "^2.4.0"
@@ -1439,6 +1435,15 @@
 			"dev": true,
 			"license": "MIT"
 		},
+		"node_modules/@sveltekit-i18n/parser-icu": {
+			"version": "1.0.8",
+			"resolved": "https://registry.npmjs.org/@sveltekit-i18n/parser-icu/-/parser-icu-1.0.8.tgz",
+			"integrity": "sha512-/LnvE1EJv+higIxB5cWIV+9neiOe+CfC7VKhpv9mnU35NcZO3yOhEZ8y6F8nHHkMYIABLcqr15yk4hSvmRGWDw==",
+			"license": "MIT",
+			"dependencies": {
+				"intl-messageformat": "^10.1.1"
+			}
+		},
 		"node_modules/@types/cookie": {
 			"version": "0.6.0",
 			"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
@@ -3326,7 +3331,6 @@
 			"version": "10.5.14",
 			"resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.5.14.tgz",
 			"integrity": "sha512-IjC6sI0X7YRjjyVH9aUgdftcmZK7WXdHeil4KwbjDnRWjnVitKpAx3rr6t6di1joFp5188VqKcobOPA6mCLG/w==",
-			"dev": true,
 			"license": "BSD-3-Clause",
 			"dependencies": {
 				"@formatjs/ecma402-abstract": "2.0.0",
@@ -5327,7 +5331,6 @@
 			"version": "2.8.1",
 			"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
 			"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
-			"dev": true,
 			"license": "0BSD"
 		},
 		"node_modules/type": {
diff --git a/frontend/package.json b/frontend/package.json
index 786f5fa7ccd23255df9f5bd304874c900772a113..6de874ce125fb5773d34583104489f0bfd83b41e 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -46,6 +46,7 @@
 	},
 	"type": "module",
 	"dependencies": {
+		"@sveltekit-i18n/parser-icu": "^1.0.8",
 		"dayjs": "^1.11.13",
 		"emoji-picker-element": "^1.23.0",
 		"linkify-html": "^4.1.3",
diff --git a/frontend/src/app.css b/frontend/src/app.css
index fac86420b4cd42400cfc5626927624898acf5f2f..124f156456817ec77b5827a6d553136d341070f8 100644
--- a/frontend/src/app.css
+++ b/frontend/src/app.css
@@ -26,3 +26,12 @@
 .input {
 	@apply border-2 border-gray-300 rounded-md p-2;
 }
+
+.no-scrollbar::-webkit-scrollbar {
+	display: none;
+}
+
+.no-scrollbar {
+	-ms-overflow-style: none; /* IE and Edge */
+	scrollbar-width: none; /* Firefox */
+}
diff --git a/frontend/src/lang/fr.json b/frontend/src/lang/fr.json
index c2bd5c0e34b94fce939fcb4e07e0148f31fb9fc9..fbd331035fb46e5e4ef341d22b73195309f4b496 100644
--- a/frontend/src/lang/fr.json
+++ b/frontend/src/lang/fr.json
@@ -22,10 +22,7 @@
 		"history": "Historique"
 	},
 	"home": {
-		"date": "Date",
-		"participants": "Participants",
 		"email": "E-mail",
-		"actions": "Actions",
 		"add": "Ajouter",
 		"deleteSessionConfirm": "Êtes-vous sûr de vouloir supprimer cette session ? Cette action est irréversible.",
 		"createSession": "Session immédiate",
@@ -42,7 +39,9 @@
 		"pastSessions": "Sessions terminées",
 		"newContact": "Ajouter un contact",
 		"bookingSuccessful": "Session réservée avec succès",
-		"bookingFailed": "Erreur lors de la réservation de la session"
+		"bookingFailed": "Erreur lors de la réservation de la session",
+		"noCurrentOrFutureSessions": "Aucune session en cours ou planifiée",
+		"noSessions": "Aucune session"
 	},
 	"login": {
 		"email": "E-mail",
@@ -225,10 +224,10 @@
 				"title": "Questionnaire hebdomadaire",
 				"description": "Au cours des 7 derniers jours...",
 				"questions": [
-					"Combien d'heures de <span class='font-bold'>cours</span> de {TARGET_LANGUAGE} avez vous suivies ?",
-					"Combien d'heures avez-vous <span class='font-bold'>regardé des vidéos</span> en {TARGET_LANGUAGE} (films, séries, Youtube...) ou <span class='font-bold'>écouté des contenus</span> en {TARGET_LANGUAGE} (podcasts, radio, cours universitaires...) ?",
-					"Combien d'heures avez-vous <span class='font-bold'>lu des textes</span> en {TARGET_LANGUAGE} (livre, journal, BD, sites web...) ?",
-					"Combien d'heures avez-vous <span class='font-bold'>parlé</span> en {TARGET_LANGUAGE} (discussions avec amis, famille, collègues...) ?"
+					"Combien d'heures de <span class='font-bold'>cours</span> de {lang} avez vous suivies ?",
+					"Combien d'heures avez-vous <span class='font-bold'>regardé des vidéos</span> en {lang} (films, séries, Youtube...) ou <span class='font-bold'>écouté des contenus</span> en {lang} (podcasts, radio, cours universitaires...) ?",
+					"Combien d'heures avez-vous <span class='font-bold'>lu des textes</span> en {lang} (livre, journal, BD, sites web...) ?",
+					"Combien d'heures avez-vous <span class='font-bold'>parlé</span> en {lang} (discussions avec amis, famille, collègues...) ?"
 				],
 				"answers": {
 					"placeholder": "",
@@ -286,6 +285,20 @@
 			"november": "novembre",
 			"december": "décembre"
 		},
+		"shortMonth": {
+			"january": "janv.",
+			"february": "févr.",
+			"march": "mars",
+			"april": "avr.",
+			"may": "mai",
+			"june": "juin",
+			"july": "juil.",
+			"august": "août",
+			"september": "sept.",
+			"october": "oct.",
+			"november": "nov.",
+			"december": "déc."
+		},
 		"days": {
 			"monday": "Lundi",
 			"tuesday": "Mardi",
@@ -302,6 +315,15 @@
 			"5": "Samedi",
 			"6": "Dimanche"
 		},
+		"past": {
+			"year": "Il y a {n, plural, one {# an} other {# ans}}",
+			"month": "Il y a {n, plural, one {# mois} other {# mois}}",
+			"day": "Il y a {n, plural, one {# jour} other {# jours}}",
+			"hour": "Il y a {n, plural, one {# heure} other {# heures}}",
+			"today": "Aujourd'hui",
+			"yesterday": "Hier",
+			"justNow": "Il y a moins d'une heure"
+		},
 		"language": {
 			"fr": "Français",
 			"en": "Anglais",
@@ -315,7 +337,13 @@
 		"words": {
 			"date": "Date",
 			"messages": "Messages",
-			"actions": "Actions"
+			"actions": "Actions",
+			"participants": "Participants",
+			"status": "Statut",
+			"date": "Date",
+			"programed": "Programmée",
+			"inProgress": "En cours",
+			"finished": "Terminée"
 		}
 	},
 	"inputs": {
diff --git a/frontend/src/lib/components/users/weeklySurvey.svelte b/frontend/src/lib/components/users/weeklySurvey.svelte
index 76790f854fb6e5355d45e659e0992fea374280cb..8143e783b884b73140fb9f8f69cddec53a50a731 100644
--- a/frontend/src/lib/components/users/weeklySurvey.svelte
+++ b/frontend/src/lib/components/users/weeklySurvey.svelte
@@ -49,10 +49,9 @@
 			<label class="form-control w-full">
 				<div class="label">
 					<span class="label-text"
-						>{@html $t('session.modal.weekly.questions.' + i).replaceAll(
-							'{TARGET_LANGUAGE}',
-							$t('utils.language.' + $user?.target_language).toLowerCase()
-						)}</span
+						>{@html $t('session.modal.weekly.questions.' + i, {
+							lang: $t('utils.language.' + $user?.target_language).toLowerCase()
+						})}</span
 					>
 				</div>
 				<select id={'questions-' + i} class="select select-bordered">
diff --git a/frontend/src/lib/services/i18n.ts b/frontend/src/lib/services/i18n.ts
index 7158bc8f2cfec1a9903fb6a587f35923922edc05..f5e350b0c5275e541f19b33437769056a054b68b 100644
--- a/frontend/src/lib/services/i18n.ts
+++ b/frontend/src/lib/services/i18n.ts
@@ -1,6 +1,12 @@
-import i18n, { type Config } from 'sveltekit-i18n';
+import i18n from '@sveltekit-i18n/base';
+import parser from '@sveltekit-i18n/parser-icu';
+
+import type { Config } from '@sveltekit-i18n/parser-icu';
 
 const config: Config = {
+	parser: parser({
+		ignoreTag: true
+	}),
 	loaders: [
 		{
 			locale: 'en',
diff --git a/frontend/src/lib/utils/date.ts b/frontend/src/lib/utils/date.ts
index c8de2aa14b74b6fdfdabaa5bba3e601591e5edeb..c276e2d2c6aa0bd8de3073db92eadffc851b9d0d 100644
--- a/frontend/src/lib/utils/date.ts
+++ b/frontend/src/lib/utils/date.ts
@@ -32,6 +32,37 @@ export function getFullMonth(id: number): string {
 	}
 }
 
+export function getShortMonth(id: number): string {
+	switch (id) {
+		case 0:
+			return get(t)('utils.shortMonth.january');
+		case 1:
+			return get(t)('utils.shortMonth.february');
+		case 2:
+			return get(t)('utils.shortMonth.march');
+		case 3:
+			return get(t)('utils.shortMonth.april');
+		case 4:
+			return get(t)('utils.shortMonth.may');
+		case 5:
+			return get(t)('utils.shortMonth.june');
+		case 6:
+			return get(t)('utils.shortMonth.july');
+		case 7:
+			return get(t)('utils.shortMonth.august');
+		case 8:
+			return get(t)('utils.shortMonth.september');
+		case 9:
+			return get(t)('utils.shortMonth.october');
+		case 10:
+			return get(t)('utils.shortMonth.november');
+		case 11:
+			return get(t)('utils.shortMonth.december');
+		default:
+			return '??';
+	}
+}
+
 export function displayDate(date: Date): string {
 	if (date === null) return '';
 
@@ -72,19 +103,21 @@ export function displayTime(date: Date): string {
 		now.getFullYear() === date.getFullYear() &&
 		now.getMonth() === date.getMonth()
 	) {
-		return hours + ':' + minutes;
+		return ('0' + hours).slice(-2) + ':' + ('0' + minutes).slice(-2);
 	}
 
 	const day = date.getDate().toString();
 	const month = getFullMonth(date.getMonth());
 
 	if (now.getFullYear() === date.getFullYear()) {
-		return day + ' ' + month + ' ' + hours + ':' + minutes;
+		return day + ' ' + month + ' ' + ('0' + hours).slice(-2) + ':' + ('0' + minutes).slice(-2);
 	}
 
 	const year = date.getFullYear().toString();
 
-	return day + ' ' + month + ' ' + year + ' ' + hours + ':' + minutes;
+	return (
+		day + ' ' + month + ' ' + year + ' ' + ('0' + hours).slice(-2) + ':' + ('0' + minutes).slice(-2)
+	);
 }
 
 export function displayDuration(start: Date, end: Date): string | null {
@@ -106,3 +139,39 @@ export function parseToLocalDate(dateStr: string): Date {
 export function formatToUTCDate(date: Date): string {
 	return date.toISOString().split('Z')[0];
 }
+
+export function displayShortTime(date: Date): string {
+	const now = new Date();
+
+	return (
+		('0' + date.getDate()).slice(-2) +
+		' ' +
+		getShortMonth(date.getMonth()) +
+		(date.getFullYear() != now.getFullYear() ? ' ' + date.getFullYear() : '') +
+		' ' +
+		('0' + date.getHours()).slice(-2) +
+		'h'
+	);
+}
+
+export function displayTimeSince(date: Date): string {
+	const now = new Date();
+	const diff = now.getTime() - date.getTime();
+	const seconds = Math.floor(diff / 1000);
+	const minutes = Math.floor(seconds / 60);
+	const hours = Math.floor(minutes / 60);
+	const days = Math.floor(hours / 24);
+	const months = Math.floor(days / 30);
+	const years = Math.floor(months / 12);
+	if (years > 0) {
+		return get(t)('utils.past.year', { n: years });
+	} else if (months > 0) {
+		return get(t)('utils.past.month', { n: months });
+	} else if (days === 1) {
+		return get(t)('utils.past.yesterday');
+	} else if (days > 0) {
+		return get(t)('utils.past.day', { n: days });
+	} else {
+		return get(t)('utils.past.today');
+	}
+}
diff --git a/frontend/src/routes/+page.svelte b/frontend/src/routes/+page.svelte
index 5acdde5d92dccd0f59531a4e641de84da689efb3..ed9f6fef645c15796ec431ddc8aaa58ffe989371 100644
--- a/frontend/src/routes/+page.svelte
+++ b/frontend/src/routes/+page.svelte
@@ -1,13 +1,14 @@
 <script lang="ts">
 	import Session from '$lib/types/session';
 	import { onMount } from 'svelte';
-	import { displayTime } from '$lib/utils/date';
+	import { displayShortTime, displayTimeSince } from '$lib/utils/date';
 	import {
 		AcademicCap,
 		Sparkles,
 		Icon,
 		User as UserIcon,
-		MagnifyingGlass
+		MagnifyingGlass,
+		ArrowRightCircle
 	} from 'svelte-hero-icons';
 	import { t } from '$lib/services/i18n';
 	import User, { user } from '$lib/types/user';
@@ -27,14 +28,19 @@
 	let modalNew = false;
 	let nickname = '';
 
+	let showTerminatedSessions = false;
+
 	async function selectContact(c: User | null) {
+		showTerminatedSessions = false;
 		contact = c;
 		if (!contact) {
 			contactSessions = [];
 			return;
 		}
 
-		contactSessions = Session.parseAll(await getUserContactSessionsAPI($user!.id, contact.id));
+		contactSessions = Session.parseAll(await getUserContactSessionsAPI($user!.id, contact.id)).sort(
+			(a, b) => b.start_time.getTime() - a.start_time.getTime()
+		);
 	}
 
 	onMount(async () => {
@@ -103,7 +109,9 @@
 					return;
 				}
 				toastSuccess(get(t)('home.bookingSuccessful'));
-				contactSessions = Session.parseAll(await getUserContactSessionsAPI($user!.id, contact.id));
+				contactSessions = Session.parseAll(
+					await getUserContactSessionsAPI($user!.id, contact.id)
+				).sort((a, b) => b.start_time.getTime() - a.start_time.getTime());
 			}
 		});
 	});
@@ -113,7 +121,9 @@
 		let session = await Session.create();
 		if (!session) return;
 		await session.addUser(contact);
-		contactSessions = [...contactSessions, session];
+		contactSessions = [...contactSessions, session].sort(
+			(a, b) => b.start_time.getTime() - a.start_time.getTime()
+		);
 	}
 
 	async function searchNickname() {
@@ -130,18 +140,13 @@
 	}
 </script>
 
-<svelte:head>
-	<script>
-	</script>
-</svelte:head>
-
 {#if ready}
-	<div class="h-full w-full flex">
-		<ul class="h-full [width:_clamp(200px,25%,500px)] overflow-y-scroll border-r-2 flex flex-col">
+	<div class="flex-row h-full flex py-4 flex-grow overflow-y-hidden">
+		<div class="flex flex-col border shadow-[0_0_6px_0_rgba(0,14,156,.2)] min-w-72 rounded-r-xl">
 			<div class="flex-grow">
 				{#each contacts as c (c.id)}
-					<li
-						class="h-20 flex border-gray-300 border-b-2 hover:bg-gray-200 hover:cursor-pointer"
+					<div
+						class="h-24 flex border-gray-300 border-b-2 hover:bg-gray-200 hover:cursor-pointer p-4"
 						class:bg-gray-200={c.id === contact?.id}
 						on:click={() => selectContact(c)}
 						role="button"
@@ -149,19 +154,19 @@
 						tabindex="0"
 						on:keydown={(e) => e.key === 'Enter' && selectContact(c)}
 					>
-						<div class="w-16 ml-2 mr-4 p-4 avatar bg-gray-300 mask-squircle mask">
+						<div class="w-16 ml-2 mr-4 p-4 bg-gray-300 rounded-2xl">
 							{#if c.type == 0}
 								<Icon src={Sparkles} class="mask mask-squircle" />
 							{:else if c.type == 1}
-								<Icon src={AcademicCap} />
+								<Icon src={AcademicCap} class="" />
 							{:else}
 								<Icon src={UserIcon} />
 							{/if}
 						</div>
-						<div class="flex items-center text-lg">
+						<div class="text-lg font-bold capitalize flex items-center">
 							{c.nickname}
 						</div>
-					</li>
+					</div>
 				{/each}
 			</div>
 			<button
@@ -170,80 +175,125 @@
 			>
 				+
 			</button>
-		</ul>
-		<div class="flex-grow flex-col flex">
-			{#if contact}
-				<div class="p-4 pr-8">
-					<button on:click|preventDefault={createSession} class="button float-end">
+		</div>
+		{#if contact}
+			<div class="flex flex-col xl:mx-auto xl:w-[60rem] m-4">
+				<div>
+					<button on:click|preventDefault={createSession} class="button float-start mr-2">
 						{$t('home.createSession')}
 					</button>
-					<div class="size-4 float-end"></div>
 					<button
-						class="button float-end"
+						class="button float-start"
 						class:btn-disabled={!contact || !contact.calcom_link}
 						data-cal-link={`${contact.calcom_link}?email=${$user?.email}&name=${$user?.nickname}`}
 					>
 						{$t('home.bookSession')}
 					</button>
 				</div>
-				<div class="flex-grow p-2">
-					<h2 class="text-xl my-4 font-bold">{$t('home.currentSessions')}</h2>
-					<ul>
-						{#each contactSessions as s (s.id)}
-							{#if s.start_time <= new Date() && s.end_time >= new Date()}
-								<li>
-									<a
-										class="block p-4 m-1 mx-4 rounded-md w-[calc(100%-32px)] border-2 hover:bg-gray-200 text-center"
-										href={`/session?id=${s.id}`}
-									>
-										{displayTime(s.start_time)} - {displayTime(s.end_time)}
-									</a>
-								</li>
-							{/if}
-						{/each}
-					</ul>
-					<h2 class="text-xl my-4 font-bold">{$t('home.plannedSessions')}</h2>
-					<ul>
-						{#each contactSessions as s (s.id)}
-							{#if s.start_time > new Date()}
-								<li>
-									<a
-										class="block p-4 m-1 mx-4 rounded-md w-[calc(100%-32px)] border-2 hover:bg-gray-200 text-center"
-										href={`/session?id=${s.id}`}
-									>
-										{displayTime(s.start_time)} - {displayTime(s.end_time)}
-									</a>
-								</li>
-							{/if}
-						{/each}
-					</ul>
-					<h2 class="text-xl my-4 font-bold">{$t('home.pastSessions')}</h2>
-					<ul>
-						{#each contactSessions as s (s.id)}
-							{#if s.end_time < new Date()}
-								<li>
-									<a
-										class="block p-4 m-1 mx-4 rounded-md w-[calc(100%-32px)] border-2 hover:bg-gray-200 text-center"
-										href={`/session?id=${s.id}`}
+				<div
+					class="border p-4 mt-4 rounded-xl shadow-[0_0_6px_0_rgba(0,14,156,.2)] overflow-y-scroll no-scrollbar"
+				>
+					<table class="divide-y divide-neutral-300 text-center w-full table-fixed">
+						<thead>
+							<tr>
+								<th scope="col" class="text-left">{$t('utils.words.date')}</th>
+								<th scope="col">{$t('utils.words.status')}</th>
+								<th scope="col"># {$t('utils.words.messages').toLowerCase()}</th>
+								<th scope="col">{$t('utils.words.actions')}</th>
+							</tr>
+						</thead>
+						<tbody class="divide-y divide-neutral-200">
+							{#if contactSessions.length === 0}
+								<tr>
+									<td colspan="4" class="py-5 text-gray-500">{$t('home.noSessions')}</td>
+								</tr>
+							{:else}
+								{#if !showTerminatedSessions && contactSessions.filter((s) => s.end_time >= new Date()).length === 0}
+									<tr>
+										<td colspan="4" class="py-5 text-gray-500"
+											>{$t('home.noCurrentOrFutureSessions')}</td
+										>
+									</tr>
+								{/if}
+								{#each contactSessions as s (s.id)}
+									{#if showTerminatedSessions || s.end_time >= new Date()}
+										<tr>
+											<td class="py-2 text-left space-y-1">
+												<div>
+													{displayShortTime(s.start_time)}
+												</div>
+												<div class="text-sm italic text-gray-600">
+													{displayTimeSince(s.start_time)}
+												</div>
+											</td>
+											<td class="py-2">
+												{#if s.start_time <= new Date() && s.end_time >= new Date()}
+													<span class="bg-green-200 rounded-lg px-2 py-1"
+														>{$t('utils.words.inProgress')}</span
+													>
+												{:else if s.start_time > new Date()}
+													<span class="bg-orange-200 rounded-lg px-2 py-1"
+														>{$t('utils.words.programed')}</span
+													>
+												{:else}
+													<span class="bg-red-200 rounded-lg px-2 py-1"
+														>{$t('utils.words.finished')}</span
+													>
+												{/if}
+											</td>
+											<td class="py-2">{s.length} {$t('utils.words.messages').toLowerCase()}</td>
+											<td class="py-2">
+												<a href="/session?id={s.id}" class="group">
+													<Icon
+														src={ArrowRightCircle}
+														size="32"
+														class="text-accent mx-auto group-hover:text-white group-hover:bg-accent rounded-full"
+													/>
+												</a>
+											</td>
+										</tr>
+									{/if}
+								{/each}
+								<tr>
+									<td
+										class="py-2 hover:cursor-pointer"
+										colspan="4"
+										on:click={() => (showTerminatedSessions = !showTerminatedSessions)}
 									>
-										{displayTime(s.start_time)} - {displayTime(s.end_time)}
-									</a>
-								</li>
+										<button aria-label={showTerminatedSessions ? 'Hide' : 'Show'}>
+											<svg
+												class="size-3 ms-3"
+												aria-hidden="true"
+												xmlns="http://www.w3.org/2000/svg"
+												fill="none"
+												viewBox="0 0 10 6"
+												class:rotate-180={showTerminatedSessions}
+											>
+												<path
+													stroke="currentColor"
+													stroke-linecap="round"
+													stroke-linejoin="round"
+													stroke-width="2"
+													d="m1 1 4 4 4-4"
+												/>
+											</svg>
+										</button>
+									</td>
+								</tr>
 							{/if}
-						{/each}
-					</ul>
+						</tbody>
+					</table>
 				</div>
-			{/if}
-		</div>
+			</div>
+		{/if}
 	</div>
 {/if}
 
 <dialog
-	class="modal"
+	class="modal bg-black bg-opacity-50"
 	open={modalNew}
 	on:close={() => (modalNew = false)}
-	on:keydown={(e) => e.key === 'Escape' && (modalNew = false)}
-	tabindex="0"
+	tabindex="-1"
 >
 	<div class="modal-box">
 		<h2 class="text-xl font-bold mb-4">{$t('home.newContact')}</h2>
@@ -253,6 +303,7 @@
 				placeholder={$t('home.email')}
 				bind:value={nickname}
 				class="input flex-grow mr-2"
+				on:keydown={(e) => e.key === 'Escape' && (modalNew = false)}
 			/>
 			<button class="button w-16" on:click={searchNickname}>
 				<Icon src={MagnifyingGlass} />